Spaces:
Sleeping
Sleeping
| import requests | |
| import pandas as pd | |
| import gradio as gr | |
| import plotly.graph_objects as go | |
| import plotly.express as px | |
| from datetime import datetime, timedelta | |
| import json | |
| from web3 import Web3 | |
| import os | |
| from app_trans_new import create_transcation_visualizations,create_active_agents_visualizations | |
| # Load environment variables from .env file | |
| # RPC URLs | |
| OPTIMISM_RPC_URL = os.getenv('OPTIMISM_RPC_URL') | |
| MODE_RPC_URL = os.getenv('MODE_RPC_URL') | |
| # Initialize Web3 instances | |
| web3_instances = { | |
| 'optimism': Web3(Web3.HTTPProvider(OPTIMISM_RPC_URL)), | |
| 'mode': Web3(Web3.HTTPProvider(MODE_RPC_URL)) | |
| } | |
| # Contract addresses for service registries | |
| contract_addresses = { | |
| 'optimism': '0x3d77596beb0f130a4415df3D2D8232B3d3D31e44', | |
| 'mode': '0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE' | |
| } | |
| # Load the ABI from the provided JSON file | |
| with open('./contracts/service_registry_abi.json', 'r') as abi_file: | |
| contract_abi = json.load(abi_file) | |
| # Create the contract instances | |
| service_registries = { | |
| chain_name: web3.eth.contract(address=contract_addresses[chain_name], abi=contract_abi) | |
| for chain_name, web3 in web3_instances.items() | |
| } | |
| # Check if connections are successful | |
| for chain_name, web3_instance in web3_instances.items(): | |
| if not web3_instance.is_connected(): | |
| raise Exception(f"Failed to connect to the {chain_name.capitalize()} network.") | |
| else: | |
| print(f"Successfully connected to the {chain_name.capitalize()} network.") | |
| def get_transfers(integrator: str, wallet: str) -> str: | |
| url = f"https://li.quest/v1/analytics/transfers?&wallet={wallet}&fromTimestamp=1726165800" | |
| headers = {"accept": "application/json"} | |
| response = requests.get(url, headers=headers) | |
| return response.json() | |
| def fetch_and_aggregate_transactions(): | |
| aggregated_transactions = [] | |
| daily_agent_counts = {} | |
| seen_agents = set() | |
| for chain_name, service_registry in service_registries.items(): | |
| web3 = web3_instances[chain_name] | |
| total_services = service_registry.functions.totalSupply().call() | |
| for service_id in range(1, total_services + 1): | |
| service = service_registry.functions.getService(service_id).call() | |
| agent_ids = service[-1] | |
| if 40 in agent_ids or 25 in agent_ids: | |
| agent_address = service_registry.functions.getAgentInstances(service_id).call()[1][0] | |
| response_transfers = get_transfers("valory", agent_address) | |
| transfers = response_transfers.get("transfers", []) | |
| if isinstance(transfers, list): | |
| aggregated_transactions.extend(transfers) | |
| # Track the daily number of agents | |
| current_date = "" | |
| creation_event = service_registry.events.CreateService.create_filter(from_block=0, argument_filters={'serviceId': service_id}).get_all_entries() | |
| if creation_event: | |
| block_number = creation_event[0]['blockNumber'] | |
| block = web3.eth.get_block(block_number) | |
| creation_timestamp = datetime.fromtimestamp(block['timestamp']) | |
| date_str = creation_timestamp.strftime('%Y-%m-%d') | |
| current_date = date_str | |
| # Ensure each agent is only counted once based on first registered date | |
| if agent_address not in seen_agents: | |
| seen_agents.add(agent_address) | |
| if date_str not in daily_agent_counts: | |
| daily_agent_counts[date_str] = set() | |
| daily_agent_counts[date_str].add(agent_address) | |
| daily_agent_counts = {date: len(agents) for date, agents in daily_agent_counts.items()} | |
| return aggregated_transactions, daily_agent_counts | |
| # Function to parse the transaction data and prepare it for visualization | |
| def process_transactions_and_agents(data): | |
| transactions, daily_agent_counts = data | |
| # Convert the data into a pandas DataFrame for easy manipulation | |
| rows = [] | |
| for tx in transactions: | |
| # Normalize amounts | |
| sending_amount = float(tx["sending"]["amount"]) / (10 ** tx["sending"]["token"]["decimals"]) | |
| receiving_amount = float(tx["receiving"]["amount"]) / (10 ** tx["receiving"]["token"]["decimals"]) | |
| # Convert timestamps to datetime objects | |
| sending_timestamp = datetime.utcfromtimestamp(tx["sending"]["timestamp"]) | |
| receiving_timestamp = datetime.utcfromtimestamp(tx["receiving"]["timestamp"]) | |
| # Prepare row data | |
| rows.append({ | |
| "transactionId": tx["transactionId"], | |
| "from_address": tx["fromAddress"], | |
| "to_address": tx["toAddress"], | |
| "sending_chain": tx["sending"]["chainId"], | |
| "receiving_chain": tx["receiving"]["chainId"], | |
| "sending_token_symbol": tx["sending"]["token"]["symbol"], | |
| "receiving_token_symbol": tx["receiving"]["token"]["symbol"], | |
| "sending_amount": sending_amount, | |
| "receiving_amount": receiving_amount, | |
| "sending_amount_usd": float(tx["sending"]["amountUSD"]), | |
| "receiving_amount_usd": float(tx["receiving"]["amountUSD"]), | |
| "sending_gas_used": int(tx["sending"]["gasUsed"]), | |
| "receiving_gas_used": int(tx["receiving"]["gasUsed"]), | |
| "sending_timestamp": sending_timestamp, | |
| "receiving_timestamp": receiving_timestamp, | |
| "date": sending_timestamp.date(), # Group by day | |
| "week": sending_timestamp.strftime('%Y-%m-%d') # Group by week | |
| }) | |
| df_transactions = pd.DataFrame(rows) | |
| df_transactions = df_transactions.drop_duplicates() | |
| df_agents = pd.DataFrame(list(daily_agent_counts.items()), columns=['date', 'agent_count']) | |
| df_agents['date'] = pd.to_datetime(df_agents['date']) | |
| df_agents['week'] = df_agents['date'].dt.to_period('W').apply(lambda r: r.start_time) | |
| df_agents_weekly = df_agents[['week', 'agent_count']].groupby('week').sum().reset_index() | |
| return df_transactions, df_agents, df_agents_weekly | |
| # Function to create visualizations based on the metrics | |
| def create_visualizations(): | |
| transactions_data = fetch_and_aggregate_transactions() | |
| df_transactions, df_agents, df_agents_weekly = process_transactions_and_agents(transactions_data) | |
| # Fetch daily value locked data | |
| df_tvl = pd.read_csv('daily_value_locked.csv') | |
| # Calculate total value locked per chain per day | |
| df_tvl["total_value_locked_usd"] = df_tvl["amount0_usd"] + df_tvl["amount1_usd"] | |
| df_tvl_daily = df_tvl.groupby(["date", "chain_name"])["total_value_locked_usd"].sum().reset_index() | |
| df_tvl_daily['date'] = pd.to_datetime(df_tvl_daily['date']) | |
| # Filter out dates with zero total value locked | |
| df_tvl_daily = df_tvl_daily[df_tvl_daily["total_value_locked_usd"] > 0] | |
| chain_name_map = { | |
| "mode": "Mode", | |
| "base": "Base", | |
| "ethereum": "Ethereum", | |
| "optimism": "Optimism" | |
| } | |
| df_tvl_daily["chain_name"] = df_tvl_daily["chain_name"].map(chain_name_map) | |
| # Plot total value locked | |
| fig_tvl = px.bar( | |
| df_tvl_daily, | |
| x="date", | |
| y="total_value_locked_usd", | |
| color="chain_name", | |
| opacity=0.7, | |
| title="Total Volume Invested in Pools in Different Chains Daily", | |
| labels={"date": "Date","chain_name": "Transaction Chain", "total_value_locked_usd": "Total Volume Invested (USD)"}, | |
| barmode='stack', | |
| color_discrete_map={ | |
| "Mode": "orange", | |
| "Base": "purple", | |
| "Ethereum": "darkgreen", | |
| "Optimism": "blue" | |
| } | |
| ) | |
| fig_tvl.update_layout( | |
| xaxis_title="Date", | |
| yaxis=dict(tickmode='linear', tick0=0, dtick=4), | |
| xaxis=dict( | |
| tickmode='array', | |
| tickvals=df_tvl_daily['date'], | |
| ticktext=df_tvl_daily['date'].dt.strftime('%b %d'), | |
| tickangle=-45, | |
| ), | |
| bargap=0.6, # Increase gap between bar groups (0-1) | |
| bargroupgap=0.1, # Decrease gap between bars in a group (0-1) | |
| height=600, | |
| width=1200, # Specify width to prevent bars from being too wide | |
| showlegend=True, | |
| template='plotly_white' | |
| ) | |
| fig_tvl.update_xaxes(tickformat="%b %d") | |
| chain_name_map = { | |
| 10: "Optimism", | |
| 8453: "Base", | |
| 1: "Ethereum", | |
| 34443: "Mode" | |
| } | |
| df_transactions["sending_chain"] = df_transactions["sending_chain"].map(chain_name_map) | |
| df_transactions["receiving_chain"] = df_transactions["receiving_chain"].map(chain_name_map) | |
| df_transactions["sending_chain"] = df_transactions["sending_chain"].astype(str) | |
| df_transactions["receiving_chain"] = df_transactions["receiving_chain"].astype(str) | |
| df_transactions['date'] = pd.to_datetime(df_transactions['date']) | |
| df_transactions["is_swap"] = df_transactions.apply(lambda x: x["sending_chain"] == x["receiving_chain"], axis=1) | |
| swaps_per_chain = df_transactions[df_transactions["is_swap"]].groupby(["date", "sending_chain"]).size().reset_index(name="swap_count") | |
| fig_swaps_chain = px.bar( | |
| swaps_per_chain, | |
| x="date", | |
| y="swap_count", | |
| color="sending_chain", | |
| title="Chain Daily Activity: Swaps", | |
| labels={"sending_chain": "Transaction Chain", "swap_count": "Daily Swap Nr"}, | |
| barmode="stack", | |
| opacity=0.7, | |
| color_discrete_map={ | |
| "Optimism": "blue", | |
| "Ethereum": "darkgreen", | |
| "Base": "purple", | |
| "Mode": "orange" | |
| } | |
| ) | |
| fig_swaps_chain.update_layout( | |
| xaxis_title="Date", | |
| yaxis_title="Daily Swap Count", | |
| yaxis=dict(tickmode='linear', tick0=0, dtick=1), | |
| xaxis=dict( | |
| tickmode='array', | |
| tickvals=[d for d in swaps_per_chain['date']], | |
| ticktext=[d.strftime('%m-%d') for d in swaps_per_chain['date']], | |
| tickangle=-45, | |
| ), | |
| bargap=0.6, | |
| bargroupgap=0.1, | |
| height=600, | |
| width=1200, | |
| margin=dict(l=50, r=50, t=50, b=50), | |
| showlegend=True, | |
| legend=dict( | |
| yanchor="top", | |
| y=0.99, | |
| xanchor="right", | |
| x=0.99 | |
| ), | |
| template='plotly_white' | |
| ) | |
| fig_swaps_chain.update_xaxes(tickformat="%m-%d") | |
| df_transactions["is_bridge"] = df_transactions.apply(lambda x: x["sending_chain"] != x["receiving_chain"], axis=1) | |
| bridges_per_chain = df_transactions[df_transactions["is_bridge"]].groupby(["date", "sending_chain"]).size().reset_index(name="bridge_count") | |
| fig_bridges_chain = px.bar( | |
| bridges_per_chain, | |
| x="date", | |
| y="bridge_count", | |
| color="sending_chain", | |
| title="Chain Daily Activity: Bridges", | |
| labels={"sending_chain": "Transaction Chain", "bridge_count": "Daily Bridge Nr"}, | |
| barmode="stack", | |
| opacity=0.7, | |
| color_discrete_map={ | |
| "Optimism": "blue", | |
| "Ethereum": "darkgreen", | |
| "Base": "purple", | |
| "Mode": "orange" | |
| } | |
| ) | |
| fig_bridges_chain.update_layout( | |
| xaxis_title="Date", | |
| yaxis_title="Daily Bridge Count", | |
| yaxis=dict(tickmode='linear', tick0=0, dtick=1), | |
| xaxis=dict( | |
| tickmode='array', | |
| tickvals=[d for d in bridges_per_chain['date']], | |
| ticktext=[d.strftime('%m-%d') for d in bridges_per_chain['date']], | |
| tickangle=-45, | |
| ), | |
| bargap=0.6, | |
| bargroupgap=0.1, | |
| height=600, | |
| width=1200, | |
| margin=dict(l=50, r=50, t=50, b=50), | |
| showlegend=True, | |
| legend=dict( | |
| yanchor="top", | |
| y=0.99, | |
| xanchor="right", | |
| x=0.99 | |
| ), | |
| template='plotly_white' | |
| ) | |
| fig_bridges_chain.update_xaxes(tickformat="%m-%d") | |
| df_agents['date'] = pd.to_datetime(df_agents['date']) | |
| daily_agents_df = df_agents.groupby('date').agg({'agent_count': 'sum'}).reset_index() | |
| daily_agents_df.rename(columns={'agent_count': 'daily_agent_count'}, inplace=True) | |
| weekly_agents_df = df_agents.groupby('week').agg({'agent_count': 'sum'}).reset_index() | |
| weekly_agents_df.rename(columns={'agent_count': 'weekly_agent_count'}, inplace=True) | |
| merged_df = pd.merge(daily_agents_df, df_agents[['date', 'week']], on='date', how='left') | |
| weekly_merged_df = pd.merge(merged_df, weekly_agents_df, on='week', how='left') | |
| adjustment_date = pd.to_datetime('2024-11-15') | |
| weekly_merged_df.loc[weekly_merged_df['date'] == adjustment_date, 'daily_agent_count'] -= 1 | |
| weekly_merged_df.loc[weekly_merged_df['date'] == adjustment_date, 'weekly_agent_count'] -= 1 | |
| fig_agents_registered = go.Figure(data=[ | |
| go.Bar( | |
| name='Daily nr of Registered Agents', | |
| x=weekly_merged_df['date'], | |
| y=weekly_merged_df['daily_agent_count'], | |
| opacity=0.7, | |
| marker_color='blue' | |
| ), | |
| go.Bar( | |
| name='Total Weekly Nr of Registered Agents', | |
| x=weekly_merged_df['date'], | |
| y=weekly_merged_df['weekly_agent_count'], | |
| opacity=0.7, | |
| marker_color='purple' | |
| ) | |
| ]) | |
| fig_agents_registered.update_layout( | |
| xaxis_title='Date', | |
| yaxis_title='Number of Agents', | |
| title="Nr of Agents Registered", | |
| barmode='group', | |
| yaxis=dict(tickmode='linear', tick0=0, dtick=1), | |
| xaxis=dict( | |
| tickmode='array', | |
| tickvals=weekly_merged_df['date'], | |
| ticktext=[d.strftime("%b %d") for d in weekly_merged_df['date']], | |
| tickangle=-45 | |
| ), | |
| bargap=0.6, | |
| height=600, | |
| width=1200, | |
| margin=dict(l=50, r=50, t=50, b=50), | |
| showlegend=True, | |
| template='plotly_white' | |
| ) | |
| return fig_swaps_chain, fig_bridges_chain, fig_agents_registered,fig_tvl | |
| # Gradio interface | |
| def dashboard(): | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# Valory Transactions Dashboard") | |
| with gr.Tab("Chain Daily activity"): | |
| fig_tx_chain = create_transcation_visualizations() | |
| gr.Plot(fig_tx_chain) | |
| fig_swaps_chain, fig_bridges_chain, fig_agents_registered,fig_tvl = create_visualizations() | |
| with gr.Tab("Swaps Daily"): | |
| gr.Plot(fig_swaps_chain) | |
| with gr.Tab("Bridges Daily"): | |
| gr.Plot(fig_bridges_chain) | |
| with gr.Tab("Nr of Agents Registered"): | |
| gr.Plot(fig_agents_registered) | |
| with gr.Tab("DAA"): | |
| fig_agents_with_transactions_daily = create_active_agents_visualizations() | |
| gr.Plot(fig_agents_with_transactions_daily) | |
| with gr.Tab("Total Value Locked"): | |
| gr.Plot(fig_tvl) | |
| return demo | |
| # Launch the dashboard | |
| if __name__ == "__main__": | |
| dashboard().launch() |