bdxn_balances / app.py
Trireme's picture
Upload folder using huggingface_hub
3f78cb9 verified
Raw
History Blame Contribute Delete
9.64 kB
import requests
import asyncio
import aiohttp
import pandas as pd
import urllib
import gradio as gr
import os
import numpy as np
base_addresses = ["0x59B7224184a81b5F5Afad309276167F5D124DFd4",'0x04E072F9D0481502c2aA56374EfDbFC49a8E4E68','0xA6bbEFBB13BBbcA0022a270c734674146DCcf668','0xe89F6D42C58FD97a430Fd7F4F4dAE975014f41fE','0x4FDb69f1D4c81926471d4882F97194d9DcCd2388','0x89315a842495f78f7fF328e9e2f011154A4d05Ab','0xa380743AF3fEc342c568f46B8C4F32eCD0e5BC4C','0x27489C8f65a59A20a63F8b7bB0903A6FA63d9EEE',"0xd9A0d302d64c4F2bFe6D7932B9d0eD9532B09648","0xCB8943568739c3d448073f7eB84479e915F02298","0xe8c75AbeCFaa3a2C67971C37cfbbF14b494c8956","0x0d65eB6944a772fdc2e8B23A7C55521CdD9d5A31","0x41386078C90ab3BDD50f76Ec6AE36D29dbfcB32C","0xD133C70CD8ea12fa83dd4AD7b96a370ae1980345","0x1504Ea6509Fdd6496009Ff75d120c05E288F5946","0x898b13f4a886F7cb60E725A246369242bC1eDF84","0xcbFd72C541859D6c5e5Ae34448162098c32cFE6A","0xEDc051c67DBfce7A2dC0D1BD338711ACe204919f"]
lp_wallets = []
def chunk_addresses(addresses, size):
return [addresses[i:i + size] for i in range(0, len(addresses), size)]
API_URL = "https://api.g.alchemy.com/data/v1/yhe6L3PXmiENzS1sP9Fu4_T5E3l0QyeB/assets/tokens/by-address"
async def fetch_batch(session, batch,chain):
json_payload = {
"addresses": [{"address": addr, "networks": [chain]} for addr in batch],
"withMetadata": True,
"withPrices": True,
"includeNativeTokens": True
}
async with session.post(API_URL, json=json_payload) as response:
response = await response.json()
return response['data']['tokens']
async def get_wallet_base_balances(addresses):
async with aiohttp.ClientSession() as session:
batches = chunk_addresses(addresses, 3)
tasks = [fetch_batch(session, batch,"bnb-mainnet") for batch in batches]
responses = await asyncio.gather(*tasks)
first_parts = []
rest_parts = []
for res in responses:
first_parts.extend(res[:3])
rest_parts.extend(res[3:])
responses = first_parts + rest_parts
df = pd.DataFrame(responses)
for i in range(len(addresses)):
df.at[i,'tokenMetadata'] = {}
'''vice_data = {
"decimals": 18,
"logo": 'null',
"name": "",
"symbol": "VICE"
}
df['tokenMetadata'] = np.where(df['tokenAddress'] == '0xfd409bc96d126bc8a56479d4c7672015d539f96c',vice_data,df['tokenMetadata'])'''
df['tokenBalance'] = df['tokenBalance'].apply(lambda x : int(x,16))
df['decimals'] = df['tokenMetadata'].apply(lambda x : x.get('decimals',0))
df['tokenBalance'] = df['tokenBalance']/(10**df['decimals'])
for i in range(len(addresses)):
df.at[i, 'tokenBalance'] = df.at[i, 'tokenBalance'] / (10**18)
df['symbol'] = df['tokenMetadata'].apply(lambda x : x.get('symbol',''))
for i in range(len(addresses)):
df.at[i,'symbol'] = 'BNB'
df['currentPrice'] = df['tokenPrices'].apply(lambda x : x[0].get('value',0) if len(x) > 0 else 0)
df.drop(columns=['tokenPrices','tokenMetadata','network','tokenAddress'], inplace=True)
df = df.dropna()
df['tokenBalance'] = pd.to_numeric(df['tokenBalance'], errors='coerce')
df = df[df['tokenBalance'] != 0]
df['tokenBalance'] = pd.to_numeric(df['tokenBalance'], errors='coerce')
df['currentPrice'] = pd.to_numeric(df['currentPrice'], errors='coerce')
bnb_price = df.loc[df['symbol']=='BNB','currentPrice'].values[0]
base_price = df.loc[df['symbol']=='BDXN','currentPrice'].values[0]
df['value'] = df['tokenBalance'] * df['currentPrice']
df = df[df['symbol'].isin(['BDXN', 'BNB', 'USDT', 'USDC'])]
print(df)
return df, df['value'].sum(), bnb_price, base_price
async def fetch_lp():
url = "https://public.zapper.xyz/graphql"
headers = {
"Content-Type": "application/json",
"x-zapper-api-key": "8fe2c210-66e0-4ef9-9505-96a901c9b042"
}
query = """
query AppBalances($addresses: [Address!]!, $first: Int = 10) {
portfolioV2(addresses: $addresses) {
appBalances {
totalBalanceUSD
byApp(first: $first) {
totalCount
edges {
node {
balanceUSD
app {
displayName
imgUrl
description
category { name }
}
network {
name
chainId
}
positionBalances(first: 10) {
edges {
node {
... on AppTokenPositionBalance {
type
symbol
balance
balanceUSD
price
groupLabel
displayProps {
label
images
}
}
... on ContractPositionBalance {
type
balanceUSD
groupLabel
tokens {
metaType
token {
... on BaseTokenPositionBalance {
symbol
balance
balanceUSD
}
}
}
displayProps {
label
images
}
}
}
}
}
}
}
}
}
}
}
"""
variables = {
"addresses": lp_wallets,
"first": 5
}
payload = {
"query": query,
"variables": variables
}
response = requests.post(url, json=payload, headers=headers)
response = response.json()
df = pd.json_normalize(response['data']['portfolioV2']['appBalances']['byApp']['edges'])
def agg_balances(lp):
lps = []
for i in range(len(lp)):
two = lp['node.tokens'].iloc[i]
more_lp = pd.json_normalize(two)
more_lp['token.balance'] = more_lp['token.balance'].apply(pd.to_numeric,errors='coerce')
more_lp['token.balanceUSD'] = more_lp['token.balanceUSD'].apply(pd.to_numeric,errors='coerce')
x = more_lp.groupby('token.symbol')[['token.balance','token.balanceUSD']].sum().reset_index()
#x.columns = x.iloc[0] # Set first row as column headers
#x = x.drop(x.index[0]).reset_index(drop=True) # Drop the row that became header
#x = x.apply(pd.to_numeric, errors='coerce') # Convert all to numeric
lps.append(x)
bals_df = pd.concat(lps, ignore_index=True)
bals_df['token.balance'] = bals_df['token.balance'].apply(pd.to_numeric,errors='coerce')
bals_df['token.balanceUSD'] = bals_df['token.balanceUSD'].apply(pd.to_numeric,errors='coerce')
bals_df.fillna(0, inplace=True)
bals_df = bals_df.groupby('token.symbol').sum().reset_index()
return bals_df
def get_dex_balances(df):
balances = []
if df.empty:
return
for i in range(len(pd.json_normalize(df['node.positionBalances.edges']))):
balances.append((df['node.app.displayName'].iloc[i],agg_balances(pd.json_normalize(df['node.positionBalances.edges'].iloc[i]))))
final_balances = []
for i in range(len(balances)):
df = balances[i]
dex_name = df[0] # or extract from your grouped index
df_pivot = df[1].pivot_table(index=None, columns='token.symbol', values='token.balance')
# Add DEX column and reorder
df_pivot.insert(0,'DEX', dex_name)
# Remove the first level of row index (e.g., 'token.symbol')
df_pivot = df_pivot.reset_index(drop=True)
df_pivot.columns.name = None
final_balances.append(df_pivot)
final_balances = pd.concat(final_balances, ignore_index=True)
final_balances.fillna(0, inplace=True)
return final_balances
final_balances = get_dex_balances(df)
return final_balances.T.drop('DEX').reset_index().rename(columns={'index':'symbol',0:'amount'}) if not(final_balances.empty) else pd.DataFrame([{}])
async def get_all_dfs():
start_base = 1194576.2780014 + 2812714.13692583
starting_df = pd.DataFrame({
"symbol": ["BDXN"],
"amount": [start_base],
"value": [start_base*0.021]
})
df, total, bnb_price, bdxn_price = await get_wallet_base_balances(base_addresses)
df = df.groupby('symbol').agg({"tokenBalance":"sum","value":"sum"}).reset_index()
df = df.rename(columns={'tokenBalance':'amount'})
df_total = df.copy()
total_value = df["value"].sum()
total_row = {
"symbol": "TOTAL",
"amount": "", # or "" if you prefer an empty string
"value": total_value,
}
df_total = pd.concat([df_total, pd.DataFrame([total_row])], ignore_index=True)
return starting_df,df_total
with gr.Blocks() as demo:
gr.Markdown("## BDXN Balances & PnL")
df0_out = gr.Dataframe(label="Starting Balances")
df1_out = gr.Dataframe(label="Total Current Balances")
demo.load(
fn= get_all_dfs,
inputs = [],
outputs=[df0_out,df1_out]
)
demo.launch(debug=True, share=True)