Spaces:
Runtime error
Runtime error
File size: 10,141 Bytes
06c9fc9 c074aa5 e5457b7 06c9fc9 ddbfd8d e5457b7 32253ac e5457b7 32253ac 64fdbb7 e5457b7 64fdbb7 e5457b7 64fdbb7 e5457b7 64fdbb7 32253ac 64fdbb7 6b92fa1 32253ac 64fdbb7 6b92fa1 32253ac 64fdbb7 32253ac 64fdbb7 32253ac 64fdbb7 604a5b9 64fdbb7 604a5b9 64fdbb7 e5457b7 64fdbb7 e5457b7 604a5b9 64fdbb7 e5457b7 ddbfd8d c074aa5 2fce877 b5adfa8 2fce877 791fbae b5adfa8 06c9fc9 32253ac 64fdbb7 e5457b7 b5adfa8 c074aa5 e5457b7 c074aa5 b5adfa8 e2ec4cf e5457b7 c074aa5 64fdbb7 e5457b7 ae5716a e5457b7 64fdbb7 e5457b7 64fdbb7 e5457b7 ae5716a e5457b7 06c9fc9 e5457b7 32253ac e5457b7 32253ac e5457b7 32253ac e5457b7 32253ac e5457b7 06c9fc9 2fce877 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
import gradio as gr
import pandas as pd
import bittensor as bt
import requests
from apscheduler.schedulers.background import BackgroundScheduler
# 1. Define data functions first
def get_validator_data() -> pd.DataFrame:
if subtensor is None or metagraph is None:
return pd.DataFrame(columns=['Name', 'UID', 'Axon', 'API', 'Step', 'Recent Bits', 'Updated', 'VTrust'])
try:
validator_ids = list(set([i for i in range(len(metagraph.validator_permit))
if metagraph.validator_permit[i] and
metagraph.active[i] and
str(metagraph.axons[i].ip) != "0.0.0.0"]))
except Exception as e:
print(f"Error getting validator IDs: {e}")
validator_ids = []
current_block = subtensor.block
results = []
for uid in validator_ids:
validator_info = {
'Name': 'unavailable',
'UID': uid,
'Axon': 'unavailable',
'Step': 0,
'Recent Bits': 0,
'Updated': 0,
'VTrust': 0,
'API': 'β'
}
try:
# Get validator name
try:
identity = subtensor.substrate.query('SubtensorModule', 'Identities', [metagraph.coldkeys[uid]])
validator_info['Name'] = identity.value["name"] if identity != None else 'unnamed'
except Exception as e:
print(f"Error getting Name for UID {uid}: {str(e)}")
validator_info['Axon'] = f"{metagraph.axons[uid].ip}:{metagraph.axons[uid].port}"
# Get Step and Range from endpoints
try:
axon_endpoint = f"http://{validator_info['Axon']}"
step_response = requests.get(f"{axon_endpoint}/step", timeout=5)
step_response.raise_for_status()
validator_info['Step'] = step_response.json()
bits_response = requests.get(
f"{axon_endpoint}/bits",
headers={"range": "bytes=-1"},
timeout=5
)
bits_response.raise_for_status()
binary_string = ''.join(format(byte, '08b') for byte in bits_response.content)
validator_info['Recent Bits'] = binary_string[-8:]
validator_info['API'] = '<span class="api-status api-up">β
</span>' if bits_response.ok else '<span class="api-status api-down">β</span>'
except requests.Timeout:
print(f"Timeout while connecting to {axon_endpoint}")
except Exception as e:
print(f"Error connecting to {axon_endpoint}: {e}")
try:
last_update = int(metagraph.last_update[uid])
validator_info['Updated'] = current_block - last_update
except Exception as e:
print(f"Error getting Updated for UID {uid}: {str(e)}")
try:
validator_info['VTrust'] = float(metagraph.validator_trust[uid])
except Exception as e:
print(f"Error getting VTrust for UID {uid}: {str(e)}")
except Exception as e:
print(f"Error getting Axon for UID {uid}: {str(e)}")
results.append(validator_info)
df = pd.DataFrame(results)
df['VTrust'] = df['VTrust'].round(4)
return df.sort_values('Step', ascending=False)[['Name', 'UID', 'Axon', 'API', 'Step', 'Recent Bits', 'Updated', 'VTrust']]
# 2. Initialize bittensor and load data
try:
subtensor = bt.subtensor()
metagraph = bt.metagraph(netuid=36)
initial_df = get_validator_data()
initial_timestamp = pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S UTC")
print("β
Data loaded successfully")
except Exception as e:
print(f"β Failed to initialize: {e}")
initial_df = pd.DataFrame()
initial_timestamp = "Failed to load initial data"
# 3. Then CSS and UI components
background_url = "https://cdn-lfs.hf.co/repos/a4/b4/a4b48e51a6a5ebd9414fc6798da9acf09a6a9425ea160334a1a81c4ad3fdb801/7f89926e2018d54403ac1dc8b0d6fe2401a6489d7da11df27259a07cde7acf87?response-content-disposition=inline%3B+filename*%3DUTF-8%27%27background2.png%3B+filename%3D%22background2.png%22%3B&response-content-type=image%2Fpng&Expires=1731722075&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTczMTcyMjA3NX19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLWxmcy5oZi5jby9yZXBvcy9hNC9iNC9hNGI0OGU1MWE2YTVlYmQ5NDE0ZmM2Nzk4ZGE5YWNmMDlhNmE5NDI1ZWExNjAzMzRhMWE4MWM0YWQzZmRiODAxLzdmODk5MjZlMjAxOGQ1NDQwM2FjMWRjOGIwZDZmZTI0MDFhNjQ4OWQ3ZGExMWRmMjcyNTlhMDdjZGU3YWNmODc%7EcmVzcG9uc2UtY29udGVudC1kaXNwb3NpdGlvbj0qJnJlc3BvbnNlLWNvbnRlbnQtdHlwZT0qIn1dfQ__&Signature=Y9KvhLMB7xHfQUnq2RC4rMDegTBzbqoMiHAIJzVKy%7E7ajPw2p-AQ19KCYCaXPNbElSV7PZowowMOS%7EtK98A7SM4ndHDePx3OcD%7EDNP8w150rLj58XeCZuVSZ32ayv%7Eb6nZEwYjUbrtrFboN5T9HG8xezW7BgmcXzV3iHppgSNu%7EnwKwJvorVr%7EyddXC6AMsAjsYKYOl1AxnkiMiIKeoD7Rd4ZaAlQsbqAC31BfnbSkBfPq4g0HlCiQYvYsxoofyLsGslnx9X5yIPaYRIRz3uJibPwDZg6GCEYViOfKWwiWV74iA1ptt2DeWLSxBRkjRfnv-HMAs25GmMjqyF85o8vA__&Key-Pair-Id=K3RPWS32NSSJCE"
custom_css = """
#component-0 {
max-width: 100% !important;
padding: 0 !important;
margin: 0 !important;
}
.gradio-container {
max-width: 100% !important;
padding: 0 !important;
margin: 0 !important;
background-image: url('""" + background_url + """') !important;
background-size: cover !important;
background-position: center !important;
background-repeat: no-repeat !important;
min-height: 100vh !important;
}
.header-box {
text-align: center;
max-width: 100%;
margin: 20px auto;
padding: 1rem;
background-color: rgba(17, 24, 39, 0.95); /* Darker, more opaque background */
border-radius: 1rem;
}
.header-box h1 {
color: white;
margin: 0;
font-size: 2rem;
}
.header-box p {
color: white; /* Changed to white instead of gray */
margin-top: 0.5rem;
}
"""
# Data functions first
def fetch_data():
# your data fetching logic
pass
def create_leaderboard():
try:
data = fetch_data()
if not data:
return pd.DataFrame()
return data
except Exception as e:
print(f"Error creating leaderboard: {e}")
return pd.DataFrame()
def update_data():
try:
data = create_leaderboard()
error_msg = ""
success = True
except Exception as e:
data = pd.DataFrame()
error_msg = f"Error loading data: {str(e)}"
success = False
return data, error_msg, not success
# Add this before creating the app
header_html = """
<div class="header-box">
<h1>SN36 Validator Leaderboard</h1>
<p>Real-time validator status monitoring</p>
</div>
"""
# UI components last
# Create the Gradio interface with custom theme
app = gr.Blocks(
title="SN36 Validator Leaderboard",
css=custom_css,
theme=gr.themes.Soft().set(
body_background_fill="rgba(17, 24, 39, 0.95)",
background_fill_secondary="rgba(17, 24, 39, 0.95)",
)
)
with app:
gr.HTML(header_html)
with gr.Tabs(elem_id="main-tabs"):
with gr.Tab("π Leaderboard", elem_id="leaderboard-tab"):
# Initialize with preloaded data
leaderboard = gr.DataFrame(
value=initial_df,
headers=["Name", "UID", "Axon", "API", "Step", "Recent Bits", "Updated", "VTrust"],
datatype=["str", "number", "str", "html", "number", "str", "number", "number"],
elem_id="leaderboard-table",
render=True
)
# Initialize with preloaded timestamp
status_message = gr.Markdown(
value=f"Last updated: {initial_timestamp}",
elem_classes=["status-msg"]
)
with gr.Row(equal_height=True):
refresh_button = gr.Button("π Refresh Data", variant="primary", elem_classes=["refresh-btn"])
auto_refresh = gr.Checkbox(
label="Auto-refresh (5 min)",
value=True,
interactive=True
)
with gr.Tab("βΉοΈ About"):
gr.Markdown(
"""
<div style="color: white;">
## About this Leaderboard
This dashboard shows real-time information about validators on the network:
- **Name**: Validator's registered name on the network
- **UID**: Unique identifier of the validator
- **Axon**: Validator's Axon address (IP:port)
- **API**: API status (β
online, β offline)
- **Step**: Current step count (0 if unavailable)
- **Range**: Validator's bit range (0 if unavailable)
- **Updated**: Blocks since last update (0 if unavailable)
- **VTrust**: Validator's trust score (0 if unavailable)
Data is automatically refreshed every 5 minutes, or you can manually refresh using the button.
</div>
"""
)
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],
queue=False
)
# Auto-refresh logic
def setup_auto_refresh():
app.scheduler = BackgroundScheduler()
app.scheduler.add_job(
lambda: app.queue(update_leaderboard),
'interval',
minutes=5
)
app.scheduler.start()
# Initial data load
app.load(
fn=update_leaderboard,
outputs=[leaderboard, status_message]
)
setup_auto_refresh()
# Launch the interface with file serving enabled
app.launch(
share=False
) |