generated from nathanwoodburn/python-webserver-template
feat: Add lending positions
All checks were successful
Build Docker / BuildImage (push) Successful in 36s
All checks were successful
Build Docker / BuildImage (push) Successful in 36s
This commit is contained in:
parent
24cff2a523
commit
c3d6e681ce
3
cache.py
3
cache.py
@ -5,7 +5,7 @@ import threading
|
||||
from functools import wraps
|
||||
from time import time, sleep
|
||||
|
||||
def file_cache(folder="cache", ttl=3600):
|
||||
def file_cache(ttl=3600):
|
||||
"""
|
||||
Decorator to cache function results in the specified folder with a TTL.
|
||||
|
||||
@ -13,6 +13,7 @@ def file_cache(folder="cache", ttl=3600):
|
||||
folder (str): Directory where cached files will be stored.
|
||||
ttl (int): Time-to-live for the cache in seconds.
|
||||
"""
|
||||
folder="cache"
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder)
|
||||
|
||||
|
2
cache/1981e30de11cf0845e8b5affb4dc75e0.json
vendored
2
cache/1981e30de11cf0845e8b5affb4dc75e0.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709841.1727908, "result": 3951.21}
|
||||
{"timestamp": 1733719019.8687048, "result": 3917.66}
|
2
cache/1ccff5c6f117409fea0c861aa44b8e62.json
vendored
2
cache/1ccff5c6f117409fea0c861aa44b8e62.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709904.048873, "result": 1.17}
|
||||
{"timestamp": 1733718944.0457852, "result": 1.16}
|
2
cache/29409a8a40dd2d547a7a44b8f6758f54.json
vendored
2
cache/29409a8a40dd2d547a7a44b8f6758f54.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709837.4863276, "result": 4.19}
|
||||
{"timestamp": 1733719021.134048, "result": 4.19}
|
2
cache/4104ed0427efe63d4ca0dead970a4391.json
vendored
2
cache/4104ed0427efe63d4ca0dead970a4391.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709838.508297, "result": 246.79}
|
||||
{"timestamp": 1733719018.4388325, "result": 245.52}
|
2
cache/46c1ec7f5edb30c070003dc54e072f41.json
vendored
2
cache/46c1ec7f5edb30c070003dc54e072f41.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709902.6437316, "result": 4.22}
|
||||
{"timestamp": 1733719082.3050148, "result": 4.18}
|
2
cache/598f5dbf97fb0d45cbc6e1a5b0a3b575.json
vendored
2
cache/598f5dbf97fb0d45cbc6e1a5b0a3b575.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709835.4421465, "result": 232.42}
|
||||
{"timestamp": 1733718865.254725, "result": 231.94}
|
2
cache/6cc6c6a0b2d0654f551d33209c1fd824.json
vendored
2
cache/6cc6c6a0b2d0654f551d33209c1fd824.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709903.0252566, "result": 4.38}
|
||||
{"timestamp": 1733719142.596215, "result": 4.32}
|
2
cache/6eec370e2713cfc84c84e1080b8a191a.json
vendored
2
cache/6eec370e2713cfc84c84e1080b8a191a.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709833.6583126, "result": 303.899783283}
|
||||
{"timestamp": 1733719398.4783282, "result": 326.899783283}
|
2
cache/790b28a9a21cf694ad9577ef1072ac9e.json
vendored
2
cache/790b28a9a21cf694ad9577ef1072ac9e.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709835.0307581, "result": 0.009281764}
|
||||
{"timestamp": 1733718864.8976314, "result": 0.038218578}
|
2
cache/a071d7bdda25c22e42ad7840f17c4b0e.json
vendored
2
cache/a071d7bdda25c22e42ad7840f17c4b0e.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709839.3296363, "result": 0.99943}
|
||||
{"timestamp": 1733719021.178202, "result": 1.0}
|
2
cache/a099e7e540e16a185b0279b9494e5099.json
vendored
2
cache/a099e7e540e16a185b0279b9494e5099.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709841.9973485, "result": 99348}
|
||||
{"timestamp": 1733719020.2031393, "result": 98929}
|
2
cache/a0ee60913ba556f39d128e7d7249e788.json
vendored
2
cache/a0ee60913ba556f39d128e7d7249e788.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709903.03487, "result": [{"mint": "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4", "balance": 24.661756, "price": 4.19, "value": 103.33275764000001, "name": "Jupiter Perpetuals Liquidity Provider Token", "symbol": "jlp"}, {"mint": "jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v", "balance": 0.039815492, "price": 246.79, "value": 9.82606527068, "name": "Jupiter Staked SOL", "symbol": "jupsol"}, {"mint": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", "balance": 0.00255735, "price": 3951.21, "value": 10.104626893499999, "name": "Ethereum (Wormhole)", "symbol": "eth"}, {"mint": "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", "balance": 0.00035766, "price": 99348, "value": 35.532805679999996, "name": "Wrapped BTC (Wormhole)", "symbol": "wbtc"}, {"mint": "0x2::sui::SUI", "balance": 0.902850107, "price": 4.22, "value": 3.81002745154, "name": "Sui", "symbol": "sui"}, {"mint": "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT", "balance": 9.658874002, "price": 4.38, "value": 42.30586812876, "name": "Volo Staked SUI", "symbol": "vsui"}]}
|
||||
{"timestamp": 1733719142.5989292, "result": [{"mint": "jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v", "balance": 0.039815492, "price": 245.52, "value": 9.775499595840001, "name": "Jupiter Staked SOL", "symbol": "jupsol"}, {"mint": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", "balance": 0.00255735, "price": 3917.66, "value": 10.018827800999999, "name": "Ethereum (Wormhole)", "symbol": "eth"}, {"mint": "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", "balance": 0.00035766, "price": 98929, "value": 35.38294614, "name": "Wrapped BTC (Wormhole)", "symbol": "wbtc"}, {"mint": "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4", "balance": 19.88979, "price": 4.19, "value": 83.33822010000002, "name": "Jupiter Perpetuals Liquidity Provider Token", "symbol": "jlp"}, {"mint": "0x2::sui::SUI", "balance": 0.902850107, "price": 4.18, "value": 3.77391344726, "name": "Sui", "symbol": "sui"}, {"mint": "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT", "balance": 9.658874002, "price": 4.32, "value": 41.72633568864, "name": "Volo Staked SUI", "symbol": "vsui"}]}
|
2
cache/c652e896f57f598d23e3dbebdb815ef6.json
vendored
2
cache/c652e896f57f598d23e3dbebdb815ef6.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709903.0345013, "result": [{"mint": "0x2::sui::SUI", "balance": 0.902850107, "price": 4.22, "value": 3.81002745154, "name": "Sui", "symbol": "sui"}, {"mint": "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT", "balance": 9.658874002, "price": 4.38, "value": 42.30586812876, "name": "Volo Staked SUI", "symbol": "vsui"}]}
|
||||
{"timestamp": 1733719142.5983186, "result": [{"mint": "0x2::sui::SUI", "balance": 0.902850107, "price": 4.18, "value": 3.77391344726, "name": "Sui", "symbol": "sui"}, {"mint": "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT", "balance": 9.658874002, "price": 4.32, "value": 41.72633568864, "name": "Volo Staked SUI", "symbol": "vsui"}]}
|
2
cache/ccf2a009e56f1b05d471a55d9c9ea8ea.json
vendored
2
cache/ccf2a009e56f1b05d471a55d9c9ea8ea.json
vendored
@ -1 +1 @@
|
||||
{"timestamp": 1733709903.5823874, "result": 82.815227}
|
||||
{"timestamp": 1733719016.3804839, "result": 82.815227}
|
1
cache/d4e81748ee91683b2c48adaa5cf95187.json
vendored
Normal file
1
cache/d4e81748ee91683b2c48adaa5cf95187.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"timestamp": 1733719016.581333, "result": [{"name": "Kamino USDC Lending", "description": "Kamino USDC Lending", "apy": 26.85, "url": "https://app.kamino.finance/lending/reserve/DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek/Ga4rZytCpq1unD4DbEJ5bkHeUz9g3oh9AAFEi6vSauXp", "value": 20, "updated": "1733717057", "type": "Lending"}, {"name": "dYdX MegaVault", "description": "dYdX MegaVault", "apy": 46, "url": "https://app.kamino.finance/lending/reserve/DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek/Ga4rZytCpq1unD4DbEJ5bkHeUz9g3oh9AAFEi6vSauXp", "value": 23, "updated": "1733717057", "type": "Lending"}]}
|
94
server.py
94
server.py
@ -123,20 +123,23 @@ def index():
|
||||
vaultBalance = getVaultBalance()
|
||||
vaultBalance = "{:.2f}".format(vaultBalance)
|
||||
|
||||
# For testing
|
||||
# tokenSupply = 20
|
||||
# tokenValue = 1.01
|
||||
# tokens = [{"symbol":"stWDBRN","name":"Stake With Us","value":1.01}]
|
||||
# solValue = 10
|
||||
# vaultBalance = "20.00"
|
||||
# pie_chart_data = [(token['symbol'].upper(), token['value'], f"{token['name']}: ${'{:.2f}'.format(token['value'])}") for token in tokens]
|
||||
# pie_chart_data.append(("SOL", solValue, f"Solana: ${'{:.2f}'.format(solValue)}"))
|
||||
|
||||
pie_chart_data = [(token['symbol'].upper(), token['value'], f"{token['name']}: ${'{:.2f}'.format(token['value'])}") for token in tokens]
|
||||
pie_chart_data.append(("SOL", solValue, f"Solana: ${'{:.2f}'.format(solValue)}"))
|
||||
# cardanoBalance = getCardanoValue(vault_cardano_address)
|
||||
# cardanoBalance = "{:.2f}".format(cardanoBalance)
|
||||
# pie_chart_data.append(
|
||||
# ("ADA", cardanoBalance, f"Cardano: ${cardanoBalance}"))
|
||||
|
||||
# other_investment_types = {}
|
||||
# other_investments = getOtherInvestments()
|
||||
# for investment in other_investments:
|
||||
# if investment["type"] not in other_investment_types:
|
||||
# other_investment_types[investment["type"]] = 0
|
||||
# other_investment_types[investment["type"]] += investment["value"]
|
||||
|
||||
cardanoBalance = getCardanoValue(vault_cardano_address)
|
||||
cardanoBalance = "{:.2f}".format(cardanoBalance)
|
||||
pie_chart_data.append(
|
||||
("ADA", cardanoBalance, f"Cardano: ${cardanoBalance}"))
|
||||
# for investment_type in other_investment_types:
|
||||
# pie_chart_data.append((investment_type, other_investment_types[investment_type], f"{investment_type}: ${other_investment_types[investment_type]}"))
|
||||
|
||||
return render_template("index.html", value=tokenValue, supply=tokenSupply, vault=vaultBalance)
|
||||
|
||||
@ -192,7 +195,7 @@ def getTokenSupplyString() -> str:
|
||||
supply = getTokenSupply()
|
||||
return "{:.2f}".format(supply)
|
||||
|
||||
@cache.file_cache()
|
||||
@cache.file_cache(60)
|
||||
def getTokenSupply() -> int:
|
||||
supply = solana_client.get_token_supply(stWDBRN_token_mint)
|
||||
return supply.value.ui_amount
|
||||
@ -219,10 +222,11 @@ def getVaultBalance() -> int:
|
||||
|
||||
vaultBalance += tokenValue
|
||||
vaultBalance += getCardanoValue(vault_cardano_address)
|
||||
vaultBalance += getOtherInvestmentsValue()
|
||||
|
||||
return vaultBalance
|
||||
|
||||
@cache.file_cache()
|
||||
@cache.file_cache(300)
|
||||
def getTokens(chain:str=None):
|
||||
tokens = []
|
||||
|
||||
@ -299,7 +303,7 @@ def getTokenPrice():
|
||||
get_cardano_balance_cache = TTLCache(maxsize=1, ttl=3600)
|
||||
|
||||
|
||||
@cache.file_cache()
|
||||
@cache.file_cache(300)
|
||||
def getCardanoBalance(address: str):
|
||||
# Get balance of cardano address
|
||||
try:
|
||||
@ -325,7 +329,7 @@ def getCardanoValue(address: str):
|
||||
# endregion
|
||||
|
||||
# region Sui
|
||||
@cache.file_cache()
|
||||
@cache.file_cache(300)
|
||||
def getSuiTokens(address: str):
|
||||
url = "https://fullnode.mainnet.sui.io/"
|
||||
|
||||
@ -369,6 +373,37 @@ def getSuiTokens(address: str):
|
||||
|
||||
# endregion
|
||||
|
||||
# region Other Investments
|
||||
@cache.file_cache(300)
|
||||
def getOtherInvestments():
|
||||
data = requests.get("https://cloud.woodburn.au/s/stwdbrn_other/download/other_investments.json")
|
||||
return data.json()
|
||||
|
||||
def getOtherInvestmentTypes():
|
||||
data = getOtherInvestments()
|
||||
types = {}
|
||||
for investment in data:
|
||||
if investment["type"] not in types:
|
||||
types[investment["type"]] = {
|
||||
"name": investment["type"],
|
||||
"description": investment["type"],
|
||||
"value": 0,
|
||||
"amount": 0,
|
||||
}
|
||||
types[investment["type"]]["value"] += investment["value"]
|
||||
types[investment["type"]]["amount"] += 1
|
||||
return types
|
||||
|
||||
|
||||
def getOtherInvestmentsValue():
|
||||
data = getOtherInvestments()
|
||||
value = 0
|
||||
for investment in data:
|
||||
value += investment["value"]
|
||||
return value
|
||||
|
||||
# endregion
|
||||
|
||||
# region API Routes
|
||||
|
||||
@app.route("/api/v1/tokens")
|
||||
@ -425,6 +460,15 @@ def api_token():
|
||||
for key in token:
|
||||
token[key]["tooltip"] = f"{token[key]['amount']} {key} (${token[key]['value']})"
|
||||
|
||||
other_investment_types = getOtherInvestmentTypes()
|
||||
for investment_type in other_investment_types:
|
||||
token[investment_type] = {
|
||||
"name": f'{other_investment_types[investment_type]["name"]} Positions',
|
||||
"description": other_investment_types[investment_type]["description"],
|
||||
"value": round(other_investment_types[investment_type]["value"] / supply,2),
|
||||
"amount": other_investment_types[investment_type]["amount"],
|
||||
"tooltip": f"{other_investment_types[investment_type]['amount']} Positions (${other_investment_types[investment_type]['value']})"
|
||||
}
|
||||
|
||||
token["total"] = {
|
||||
"name": "stWDBRN",
|
||||
@ -481,6 +525,19 @@ def api_vault():
|
||||
for key in vault:
|
||||
vault[key]["tooltip"] = f"{vault[key]['amount']} {key} (${vault[key]['value']})"
|
||||
|
||||
|
||||
other_investment_types = getOtherInvestmentTypes()
|
||||
for investment_type in other_investment_types:
|
||||
vault[investment_type] = {
|
||||
"name": f'{other_investment_types[investment_type]["name"]} Positions',
|
||||
"description": other_investment_types[investment_type]["description"],
|
||||
"value": other_investment_types[investment_type]["value"],
|
||||
"amount": other_investment_types[investment_type]["amount"],
|
||||
"tooltip": f"{other_investment_types[investment_type]['amount']} Positions (${other_investment_types[investment_type]['value']})"
|
||||
}
|
||||
|
||||
|
||||
|
||||
vault["total"] = {
|
||||
"name": "Vault",
|
||||
"description": "Total Vault value (USD)",
|
||||
@ -488,6 +545,11 @@ def api_vault():
|
||||
}
|
||||
|
||||
return jsonify(vault)
|
||||
|
||||
@app.route("/api/v1/other")
|
||||
def api_other_investments():
|
||||
data = getOtherInvestments()
|
||||
return jsonify(data)
|
||||
|
||||
@app.route("/api/v1/deposit",methods=["POST"])
|
||||
def api_deposit():
|
||||
|
BIN
stWDBRN.bsdesign
BIN
stWDBRN.bsdesign
Binary file not shown.
@ -164,7 +164,15 @@
|
||||
nameCell.style.padding = '8px 20px';
|
||||
|
||||
const amountCell = document.createElement('td');
|
||||
amountCell.textContent = `${data[token].amount} ${token}`;
|
||||
|
||||
// If token in other investments
|
||||
otherInvestments = ["Lending"]
|
||||
if (otherInvestments.includes(token)) {
|
||||
amountCell.textContent = `${data[token].amount} Positions`;
|
||||
}
|
||||
else {
|
||||
amountCell.textContent = `${data[token].amount} ${token}`;
|
||||
}
|
||||
amountCell.style.border = '1px solid #ccc';
|
||||
amountCell.style.padding = '8px 20px';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user