1010import plotly .graph_objects as go
1111
1212from bittensor_cli .src import COLOR_PALETTE
13+ from bittensor_cli .src .bittensor .chain_data import DynamicInfo
1314from bittensor_cli .src .bittensor .utils import (
1415 console ,
1516 err_console ,
@@ -28,6 +29,7 @@ async def price(
2829 netuids : list [int ],
2930 all_netuids : bool = False ,
3031 interval_hours : int = 4 ,
32+ current_only : bool = False ,
3133 html_output : bool = False ,
3234 log_scale : bool = False ,
3335 json_output : bool = False ,
@@ -41,45 +43,96 @@ async def price(
4143 blocks_per_hour = int (3600 / 12 ) # ~300 blocks per hour
4244 total_blocks = blocks_per_hour * interval_hours
4345
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+ )
4752
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 ))
5156
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 )
5762
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 )
6671
6772 subnet_data = _process_subnet_data (
6873 block_numbers , all_subnet_infos , netuids , all_netuids
6974 )
75+ if not subnet_data :
76+ err_console .print ("[red]No valid price data found for any subnet[/red]" )
77+ return
7078
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
7895 )
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+ }
81120 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
83136
84137
85138def _process_subnet_data (block_numbers , all_subnet_infos , netuids , all_netuids ):
@@ -626,3 +679,46 @@ def color_label(text):
626679 )
627680
628681 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