Skip to content

Commit 70138f3

Browse files
committed
Subnets list
1 parent ad64a11 commit 70138f3

File tree

2 files changed

+104
-41
lines changed

2 files changed

+104
-41
lines changed

bittensor_cli/cli.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4441,6 +4441,7 @@ def subnets_list(
44414441
quiet: bool = Options.quiet,
44424442
verbose: bool = Options.verbose,
44434443
live_mode: bool = Options.live,
4444+
json_output: bool = Options.json_output,
44444445
):
44454446
"""
44464447
List all subnets and their detailed information.
@@ -4468,7 +4469,10 @@ def subnets_list(
44684469
44694470
[green]$[/green] btcli subnets list
44704471
"""
4471-
self.verbosity_handler(quiet, verbose)
4472+
if json_output and live_mode:
4473+
print_error("Cannot use --json-output and --live at the same time.")
4474+
return
4475+
self.verbosity_handler(quiet, verbose, json_output)
44724476
subtensor = self.initialize_chain(network)
44734477
return self._run_command(
44744478
subnets.subnets_list(
@@ -4478,6 +4482,7 @@ def subnets_list(
44784482
not self.config.get("use_cache", True),
44794483
verbose,
44804484
live_mode,
4485+
json_output,
44814486
)
44824487
)
44834488

bittensor_cli/src/commands/subnets/subnets.py

Lines changed: 98 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
prompt_for_identity,
3535
get_subnet_name,
3636
unlock_key,
37+
json_console,
3738
)
3839

3940
if TYPE_CHECKING:
@@ -206,40 +207,41 @@ async def subnets_list(
206207
no_cache: bool,
207208
verbose: bool,
208209
live: bool,
210+
json_output: bool,
209211
):
210212
"""List all subnet netuids in the network."""
211213

212214
async def fetch_subnet_data():
213-
block_number = await subtensor.substrate.get_block_number(None)
214-
subnets = await subtensor.all_subnets()
215+
block_number_ = await subtensor.substrate.get_block_number(None)
216+
subnets_ = await subtensor.all_subnets()
215217

216218
# Sort subnets by market cap, keeping the root subnet in the first position
217-
root_subnet = next(s for s in subnets if s.netuid == 0)
219+
root_subnet = next(s for s in subnets_ if s.netuid == 0)
218220
other_subnets = sorted(
219-
[s for s in subnets if s.netuid != 0],
221+
[s for s in subnets_ if s.netuid != 0],
220222
key=lambda x: (x.alpha_in.tao + x.alpha_out.tao) * x.price.tao,
221223
reverse=True,
222224
)
223225
sorted_subnets = [root_subnet] + other_subnets
224-
return sorted_subnets, block_number
226+
return sorted_subnets, block_number_
225227

226228
def calculate_emission_stats(
227-
subnets: list, block_number: int
229+
subnets_: list, block_number_: int
228230
) -> tuple[Balance, str]:
229231
# We do not include the root subnet in the emission calculation
230232
total_tao_emitted = sum(
231-
subnet.tao_in.tao for subnet in subnets if subnet.netuid != 0
233+
subnet.tao_in.tao for subnet in subnets_ if subnet.netuid != 0
232234
)
233-
emission_percentage = (total_tao_emitted / block_number) * 100
235+
emission_percentage = (total_tao_emitted / block_number_) * 100
234236
percentage_color = "dark_sea_green" if emission_percentage < 100 else "red"
235237
formatted_percentage = (
236238
f"[{percentage_color}]{emission_percentage:.2f}%[/{percentage_color}]"
237239
)
238240
if not verbose:
239-
percentage_string = f"τ {millify_tao(total_tao_emitted)}/{millify_tao(block_number)} ({formatted_percentage})"
241+
percentage_string = f"τ {millify_tao(total_tao_emitted)}/{millify_tao(block_number_)} ({formatted_percentage})"
240242
else:
241243
percentage_string = (
242-
f"τ {total_tao_emitted:.1f}/{block_number} ({formatted_percentage})"
244+
f"τ {total_tao_emitted:.1f}/{block_number_} ({formatted_percentage})"
243245
)
244246
return total_tao_emitted, percentage_string
245247

@@ -249,7 +251,7 @@ def define_table(
249251
total_netuids: int,
250252
tao_emission_percentage: str,
251253
):
252-
table = Table(
254+
defined_table = Table(
253255
title=f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]Subnets"
254256
f"\nNetwork: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{subtensor.network}\n\n",
255257
show_footer=True,
@@ -262,61 +264,61 @@ def define_table(
262264
pad_edge=True,
263265
)
264266

265-
table.add_column(
267+
defined_table.add_column(
266268
"[bold white]Netuid",
267269
style="grey89",
268270
justify="center",
269271
footer=str(total_netuids),
270272
)
271-
table.add_column("[bold white]Name", style="cyan", justify="left")
272-
table.add_column(
273+
defined_table.add_column("[bold white]Name", style="cyan", justify="left")
274+
defined_table.add_column(
273275
f"[bold white]Price \n({Balance.get_unit(0)}_in/{Balance.get_unit(1)}_in)",
274276
style="dark_sea_green2",
275277
justify="left",
276278
footer=f"τ {total_rate}",
277279
)
278-
table.add_column(
280+
defined_table.add_column(
279281
f"[bold white]Market Cap \n({Balance.get_unit(1)} * Price)",
280282
style="steel_blue3",
281283
justify="left",
282284
)
283-
table.add_column(
285+
defined_table.add_column(
284286
f"[bold white]Emission ({Balance.get_unit(0)})",
285287
style=COLOR_PALETTE["POOLS"]["EMISSION"],
286288
justify="left",
287289
footer=f"τ {total_emissions}",
288290
)
289-
table.add_column(
291+
defined_table.add_column(
290292
f"[bold white]P ({Balance.get_unit(0)}_in, {Balance.get_unit(1)}_in)",
291293
style=COLOR_PALETTE["STAKE"]["TAO"],
292294
justify="left",
293295
footer=f"{tao_emission_percentage}",
294296
)
295-
table.add_column(
297+
defined_table.add_column(
296298
f"[bold white]Stake ({Balance.get_unit(1)}_out)",
297299
style=COLOR_PALETTE["STAKE"]["STAKE_ALPHA"],
298300
justify="left",
299301
)
300-
table.add_column(
302+
defined_table.add_column(
301303
f"[bold white]Supply ({Balance.get_unit(1)})",
302304
style=COLOR_PALETTE["POOLS"]["ALPHA_IN"],
303305
justify="left",
304306
)
305307

306-
table.add_column(
308+
defined_table.add_column(
307309
"[bold white]Tempo (k/n)",
308310
style=COLOR_PALETTE["GENERAL"]["TEMPO"],
309311
justify="left",
310312
overflow="fold",
311313
)
312-
return table
314+
return defined_table
313315

314316
# Non-live mode
315-
def create_table(subnets, block_number):
317+
def _create_table(subnets_, block_number_):
316318
rows = []
317-
_, percentage_string = calculate_emission_stats(subnets, block_number)
319+
_, percentage_string = calculate_emission_stats(subnets_, block_number_)
318320

319-
for subnet in subnets:
321+
for subnet in subnets_:
320322
netuid = subnet.netuid
321323
symbol = f"{subnet.symbol}\u200e"
322324

@@ -363,7 +365,7 @@ def create_table(subnets, block_number):
363365
# Prepare cells
364366
netuid_cell = str(netuid)
365367
subnet_name_cell = (
366-
f"[{COLOR_PALETTE['GENERAL']['SYMBOL']}]{subnet.symbol if netuid != 0 else 'τ'}[/{COLOR_PALETTE['GENERAL']['SYMBOL']}]"
368+
f"[{COLOR_PALETTE.G.SYM}]{subnet.symbol if netuid != 0 else 'τ'}[/{COLOR_PALETTE.G.SYM}]"
367369
f" {get_subnet_name(subnet)}"
368370
)
369371
emission_cell = f"τ {emission_tao:,.4f}"
@@ -396,23 +398,76 @@ def create_table(subnets, block_number):
396398
)
397399

398400
total_emissions = round(
399-
sum(subnet.tao_in_emission.tao for subnet in subnets if subnet.netuid != 0),
401+
sum(
402+
subnet.tao_in_emission.tao for subnet in subnets_ if subnet.netuid != 0
403+
),
400404
4,
401405
)
402406
total_rate = round(
403-
sum(float(subnet.price.tao) for subnet in subnets if subnet.netuid != 0), 4
407+
sum(float(subnet.price.tao) for subnet in subnets_ if subnet.netuid != 0), 4
404408
)
405-
total_netuids = len(subnets)
406-
table = define_table(
409+
total_netuids = len(subnets_)
410+
defined_table = define_table(
407411
total_emissions, total_rate, total_netuids, percentage_string
408412
)
409413

410414
for row in rows:
411-
table.add_row(*row)
412-
return table
415+
defined_table.add_row(*row)
416+
return defined_table
417+
418+
def dict_table(subnets_, block_number_) -> dict:
419+
subnet_rows = {}
420+
total_tao_emitted, _ = calculate_emission_stats(subnets_, block_number_)
421+
total_emissions = 0.0
422+
total_rate = 0.0
423+
total_netuids = len(subnets_)
424+
emission_percentage = (total_tao_emitted / block_number_) * 100
425+
for subnet in subnets_:
426+
total_emissions += subnet.tao_in_emission.tao
427+
total_rate += subnet.price.tao
428+
netuid = subnet.netuid
429+
if netuid == 0:
430+
emission_tao = 0.0
431+
else:
432+
emission_tao = subnet.tao_in_emission.tao
433+
alpha_in_value = subnet.alpha_in.tao
434+
alpha_out_value = subnet.alpha_out.tao
435+
price_value = subnet.price.tao
436+
market_cap = (subnet.alpha_in.tao + subnet.alpha_out.tao) * subnet.price.tao
437+
tao_in = subnet.tao_in.tao if netuid != 0 else None
438+
alpha_in = alpha_in_value if netuid != 0 else None
439+
alpha_out = alpha_out_value if netuid != 0 else None
440+
supply = subnet.alpha_in.tao + subnet.alpha_out.tao
441+
subnet_name = get_subnet_name(subnet)
442+
tempo = {
443+
"blocks_since_last_step": (
444+
subnet.blocks_since_last_step if netuid != 0 else None
445+
),
446+
"sn_tempo": (subnet.tempo if netuid != 0 else None),
447+
}
448+
subnet_rows[netuid] = {
449+
"netuid": netuid,
450+
"subnet_name": subnet_name,
451+
"price": price_value,
452+
"market_cap": market_cap,
453+
"emission": emission_tao,
454+
"liquidity": {"tao_in": tao_in, "alpha_in": alpha_in},
455+
"alpha_out": alpha_out,
456+
"supply": supply,
457+
"tempo": tempo,
458+
}
459+
output = {
460+
"total_tao_emitted": total_tao_emitted,
461+
"total_emissions": total_emissions,
462+
"total_rate": total_rate,
463+
"total_netuids": total_netuids,
464+
"emission_percentage": emission_percentage,
465+
"subnets": subnet_rows,
466+
}
467+
return output
413468

414469
# Live mode
415-
def create_table_live(subnets, previous_data, block_number):
470+
def create_table_live(subnets_, previous_data_, block_number_):
416471
def format_cell(
417472
value, previous_value, unit="", unit_first=False, precision=4, millify=False
418473
):
@@ -516,9 +571,9 @@ def format_liquidity_cell(
516571

517572
rows = []
518573
current_data = {} # To store current values for comparison in the next update
519-
_, percentage_string = calculate_emission_stats(subnets, block_number)
574+
_, percentage_string = calculate_emission_stats(subnets_, block_number_)
520575

521-
for subnet in subnets:
576+
for subnet in subnets_:
522577
netuid = subnet.netuid
523578
symbol = f"{subnet.symbol}\u200e"
524579

@@ -541,7 +596,7 @@ def format_liquidity_cell(
541596
"supply": supply,
542597
"blocks_since_last_step": subnet.blocks_since_last_step,
543598
}
544-
prev = previous_data.get(netuid, {}) if previous_data else {}
599+
prev = previous_data_.get(netuid, {}) if previous_data_ else {}
545600

546601
# Prepare cells
547602
if netuid == 0:
@@ -652,17 +707,17 @@ def format_liquidity_cell(
652707
)
653708

654709
# Calculate totals
655-
total_netuids = len(subnets)
710+
total_netuids = len(subnets_)
656711
_total_emissions = sum(
657-
subnet.tao_in_emission.tao for subnet in subnets if subnet.netuid != 0
712+
subnet.tao_in_emission.tao for subnet in subnets_ if subnet.netuid != 0
658713
)
659714
total_emissions = (
660715
f"{millify_tao(_total_emissions)}"
661716
if not verbose
662717
else f"{_total_emissions:,.2f}"
663718
)
664719

665-
total_rate = sum(subnet.price.tao for subnet in subnets if subnet.netuid != 0)
720+
total_rate = sum(subnet.price.tao for subnet in subnets_ if subnet.netuid != 0)
666721
total_rate = (
667722
f"{millify_tao(total_rate)}" if not verbose else f"{total_rate:,.2f}"
668723
)
@@ -733,8 +788,11 @@ def format_liquidity_cell(
733788
else:
734789
# Non-live mode
735790
subnets, block_number = await fetch_subnet_data()
736-
table = create_table(subnets, block_number)
737-
console.print(table)
791+
if json_output:
792+
json_console.print(json.dumps(dict_table(subnets, block_number)))
793+
else:
794+
table = _create_table(subnets, block_number)
795+
console.print(table)
738796

739797
return
740798
# TODO: Temporarily returning till we update docs

0 commit comments

Comments
 (0)