File size: 3,949 Bytes
06c9fc9
e5457b7
 
06c9fc9
 
 
e5457b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06c9fc9
 
e5457b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06c9fc9
e5457b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06c9fc9
 
e5457b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06c9fc9
e5457b7
 
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
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()