bittensor-cli 8.2.0rc10__tar.gz → 8.2.0rc12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/PKG-INFO +1 -1
  2. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/__init__.py +1 -1
  3. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/cli.py +34 -16
  4. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/chain_data.py +12 -6
  5. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/stake/stake.py +6 -2
  6. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/subnets.py +142 -32
  7. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/sudo.py +13 -7
  8. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/wallets.py +63 -174
  9. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli.egg-info/PKG-INFO +1 -1
  10. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli.egg-info/requires.txt +1 -0
  11. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/README.md +0 -0
  12. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/doc_generation_helper.py +0 -0
  13. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/__init__.py +0 -0
  14. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/__init__.py +0 -0
  15. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/async_substrate_interface.py +0 -0
  16. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/balances.py +0 -0
  17. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/extrinsics/__init__.py +0 -0
  18. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/extrinsics/registration.py +0 -0
  19. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/extrinsics/root.py +0 -0
  20. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/extrinsics/transfer.py +0 -0
  21. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/minigraph.py +0 -0
  22. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/networking.py +0 -0
  23. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/subtensor_interface.py +0 -0
  24. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/templates/table.j2 +0 -0
  25. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/bittensor/utils.py +0 -0
  26. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/__init__.py +0 -0
  27. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/stake/__init__.py +0 -0
  28. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/stake/children_hotkeys.py +0 -0
  29. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli/src/commands/weights.py +0 -0
  30. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli.egg-info/SOURCES.txt +0 -0
  31. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli.egg-info/dependency_links.txt +0 -0
  32. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli.egg-info/entry_points.txt +0 -0
  33. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/bittensor_cli.egg-info/top_level.txt +0 -0
  34. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/setup.cfg +0 -0
  35. {bittensor-cli-8.2.0rc10 → bittensor-cli-8.2.0rc12}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bittensor-cli
3
- Version: 8.2.0rc10
3
+ Version: 8.2.0rc12
4
4
  Summary: Bittensor CLI
5
5
  Home-page: https://github.com/opentensor/btcli
6
6
  Author: bittensor.com
@@ -18,6 +18,6 @@
18
18
  from .cli import CLIManager
19
19
 
20
20
 
21
- __version__ = "8.2.0rc10"
21
+ __version__ = "8.2.0rc12"
22
22
 
23
23
  __all__ = ["CLIManager", "__version__"]
@@ -62,7 +62,7 @@ except ImportError:
62
62
  pass
63
63
 
64
64
 
65
- __version__ = "8.2.0rc10"
65
+ __version__ = "8.2.0rc12"
66
66
 
67
67
 
68
68
  _core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0)
@@ -645,12 +645,13 @@ class CLIManager:
645
645
  "balance", rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"]
646
646
  )(self.wallet_balance)
647
647
  self.wallet_app.command(
648
- "history", rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"]
648
+ "history",
649
+ rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
650
+ hidden=True,
649
651
  )(self.wallet_history)
650
652
  self.wallet_app.command(
651
653
  "overview",
652
654
  rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
653
- hidden=True,
654
655
  )(self.wallet_overview)
655
656
  self.wallet_app.command(
656
657
  "transfer", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
@@ -748,10 +749,13 @@ class CLIManager:
748
749
  )(self.subnets_register)
749
750
  self.subnets_app.command(
750
751
  "metagraph", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"], hidden=True
751
- )(self.subnets_show) #Aliased to `s show` for now
752
+ )(self.subnets_show) # Aliased to `s show` for now
752
753
  self.subnets_app.command(
753
754
  "show", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
754
755
  )(self.subnets_show)
756
+ self.subnets_app.command(
757
+ "price", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"], hidden=True
758
+ )(self.subnets_price)
755
759
 
756
760
  # weights commands
757
761
  self.weights_app.command(
@@ -1409,12 +1413,6 @@ class CLIManager:
1409
1413
  "Hotkeys names must be a comma-separated list, e.g., `--exclude-hotkeys hk1,hk2`.",
1410
1414
  )
1411
1415
 
1412
- # For Rao games
1413
- effective_network = get_effective_network(self.config, network)
1414
- if is_rao_network(effective_network):
1415
- print_error("This command is disabled on the 'rao' network.")
1416
- raise typer.Exit()
1417
-
1418
1416
  return self._run_command(
1419
1417
  wallets.overview(
1420
1418
  wallet,
@@ -1425,6 +1423,7 @@ class CLIManager:
1425
1423
  include_hotkeys,
1426
1424
  exclude_hotkeys,
1427
1425
  netuids_filter=netuids,
1426
+ verbose=verbose,
1428
1427
  )
1429
1428
  )
1430
1429
 
@@ -1600,6 +1599,8 @@ class CLIManager:
1600
1599
 
1601
1600
  [bold]Note[/bold]: The `inspect` command is for displaying information only and does not perform any transactions or state changes on the blockchain. It is intended to be used with Bittensor CLI and not as a standalone function in user code.
1602
1601
  """
1602
+ print_error("This command is disabled on the 'rao' network.")
1603
+ raise typer.Exit()
1603
1604
  self.verbosity_handler(quiet, verbose)
1604
1605
 
1605
1606
  if netuids:
@@ -1615,11 +1616,6 @@ class CLIManager:
1615
1616
  wallet = self.wallet_ask(
1616
1617
  wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
1617
1618
  )
1618
- # For Rao games
1619
- effective_network = get_effective_network(self.config, network)
1620
- if is_rao_network(effective_network):
1621
- print_error("This command is disabled on the 'rao' network.")
1622
- raise typer.Exit()
1623
1619
 
1624
1620
  self.initialize_chain(network)
1625
1621
  return self._run_command(
@@ -2791,7 +2787,7 @@ class CLIManager:
2791
2787
  [blue bold]Note[/blue bold]: This command is for users who wish to reallocate their stake or withdraw them from the network. It allows for flexible management of TAO stake across different neurons (hotkeys) on the network.
2792
2788
  """
2793
2789
  self.verbosity_handler(quiet, verbose)
2794
- # TODO: Coldkey related unstakes need to be updated. Patching for now.
2790
+ # TODO: Coldkey related unstakes need to be updated. Patching for now.
2795
2791
  unstake_all_alpha = False
2796
2792
  unstake_all = False
2797
2793
 
@@ -3562,6 +3558,28 @@ class CLIManager:
3562
3558
  )
3563
3559
  )
3564
3560
 
3561
+ def subnets_price(
3562
+ self,
3563
+ network: Optional[list[str]] = Options.network,
3564
+ netuid: int = Options.netuid,
3565
+ interval_hours: int = typer.Option(
3566
+ 24,
3567
+ "--interval-hours",
3568
+ "--interval",
3569
+ help="The number of hours to show the historical price for.",
3570
+ ),
3571
+ ):
3572
+ """
3573
+ Shows the historical price of a subnet for the past 24 hours.
3574
+
3575
+ EXAMPLE
3576
+
3577
+ [green]$[/green] btcli subnets price --netuid 1
3578
+ """
3579
+ return self._run_command(
3580
+ subnets.price(self.initialize_chain(network), netuid, interval_hours)
3581
+ )
3582
+
3565
3583
  def subnets_show(
3566
3584
  self,
3567
3585
  network: Optional[list[str]] = Options.network,
@@ -97,11 +97,13 @@ def decode_hex_identity(info_dictionary):
97
97
  return decoded_info
98
98
 
99
99
 
100
- def process_stake_data(stake_data):
100
+ def process_stake_data(stake_data, netuid):
101
101
  decoded_stake_data = {}
102
102
  for account_id_bytes, stake_ in stake_data:
103
103
  account_id = decode_account_id(account_id_bytes)
104
- decoded_stake_data.update({account_id: Balance.from_rao(stake_)})
104
+ decoded_stake_data.update(
105
+ {account_id: Balance.from_rao(stake_).set_unit(netuid)}
106
+ )
105
107
  return decoded_stake_data
106
108
 
107
109
 
@@ -371,7 +373,7 @@ class NeuronInfo:
371
373
  @classmethod
372
374
  def from_vec_u8(cls, vec_u8: bytes) -> "NeuronInfo":
373
375
  n = bt_decode.NeuronInfo.decode(vec_u8)
374
- stake_dict = process_stake_data(n.stake)
376
+ stake_dict = process_stake_data(n.stake, n.netuid)
375
377
  total_stake = sum(stake_dict.values()) if stake_dict else Balance(0)
376
378
  axon_info = n.axon_info
377
379
  coldkey = decode_account_id(n.coldkey)
@@ -491,8 +493,12 @@ class NeuronInfoLite:
491
493
  prometheus_info = item.prometheus_info
492
494
  pruning_score = item.pruning_score
493
495
  rank = item.rank
494
- stake_dict = process_stake_data(item.stake)
495
- stake = sum(stake_dict.values()) if stake_dict else Balance(0)
496
+ stake_dict = process_stake_data(item.stake, item.netuid)
497
+ stake = (
498
+ sum(stake_dict.values())
499
+ if stake_dict
500
+ else Balance(0).set_unit(item.netuid)
501
+ )
496
502
  trust = item.trust
497
503
  uid = item.uid
498
504
  validator_permit = item.validator_permit
@@ -899,7 +905,7 @@ class DynamicInfo:
899
905
  def from_vec_u8(cls, vec_u8: list[int]) -> Optional["DynamicInfo"]:
900
906
  if len(vec_u8) == 0:
901
907
  return None
902
- decoded = from_scale_encoding(vec_u8, ChainDataType.DynamicInfo, is_option=True)
908
+ decoded = from_scale_encoding(vec_u8, ChainDataType.DynamicInfo)
903
909
  if decoded is None:
904
910
  return None
905
911
  return DynamicInfo.fix_decoded_values(decoded)
@@ -10,11 +10,11 @@ from rich.prompt import Confirm, FloatPrompt, Prompt
10
10
  from rich.table import Table
11
11
  from rich import box
12
12
  from rich.progress import Progress, BarColumn, TextColumn
13
- from rich.console import Console, Group
13
+ from rich.console import Group
14
14
  from rich.live import Live
15
15
  from substrateinterface.exceptions import SubstrateRequestException
16
16
 
17
- from bittensor_cli.src import COLOR_PALETTE, SUBNETS
17
+ from bittensor_cli.src import COLOR_PALETTE
18
18
  from bittensor_cli.src.bittensor.balances import Balance
19
19
  from bittensor_cli.src.bittensor.chain_data import StakeInfo
20
20
  from bittensor_cli.src.bittensor.utils import (
@@ -2424,6 +2424,10 @@ async def stake_list(
2424
2424
  hotkeys_to_substakes[hotkey] = []
2425
2425
  hotkeys_to_substakes[hotkey].append(substake)
2426
2426
 
2427
+ if not hotkeys_to_substakes:
2428
+ print_error(f"No stakes found for coldkey ss58: ({coldkey_address})")
2429
+ raise typer.Exit()
2430
+
2427
2431
  if live:
2428
2432
  # Select one hokkey for live monitoring
2429
2433
  if len(hotkeys_to_substakes) > 1:
@@ -3,18 +3,17 @@ import json
3
3
  import sqlite3
4
4
  from typing import TYPE_CHECKING, Optional, cast
5
5
  import typer
6
+ import plotille
6
7
 
7
8
  from bittensor_wallet import Wallet
8
9
  from bittensor_wallet.errors import KeyFileError
9
10
  from rich.prompt import Confirm, Prompt
10
- from rich.console import Console, Group
11
- from rich.spinner import Spinner
12
- from rich.text import Text
11
+ from rich.console import Group
13
12
  from rich.progress import Progress, BarColumn, TextColumn
14
13
  from rich.table import Column, Table
15
14
  from rich import box
16
15
 
17
- from bittensor_cli.src import COLOR_PALETTE, SUBNETS
16
+ from bittensor_cli.src import COLOR_PALETTE
18
17
  from bittensor_cli.src.bittensor.balances import Balance
19
18
  from bittensor_cli.src.bittensor.chain_data import SubnetState
20
19
  from bittensor_cli.src.bittensor.extrinsics.registration import (
@@ -26,7 +25,6 @@ from rich.live import Live
26
25
  from bittensor_cli.src.bittensor.minigraph import MiniGraph
27
26
  from bittensor_cli.src.commands.wallets import set_id, get_id
28
27
  from bittensor_cli.src.bittensor.utils import (
29
- RAO_PER_TAO,
30
28
  console,
31
29
  create_table,
32
30
  err_console,
@@ -228,7 +226,9 @@ async def subnets_list(
228
226
  if not verbose:
229
227
  percentage_string = f"τ {millify_tao(total_tao_emitted)}/{millify_tao(block_number)} ({formatted_percentage})"
230
228
  else:
231
- percentage_string = f"τ {total_tao_emitted:.1f}/{block_number} ({formatted_percentage})"
229
+ percentage_string = (
230
+ f"τ {total_tao_emitted:.1f}/{block_number} ({formatted_percentage})"
231
+ )
232
232
  return total_tao_emitted, percentage_string
233
233
 
234
234
  def define_table(
@@ -323,9 +323,7 @@ async def subnets_list(
323
323
  if not verbose
324
324
  else f"{subnet.alpha_out.tao:,.4f}"
325
325
  )
326
- price_value = (
327
- f"{subnet.price.tao:,.4f}"
328
- )
326
+ price_value = f"{subnet.price.tao:,.4f}"
329
327
 
330
328
  # Market Cap
331
329
  market_cap = (subnet.alpha_in.tao + subnet.alpha_out.tao) * subnet.price.tao
@@ -343,8 +341,8 @@ async def subnets_list(
343
341
  if netuid != 0
344
342
  else "-"
345
343
  )
346
-
347
344
  alpha_in_cell = f"{alpha_in_value} {symbol}" if netuid != 0 else "-"
345
+ liquidity_cell = f"{tao_in_cell}, {alpha_in_cell}"
348
346
 
349
347
  # Supply
350
348
  supply = subnet.alpha_in.tao + subnet.alpha_out.tao
@@ -358,7 +356,6 @@ async def subnets_list(
358
356
  )
359
357
  emission_cell = f"τ {emission_tao:,.4f}"
360
358
  price_cell = f"{price_value} τ/{symbol}"
361
- liquidity_cell = f"{tao_in_cell}, {alpha_in_cell}"
362
359
  alpha_out_cell = (
363
360
  f"{alpha_out_value} {symbol}"
364
361
  if netuid != 0
@@ -1053,9 +1050,7 @@ async def show(
1053
1050
  print_error(f"Subnet {netuid_} does not exist")
1054
1051
  raise typer.Exit()
1055
1052
  elif len(subnet_state.hotkeys) == 0:
1056
- print_error(
1057
- f"Subnet {netuid_} is currently empty with 0 UIDs registered."
1058
- )
1053
+ print_error(f"Subnet {netuid_} is currently empty with 0 UIDs registered.")
1059
1054
  raise typer.Exit()
1060
1055
 
1061
1056
  # Define table properties
@@ -1156,7 +1151,7 @@ async def show(
1156
1151
  ):
1157
1152
  if uid_identity == "~":
1158
1153
  uid_identity = (
1159
- f"[dark_sea_green3](*Owner controlled)[/dark_sea_green3]"
1154
+ "[dark_sea_green3](*Owner controlled)[/dark_sea_green3]"
1160
1155
  )
1161
1156
  else:
1162
1157
  uid_identity = (
@@ -1174,7 +1169,9 @@ async def show(
1174
1169
  f"{subnet_state.alpha_stake[idx].tao:.4f} {subnet_info.symbol}"
1175
1170
  if verbose
1176
1171
  else f"{millify_tao(subnet_state.alpha_stake[idx])} {subnet_info.symbol}", # Alpha Stake
1177
- f"τ {tao_stake.tao:.4f}" if verbose else f"τ {millify_tao(tao_stake)}", # Tao Stake
1172
+ f"τ {tao_stake.tao:.4f}"
1173
+ if verbose
1174
+ else f"τ {millify_tao(tao_stake)}", # Tao Stake
1178
1175
  # str(subnet_state.dividends[idx]),
1179
1176
  f"{Balance.from_tao(hotkey_block_emission).set_unit(netuid_).tao:.5f}", # Dividends
1180
1177
  f"{subnet_state.incentives[idx]:.4f}", # Incentive
@@ -1300,22 +1297,22 @@ async def show(
1300
1297
  # f"\n Stake: [{COLOR_PALETTE['STAKE']['STAKE_ALPHA']}]{subnet_info.alpha_out.tao:,.5f} {subnet_info.symbol}[/{COLOR_PALETTE['STAKE']['STAKE_ALPHA']}]"
1301
1298
  f"\n Tempo: [{COLOR_PALETTE['STAKE']['STAKE_ALPHA']}]{subnet_info.blocks_since_last_step}/{subnet_info.tempo}[/{COLOR_PALETTE['STAKE']['STAKE_ALPHA']}]"
1302
1299
  )
1303
- # console.print(
1304
- # """
1305
- # Description:
1306
- # The table displays the subnet participants and their metrics.
1307
- # The columns are as follows:
1308
- # - UID: The hotkey index in the subnet.
1309
- # - TAO: The sum of all TAO balances for this hotkey accross all subnets.
1310
- # - Stake: The stake balance of this hotkey on this subnet.
1311
- # - Weight: The stake-weight of this hotkey on this subnet. Computed as an average of the normalized TAO and Stake columns of this subnet.
1312
- # - Dividends: Validating dividends earned by the hotkey.
1313
- # - Incentives: Mining incentives earned by the hotkey (always zero in the RAO demo.)
1314
- # - Emission: The emission accrued to this hokey on this subnet every block (in staking units).
1315
- # - Hotkey: The hotkey ss58 address.
1316
- # - Coldkey: The coldkey ss58 address.
1317
- # """
1318
- # )
1300
+ # console.print(
1301
+ # """
1302
+ # Description:
1303
+ # The table displays the subnet participants and their metrics.
1304
+ # The columns are as follows:
1305
+ # - UID: The hotkey index in the subnet.
1306
+ # - TAO: The sum of all TAO balances for this hotkey accross all subnets.
1307
+ # - Stake: The stake balance of this hotkey on this subnet.
1308
+ # - Weight: The stake-weight of this hotkey on this subnet. Computed as an average of the normalized TAO and Stake columns of this subnet.
1309
+ # - Dividends: Validating dividends earned by the hotkey.
1310
+ # - Incentives: Mining incentives earned by the hotkey (always zero in the RAO demo.)
1311
+ # - Emission: The emission accrued to this hokey on this subnet every block (in staking units).
1312
+ # - Hotkey: The hotkey ss58 address.
1313
+ # - Coldkey: The coldkey ss58 address.
1314
+ # """
1315
+ # )
1319
1316
 
1320
1317
  if delegate_selection:
1321
1318
  while True:
@@ -2054,3 +2051,116 @@ async def metagraph_cmd(
2054
2051
  table.add_row(*row)
2055
2052
 
2056
2053
  console.print(table)
2054
+
2055
+
2056
+ async def price(
2057
+ subtensor: "SubtensorInterface",
2058
+ netuid: int,
2059
+ interval_hours: int = 24,
2060
+ ):
2061
+ """Plot historical subnet price data in the CLI."""
2062
+
2063
+ blocks_per_hour = int(3600 / 12) # ~300 blocks per hour
2064
+ total_blocks = blocks_per_hour * interval_hours
2065
+
2066
+ with console.status(":chart_increasing: Fetching historical price data..."):
2067
+ current_block_hash = await subtensor.substrate.get_chain_head()
2068
+ current_block = await subtensor.substrate.get_block_number(current_block_hash)
2069
+
2070
+ # Block range
2071
+ step = 300
2072
+ start_block = max(0, current_block - total_blocks)
2073
+ block_numbers = range(start_block, current_block + 1, step)
2074
+
2075
+ # Fetch all block hashes
2076
+ block_hash_cors = [
2077
+ subtensor.substrate.get_block_hash(bn) for bn in block_numbers
2078
+ ]
2079
+ block_hashes = await asyncio.gather(*block_hash_cors)
2080
+
2081
+ # Fetch subnet data for each block
2082
+ subnet_info_cors = [
2083
+ subtensor.get_subnet_dynamic_info(netuid, bh) for bh in block_hashes
2084
+ ]
2085
+ subnet_infos = await asyncio.gather(*subnet_info_cors)
2086
+
2087
+ prices = []
2088
+ for subnet_info in subnet_infos:
2089
+ prices.append(subnet_info.price.tao)
2090
+
2091
+ if not prices:
2092
+ err_console.print(f"[red]No price data found for subnet {netuid}[/red]")
2093
+ return
2094
+
2095
+ fig = plotille.Figure()
2096
+ fig.width = 60
2097
+ fig.height = 20
2098
+ fig.color_mode = "rgb"
2099
+ fig.background = None
2100
+
2101
+ block_numbers = list(range(current_block - total_blocks, current_block + 1, step))
2102
+
2103
+ def color_label(text):
2104
+ return plotille.color(text, fg=(186, 233, 143), mode="rgb") # Green
2105
+
2106
+ fig.x_label = color_label("Block")
2107
+ fig.y_label = color_label(f"Price ({Balance.get_unit(netuid)})")
2108
+
2109
+ fig.set_x_limits(min_=min(block_numbers), max_=max(block_numbers))
2110
+ fig.set_y_limits(min_=min(prices) * 0.95, max_=max(prices) * 1.05)
2111
+
2112
+ fig.plot(
2113
+ block_numbers,
2114
+ prices,
2115
+ label=f"Subnet {netuid} Price",
2116
+ interp="linear",
2117
+ lc="bae98f", # Green hex
2118
+ )
2119
+
2120
+ subnet = subnet_infos[-1]
2121
+ console.print(
2122
+ f"\n[{COLOR_PALETTE['GENERAL']['SYMBOL']}]Subnet {netuid} - {subnet.symbol} [cyan]{get_subnet_name(subnet)}"
2123
+ )
2124
+ console.print(
2125
+ f"Current: [blue]{prices[-1]:.6f}{Balance.get_unit(netuid)}"
2126
+ if netuid != 0
2127
+ else f"Current: [blue]{Balance.get_unit(netuid)} {prices[-1]:.6f}"
2128
+ )
2129
+ console.print(
2130
+ f"{interval_hours}h High: [dark_sea_green3]{max(prices):.6f}{Balance.get_unit(netuid)}"
2131
+ if netuid != 0
2132
+ else f"{interval_hours}h High: [dark_sea_green3]{Balance.get_unit(netuid)} {max(prices):.6f}"
2133
+ )
2134
+ console.print(
2135
+ f"{interval_hours}h Low: [red]{min(prices):.6f}{Balance.get_unit(netuid)}"
2136
+ if netuid != 0
2137
+ else f"{interval_hours}h Low: [red]{Balance.get_unit(netuid)} {min(prices):.6f}"
2138
+ )
2139
+
2140
+ change_color = "dark_sea_green3" if prices[-1] > prices[0] else "red"
2141
+ console.print(
2142
+ f"{interval_hours}h Change: "
2143
+ f"[{change_color}]{((prices[-1] - prices[0]) / prices[0] * 100):.2f}%\n"
2144
+ )
2145
+ print(fig.show())
2146
+ console.print("\nLatest stats:")
2147
+ console.print(
2148
+ f"Supply: [{COLOR_PALETTE['POOLS']['ALPHA_IN']}]{subnet.alpha_in.tao + subnet.alpha_out.tao:,.2f} {Balance.get_unit(netuid)}"
2149
+ if netuid != 0
2150
+ else f"Supply: [{COLOR_PALETTE['POOLS']['ALPHA_IN']}]{Balance.get_unit(netuid)} {subnet.alpha_in.tao + subnet.alpha_out.tao:,.2f}"
2151
+ )
2152
+ console.print(
2153
+ f"Market Cap: [steel_blue3]{subnet.price.tao * (subnet.alpha_in.tao + subnet.alpha_out.tao):,.2f} {Balance.get_unit(netuid)} / 21M"
2154
+ if netuid != 0
2155
+ else f"Market Cap: [steel_blue3]{Balance.get_unit(netuid)} {subnet.price.tao * (subnet.alpha_in.tao + subnet.alpha_out.tao):,.2f} / 21M"
2156
+ )
2157
+ console.print(
2158
+ f"Emission: [{COLOR_PALETTE['POOLS']['EMISSION']}]{subnet.emission.tao:,.2f} {Balance.get_unit(netuid)}"
2159
+ if netuid != 0
2160
+ else f"Emission: [{COLOR_PALETTE['POOLS']['EMISSION']}]{Balance.get_unit(netuid)} {subnet.emission.tao:,.2f}"
2161
+ )
2162
+ console.print(
2163
+ f"Stake: [{COLOR_PALETTE['STAKE']['TAO']}]{subnet.alpha_out.tao:,.2f} {Balance.get_unit(netuid)}"
2164
+ if netuid != 0
2165
+ else f"Stake: [{COLOR_PALETTE['STAKE']['TAO']}]{Balance.get_unit(netuid)} {subnet.alpha_out.tao:,.2f}"
2166
+ )
@@ -9,7 +9,7 @@ from rich.table import Column, Table
9
9
  from rich.prompt import Confirm
10
10
  from scalecodec import GenericCall
11
11
 
12
- from bittensor_cli.src import HYPERPARAMS, DelegatesDetails, COLOR_PALETTE, SUBNETS
12
+ from bittensor_cli.src import HYPERPARAMS, DelegatesDetails, COLOR_PALETTE
13
13
  from bittensor_cli.src.bittensor.chain_data import decode_account_id
14
14
  from bittensor_cli.src.bittensor.utils import (
15
15
  console,
@@ -445,7 +445,9 @@ async def set_take_extrinsic(
445
445
  if not success:
446
446
  err_console.print(err)
447
447
  else:
448
- console.print(":white_heavy_check_mark: [dark_sea_green_3]Finalized[/dark_sea_green_3]")
448
+ console.print(
449
+ ":white_heavy_check_mark: [dark_sea_green_3]Finalized[/dark_sea_green_3]"
450
+ )
449
451
  return success
450
452
 
451
453
 
@@ -502,9 +504,9 @@ async def get_hyperparameters(subtensor: "SubtensorInterface", netuid: int):
502
504
  raise typer.Exit()
503
505
 
504
506
  table = Table(
505
- Column("[white]HYPERPARAMETER", style=COLOR_PALETTE['SUDO']['HYPERPARAMETER']),
506
- Column("[white]VALUE", style=COLOR_PALETTE['SUDO']['VALUE']),
507
- Column("[white]NORMALIZED", style=COLOR_PALETTE['SUDO']['NORMALIZED']),
507
+ Column("[white]HYPERPARAMETER", style=COLOR_PALETTE["SUDO"]["HYPERPARAMETER"]),
508
+ Column("[white]VALUE", style=COLOR_PALETTE["SUDO"]["VALUE"]),
509
+ Column("[white]NORMALIZED", style=COLOR_PALETTE["SUDO"]["NORMALIZED"]),
508
510
  title=f"[{COLOR_PALETTE['GENERAL']['HEADER']}]\nSubnet Hyperparameters\n NETUID: "
509
511
  f"[{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid}"
510
512
  f"{f' ({subnet_info.subnet_name})' if subnet_info.subnet_name is not None else ''}"
@@ -716,10 +718,14 @@ async def set_take(
716
718
  return False
717
719
  else:
718
720
  new_take = await get_current_take(subtensor, wallet)
719
- console.print(f"New take is [{COLOR_PALETTE['POOLS']['RATE']}]{new_take * 100.:.2f}%")
721
+ console.print(
722
+ f"New take is [{COLOR_PALETTE['POOLS']['RATE']}]{new_take * 100.:.2f}%"
723
+ )
720
724
  return True
721
725
 
722
- console.print(f"Setting take on [{COLOR_PALETTE['GENERAL']['LINKS']}]network: {subtensor.network}")
726
+ console.print(
727
+ f"Setting take on [{COLOR_PALETTE['GENERAL']['LINKS']}]network: {subtensor.network}"
728
+ )
723
729
 
724
730
  try:
725
731
  wallet.unlock_hotkey()
@@ -1,12 +1,7 @@
1
1
  import asyncio
2
- import binascii
3
2
  import itertools
4
3
  import os
5
- import sys
6
4
  from collections import defaultdict
7
- from concurrent.futures import ProcessPoolExecutor
8
- from functools import partial
9
- from sys import getsizeof
10
5
  from typing import Any, Collection, Generator, Optional
11
6
 
12
7
  import aiohttp
@@ -16,29 +11,23 @@ from bittensor_wallet.keyfile import Keyfile
16
11
  from fuzzywuzzy import fuzz
17
12
  from rich import box
18
13
  from rich.align import Align
19
- from rich.prompt import Confirm, Prompt
20
14
  from rich.table import Column, Table
21
15
  from rich.tree import Tree
22
16
  from rich.padding import Padding
23
- from rich.prompt import IntPrompt
24
17
  from scalecodec import ScaleBytes
25
- import scalecodec
26
18
  import typer
27
19
 
28
- from bittensor_cli.src import TYPE_REGISTRY, COLOR_PALETTE
20
+ from bittensor_cli.src import COLOR_PALETTE
29
21
  from bittensor_cli.src.bittensor import utils
30
22
  from bittensor_cli.src.bittensor.balances import Balance
31
23
  from bittensor_cli.src.bittensor.chain_data import (
32
24
  DelegateInfo,
33
25
  NeuronInfoLite,
34
26
  StakeInfo,
35
- custom_rpc_type_registry,
36
- decode_account_id,
37
27
  )
38
28
  from bittensor_cli.src.bittensor.extrinsics.registration import (
39
29
  run_faucet_extrinsic,
40
30
  swap_hotkey_extrinsic,
41
- is_hotkey_registered,
42
31
  )
43
32
  from bittensor_cli.src.bittensor.extrinsics.transfer import transfer_extrinsic
44
33
  from bittensor_cli.src.bittensor.networking import int_to_ip
@@ -47,7 +36,6 @@ from bittensor_cli.src.bittensor.utils import (
47
36
  RAO_PER_TAO,
48
37
  console,
49
38
  convert_blocks_to_time,
50
- decode_scale_bytes,
51
39
  err_console,
52
40
  print_error,
53
41
  print_verbose,
@@ -55,10 +43,18 @@ from bittensor_cli.src.bittensor.utils import (
55
43
  get_hotkey_wallets_for_wallet,
56
44
  is_valid_ss58_address,
57
45
  validate_coldkey_presence,
58
- retry_prompt,
46
+ get_subnet_name,
47
+ millify_tao,
59
48
  )
60
49
 
61
50
 
51
+ class WalletLike:
52
+ def __init__(self, name=None, hotkey_ss58=None, hotkey_str=None):
53
+ self.name = name
54
+ self.hotkey_ss58 = hotkey_ss58
55
+ self.hotkey_str = hotkey_str
56
+
57
+
62
58
  async def regen_coldkey(
63
59
  wallet: Wallet,
64
60
  mnemonic: Optional[str],
@@ -603,17 +599,19 @@ async def overview(
603
599
  include_hotkeys: Optional[list[str]] = None,
604
600
  exclude_hotkeys: Optional[list[str]] = None,
605
601
  netuids_filter: Optional[list[int]] = None,
602
+ verbose: bool = False,
606
603
  ):
607
604
  """Prints an overview for the wallet's coldkey."""
608
605
 
609
606
  total_balance = Balance(0)
610
607
 
611
608
  # We are printing for every coldkey.
612
- print_verbose("Fetching total balance for coldkey/s")
613
609
  block_hash = await subtensor.substrate.get_chain_head()
614
610
  all_hotkeys, total_balance = await _get_total_balance(
615
611
  total_balance, subtensor, wallet, all_wallets, block_hash=block_hash
616
612
  )
613
+ _dynamic_info = await subtensor.get_all_subnet_dynamic_info()
614
+ dynamic_info = {info.netuid: info for info in _dynamic_info}
617
615
 
618
616
  with console.status(
619
617
  f":satellite: Synchronizing with chain [white]{subtensor.network}[/white]",
@@ -621,9 +619,6 @@ async def overview(
621
619
  ) as status:
622
620
  # We are printing for a select number of hotkeys from all_hotkeys.
623
621
  if include_hotkeys or exclude_hotkeys:
624
- print_verbose(
625
- "Fetching for select hotkeys passed in 'include_hotkeys'", status
626
- )
627
622
  all_hotkeys = _get_hotkeys(include_hotkeys, exclude_hotkeys, all_hotkeys)
628
623
 
629
624
  # Check we have keys to display.
@@ -633,17 +628,14 @@ async def overview(
633
628
 
634
629
  # Pull neuron info for all keys.
635
630
  neurons: dict[str, list[NeuronInfoLite]] = {}
636
- print_verbose("Fetching subnet netuids", status)
637
631
  block, all_netuids = await asyncio.gather(
638
632
  subtensor.substrate.get_block_number(None),
639
633
  subtensor.get_all_subnet_netuids(),
640
634
  )
641
635
 
642
- print_verbose("Filtering netuids by registered hotkeys", status)
643
636
  netuids = await subtensor.filter_netuids_by_registered_hotkeys(
644
637
  all_netuids, netuids_filter, all_hotkeys, reuse_block=True
645
638
  )
646
- # bittensor.logging.debug(f"Netuids to check: {netuids}")
647
639
 
648
640
  for netuid in netuids:
649
641
  neurons[str(netuid)] = []
@@ -664,104 +656,17 @@ async def overview(
664
656
  )
665
657
  all_hotkeys, _ = validate_coldkey_presence(all_hotkeys)
666
658
 
667
- print_verbose("Fetching key addresses", status)
668
659
  all_hotkey_addresses, hotkey_coldkey_to_hotkey_wallet = _get_key_address(
669
660
  all_hotkeys
670
661
  )
671
662
 
672
- print_verbose("Pulling and processing neuron information for all keys", status)
673
663
  results = await _get_neurons_for_netuids(
674
664
  subtensor, netuids, all_hotkey_addresses
675
665
  )
676
666
  neurons = _process_neuron_results(results, neurons, netuids)
677
- total_coldkey_stake_from_metagraph = await _calculate_total_coldkey_stake(
678
- neurons
679
- )
680
-
681
- alerts_table = Table(show_header=True, header_style="bold magenta")
682
- alerts_table.add_column("🥩 alert!")
683
-
684
- coldkeys_to_check = []
685
- ck_stakes = await subtensor.get_total_stake_for_coldkey(
686
- *(
687
- coldkey_wallet.coldkeypub.ss58_address
688
- for coldkey_wallet in all_coldkey_wallets
689
- if coldkey_wallet.coldkeypub
690
- ),
691
- block_hash=block_hash,
692
- )
693
- for coldkey_wallet in all_coldkey_wallets:
694
- if coldkey_wallet.coldkeypub:
695
- # Check if we have any stake with hotkeys that are not registered.
696
- difference = (
697
- ck_stakes[coldkey_wallet.coldkeypub.ss58_address]
698
- - total_coldkey_stake_from_metagraph[
699
- coldkey_wallet.coldkeypub.ss58_address
700
- ]
701
- )
702
- if difference == 0:
703
- continue # We have all our stake registered.
704
-
705
- coldkeys_to_check.append(coldkey_wallet)
706
- alerts_table.add_row(
707
- "Found [light_goldenrod2]{}[/light_goldenrod2] stake with coldkey [bright_magenta]{}[/bright_magenta] that is not registered.".format(
708
- abs(difference), coldkey_wallet.coldkeypub.ss58_address
709
- )
710
- )
711
-
712
- if coldkeys_to_check:
713
- # We have some stake that is not with a registered hotkey.
714
- if "-1" not in neurons:
715
- neurons["-1"] = []
716
-
717
- print_verbose("Checking coldkeys for de-registered stake", status)
718
- results = await asyncio.gather(
719
- *[
720
- _get_de_registered_stake_for_coldkey_wallet(
721
- subtensor, all_hotkey_addresses, coldkey_wallet
722
- )
723
- for coldkey_wallet in coldkeys_to_check
724
- ]
725
- )
726
-
727
- for result in results:
728
- coldkey_wallet, de_registered_stake, err_msg = result
729
- if err_msg is not None:
730
- err_console.print(err_msg)
731
-
732
- if len(de_registered_stake) == 0:
733
- continue # We have no de-registered stake with this coldkey.
734
-
735
- de_registered_neurons = []
736
- for hotkey_addr, our_stake in de_registered_stake:
737
- # Make a neuron info lite for this hotkey and coldkey.
738
- de_registered_neuron = NeuronInfoLite.get_null_neuron()
739
- de_registered_neuron.hotkey = hotkey_addr
740
- de_registered_neuron.coldkey = coldkey_wallet.coldkeypub.ss58_address
741
- de_registered_neuron.total_stake = Balance(our_stake)
742
- de_registered_neurons.append(de_registered_neuron)
743
-
744
- # Add this hotkey to the wallets dict
745
- wallet_ = Wallet(name=wallet)
746
- wallet_.hotkey_ss58 = hotkey_addr
747
- wallet.hotkey_str = hotkey_addr[:5] # Max length of 5 characters
748
- # Indicates a hotkey not on local machine but exists in stake_info obj on-chain
749
- if hotkey_coldkey_to_hotkey_wallet.get(hotkey_addr) is None:
750
- hotkey_coldkey_to_hotkey_wallet[hotkey_addr] = {}
751
- hotkey_coldkey_to_hotkey_wallet[hotkey_addr][
752
- coldkey_wallet.coldkeypub.ss58_address
753
- ] = wallet_
754
-
755
- # Add neurons to overview.
756
- neurons["-1"].extend(de_registered_neurons)
757
-
758
667
  # Setup outer table.
759
668
  grid = Table.grid(pad_edge=True)
760
669
 
761
- # If there are any alerts, add them to the grid
762
- if len(alerts_table.rows) > 0:
763
- grid.add_row(alerts_table)
764
-
765
670
  # Add title
766
671
  if not all_wallets:
767
672
  title = "[underline dark_orange]Wallet[/underline dark_orange]\n"
@@ -780,9 +685,6 @@ async def overview(
780
685
  )
781
686
  )
782
687
  # Generate rows per netuid
783
- hotkeys_seen = set()
784
- total_neurons = 0
785
- total_stake = 0.0
786
688
  tempos = await asyncio.gather(
787
689
  *[
788
690
  subtensor.get_hyperparameter("Tempo", netuid, block_hash)
@@ -790,7 +692,6 @@ async def overview(
790
692
  ]
791
693
  )
792
694
  for netuid, subnet_tempo in zip(netuids, tempos):
793
- last_subnet = netuid == netuids[-1]
794
695
  table_data = []
795
696
  total_rank = 0.0
796
697
  total_trust = 0.0
@@ -799,6 +700,8 @@ async def overview(
799
700
  total_incentive = 0.0
800
701
  total_dividends = 0.0
801
702
  total_emission = 0
703
+ total_stake = 0
704
+ total_neurons = 0
802
705
 
803
706
  for nn in neurons[str(netuid)]:
804
707
  hotwallet = hotkey_coldkey_to_hotkey_wallet.get(nn.hotkey, {}).get(
@@ -807,8 +710,7 @@ async def overview(
807
710
  if not hotwallet:
808
711
  # Indicates a mismatch between what the chain says the coldkey
809
712
  # is for this hotkey and the local wallet coldkey-hotkey pair
810
- hotwallet = Wallet(name=nn.coldkey[:7])
811
- hotwallet.hotkey_str = nn.hotkey[:7]
713
+ hotwallet = WalletLike(name=nn.coldkey[:7], hotkey_str=nn.hotkey[:7])
812
714
 
813
715
  nn: NeuronInfoLite
814
716
  uid = nn.uid
@@ -820,7 +722,7 @@ async def overview(
820
722
  validator_trust = nn.validator_trust
821
723
  incentive = nn.incentive
822
724
  dividends = nn.dividends
823
- emission = int(nn.emission / (subnet_tempo + 1) * 1e9)
725
+ emission = int(nn.emission / (subnet_tempo + 1) * 1e9) # Per block
824
726
  last_update = int(block - nn.last_update)
825
727
  validator_permit = nn.validator_permit
826
728
  row = [
@@ -828,14 +730,14 @@ async def overview(
828
730
  hotwallet.hotkey_str,
829
731
  str(uid),
830
732
  str(active),
831
- "{:.5f}".format(stake),
832
- "{:.5f}".format(rank),
833
- "{:.5f}".format(trust),
834
- "{:.5f}".format(consensus),
835
- "{:.5f}".format(incentive),
836
- "{:.5f}".format(dividends),
837
- "{:_}".format(emission),
838
- "{:.5f}".format(validator_trust),
733
+ f"{stake:.4f}" if verbose else millify_tao(stake),
734
+ f"{rank:.4f}" if verbose else millify_tao(rank),
735
+ f"{trust:.4f}" if verbose else millify_tao(trust),
736
+ f"{consensus:.4f}" if verbose else millify_tao(consensus),
737
+ f"{incentive:.4f}" if verbose else millify_tao(incentive),
738
+ f"{dividends:.4f}" if verbose else millify_tao(dividends),
739
+ f"{emission:.4f}",
740
+ f"{validator_trust:.4f}" if verbose else millify_tao(validator_trust),
839
741
  "*" if validator_permit else "",
840
742
  str(last_update),
841
743
  (
@@ -853,23 +755,15 @@ async def overview(
853
755
  total_dividends += dividends
854
756
  total_emission += emission
855
757
  total_validator_trust += validator_trust
856
-
857
- if (nn.hotkey, nn.coldkey) not in hotkeys_seen:
858
- # Don't double count stake on hotkey-coldkey pairs.
859
- hotkeys_seen.add((nn.hotkey, nn.coldkey))
860
- total_stake += stake
861
-
862
- # netuid -1 are neurons that are de-registered.
863
- if netuid != "-1":
864
- total_neurons += 1
758
+ total_stake += stake
759
+ total_neurons += 1
865
760
 
866
761
  table_data.append(row)
867
762
 
868
763
  # Add subnet header
869
- if netuid == "-1":
870
- grid.add_row("Deregistered Neurons")
871
- else:
872
- grid.add_row(f"Subnet: [dark_orange]{netuid}[/dark_orange]")
764
+ grid.add_row(
765
+ f"Subnet: [dark_orange]{netuid}: {get_subnet_name(dynamic_info[netuid])} {dynamic_info[netuid].symbol}[/dark_orange]"
766
+ )
873
767
  width = console.width
874
768
  table = Table(
875
769
  show_footer=False,
@@ -878,45 +772,34 @@ async def overview(
878
772
  expand=True,
879
773
  width=width - 5,
880
774
  )
881
- if last_subnet:
882
- table.add_column(
883
- "[white]COLDKEY", str(total_neurons), style="bold bright_cyan", ratio=2
884
- )
885
- table.add_column(
886
- "[white]HOTKEY", str(total_neurons), style="bright_cyan", ratio=2
887
- )
888
- else:
889
- # No footer for non-last subnet.
890
- table.add_column("[white]COLDKEY", style="bold bright_cyan", ratio=2)
891
- table.add_column("[white]HOTKEY", style="bright_cyan", ratio=2)
775
+
776
+ table.add_column("[white]COLDKEY", style="bold bright_cyan", ratio=2)
777
+ table.add_column("[white]HOTKEY", style="bright_cyan", ratio=2)
892
778
  table.add_column(
893
779
  "[white]UID", str(total_neurons), style="rgb(42,161,152)", ratio=1
894
780
  )
895
781
  table.add_column(
896
782
  "[white]ACTIVE", justify="right", style="#8787ff", no_wrap=True, ratio=1
897
783
  )
898
- if last_subnet:
899
- table.add_column(
900
- "[white]STAKE(\u03c4)",
901
- "\u03c4{:.5f}".format(total_stake),
902
- footer_style="bold white",
903
- justify="right",
904
- style="dark_orange",
905
- no_wrap=True,
906
- ratio=1,
907
- )
908
- else:
909
- # No footer for non-last subnet.
910
- table.add_column(
911
- "[white]STAKE(\u03c4)",
912
- justify="right",
913
- style="dark_orange",
914
- no_wrap=True,
915
- ratio=1.5,
916
- )
784
+
785
+ _total_stake_formatted = (
786
+ f"{total_stake:.4f}" if verbose else millify_tao(total_stake)
787
+ )
788
+ table.add_column(
789
+ "[white]STAKE(\u03c4)"
790
+ if netuid == 0
791
+ else f"[white]STAKE({Balance.get_unit(netuid)})",
792
+ f"{_total_stake_formatted} {Balance.get_unit(netuid)}"
793
+ if netuid != 0
794
+ else f"{Balance.get_unit(netuid)} {_total_stake_formatted}",
795
+ justify="right",
796
+ style="dark_orange",
797
+ no_wrap=True,
798
+ ratio=1.5,
799
+ )
917
800
  table.add_column(
918
801
  "[white]RANK",
919
- "{:.5f}".format(total_rank),
802
+ f"{total_rank:.4f}",
920
803
  justify="right",
921
804
  style="medium_purple",
922
805
  no_wrap=True,
@@ -924,7 +807,7 @@ async def overview(
924
807
  )
925
808
  table.add_column(
926
809
  "[white]TRUST",
927
- "{:.5f}".format(total_trust),
810
+ f"{total_trust:.4f}",
928
811
  justify="right",
929
812
  style="green",
930
813
  no_wrap=True,
@@ -932,7 +815,7 @@ async def overview(
932
815
  )
933
816
  table.add_column(
934
817
  "[white]CONSENSUS",
935
- "{:.5f}".format(total_consensus),
818
+ f"{total_consensus:.4f}",
936
819
  justify="right",
937
820
  style="rgb(42,161,152)",
938
821
  no_wrap=True,
@@ -940,7 +823,7 @@ async def overview(
940
823
  )
941
824
  table.add_column(
942
825
  "[white]INCENTIVE",
943
- "{:.5f}".format(total_incentive),
826
+ f"{total_incentive:.4f}",
944
827
  justify="right",
945
828
  style="#5fd7ff",
946
829
  no_wrap=True,
@@ -948,7 +831,7 @@ async def overview(
948
831
  )
949
832
  table.add_column(
950
833
  "[white]DIVIDENDS",
951
- "{:.5f}".format(total_dividends),
834
+ f"{total_dividends:.4f}",
952
835
  justify="right",
953
836
  style="#8787d7",
954
837
  no_wrap=True,
@@ -956,7 +839,7 @@ async def overview(
956
839
  )
957
840
  table.add_column(
958
841
  "[white]EMISSION(\u03c1)",
959
- "\u03c1{:_}".format(total_emission),
842
+ f"\u03c1{total_emission}",
960
843
  justify="right",
961
844
  style="#d7d7ff",
962
845
  no_wrap=True,
@@ -964,7 +847,7 @@ async def overview(
964
847
  )
965
848
  table.add_column(
966
849
  "[white]VTRUST",
967
- "{:.5f}".format(total_validator_trust),
850
+ f"{total_validator_trust:.4f}",
968
851
  justify="right",
969
852
  style="magenta",
970
853
  no_wrap=True,
@@ -1283,6 +1166,8 @@ async def inspect(
1283
1166
  delegates_: list[tuple[DelegateInfo, Balance]],
1284
1167
  ) -> Generator[list[str], None, None]:
1285
1168
  for d_, staked in delegates_:
1169
+ if not staked.tao > 0:
1170
+ continue
1286
1171
  if d_.hotkey_ss58 in registered_delegate_info:
1287
1172
  delegate_name = registered_delegate_info[d_.hotkey_ss58].display
1288
1173
  else:
@@ -1292,7 +1177,11 @@ async def inspect(
1292
1177
  + [
1293
1178
  str(delegate_name),
1294
1179
  str(staked),
1295
- str(d_.total_daily_return.tao * (staked.tao / d_.total_stake.tao)),
1180
+ str(
1181
+ d_.total_daily_return.tao * (staked.tao / d_.total_stake.tao)
1182
+ if d_.total_stake.tao != 0
1183
+ else 0
1184
+ ),
1296
1185
  ]
1297
1186
  + [""] * 4
1298
1187
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bittensor-cli
3
- Version: 8.2.0rc10
3
+ Version: 8.2.0rc12
4
4
  Summary: Bittensor CLI
5
5
  Home-page: https://github.com/opentensor/btcli
6
6
  Author: bittensor.com
@@ -18,6 +18,7 @@ typer~=0.12
18
18
  websockets>=14.1
19
19
  bittensor-wallet>=2.0.2
20
20
  bt-decode==0.4.0
21
+ plotille
21
22
 
22
23
  [cuda]
23
24
  cubit>=1.1.0