Spaces:
Sleeping
Sleeping
File size: 7,511 Bytes
bd12326 6655e35 e5a819a bd12326 a72fedf bd12326 6655e35 e5a819a 6655e35 bd12326 6655e35 bd12326 6655e35 bd12326 6655e35 bd12326 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | # -*- coding: utf-8 -*-
import asyncio
from pymongo import MongoClient
import aiohttp
import pandas as pd
import requests
import json
import urllib.parse
import gradio as gr
import datetime
import os
import subprocess, json
def get_lp_positions(node_path="meteora/index.js"):
"""
Runs the Node.js script, parses the output, and returns a combined DataFrame
with tokenX and tokenY positions.
"""
try:
# Run Node.js script
result = subprocess.run(
["node", node_path],
capture_output=True,
text=True
)
# Optional: print warnings
if result.stderr.strip():
print("Node STDERR:", result.stderr)
# Handle Node.js errors
if result.returncode != 0:
print("Node.js exited with an error")
return pd.DataFrame() # return empty DataFrame on failure
# Parse JSON output
positions = json.loads(result.stdout) if result.stdout.strip() else []
if not positions:
return pd.DataFrame()
# Normalize JSON to DataFrame
lp_df_real = pd.json_normalize(positions)
lp_df_real.drop(columns=['positionAccountAddress'], inplace=True, errors='ignore')
# Split tokenY
y_df_real = lp_df_real[['tokenYAddress','tokenYAmount']].copy()
lp_df_real.rename(columns={'tokenXAddress':'symbol','tokenXAmount':'balance'}, inplace=True)
y_df_real.rename(columns={'tokenYAddress':'symbol','tokenYAmount':'balance'}, inplace=True)
# Combine tokenX and tokenY DataFrames
final_lp_df = pd.concat([lp_df_real, y_df_real], ignore_index=True).dropna(axis=1)
return final_lp_df
except Exception as e:
print(f"Error in get_lp_positions: {e}")
return pd.DataFrame() # fallback empty DataFrame
wallets = [
"41KL7hbeA2dDuX6gCUFhVaozACnx2hLvGBuY4tgrpJ31",
"5Xihd2FdAXZnER7HWjT8GiZm14hyPiUpGfqLLL86yaa9",
"fYYLvdb82NkUQ6EgT7U6N52A2cN6V1dBKEJuvDwwjKj"
]
def parse_solscan_results(results):
if isinstance(results, dict):
results = [results]
records = []
for entry in results:
data = entry.get("data", {})
if not data or not data.get("success"):
continue
payload = data.get("data", {})
# Native SOL
native = payload.get("native_balance", {})
if native:
records.append({
"symbol": native.get("token_symbol", "SOL"),
"balance": native.get("balance", 0),
"value": native.get("value", 0)
})
# Tokens
for token in payload.get("tokens", []):
records.append({
"symbol": token.get("token_symbol"),
"balance": token.get("balance", 0),
"value": token.get("value", 0)
})
df = pd.DataFrame(records, columns=["address","symbol", "balance", "value"])
if not df.empty:
df = df.groupby(["symbol"], as_index=False).agg({
"balance": "sum",
"value": "sum"
})
return df
def parse_solscan_results_addresses(results):
if isinstance(results, dict):
results = [results]
records = []
for entry in results:
address = entry.get("address")
data = entry.get("data", {})
if not data or not data.get("success"):
continue
payload = data.get("data", {})
# Native SOL
native = payload.get("native_balance", {})
if native:
records.append({
"address": address,
"symbol": native.get("token_symbol", "SOL"),
"balance": native.get("balance", 0),
"value": native.get("value", 0)
})
# Tokens
for token in payload.get("tokens", []):
records.append({
"address": address,
"symbol": token.get("token_symbol"),
"balance": token.get("balance", 0),
"value": token.get("value", 0)
})
# Make sure DataFrame has the expected columns even if empty
df = pd.DataFrame(records, columns=["address", "symbol", "balance", "value"])
# Only group if DataFrame is not empty
if not df.empty:
df = df.groupby(["address", "symbol"], as_index=False).agg({
"balance": "sum",
"value": "sum"
})
return df
async def get_sol_balances(sol_addresses):
SOLSCAN_KEY = os.getenv('SOLSCAN_KEY')
headers = {
"token": SOLSCAN_KEY
}
async def fetch_wallet(session, wallet_address):
url = f"https://pro-api.solscan.io/v2.0/account/portfolio?address={wallet_address}&exclude_low_score_tokens=false"
async with session.get(url, headers=headers) as response:
if response.status != 200:
return {"address": wallet_address, "error": f"HTTP {response.status}"}
try:
data = await response.json()
except Exception as e:
return {"address": wallet_address, "error": str(e)}
res = {"address": wallet_address, "data": data}
return parse_solscan_results_addresses([res])
async with aiohttp.ClientSession() as session:
tasks = [fetch_wallet(session, addr) for addr in sol_addresses]
results = await asyncio.gather(*tasks)
final_df = pd.concat(results, ignore_index=True)
final_df = final_df.groupby(["address","symbol"], as_index=False).agg({
"balance": "sum",
"value": "sum"
})
final_df = final_df[final_df['symbol'].isin(['SOL', 'WSOL','HYPER'])]
return final_df.groupby('symbol').agg({"balance":"sum","value":"sum"}).reset_index()
async def get_all_dfs():
starting_df = pd.DataFrame([{"symbol":"HYPER","balance":5000000,"value":68500},{"symbol":"SOL","balance":240,"value":42960}])
final_df = await get_sol_balances(wallets)
hyper_price = float(final_df.loc[final_df['symbol']=='HYPER','value'] / final_df.loc[final_df['symbol']=='HYPER','balance'])
sol_price = float(final_df.loc[final_df['symbol']=='SOL','value'] / final_df.loc[final_df['symbol']=='SOL','balance'])
symbolMap = {'So11111111111111111111111111111111111111112':'SOL','Aq8Gocyvyyi8xk5EYxd6viUfVmVvs9T9R6mZFzZFpump':'HYPER'}
priceMap = {'SOL':sol_price,'HYPER':hyper_price}
lp_df0 = get_lp_positions()
lp_df0['symbol'] = lp_df0['symbol'].map(symbolMap)
lp_df0['value'] = lp_df0['balance'] * lp_df0['symbol'].map(priceMap)
lp_df0 = lp_df0.groupby('symbol').agg({'balance':'sum','value':'sum'}).reset_index()
#lp_df = pd.DataFrame([{"symbol":"HYPER","balance":2_800_000,"value":2_800_000*hyper_price}])
total_balances = pd.concat([final_df,lp_df0]).groupby('symbol').agg({"balance":"sum","value":"sum"}).reset_index()
pnl = total_balances['value'].sum() - starting_df['value'].sum()
pnl = f"{pnl:,.2f}"
return starting_df,lp_df0,final_df,total_balances,pnl
with gr.Blocks() as demo:
gr.Markdown("## HYPER Balances ")
starting = gr.DataFrame(label= "Starting Balances ")
lp_real = gr.DataFrame(label="LP Position Balances")
final = gr.DataFrame(label = "Wallet Balances")
total_balances = gr.DataFrame(label="Total")
pnl = gr.Textbox(label="PnL ($) (AUM)")
demo.load(
fn= get_all_dfs,
inputs = [],
outputs=[starting,lp_real,final,total_balances,pnl]
)
demo.launch(debug=True, share=True)
|