Spaces:
Running
Running
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 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) | |
# 1. Chain Daily Activity: Transactions | |
tx_per_chain_agent = df.groupby(["date", "sending_chain"]).size().reset_index(name="transaction_count") | |
fig_tx_chain_agent = px.bar( | |
tx_per_chain_agent, | |
x="date", | |
y="transaction_count", | |
color="sending_chain", | |
title="Chain Daily Activity: Transactions", | |
labels={"transaction_count": "Daily Transaction Nr"}, | |
barmode="stack" | |
) | |
# 2. Number of Opportunities Taken per Agent per Day | |
opportunities_per_agent = df.groupby(["date", "from_address"]).size().reset_index(name="opportunities_taken") | |
fig_opportunities_agent = px.bar(opportunities_per_agent, x="date", y="opportunities_taken", color="from_address", | |
title="Number of Opportunities Taken per Agent per Day") | |
# 3. Amount of Investment in Pools Daily per Agent (Note: Assuming sending_amount_usd as investment) | |
# Since we might not have explicit data about pool investments, we'll use sending_amount_usd | |
investment_per_agent = df.groupby(["date", "from_address"])["sending_amount_usd"].sum().reset_index() | |
fig_investment_agent = px.bar(investment_per_agent, x="date", y="sending_amount_usd", color="from_address", | |
title="Amount of Investment (USD) per Agent per Day") | |
# 4. Number of Swaps per Day | |
df["is_swap"] = df.apply(lambda x: x["sending_token_symbol"] != x["receiving_token_symbol"], axis=1) | |
swaps_per_day = df[df["is_swap"]].groupby("date").size().reset_index(name="swap_count") | |
fig_swaps_per_day = px.bar(swaps_per_day, x="date", y="swap_count", title="Number of Swaps per Day") | |
# 5. Aggregated Metrics over All Traders | |
amount_usd = df["sending_amount_usd"] | |
stats = { | |
"Total": amount_usd.sum(), | |
"Average": amount_usd.mean(), | |
"Min": amount_usd.min(), | |
"Max": amount_usd.max(), | |
"25th Percentile": amount_usd.quantile(0.25), | |
"50th Percentile (Median)": amount_usd.median(), | |
"75th Percentile": amount_usd.quantile(0.75), | |
} | |
stats_df = pd.DataFrame(list(stats.items()), columns=["Metric", "Value"]) | |
# Visualization for Aggregated Metrics | |
fig_stats = px.bar(stats_df, x="Metric", y="Value", title="Aggregated Transaction Amount Metrics (USD)") | |
return fig_tx_chain_agent, fig_opportunities_agent, fig_investment_agent, fig_swaps_per_day, fig_stats | |
# Gradio interface | |
def dashboard(): | |
with gr.Blocks() as demo: | |
gr.Markdown("# Valory Transactions Dashboard") | |
# Fetch and display visualizations | |
with gr.Tab("Transactions per Chain per Agent"): | |
fig_tx_chain_agent, _, _, _, _ = create_visualizations() | |
gr.Plot(fig_tx_chain_agent) | |
with gr.Tab("Opportunities per Agent"): | |
_, fig_opportunities_agent, _, _, _ = create_visualizations() | |
gr.Plot(fig_opportunities_agent) | |
with gr.Tab("Investment per Agent"): | |
_, _, fig_investment_agent, _, _ = create_visualizations() | |
gr.Plot(fig_investment_agent) | |
with gr.Tab("Swaps per Day"): | |
_, _, _, fig_swaps_per_day, _ = create_visualizations() | |
gr.Plot(fig_swaps_per_day) | |
with gr.Tab("Aggregated Metrics"): | |
_, _, _, _, fig_stats = create_visualizations() | |
gr.Plot(fig_stats) | |
return demo | |
# Launch the dashboard | |
if __name__ == "__main__": | |
dashboard().launch() |