Trireme commited on
Commit
9c06059
·
verified ·
1 Parent(s): 0e8c587

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. patchy_trades.py +147 -4
patchy_trades.py CHANGED
@@ -4,6 +4,8 @@ import pandas as pd
4
  import gradio as gr
5
  import os
6
  from datetime import datetime
 
 
7
 
8
 
9
 
@@ -48,6 +50,7 @@ wallets = [
48
 
49
  API_TOKEN = os.getenv('SOLSCAN_KEY')
50
 
 
51
  headers = {
52
  "token": API_TOKEN
53
  }
@@ -116,11 +119,148 @@ def get_token_delta(row):
116
  else:
117
  return None # or 'other', if you prefer
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  # Setup sync wrapper
120
  async def main():
121
  # Run async main and prepare data
122
  # Run the async code
123
  final_df = await process()
 
124
 
125
  cols_to_convert = ['routers.amount1', 'routers.token1_decimals']
126
  final_df[cols_to_convert] = final_df[cols_to_convert].apply(pd.to_numeric, errors='coerce')
@@ -154,11 +294,13 @@ async def main():
154
  lambda x: datetime.fromisoformat(x.replace("Z", "+00:00")).strftime("%B %d, %Y at %I:%M %p (UTC)")
155
  )
156
 
157
- return final_df
158
 
159
  # Async display function
160
  async def display_results():
161
- final_df = await main()
 
 
162
  dollar_delta = final_df['dollar delta'].sum()
163
  token_delta = final_df['token delta'].sum()
164
  avg_position = abs(dollar_delta / token_delta)
@@ -168,14 +310,15 @@ async def display_results():
168
  f"**Token delta:** {token_delta:.2f} \n"
169
  f"**Avg position:** {avg_position:.6f}"
170
  )
171
- return final_df, metrics
172
 
173
  # Gradio UI with async load
174
  with gr.Blocks() as demo:
175
  gr.Markdown("# Patchy Trades")
176
  df_output = gr.Dataframe(label="All Trades")
 
177
  metrics_output = gr.Markdown(label="Metrics Summary")
178
 
179
- demo.load(fn=display_results, outputs=[df_output, metrics_output])
180
 
181
  demo.launch()
 
4
  import gradio as gr
5
  import os
6
  from datetime import datetime
7
+ from pymongo import MongoClient
8
+ import urllib
9
 
10
 
11
 
 
50
 
51
  API_TOKEN = os.getenv('SOLSCAN_KEY')
52
 
53
+
54
  headers = {
55
  "token": API_TOKEN
56
  }
 
119
  else:
120
  return None # or 'other', if you prefer
121
 
122
+ #LIMIT ORDERS ===================================================================================
123
+
124
+ SCRAPE_DO_TOKEN = os.getenv('SCRAPE_DO_TOKEN')
125
+ client = MongoClient(os.getenv('MONGO_DB_URI'))
126
+ db_1 = client["billy_balances"]
127
+ token_collection = db_1["turnstile-tokens"]
128
+
129
+ turnstile_token = token_collection.find_one(sort=[("timestamp", -1)])['x-turnstile-token']
130
+
131
+ common_headers = {
132
+ "accept": "application/json",
133
+ "accept-encoding": "identity",
134
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
135
+ "authorization": "Bearer CGtF4EdvDbBpwUXmZSKW3HsYkajy7e",
136
+ "content-type": "application/json",
137
+ "origin": "https://portfolio.jup.ag",
138
+ "referer": "https://portfolio.jup.ag/",
139
+ "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",
140
+ "x-turnstile-token": turnstile_token # keep this updated
141
+ }
142
+
143
+ async def fetch_portfolio(session, wallet_address, results):
144
+ base_url = f"https://portfolio-api-jup.sonar.watch/v1/portfolio/fetch?address={wallet_address}&addressSystem=solana"
145
+ encoded_url = urllib.parse.quote(base_url)
146
+ proxy_url = f"http://api.scrape.do/?token={SCRAPE_DO_TOKEN}&url={encoded_url}&forwardHeaders=True&super=True"
147
+
148
+ try:
149
+ async with session.get(proxy_url, headers=common_headers) as resp:
150
+ text = await resp.json()
151
+ if resp.status == 200:
152
+ print(f"✅ Wallet {wallet_address[:6]}...: success")
153
+ results.append({"wallet": wallet_address,"data": text})
154
+ else:
155
+ print(f"❌ Wallet {wallet_address[:6]}...: HTTP {resp.status}")
156
+ results.append({"wallet": wallet_address, "data": None})
157
+ except Exception as e:
158
+ print(f"⚠️ Error fetching {wallet_address}: {e}")
159
+ results.append({"wallet": wallet_address, "status": "error", "error": str(e)})
160
+
161
+ BATCH_SIZE = 20
162
+
163
+ async def get_data(wallet_addresses):
164
+ results = []
165
+
166
+ async with aiohttp.ClientSession() as session:
167
+ # Split addresses into batches
168
+ for i in range(0, len(wallet_addresses), BATCH_SIZE):
169
+ batch = wallet_addresses[i:i + BATCH_SIZE]
170
+ tasks = [fetch_portfolio(session, address, results) for address in batch]
171
+ await asyncio.gather(*tasks)
172
+ await asyncio.sleep(0.5) # optional: rate limit delay
173
+
174
+ return results
175
+
176
+ all_elements = []
177
+
178
+ async def process_limits():
179
+ portfolios = await get_data(wallets)
180
+ df = pd.DataFrame(portfolios)
181
+
182
+ print(df)
183
+
184
+ for index, row in df.iterrows():
185
+ data = row['data']
186
+ original_row = row['wallet']
187
+
188
+ # Token info mapping
189
+ token_info = data.get('tokenInfo', {}).get('solana', {})
190
+
191
+ # Navigate to assets list
192
+ elements = data.get('elements', [])
193
+ for element in elements:
194
+ if element.get("platformId") == "jupiter-exchange":
195
+ element['wallet'] = original_row
196
+ all_elements.append(element)
197
+ '''input_token = element.get("data", {}).get("assets", {}).get("input", {})
198
+ if input_token:
199
+ token_data = input_token.get("data", {})
200
+ address = token_data.get("address")
201
+ value = input_token.get("value")
202
+ amount = token_data.get("amount")
203
+ symbol = token_info.get(address, {}).get("symbol", address)
204
+
205
+ jup_rows.append({
206
+ "original_row": original_row,
207
+ "address": address,
208
+ "symbol": symbol,
209
+ "amount": amount,
210
+ "value": value
211
+ })'''
212
+
213
+
214
+ async def process_limitss():
215
+ await process_limits()
216
+ order_df = pd.json_normalize(all_elements)
217
+ print(order_df)
218
+
219
+ def classify_type(row):
220
+ if row['data.inputAddress'] == '6D6ccmg71x56V5Je1Mh82MFPYL38gaZqNc2LG1XMbonk':
221
+ return 'sell'
222
+ elif row['data.outputAddress'] == '6D6ccmg71x56V5Je1Mh82MFPYL38gaZqNc2LG1XMbonk':
223
+ return 'buy'
224
+ else:
225
+ return None # or 'other', if you prefer
226
+
227
+ order_df['type'] = order_df.apply(classify_type, axis=1)
228
+ def get_token_amounts(row):
229
+ if row['type'] == 'sell':
230
+ return float(row['data.assets.input.data.amount'])
231
+ elif row['type'] == 'buy':
232
+ return float(row['data.expectedOutputAmount'])
233
+ else:
234
+ return None # or 'other', if you prefer
235
+
236
+ order_df['base_token_amount'] = order_df.apply(get_token_amounts, axis=1)
237
+ order_df['outputValue'] = order_df['data.outputPrice'] * order_df['data.expectedOutputAmount']
238
+ def get_price(row):
239
+ if row['type'] == 'buy':
240
+ return row['value']/row['base_token_amount']
241
+ elif row['type'] == 'sell':
242
+ return row['outputValue']/row['base_token_amount']
243
+ else:
244
+ return None
245
+
246
+ order_df['price'] = order_df.apply(get_price,axis=1)
247
+ order_df = order_df[['wallet','label','type','value','price','data.inputAddress','data.outputAddress','data.filledPercentage']]
248
+ order_df = order_df.rename(columns={'label':'order type','data.inputAddress':'token in','data.outputAddress':'token out','data.filledPercentage':'filled percentage'})
249
+ order_df = order_df.rename(columns={'type':'side','order type':'type','value':'value($)'})
250
+ order_df = order_df.sort_values('price',ascending=False).reset_index(drop=True)
251
+ order_df['wallet number'] = order_df['wallet'].apply(lambda x : wallets.index(x) + 1)
252
+ order_df = order_df[[order_df.columns[-1]] + list(order_df.columns[:-1])]
253
+
254
+ return order_df
255
+
256
+
257
+
258
  # Setup sync wrapper
259
  async def main():
260
  # Run async main and prepare data
261
  # Run the async code
262
  final_df = await process()
263
+ order_df = await process_limitss()
264
 
265
  cols_to_convert = ['routers.amount1', 'routers.token1_decimals']
266
  final_df[cols_to_convert] = final_df[cols_to_convert].apply(pd.to_numeric, errors='coerce')
 
294
  lambda x: datetime.fromisoformat(x.replace("Z", "+00:00")).strftime("%B %d, %Y at %I:%M %p (UTC)")
295
  )
296
 
297
+ return final_df,order_df
298
 
299
  # Async display function
300
  async def display_results():
301
+ both_dfs = await main()
302
+ final_df = both_dfs[0]
303
+ order_df = both_dfs[1]
304
  dollar_delta = final_df['dollar delta'].sum()
305
  token_delta = final_df['token delta'].sum()
306
  avg_position = abs(dollar_delta / token_delta)
 
310
  f"**Token delta:** {token_delta:.2f} \n"
311
  f"**Avg position:** {avg_position:.6f}"
312
  )
313
+ return final_df,order_df,metrics
314
 
315
  # Gradio UI with async load
316
  with gr.Blocks() as demo:
317
  gr.Markdown("# Patchy Trades")
318
  df_output = gr.Dataframe(label="All Trades")
319
+ order_output = gr.Dataframe(label="All Jupiter Orders")
320
  metrics_output = gr.Markdown(label="Metrics Summary")
321
 
322
+ demo.load(fn=display_results, outputs=[df_output, order_output,metrics_output])
323
 
324
  demo.launch()