Trireme commited on
Commit
a4a226b
·
verified ·
1 Parent(s): cc41b56

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. .github/workflows/update_space.yml +28 -0
  2. README.md +3 -9
  3. app.py +171 -0
  4. requirements.txt +6 -0
.github/workflows/update_space.yml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Run Python script
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v2
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v2
18
+ with:
19
+ python-version: '3.9'
20
+
21
+ - name: Install Gradio
22
+ run: python -m pip install gradio
23
+
24
+ - name: Log in to Hugging Face
25
+ run: python -c 'import huggingface_hub; huggingface_hub.login(token="${{ secrets.hf_token }}")'
26
+
27
+ - name: Deploy to Spaces
28
+ run: gradio deploy
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: Blup Dashboard
3
- emoji: 🦀
4
- colorFrom: indigo
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 5.33.0
8
  app_file: app.py
9
- pinned: false
 
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: blup-dashboard
 
 
 
 
 
3
  app_file: app.py
4
+ sdk: gradio
5
+ sdk_version: 5.31.0
6
  ---
 
 
app.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import asyncio
3
+ import aiohttp
4
+ import pandas as pd
5
+ import urllib
6
+ import gradio as gr
7
+
8
+ addresses = [
9
+ "0x46dae11e3ab74C417d370FB0d467364397178f5d",
10
+ "0x2B3cb7D697Dd5224f3AcfC1b7EbDe77F468Dd539",
11
+ "0x7B04395AF49caf8C4Fd5FF716698D97f394d0d41",
12
+ "0x4dAFdbdB45947AB8666411AFc07F95b39Ab3841B",
13
+ "0xa2ebb53A922E8fe9E6949316b0018F95f0956Ce7",
14
+ "0x0FCc5f7845F3B2188918495f60F6294a15dc772b",
15
+ "0xefa59c4aE5BaBA2c1017Ce2Fc9c1E0E080e5F448",
16
+ "0x1C2A2D1b1A95a252AD4f9E8c9055885a1721c252",
17
+ "0xfCb81D6a2678D9f0798124BD3E46bA0E1Ff0C32c",
18
+ "0xdF04384C3AE43bD08E04692139C6B6C6Eb308B76",
19
+ "0xA734C747E53171261568DbBB1BCd699EDF01925c",
20
+ "0xC6347a0924aAbBA5E655397fbD18cb702066304b",
21
+ "0xc6300201821CB7026E0e73cC10dC9Ca5C623Ff15",
22
+ "0x2777698A53410C344e98267dB672a432c77C6Ed9",
23
+ "0xCCc07e973c04c607381b96eCBe3e426cc7c17B88",
24
+ "0xE813553077d0bfdd9615465D8A974F63bbf33aD4",
25
+ "0x0a045118cDb3fB0FDb50D2f91f04c56B28F5fD07",
26
+ "0x0bC67eE9A36f5bc8e05282E538FDe119C372a222",
27
+ "0x1ca7bCe8A7c4F62a3575279688D9E9ad337f6b3d",
28
+ "0x940665c733acBcA198306F8881c1d268E2F92DFA",
29
+ "0x6393613ca5a87Cc2BEe2eC3610EcAcD279FcBcD6",
30
+ "0xAB851cA6F8e5329Dcf9B164d312f7d5C9D41eE01",
31
+ "0xe2Db92758567D1D67A861F0645F850ddb6e216E8",
32
+ "0x4a7F42021C71Be21D3c21717743449620Abb3D25",
33
+ "0x2Bd99Ac1dCa390A543BD06F7712ece7B787752a5",
34
+ "0x8c27aa11FF3562c807C5A40e0512bDC043B39Bb0",
35
+ "0xB4e6dEa305a1A84FA0B2185F36de31bcE2c22005",
36
+ "0xA89f812f26ef2f6D89c81371A89787240c63D524",
37
+ "0xF7a54082215D4508CD674b270ECc37Bd281FD92d",
38
+ "0xc419410F5B29cdd4343013210ac194B872cF5a4B"
39
+ ]
40
+
41
+ # Chunk into groups of 3
42
+ def chunk_addresses(addresses, size):
43
+ return [addresses[i:i + size] for i in range(0, len(addresses), size)]
44
+
45
+ API_URL = "https://api.g.alchemy.com/data/v1/yhe6L3PXmiENzS1sP9Fu4_T5E3l0QyeB/assets/tokens/by-address"
46
+
47
+ async def fetch_batch(session, batch):
48
+ json_payload = {
49
+ "addresses": [{"address": addr, "networks": ["arb-mainnet"]} for addr in batch],
50
+ "withMetadata": True,
51
+ "withPrices": True,
52
+ "includeNativeTokens": True
53
+ }
54
+ async with session.post(API_URL, json=json_payload) as response:
55
+ response = await response.json()
56
+ return response['data']['tokens']
57
+
58
+ async def get_wallet_balances(addresses):
59
+ async with aiohttp.ClientSession() as session:
60
+ batches = chunk_addresses(addresses, 3)
61
+ tasks = [fetch_batch(session, batch) for batch in batches]
62
+ responses = await asyncio.gather(*tasks)
63
+ first_parts = []
64
+ rest_parts = []
65
+
66
+ for res in responses:
67
+ first_parts.extend(res[:3])
68
+ rest_parts.extend(res[3:])
69
+
70
+ responses = first_parts + rest_parts
71
+ df = pd.DataFrame(responses)
72
+ for i in range(len(addresses)):
73
+ df.at[i,'tokenMetadata'] = {}
74
+
75
+ df['tokenBalance'] = df['tokenBalance'].apply(lambda x : int(x,16))
76
+ df['decimals'] = df['tokenMetadata'].apply(lambda x : x.get('decimals',0))
77
+ df['tokenBalance'] = df['tokenBalance']/(10**df['decimals'])
78
+ for i in range(len(addresses)):
79
+ df.at[i, 'tokenBalance'] = df.at[i, 'tokenBalance'] / (10**18)
80
+
81
+ df['symbol'] = df['tokenMetadata'].apply(lambda x : x.get('symbol',''))
82
+ for i in range(len(addresses)):
83
+ df.at[i,'symbol'] = 'ETH'
84
+
85
+ df['currentPrice'] = df['tokenPrices'].apply(lambda x : x[0].get('value',None) if len(x) > 0 else None)
86
+ df.drop(columns=['tokenPrices','tokenMetadata','network','tokenAddress'], inplace=True)
87
+ df = df.dropna()
88
+ df['tokenBalance'] = pd.to_numeric(df['tokenBalance'], errors='coerce')
89
+ df = df[df['tokenBalance'] != 0]
90
+ df['tokenBalance'] = pd.to_numeric(df['tokenBalance'], errors='coerce')
91
+ df['currentPrice'] = pd.to_numeric(df['currentPrice'], errors='coerce')
92
+ df['value'] = df['tokenBalance'] * df['currentPrice']
93
+ df.drop(columns=['address','decimals'],inplace=True)
94
+
95
+ df = df[df['symbol'].isin(['BLUP', 'ETH', 'USDT', 'USDC'])]
96
+ df= df[['symbol','tokenBalance','value']]
97
+ df = df.rename(columns={'tokenBalance':'amount','value':'usd_value'})
98
+
99
+ df = df.groupby("symbol", as_index=False).sum()
100
+
101
+ return df, df['usd_value'].sum()
102
+
103
+ async def get_lp_balances():
104
+ url = "https://api.debank.com/user?id=0x275c7f2781db0b78228029f85735059c9bdd4f35"
105
+
106
+ SCRAPE_DO_TOKEN = os.getenv('SCRAPE_DO_KEY')
107
+
108
+ headers = {
109
+ "accept": "*/*",
110
+ "accept-encoding": "gzip, deflate, br, zstd",
111
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
112
+ "account": '{"random_at":1749473998,"random_id":"409f9a2ab18e40d09266e2783fb7b221","user_addr":null}',
113
+ "origin": "https://debank.com",
114
+ "priority": "u=1, i",
115
+ "referer": "https://debank.com/",
116
+ "sec-ch-ua": '"Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"',
117
+ "sec-ch-ua-mobile": "?0",
118
+ "sec-ch-ua-platform": '"macOS"',
119
+ "sec-fetch-dest": "empty",
120
+ "sec-fetch-mode": "cors",
121
+ "sec-fetch-site": "same-site",
122
+ "source": "web",
123
+ "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",
124
+ "x-api-nonce": "n_0rS1JvDi32stemeNlbalDP0AibZoN5Er25bxGuun",
125
+ "x-api-sign": "4a49625e6813d453f14b5801915e213a38f48146caa3e727a589ef0d5d12e99c",
126
+ "x-api-ts": "1749475247",
127
+ "x-api-ver": "v2"
128
+ }
129
+
130
+ encoded_url = urllib.parse.quote(url)
131
+ proxy_url = f"http://api.scrape.do/?token={SCRAPE_DO_TOKEN}&url={encoded_url}&forwardHeaders=True&super=True"
132
+ response = requests.get(proxy_url, headers=headers)
133
+
134
+ response = response.json()['data']['user']['stats']
135
+ top_coins = response['top_coins']
136
+ top_tokens = response['top_tokens']
137
+ coins = pd.DataFrame(top_coins)
138
+ tokens = pd.DataFrame(top_tokens)
139
+ balances = pd.concat([coins, tokens], axis=0)
140
+ balances.drop(columns=['id','logo_url','percent','price','chain_id'],inplace=True)
141
+ balances = balances[['symbol','amount','usd_value']]
142
+
143
+ return balances, balances['usd_value'].sum()
144
+
145
+ async def get_all_dfs():
146
+ wallet_df, wallet_total = await get_wallet_balances(addresses)
147
+ lp_df, lp_total = await get_lp_balances()
148
+ final_df = pd.concat([wallet_df,lp_df],axis=0)
149
+ return wallet_df, wallet_total, lp_df, lp_total, final_df, final_df['usd_value'].sum()
150
+
151
+
152
+ with gr.Blocks() as demo:
153
+ gr.Markdown("## BLUP Balances and PnL")
154
+
155
+ df0_out = gr.Dataframe(label="Wallet Balances")
156
+ txt0_out = gr.Textbox(label="Total Value")
157
+
158
+ df1_out = gr.Dataframe(label="LP Balances")
159
+ txt1_out = gr.Textbox(label="Total Value")
160
+
161
+ df2_out = gr.Dataframe(label="Total Balances")
162
+ txt2_out = gr.Textbox(label="Total Value")
163
+
164
+ # Load from MongoDB on app load (sync function)
165
+ demo.load(
166
+ fn= get_all_dfs,
167
+ inputs = [],
168
+ outputs=[df0_out, txt0_out, df1_out, txt1_out, df2_out, txt2_out]
169
+ )
170
+
171
+ demo.launch(debug=True, share=True)
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ aiohttp
2
+ nest_asyncio
3
+ pandas
4
+ requests
5
+ gradio
6
+ pymongo[srv]