Spaces:
Runtime error
Runtime error
import gradio as gr | |
import bittensor as bt | |
import requests | |
import pandas as pd | |
from apscheduler.schedulers.background import BackgroundScheduler | |
# Custom CSS for better appearance | |
custom_css = """ | |
.gradio-container { | |
max-width: 1200px !important; | |
margin: auto; | |
} | |
.title { | |
text-align: center; | |
margin-bottom: 1rem; | |
} | |
.status-active { color: green; } | |
.status-error { color: red; } | |
""" | |
# Initialize bittensor objects | |
subtensor = bt.subtensor() | |
metagraph = bt.metagraph(netuid=36) | |
def get_validator_data() -> pd.DataFrame: | |
validator_ids = [i for i in range(len(metagraph.validator_permit)) if metagraph.validator_permit[i]] | |
results = [] | |
for uid in validator_ids: | |
try: | |
ip = metagraph.axons[uid].ip_str().split('/')[-1] | |
response = requests.get(f'http://{ip}/step', timeout=5) | |
response.raise_for_status() | |
validator_info = { | |
'UID': uid, | |
'IP': ip, | |
'Bits': response.json().get('bits', 0), | |
'Status': 'β Active' | |
} | |
except Exception as e: | |
validator_info = { | |
'UID': uid, | |
'IP': metagraph.axons[uid].ip_str().split('/')[-1], | |
'Bits': 0, | |
'Status': f'β Error: {str(e)[:50]}...' if len(str(e)) > 50 else str(e) | |
} | |
results.append(validator_info) | |
df = pd.DataFrame(results) | |
return df.sort_values('Bits', ascending=False) | |
# Create the Gradio interface | |
demo = gr.Blocks(css=custom_css) | |
with demo: | |
gr.HTML( | |
""" | |
<div class="title"> | |
<h1>π Validator Bits Leaderboard</h1> | |
<p>Real-time tracking of validator performance and bits</p> | |
</div> | |
""" | |
) | |
with gr.Tabs() as tabs: | |
with gr.Tab("π Leaderboard"): | |
leaderboard = gr.DataFrame( | |
headers=['UID', 'IP', 'Bits', 'Status'], | |
datatype=['number', 'str', 'number', 'str'], | |
interactive=False | |
) | |
with gr.Row(): | |
refresh_button = gr.Button("π Refresh Data", variant="primary") | |
auto_refresh = gr.Checkbox( | |
label="Auto-refresh (5 min)", | |
value=True, | |
interactive=True | |
) | |
status_message = gr.Markdown("Last updated: Never") | |
with gr.Tab("βΉοΈ About"): | |
gr.Markdown( | |
""" | |
## About this Leaderboard | |
This dashboard shows real-time information about validators on the network: | |
- **UID**: Unique identifier of the validator | |
- **IP**: Validator's IP address | |
- **Bits**: Current bits count | |
- **Status**: Active/Error status of the validator | |
Data is automatically refreshed every 5 minutes, or you can manually refresh using the button. | |
""" | |
) | |
def update_leaderboard(): | |
df = get_validator_data() | |
timestamp = pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S UTC") | |
return df, f"Last updated: {timestamp}" | |
refresh_button.click( | |
fn=update_leaderboard, | |
outputs=[leaderboard, status_message] | |
) | |
# Auto-refresh logic | |
def setup_auto_refresh(): | |
if demo.scheduler: | |
demo.scheduler.shutdown() | |
demo.scheduler = BackgroundScheduler() | |
demo.scheduler.add_job( | |
lambda: demo.queue(update_leaderboard), | |
'interval', | |
minutes=5 | |
) | |
demo.scheduler.start() | |
# Initial data load | |
demo.load( | |
fn=update_leaderboard, | |
outputs=[leaderboard, status_message] | |
) | |
setup_auto_refresh() | |
# Launch the interface | |
demo.queue(default_concurrency_limit=5).launch() |