import requests from concurrent.futures import ThreadPoolExecutor, as_completed import pandas as pd import gradio as gr addresses = [ "0x420b7a61CAdF89732215355cdda4079b863BF9a1", "0x7f888b43aa77a7643858d9d84da64fdc723f431f", "0x2fa6e3ff971cca5e41d3b43bc085002b03dd5a91", "0x97703AB33AA57aBf071fee3de513A03f3cBB109f" ] results = [] def fetch_token_data(address): base_url = "https://flowscan-mainnet-72vixfrfw-findonflow.vercel.app/api/proxy" token_url = f"{base_url}?url=https%3A%2F%2Fevm.flowscan.io%2Fapi%2Fv2%2Faddresses%2F{address}%2Ftokens%3Ftype%3DERC-20&fsLayer=api" info_url = f"{base_url}?url=https%3A%2F%2Fevm.flowscan.io%2Fapi%2Fv2%2Faddresses%2F{address}&fsLayer=api" try: token_response = requests.get(token_url) token_response.raise_for_status() token_data = token_response.json() except requests.RequestException as e: token_data = {"error": str(e)} try: info_response = requests.get(info_url) info_response.raise_for_status() info_data = info_response.json() except requests.RequestException as e: info_data = {"error": str(e)} return { "address": address, "token_data": token_data, "info_data": info_data } def extract_tokens(item_list): item_list = item_list['items'] token_data = {} for item in item_list: symbol = item['token']['symbol'] decimals = item['token']['decimals'] balance = float(item['value']) / 10**float(decimals) token_data[symbol] = balance return pd.Series(token_data) def extract_flow(info_data): flow_data = {} flow_data['FLOW'] = float(info_data['coin_balance']) / 10**18 return pd.Series(flow_data) with ThreadPoolExecutor() as executor: futures = [executor.submit(fetch_token_data, addr) for addr in addresses] for future in as_completed(futures): results.append(future.result()) data_df = pd.DataFrame(results) tokens_df = data_df['token_data'].apply(extract_tokens).apply(pd.Series) flow_df = data_df['info_data'].apply(extract_flow).apply(pd.Series) df = pd.concat([ data_df['address'].reset_index(drop=True), flow_df.reset_index(drop=True), tokens_df.reset_index(drop=True) ], axis=1) address_map = { "0x420b7a61CAdF89732215355cdda4079b863BF9a1":"Treasury Wallet", "0x7f888b43aa77a7643858d9d84da64fdc723f431f":"LP Wallet", "0x2fa6e3ff971cca5e41d3b43bc085002b03dd5a91":"Taker 1", "0x97703AB33AA57aBf071fee3de513A03f3cBB109f":"Taker 2" } df['Name'] = df['address'].apply(lambda x : address_map[x]) df = df[['Name'] + [col for col in df.columns if col != 'Name']] df = df.fillna(0) priority_names = ['Taker 1', 'Taker 2'] df = df.sort_values( by='Name', key=lambda col: col.apply( lambda x: (0, priority_names.index(x)) if x in priority_names else (1, x) ) ).reset_index(drop=True) numeric_cols = df.select_dtypes(include='number').columns # Create the total row with summed values total_row = {col: df[col].sum() for col in numeric_cols} total_row.update({'Name': 'Total', 'address': ''}) # Append the total row df = pd.concat([df, pd.DataFrame([total_row])], ignore_index=True) with gr.Blocks() as demo: gr.Markdown("# FROTH Balances") gr.Dataframe(value=df, headers="keys", datatype="str", label="Token Balances") demo.launch()