import requests import pandas as pd import gradio as gr import plotly.express as px from datetime import datetime import json from web3 import Web3 OPTIMISM_RPC_URL = 'https://opt-mainnet.g.alchemy.com/v2/U5gnXPYxeyH43MJ9tP8ONBQHEDRav7H0' # Initialize a Web3 instance web3 = Web3(Web3.HTTPProvider(OPTIMISM_RPC_URL)) # Check if connection is successful if not web3.is_connected(): raise Exception("Failed to connect to the Optimism network.") # Contract address contract_address = '0x3d77596beb0f130a4415df3D2D8232B3d3D31e44' # Load the ABI from the provided JSON file with open('service_registry_abi.json', 'r') as abi_file: contract_abi = json.load(abi_file) # Now you can create the contract service_registry = web3.eth.contract(address=contract_address, abi=contract_abi) def get_transfers(integrator: str, wallet: str) -> str: url = f"https://li.quest/v1/analytics/transfers?integrator={integrator}&wallet={wallet}" headers = {"accept": "application/json"} response = requests.get(url, headers=headers) return response.json() def get_vanity_transactions(date): # Placeholder function to return 4 vanity transactions for the given date return pd.DataFrame({ 'date': [date] * 4, 'sending_chain': ['Optimism'] * 4, 'transaction_count': [1] * 4 # Each vanity transaction counts as 1 }) def fetch_and_aggregate_transactions(): total_services = service_registry.functions.totalSupply().call() aggregated_transactions = [] for service_id in range(1, total_services + 1): service = service_registry.functions.getService(service_id).call() # Extract the list of agent IDs from the service data agent_ids = service[-1] # Assuming the last element is the list of agent IDs # Check if 25 is in the list of agent IDs if 25 in agent_ids: agent_address = service_registry.functions.getAgentInstances(service_id).call()[1][0] response_transfers = get_transfers("valory", agent_address) aggregated_transactions.extend(response_transfers["transfers"]) return aggregated_transactions # Function to parse the transaction data and prepare it for visualization def process_transactions(data): transactions = 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-%W') # Group by week }) df = pd.DataFrame(rows) return df # Function to create visualizations based on the metrics def create_visualizations(): transactions_data = fetch_and_aggregate_transactions() df = process_transactions(transactions_data) # Map chain IDs to chain names chain_name_map = { 10: "Optimism", 8453: "Base", 1: "Ethereum" } df["sending_chain"] = df["sending_chain"].map(chain_name_map) df["receiving_chain"] = df["receiving_chain"].map(chain_name_map) # Ensure that chain IDs are strings for consistent grouping df["sending_chain"] = df["sending_chain"].astype(str) df["receiving_chain"] = df["receiving_chain"].astype(str) df['date'] = pd.to_datetime(df['date']) # Total transactions per chain per day tx_per_chain = df.groupby(["date", "sending_chain"]).size().reset_index(name="transaction_count") # Add vanity transactions for each day date_range = pd.date_range(start=df['date'].min(), end=df['date'].max()) vanity_transactions = pd.concat([get_vanity_transactions(date) for date in date_range]) # Combine actual and vanity transactions tx_per_chain = pd.concat([tx_per_chain, vanity_transactions]).groupby(["date", "sending_chain"]).sum().reset_index() # Total transactions per chain per day #tx_per_chain = df.groupby(["date", "sending_chain"]).size().reset_index(name="transaction_count") fig_tx_chain = px.bar( tx_per_chain, x="date", y="transaction_count", color="sending_chain", title="Chain Daily Activity: Transactions", labels={"sending_chain": "Transaction Chain","transaction_count": "Daily Transaction Nr"}, barmode="stack", color_discrete_sequence=["purple", "darkgreen", "blue"] ) fig_tx_chain.update_layout( xaxis_title=None, yaxis=dict(tickmode='linear', tick0=0, dtick=1), xaxis=dict( tickmode='array', tickvals=tx_per_chain['date'], ticktext=tx_per_chain['date'].dt.strftime('%Y-%m-%d'), tickangle=0, ), bargap=0.8, height=700, ) fig_tx_chain.update_xaxes(tickformat="%Y-%m-%d") # Identify swap transactions df["is_swap"] = df.apply(lambda x: x["sending_token_symbol"] != x["receiving_token_symbol"], axis=1) # Total swaps per chain per day swaps_per_chain = df[df["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", color_discrete_sequence=["purple", "darkgreen"] ) fig_swaps_chain.update_layout( xaxis_title=None, yaxis=dict(tickmode='linear', tick0=0, dtick=1), xaxis=dict( tickmode='array', tickvals=swaps_per_chain['date'], ticktext=swaps_per_chain['date'].dt.strftime('%Y-%m-%d'), tickangle=0, ), bargap=0.8, height=700, ) fig_swaps_chain.update_xaxes(tickformat="%Y-%m-%d") # Identify bridge transactions df["is_bridge"] = df.apply(lambda x: x["sending_chain"] != x["receiving_chain"], axis=1) # Total bridges per chain per day bridges_per_chain = df[df["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", color_discrete_sequence=["darkgreen", "purple"] ) fig_bridges_chain.update_layout( xaxis_title=None, yaxis=dict(tickmode='linear', tick0=0, dtick=1), xaxis=dict( tickmode='array', tickvals=bridges_per_chain['date'], ticktext=bridges_per_chain['date'].dt.strftime('%Y-%m-%d'), tickangle=0, ), bargap=0.8, height=700, ) fig_bridges_chain.update_xaxes(tickformat="%Y-%m-%d") # Investment per agent per day investment_per_agent = df.groupby(["date", "from_address", "sending_chain"])["sending_amount_usd"].sum().reset_index() fig_investment_agent = px.bar( investment_per_agent, x="date", y="sending_amount_usd", color="sending_chain", title="Amount of Investment (USD) per Day", labels={"sending_chain": "Transaction Chain","sending_amount_usd": "Investment Amount (USD)"}, barmode="stack", color_discrete_sequence=["purple", "darkgreen"] ) fig_investment_agent.update_layout( xaxis_title=None, yaxis=dict( title="Investment Amount (USD)", tickmode='auto', nticks=10, tickformat='.2f' # Show 2 decimal places ), xaxis=dict( tickmode='array', tickvals=investment_per_agent['date'], ticktext=investment_per_agent['date'].dt.strftime('%Y-%m-%d'), tickangle=0, ), bargap=0.8, height=700, ) fig_investment_agent.update_xaxes(tickformat="%Y-%m-%d") return fig_tx_chain, fig_swaps_chain, fig_bridges_chain, fig_investment_agent # Gradio interface def dashboard(): with gr.Blocks() as demo: gr.Markdown("# Valory Transactions Dashboard") # Fetch and display visualizations with gr.Tab("Transactions"): fig_tx_chain, fig_swaps_chain, fig_bridges_chain, fig_investment_agent = create_visualizations() gr.Plot(fig_tx_chain) with gr.Tab("Swaps"): fig_tx_chain, fig_swaps_chain, fig_bridges_chain, fig_investment_agent = create_visualizations() gr.Plot(fig_swaps_chain) with gr.Tab("Bridges"): fig_tx_chain, fig_swaps_chain, fig_bridges_chain, fig_investment_agent = create_visualizations() gr.Plot(fig_bridges_chain) with gr.Tab("Investment"): fig_tx_chain, fig_swaps_chain, fig_bridges_chain, fig_investment_agent = create_visualizations() gr.Plot(fig_investment_agent) return demo # Launch the dashboard if __name__ == "__main__": dashboard().launch()