10
10
import plotly .graph_objects as go
11
11
12
12
from bittensor_cli .src import COLOR_PALETTE
13
+ from bittensor_cli .src .bittensor .chain_data import DynamicInfo
13
14
from bittensor_cli .src .bittensor .utils import (
14
15
console ,
15
16
err_console ,
@@ -28,6 +29,7 @@ async def price(
28
29
netuids : list [int ],
29
30
all_netuids : bool = False ,
30
31
interval_hours : int = 4 ,
32
+ current_only : bool = False ,
31
33
html_output : bool = False ,
32
34
log_scale : bool = False ,
33
35
json_output : bool = False ,
@@ -41,45 +43,96 @@ async def price(
41
43
blocks_per_hour = int (3600 / 12 ) # ~300 blocks per hour
42
44
total_blocks = blocks_per_hour * interval_hours
43
45
44
- with console .status (":chart_increasing: Fetching historical price data..." ):
45
- current_block_hash = await subtensor .substrate .get_chain_head ()
46
- current_block = await subtensor .substrate .get_block_number (current_block_hash )
46
+ if not current_only :
47
+ with console .status (":chart_increasing: Fetching historical price data..." ):
48
+ current_block_hash = await subtensor .substrate .get_chain_head ()
49
+ current_block = await subtensor .substrate .get_block_number (
50
+ current_block_hash
51
+ )
47
52
48
- step = 300
49
- start_block = max (0 , current_block - total_blocks )
50
- block_numbers = list (range (start_block , current_block + 1 , step ))
53
+ step = 300
54
+ start_block = max (0 , current_block - total_blocks )
55
+ block_numbers = list (range (start_block , current_block + 1 , step ))
51
56
52
- # Block hashes
53
- block_hash_cors = [
54
- subtensor .substrate .get_block_hash (bn ) for bn in block_numbers
55
- ]
56
- block_hashes = await asyncio .gather (* block_hash_cors )
57
+ # Block hashes
58
+ block_hash_cors = [
59
+ subtensor .substrate .get_block_hash (bn ) for bn in block_numbers
60
+ ]
61
+ block_hashes = await asyncio .gather (* block_hash_cors )
57
62
58
- # We fetch all subnets when there is more than one netuid
59
- if all_netuids or len (netuids ) > 1 :
60
- subnet_info_cors = [subtensor .all_subnets (bh ) for bh in block_hashes ]
61
- else :
62
- # If there is only one netuid, we fetch the subnet info for that netuid
63
- netuid = netuids [0 ]
64
- subnet_info_cors = [subtensor .subnet (netuid , bh ) for bh in block_hashes ]
65
- all_subnet_infos = await asyncio .gather (* subnet_info_cors )
63
+ # We fetch all subnets when there is more than one netuid
64
+ if all_netuids or len (netuids ) > 1 :
65
+ subnet_info_cors = [subtensor .all_subnets (bh ) for bh in block_hashes ]
66
+ else :
67
+ # If there is only one netuid, we fetch the subnet info for that netuid
68
+ netuid = netuids [0 ]
69
+ subnet_info_cors = [subtensor .subnet (netuid , bh ) for bh in block_hashes ]
70
+ all_subnet_infos = await asyncio .gather (* subnet_info_cors )
66
71
67
72
subnet_data = _process_subnet_data (
68
73
block_numbers , all_subnet_infos , netuids , all_netuids
69
74
)
75
+ if not subnet_data :
76
+ err_console .print ("[red]No valid price data found for any subnet[/red]" )
77
+ return
70
78
71
- if not subnet_data :
72
- err_console .print ("[red]No valid price data found for any subnet[/red]" )
73
- return
74
-
75
- if html_output :
76
- await _generate_html_output (
77
- subnet_data , block_numbers , interval_hours , log_scale
79
+ if html_output :
80
+ await _generate_html_output (
81
+ subnet_data , block_numbers , interval_hours , log_scale
82
+ )
83
+ elif json_output :
84
+ json_console .print (json .dumps (_generate_json_output (subnet_data )))
85
+ else :
86
+ _generate_cli_output (subnet_data , block_numbers , interval_hours , log_scale )
87
+ else :
88
+ with console .status ("Fetching current price data..." ):
89
+ if all_netuids or len (netuids ) > 1 :
90
+ all_subnet_info = await subtensor .all_subnets ()
91
+ else :
92
+ all_subnet_info = [await subtensor .subnet (netuid = netuids [0 ])]
93
+ subnet_data = _process_current_subnet_data (
94
+ all_subnet_info , netuids , all_netuids
78
95
)
79
- elif json_output :
80
- json_console .print (json .dumps (_generate_json_output (subnet_data )))
96
+ if json_output :
97
+ json_console .print (json .dumps (_generate_json_output (subnet_data )))
98
+ else :
99
+ _generate_cli_output_current (subnet_data )
100
+
101
+
102
+ def _process_current_subnet_data (subnet_infos : list [DynamicInfo ], netuids , all_netuids ):
103
+ subnet_data = {}
104
+ if all_netuids or len (netuids ) > 1 :
105
+ # Most recent data for statistics
106
+ for subnet_info in subnet_infos :
107
+ stats = {
108
+ "current_price" : subnet_info .price ,
109
+ "supply" : subnet_info .alpha_in .tao + subnet_info .alpha_out .tao ,
110
+ "market_cap" : subnet_info .price .tao
111
+ * (subnet_info .alpha_in .tao + subnet_info .alpha_out .tao ),
112
+ "emission" : subnet_info .emission .tao ,
113
+ "stake" : subnet_info .alpha_out .tao ,
114
+ "symbol" : subnet_info .symbol ,
115
+ "name" : get_subnet_name (subnet_info ),
116
+ }
117
+ subnet_data [subnet_info .netuid ] = {
118
+ "stats" : stats ,
119
+ }
81
120
else :
82
- _generate_cli_output (subnet_data , block_numbers , interval_hours , log_scale )
121
+ subnet_info = subnet_infos [0 ]
122
+ stats = {
123
+ "current_price" : subnet_info .price .tao ,
124
+ "supply" : subnet_info .alpha_in .tao + subnet_info .alpha_out .tao ,
125
+ "market_cap" : subnet_info .price .tao
126
+ * (subnet_info .alpha_in .tao + subnet_info .alpha_out .tao ),
127
+ "emission" : subnet_info .emission .tao ,
128
+ "stake" : subnet_info .alpha_out .tao ,
129
+ "symbol" : subnet_info .symbol ,
130
+ "name" : get_subnet_name (subnet_info ),
131
+ }
132
+ subnet_data [subnet_info .netuid ] = {
133
+ "stats" : stats ,
134
+ }
135
+ return subnet_data
83
136
84
137
85
138
def _process_subnet_data (block_numbers , all_subnet_infos , netuids , all_netuids ):
@@ -626,3 +679,46 @@ def color_label(text):
626
679
)
627
680
628
681
console .print (stats_text )
682
+
683
+
684
+ def _generate_cli_output_current (subnet_data ):
685
+ for netuid , data in subnet_data .items ():
686
+ stats = data ["stats" ]
687
+
688
+ if netuid != 0 :
689
+ console .print (
690
+ f"\n [{ COLOR_PALETTE .G .SYM } ]Subnet { netuid } - { stats ['symbol' ]} "
691
+ f"[cyan]{ stats ['name' ]} [/cyan][/{ COLOR_PALETTE .G .SYM } ]\n "
692
+ f"Current: [blue]{ stats ['current_price' ]:.6f} { stats ['symbol' ]} [/blue]\n "
693
+ )
694
+ else :
695
+ console .print (
696
+ f"\n [{ COLOR_PALETTE .G .SYM } ]Subnet { netuid } - { stats ['symbol' ]} "
697
+ f"[cyan]{ stats ['name' ]} [/cyan][/{ COLOR_PALETTE .G .SYM } ]\n "
698
+ f"Current: [blue]{ stats ['symbol' ]} { stats ['current_price' ]:.6f} [/blue]\n "
699
+ )
700
+
701
+ if netuid != 0 :
702
+ stats_text = (
703
+ "\n Latest stats:\n "
704
+ f"Supply: [{ COLOR_PALETTE .P .ALPHA_IN } ]"
705
+ f"{ stats ['supply' ]:,.2f} { stats ['symbol' ]} [/{ COLOR_PALETTE .P .ALPHA_IN } ]\n "
706
+ f"Market Cap: [steel_blue3]{ stats ['market_cap' ]:,.2f} { stats ['symbol' ]} / 21M[/steel_blue3]\n "
707
+ f"Emission: [{ COLOR_PALETTE .P .EMISSION } ]"
708
+ f"{ stats ['emission' ]:,.2f} { stats ['symbol' ]} [/{ COLOR_PALETTE .P .EMISSION } ]\n "
709
+ f"Stake: [{ COLOR_PALETTE .S .TAO } ]"
710
+ f"{ stats ['stake' ]:,.2f} { stats ['symbol' ]} [/{ COLOR_PALETTE .S .TAO } ]"
711
+ )
712
+ else :
713
+ stats_text = (
714
+ "\n Latest stats:\n "
715
+ f"Supply: [{ COLOR_PALETTE .P .ALPHA_IN } ]"
716
+ f"{ stats ['symbol' ]} { stats ['supply' ]:,.2f} [/{ COLOR_PALETTE .P .ALPHA_IN } ]\n "
717
+ f"Market Cap: [steel_blue3]{ stats ['symbol' ]} { stats ['market_cap' ]:,.2f} / 21M[/steel_blue3]\n "
718
+ f"Emission: [{ COLOR_PALETTE .P .EMISSION } ]"
719
+ f"{ stats ['symbol' ]} { stats ['emission' ]:,.2f} [/{ COLOR_PALETTE .P .EMISSION } ]\n "
720
+ f"Stake: [{ COLOR_PALETTE .S .TAO } ]"
721
+ f"{ stats ['symbol' ]} { stats ['stake' ]:,.2f} [/{ COLOR_PALETTE .S .TAO } ]"
722
+ )
723
+
724
+ console .print (stats_text )
0 commit comments