Trireme commited on
Commit
1edd569
·
verified ·
1 Parent(s): 2c9e127

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. .DS_Store +0 -0
  2. app.py +38 -292
.DS_Store ADDED
Binary file (6.15 kB). View file
 
app.py CHANGED
@@ -1,7 +1,5 @@
1
  # -*- coding: utf-8 -*-
2
- import asyncio
3
  from pymongo import MongoClient
4
- import aiohttp
5
  import pandas as pd
6
  import requests
7
  import json
@@ -10,272 +8,10 @@ import gradio as gr
10
  import datetime
11
  import os
12
 
13
-
14
- wallets = [
15
- "J7QAjhEGTAx71RoS1Nnuz4aKqK866xEnRXky4zhPa2WG",
16
- "9huTEYifjBMJVhPWG3dX84S1Pr6pgXBH9i7274dpPeMr",
17
- "CoA4vLyykjYobxEsDWHEx2Rna9WribGQMxSxVkH5NwN6",
18
- "BpaD3QF9Z2YtUqPRxpTn7dgC2sBzpzxro5zrEdwhwNd9",
19
- "FWmhs5vdUSMHUE5sHPQmd1hBEQVWD8wyCPe9op3KwTNg",
20
- "HW1qacccywvtEmUK6mDWfaJfxcM1R64T8BmhfjmxA6Nx",
21
- "3QpWHc77Vze5uiqm6WDfxYawKUj1bVbKEegS3YYBLGvL",
22
- "5FyNV778E1SZ4ZBwUXCgbx43zrJFdMy4UgUysSw3yocU",
23
- "4L3wPZc8smLYQbnpMSxHCiRB5cojbtuc33NkTNsrtdug",
24
- "MruHB1owAkBQwtSkzTqTDpqZEDPmz4iUWz3oHCYHKWV"
25
- ]
26
-
27
- #SCRAPE_DO_TOKEN = os.getenv('SCRAPE_DO_KEY')
28
- #client = MongoClient(os.getenv('MONGO_DB_URI'))
29
-
30
-
31
- SCRAPE_DO_TOKEN = "c3cb4da35304433483052fb6ba0c7011fef2ff42d62"
32
- client = MongoClient("mongodb+srv://djamaal:FHmV2N733lzrLkWf@test-cluster.mys4n.mongodb.net/")
33
-
34
- db = client["billy_balances"]
35
- token_collection = db["turnstile-tokens"]
36
-
37
- turnstile_token = token_collection.find_one(sort=[("timestamp", -1)])['x-turnstile-token']
38
-
39
- common_headers = {
40
- "accept": "application/json",
41
- "accept-encoding": "identity",
42
- "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
43
- "authorization": "Bearer CGtF4EdvDbBpwUXmZSKW3HsYkajy7e",
44
- "content-type": "application/json",
45
- "origin": "https://portfolio.jup.ag",
46
- "referer": "https://portfolio.jup.ag/",
47
- "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
48
- "x-turnstile-token": turnstile_token # keep this updated
49
- }
50
-
51
- async def fetch_portfolio(session, wallet_address, results):
52
- base_url = f"https://portfolio-api-jup.sonar.watch/v1/portfolio/fetch?address={wallet_address}&addressSystem=solana"
53
- encoded_url = urllib.parse.quote(base_url)
54
- proxy_url = f"http://api.scrape.do/?token={SCRAPE_DO_TOKEN}&url={encoded_url}&forwardHeaders=True&super=True"
55
-
56
- try:
57
- async with session.get(proxy_url, headers=common_headers) as resp:
58
- text = await resp.json()
59
- if resp.status == 200:
60
- print(f"✅ Wallet {wallet_address[:6]}...: success")
61
- results.append({"wallet": wallet_address,"data": text})
62
- else:
63
- print(f"❌ Wallet {wallet_address[:6]}...: HTTP {resp.status}")
64
- results.append({"wallet": wallet_address, "data": None})
65
- except Exception as e:
66
- print(f"⚠️ Error fetching {wallet_address}: {e}")
67
- results.append({"wallet": wallet_address, "status": "error", "error": str(e)})
68
-
69
- async def get_data(wallet_addresses):
70
- results = []
71
- async with aiohttp.ClientSession() as session:
72
- tasks = [fetch_portfolio(session, address, results) for address in wallet_addresses]
73
- await asyncio.gather(*tasks)
74
- return results
75
- #Have a button function which does all this
76
-
77
- async def process_data():
78
- portfolios = await get_data(wallets)
79
- df = pd.DataFrame(portfolios)
80
- token_rows = []
81
-
82
- for index, row in df.iterrows():
83
- data = row['data']
84
-
85
- # Token info mapping
86
- token_info = data.get('tokenInfo', {}).get('solana', {})
87
-
88
- # Navigate to assets list
89
- elements = data.get('elements', [])
90
- for element in elements:
91
- if element.get('type') == 'multiple':
92
- assets = element.get('data', {}).get('assets', [])
93
- for asset in assets:
94
- asset_data = asset.get('data', {})
95
- address = asset_data.get('address')
96
- amount = asset_data.get('amount')
97
- value = asset.get('value')
98
-
99
- # Get symbol using address
100
- symbol = token_info.get(address, {}).get('symbol', 'UNKNOWN')
101
-
102
- token_rows.append({
103
- 'original_row': index,
104
- 'address': address,
105
- 'symbol': symbol,
106
- 'amount': amount,
107
- 'value': value
108
- })
109
-
110
- # Final DataFrame
111
- tokens_df = pd.DataFrame(token_rows)
112
- tokens_df['original_row'] = tokens_df['original_row'].apply(lambda x: df.loc[x, 'wallet'])
113
- tokens_df = tokens_df.dropna()
114
-
115
- # Pivot for values
116
- value_pivot = tokens_df.pivot(index='original_row', columns='symbol', values='value')
117
- value_pivot.columns = [f'{col}_value' for col in value_pivot.columns]
118
-
119
- # Pivot for amounts
120
- amount_pivot = tokens_df.pivot(index='original_row', columns='symbol', values='amount')
121
- amount_pivot.columns = [f'{col}_amount' for col in amount_pivot.columns]
122
-
123
- # Combine both
124
- final_df = pd.concat([value_pivot, amount_pivot], axis=1).reset_index()
125
-
126
- # Optional: Fill NaNs with 0
127
- final_df = final_df.fillna(0)
128
-
129
- rows = []
130
- for idx, row in df.iterrows():
131
- data = row['data']
132
- original_row = row['wallet'] # or whatever uniquely identifies the row
133
-
134
- for element in data.get("elements", []):
135
- if element.get("platformId") == "jupiter-exchange":
136
- input_token = element.get("data", {}).get("assets", {}).get("input", {})
137
- if input_token:
138
- token_data = input_token.get("data", {})
139
- address = token_data.get("address")
140
- value = input_token.get("value")
141
- amount = token_data.get("amount")
142
- symbol = token_info.get(address, {}).get("symbol", address)
143
-
144
- rows.append({
145
- "original_row": original_row,
146
- "address": address,
147
- "symbol": symbol,
148
- "amount": amount,
149
- "value": value
150
- })
151
-
152
- # Convert to DataFrame
153
- jup_tokens_df = pd.DataFrame(rows)
154
-
155
- jup_tokens_df['symbol'] = jup_tokens_df['symbol'].apply(lambda x: "SOL" if x == "So11111111111111111111111111111111111111112" else x)
156
-
157
- # Pivot
158
- # Group by original_row and symbol, sum value and amount
159
- tokens_grouped = jup_tokens_df.groupby(['original_row', 'symbol']).agg({
160
- 'value': 'sum',
161
- 'amount': 'sum'
162
- }).reset_index()
163
-
164
- # Pivot
165
- value_pivot = tokens_grouped.pivot(index='original_row', columns='symbol', values='value')
166
- value_pivot.columns = [f'{col}_value' for col in value_pivot.columns]
167
-
168
- amount_pivot = tokens_grouped.pivot(index='original_row', columns='symbol', values='amount')
169
- amount_pivot.columns = [f'{col}_amount' for col in amount_pivot.columns]
170
-
171
- jup_df = pd.concat([value_pivot, amount_pivot], axis=1).reset_index().fillna(0)
172
-
173
- if "9Rhbn9G5poLvgnFzuYBtJgbzmiipNra35QpnUek9virt_value" in jup_df.columns:
174
- jup_df = jup_df.rename(columns={"9Rhbn9G5poLvgnFzuYBtJgbzmiipNra35QpnUek9virt_value":"BILLY_value"})
175
- if "9Rhbn9G5poLvgnFzuYBtJgbzmiipNra35QpnUek9virt_amount" in jup_df.columns:
176
- jup_df = jup_df.rename(columns={"9Rhbn9G5poLvgnFzuYBtJgbzmiipNra35QpnUek9virt_amount":"BILLY_amount"})
177
-
178
- final_df1 = final_df.set_index('original_row')
179
- final_df2 = jup_df.set_index('original_row')
180
-
181
- # Combine the two DataFrames, adding values where they overlap
182
- combined_df = final_df1.add(final_df2, fill_value=0)
183
-
184
- # Reset index if you want original_row back as a column
185
- combined_df = combined_df.reset_index()
186
-
187
- # Optional: fill NaNs (if any) with 0 just in case
188
- combined_df = combined_df.fillna(0)
189
-
190
- # Sum all numeric columns except the original_row which is non-numeric
191
- totals = combined_df.select_dtypes(include='number').sum()
192
-
193
- # Add a row with these totals at the bottom of the dataframe
194
- totals_row = pd.DataFrame(totals).T
195
- totals_row['original_row'] = 'Total'
196
-
197
- # Append the totals row to the original df
198
- df_with_totals = pd.concat([combined_df, totals_row], ignore_index=True)
199
-
200
- totals = final_df.select_dtypes(include='number').sum()
201
-
202
- # Add a row with these totals at the bottom of the dataframe
203
- totals_row = pd.DataFrame(totals).T
204
- totals_row['original_row'] = 'Total'
205
-
206
- # Append the totals row to the original df
207
- final_df = pd.concat([final_df, totals_row], ignore_index=True)
208
-
209
- totals = jup_df.select_dtypes(include='number').sum()
210
-
211
- # Add a row with these totals at the bottom of the dataframe
212
- totals_row = pd.DataFrame(totals).T
213
- totals_row['original_row'] = 'Total'
214
-
215
- # Append the totals row to the original df
216
- jup_df = pd.concat([jup_df, totals_row], ignore_index=True)
217
-
218
- final_df = final_df.rename(columns={'original_row': ' '})
219
- jup_df = jup_df.rename(columns={'original_row': ' '})
220
- df_with_totals = df_with_totals.rename(columns={'original_row': ' '})
221
-
222
- sol_price = 170
223
- billy_price = 0.001845
224
-
225
- # Starting balances
226
- starting_balances = {
227
- " ": ["Total"],
228
- "SOL_amount": [344],
229
- "SOL_value": [344 * sol_price],
230
- "BILLY_amount": [75_000_000],
231
- "BILLY_value": [75_000_000 * billy_price]
232
- }
233
-
234
- # Create the DataFrame
235
- starting_df = pd.DataFrame(starting_balances)
236
-
237
- return(starting_df,final_df.tail(1),jup_df.tail(1),df_with_totals.tail(1))
238
-
239
-
240
-
241
  collection = db["balance_data"]
242
 
243
- def df_to_mongo_safe_dict(df):
244
- return {str(k): v for k, v in df.to_dict(orient="index").items()}
245
-
246
-
247
- async def display_data():
248
- df0, df1, df2, df3 = await process_data()
249
-
250
- def summarize(df):
251
- value_cols = [col for col in df.columns if "value" in col.lower()]
252
- total_value = df[value_cols].sum(axis=1).values[0] if value_cols else 0
253
- return df, total_value
254
-
255
- df0, total0 = summarize(df0)
256
- df1, total1 = summarize(df1)
257
- df2, total2 = summarize(df2)
258
- df3, total3 = summarize(df3)
259
-
260
- pnl = float(total3) - float(total0)
261
-
262
- # Save to MongoDB
263
- record = {
264
- "timestamp": datetime.datetime.utcnow(),
265
- "df0": df_to_mongo_safe_dict(df0),
266
- "total0": float(total0),
267
- "df1": df_to_mongo_safe_dict(df1),
268
- "total1": float(total1),
269
- "df2": df_to_mongo_safe_dict(df2),
270
- "total2": float(total2),
271
- "df3": df_to_mongo_safe_dict(df3),
272
- "total3": float(total3),
273
- "pnl": float(pnl)
274
- }
275
- collection.insert_one(record)
276
-
277
- return df0, total0, df1, total1, df2, total2, df3, total3, f"PNL : {pnl:,.2f}"
278
-
279
  def load_from_mongo():
280
  latest = collection.find_one(sort=[("timestamp", -1)])
281
  if latest:
@@ -283,46 +19,56 @@ def load_from_mongo():
283
  df1 = pd.DataFrame(latest["df1"]).T
284
  df2 = pd.DataFrame(latest["df2"]).T
285
  df3 = pd.DataFrame(latest["df3"]).T
 
286
 
287
  return (
288
  df0, latest["total0"],
289
  df1, latest["total1"],
290
  df2, latest["total2"],
291
  df3, latest["total3"],
292
- f"PNL : {latest['pnl']:,.2f}"
 
 
293
  )
294
  else:
295
  empty_df = pd.DataFrame()
296
- return empty_df, 0, empty_df, 0, empty_df, 0, empty_df, 0, "PNL : 0.00"
297
 
298
- with gr.Blocks() as demo:
299
- gr.Markdown("## BILLY Balances and PnL")
 
300
 
301
- df0_out = gr.Dataframe(label="Starting Balances")
302
- txt0_out = gr.Textbox(label="Starting Value Total")
303
 
304
- df1_out = gr.Dataframe(label="Wallet Balances")
305
- txt1_out = gr.Textbox(label="Wallet Value Total")
306
 
307
- df2_out = gr.Dataframe(label="JUP Limit Balances")
308
- txt2_out = gr.Textbox(label="JUP Limit Value Total")
309
 
310
- df3_out = gr.Dataframe(label="Total Balances")
311
- txt3_out = gr.Textbox(label="Current Value Total")
312
 
313
- pnl_out = gr.Textbox(label="PNL (AUM Model)")
314
 
315
- # Load from MongoDB on app load (sync function)
316
- demo.load(
317
- fn=load_from_mongo,
318
- inputs=[],
319
- outputs=[
320
- df0_out, txt0_out,
321
- df1_out, txt1_out,
322
- df2_out, txt2_out,
323
- df3_out, txt3_out,
324
- pnl_out
325
- ]
326
- )
 
 
 
 
 
 
327
 
328
- demo.launch(debug=True, share=True)
 
1
  # -*- coding: utf-8 -*-
 
2
  from pymongo import MongoClient
 
3
  import pandas as pd
4
  import requests
5
  import json
 
8
  import datetime
9
  import os
10
 
11
+ client = MongoClient(os.getenv('MONGO_DB_URI'))
12
+ db = client["Patchy_balances"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  collection = db["balance_data"]
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  def load_from_mongo():
16
  latest = collection.find_one(sort=[("timestamp", -1)])
17
  if latest:
 
19
  df1 = pd.DataFrame(latest["df1"]).T
20
  df2 = pd.DataFrame(latest["df2"]).T
21
  df3 = pd.DataFrame(latest["df3"]).T
22
+ df4 = pd.DataFrame(latest["df4"]).T
23
 
24
  return (
25
  df0, latest["total0"],
26
  df1, latest["total1"],
27
  df2, latest["total2"],
28
  df3, latest["total3"],
29
+ df4, latest["total4"],
30
+ f"PNL : {latest['pnl']:,.2f}",
31
+ f"LP Rewards : {latest['rewards']:,.2f}"
32
  )
33
  else:
34
  empty_df = pd.DataFrame()
35
+ return empty_df, 0, empty_df, 0, empty_df, 0, empty_df, 0, empty_df, 0,"PNL : $0.00","LP Rewards : $0.00"
36
 
37
+ if __name__ == "__main__":
38
+ with gr.Blocks() as demo:
39
+ gr.Markdown("## Patchy Balances and PnL")
40
 
41
+ df0_out = gr.Dataframe(label="Starting Balances")
42
+ txt0_out = gr.Textbox(label="Starting Value Total")
43
 
44
+ df2_out = gr.Dataframe(label="Wallet Balances")
45
+ txt2_out = gr.Textbox(label="Wallet Value Total")
46
 
47
+ df3_out = gr.Dataframe(label="JUP Limit Balances")
48
+ txt3_out = gr.Textbox(label="JUP Limit Value Total")
49
 
50
+ df4_out = gr.Dataframe(label="LP Balances")
51
+ txt4_out = gr.Textbox(label="LP Balances Value Total")
52
 
53
+ reward_out = gr.Textbox(label="LP Rewards")
54
 
55
+ df1_out = gr.Dataframe(label="Total Balances")
56
+ txt1_out = gr.Textbox(label="Current Value Total")
57
+
58
+ pnl_out = gr.Textbox(label="PNL (AUM Model)")
59
+
60
+ # Load from MongoDB on app load (sync function)
61
+ demo.load(
62
+ fn=load_from_mongo,
63
+ inputs=[],
64
+ outputs=[
65
+ df0_out, txt0_out,
66
+ df1_out, txt1_out,
67
+ df2_out, txt2_out,
68
+ df3_out, txt3_out,
69
+ df4_out, txt4_out,
70
+ pnl_out,reward_out
71
+ ]
72
+ )
73
 
74
+ demo.launch(debug=True, share=True)