bittensor-cli 9.0.2__py3-none-any.whl → 9.1.0__py3-none-any.whl

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.
bittensor_cli/cli.py CHANGED
@@ -32,7 +32,7 @@ from bittensor_cli.version import __version__, __version_as_int__
32
32
  from bittensor_cli.src.bittensor import utils
33
33
  from bittensor_cli.src.bittensor.balances import Balance
34
34
  from async_substrate_interface.errors import SubstrateRequestException
35
- from bittensor_cli.src.commands import sudo, wallets
35
+ from bittensor_cli.src.commands import sudo, wallets, view
36
36
  from bittensor_cli.src.commands import weights as weights_cmds
37
37
  from bittensor_cli.src.commands.subnets import price, subnets
38
38
  from bittensor_cli.src.commands.stake import (
@@ -74,8 +74,6 @@ except ImportError:
74
74
  pass
75
75
 
76
76
 
77
-
78
-
79
77
  _epilog = "Made with [bold red]:heart:[/bold red] by The Openτensor Foundaτion"
80
78
 
81
79
  np.set_printoptions(precision=8, suppress=True, floatmode="fixed")
@@ -195,8 +193,7 @@ class Options:
195
193
  )
196
194
  wait_for_finalization = typer.Option(
197
195
  True,
198
- help="If `True`, waits until the transaction is finalized "
199
- "on the blockchain.",
196
+ help="If `True`, waits until the transaction is finalized on the blockchain.",
200
197
  )
201
198
  prompt = typer.Option(
202
199
  True,
@@ -481,7 +478,7 @@ def version_callback(value: bool):
481
478
  f"{repo.active_branch.name}/"
482
479
  f"{repo.commit()}"
483
480
  )
484
- except (NameError, GitError):
481
+ except (TypeError, GitError):
485
482
  version = f"BTCLI version: {__version__}"
486
483
  typer.echo(version)
487
484
  raise typer.Exit()
@@ -515,6 +512,7 @@ class CLIManager:
515
512
  subnets_app: typer.Typer
516
513
  weights_app: typer.Typer
517
514
  utils_app = typer.Typer(epilog=_epilog)
515
+ view_app: typer.Typer
518
516
  asyncio_runner = asyncio
519
517
 
520
518
  def __init__(self):
@@ -564,6 +562,7 @@ class CLIManager:
564
562
  self.sudo_app = typer.Typer(epilog=_epilog)
565
563
  self.subnets_app = typer.Typer(epilog=_epilog)
566
564
  self.weights_app = typer.Typer(epilog=_epilog)
565
+ self.view_app = typer.Typer(epilog=_epilog)
567
566
 
568
567
  # config alias
569
568
  self.app.add_typer(
@@ -641,6 +640,14 @@ class CLIManager:
641
640
  self.utils_app, name="utils", no_args_is_help=True, hidden=True
642
641
  )
643
642
 
643
+ # view app
644
+ self.app.add_typer(
645
+ self.view_app,
646
+ name="view",
647
+ short_help="HTML view commands",
648
+ no_args_is_help=True,
649
+ )
650
+
644
651
  # config commands
645
652
  self.config_app.command("set")(self.set_config)
646
653
  self.config_app.command("get")(self.get_config)
@@ -808,6 +815,11 @@ class CLIManager:
808
815
  "commit", rich_help_panel=HELP_PANELS["WEIGHTS"]["COMMIT_REVEAL"]
809
816
  )(self.weights_commit)
810
817
 
818
+ # view commands
819
+ self.view_app.command(
820
+ "dashboard", rich_help_panel=HELP_PANELS["VIEW"]["DASHBOARD"]
821
+ )(self.view_dashboard)
822
+
811
823
  # Sub command aliases
812
824
  # Weights
813
825
  self.wallet_app.command(
@@ -1338,7 +1350,7 @@ class CLIManager:
1338
1350
  if value in Constants.networks:
1339
1351
  value = value + f" ({Constants.network_map[value]})"
1340
1352
  if key == "rate_tolerance":
1341
- value = f"{value} ({value*100}%)" if value is not None else "None"
1353
+ value = f"{value} ({value * 100}%)" if value is not None else "None"
1342
1354
 
1343
1355
  elif key in deprecated_configs:
1344
1356
  continue
@@ -1367,19 +1379,19 @@ class CLIManager:
1367
1379
  """
1368
1380
  if rate_tolerance is not None:
1369
1381
  console.print(
1370
- f"[dim][blue]Rate tolerance[/blue]: [bold cyan]{rate_tolerance} ({rate_tolerance*100}%)[/bold cyan]."
1382
+ f"[dim][blue]Rate tolerance[/blue]: [bold cyan]{rate_tolerance} ({rate_tolerance * 100}%)[/bold cyan]."
1371
1383
  )
1372
1384
  return rate_tolerance
1373
1385
  elif self.config.get("rate_tolerance") is not None:
1374
1386
  config_slippage = self.config["rate_tolerance"]
1375
1387
  console.print(
1376
- f"[dim][blue]Rate tolerance[/blue]: [bold cyan]{config_slippage} ({config_slippage*100}%)[/bold cyan] (from config)."
1388
+ f"[dim][blue]Rate tolerance[/blue]: [bold cyan]{config_slippage} ({config_slippage * 100}%)[/bold cyan] (from config)."
1377
1389
  )
1378
1390
  return config_slippage
1379
1391
  else:
1380
1392
  console.print(
1381
1393
  "[dim][blue]Rate tolerance[/blue]: "
1382
- + f"[bold cyan]{defaults.rate_tolerance} ({defaults.rate_tolerance*100}%)[/bold cyan] "
1394
+ + f"[bold cyan]{defaults.rate_tolerance} ({defaults.rate_tolerance * 100}%)[/bold cyan] "
1383
1395
  + "by default. Set this using "
1384
1396
  + "[dark_sea_green3 italic]`btcli config set`[/dark_sea_green3 italic] "
1385
1397
  + "or "
@@ -3323,9 +3335,9 @@ class CLIManager:
3323
3335
  def stake_move(
3324
3336
  self,
3325
3337
  network: Optional[list[str]] = Options.network,
3326
- wallet_name=Options.wallet_name,
3327
- wallet_path=Options.wallet_path,
3328
- wallet_hotkey=Options.wallet_hotkey,
3338
+ wallet_name: Optional[str] = Options.wallet_name,
3339
+ wallet_path: Optional[str] = Options.wallet_path,
3340
+ wallet_hotkey: Optional[str] = Options.wallet_hotkey,
3329
3341
  origin_netuid: Optional[int] = typer.Option(
3330
3342
  None, "--origin-netuid", help="Origin netuid"
3331
3343
  ),
@@ -3535,14 +3547,45 @@ class CLIManager:
3535
3547
  )
3536
3548
  self.verbosity_handler(quiet, verbose)
3537
3549
 
3550
+ if not wallet_name:
3551
+ wallet_name = Prompt.ask(
3552
+ "Enter the [blue]origin wallet name[/blue]",
3553
+ default=self.config.get("wallet_name") or defaults.wallet.name,
3554
+ )
3538
3555
  wallet = self.wallet_ask(
3539
- wallet_name,
3540
- wallet_path,
3541
- wallet_hotkey,
3542
- ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
3543
- validate=WV.WALLET_AND_HOTKEY,
3556
+ wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
3544
3557
  )
3545
3558
 
3559
+ if not wallet_hotkey:
3560
+ origin_hotkey = Prompt.ask(
3561
+ "Enter the [blue]origin hotkey[/blue] name or "
3562
+ "[blue]ss58 address[/blue] where the stake will be moved from",
3563
+ default=self.config.get("wallet_hotkey") or defaults.wallet.hotkey,
3564
+ )
3565
+ if is_valid_ss58_address(origin_hotkey):
3566
+ origin_hotkey = origin_hotkey
3567
+ else:
3568
+ wallet = self.wallet_ask(
3569
+ wallet_name,
3570
+ wallet_path,
3571
+ origin_hotkey,
3572
+ ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
3573
+ validate=WV.WALLET_AND_HOTKEY,
3574
+ )
3575
+ origin_hotkey = wallet.hotkey.ss58_address
3576
+ else:
3577
+ if is_valid_ss58_address(wallet_hotkey):
3578
+ origin_hotkey = wallet_hotkey
3579
+ else:
3580
+ wallet = self.wallet_ask(
3581
+ wallet_name,
3582
+ wallet_path,
3583
+ wallet_hotkey,
3584
+ ask_for=[],
3585
+ validate=WV.WALLET_AND_HOTKEY,
3586
+ )
3587
+ origin_hotkey = wallet.hotkey.ss58_address
3588
+
3546
3589
  if not dest_ss58:
3547
3590
  dest_ss58 = Prompt.ask(
3548
3591
  "Enter the [blue]destination wallet name[/blue] or [blue]coldkey SS58 address[/blue]"
@@ -3580,6 +3623,7 @@ class CLIManager:
3580
3623
  move_stake.transfer_stake(
3581
3624
  wallet=wallet,
3582
3625
  subtensor=self.initialize_chain(network),
3626
+ origin_hotkey=origin_hotkey,
3583
3627
  origin_netuid=origin_netuid,
3584
3628
  dest_netuid=dest_netuid,
3585
3629
  dest_coldkey_ss58=dest_ss58,
@@ -5041,6 +5085,28 @@ class CLIManager:
5041
5085
  )
5042
5086
  )
5043
5087
 
5088
+ def view_dashboard(
5089
+ self,
5090
+ network: Optional[list[str]] = Options.network,
5091
+ wallet_name: str = Options.wallet_name,
5092
+ wallet_path: str = Options.wallet_path,
5093
+ wallet_hotkey: str = Options.wallet_hotkey,
5094
+ quiet: bool = Options.quiet,
5095
+ verbose: bool = Options.verbose,
5096
+ ):
5097
+ """
5098
+ Display html dashboard with subnets list, stake, and neuron information.
5099
+ """
5100
+ self.verbosity_handler(quiet, verbose)
5101
+ if is_linux():
5102
+ print_linux_dependency_message()
5103
+ wallet = self.wallet_ask(
5104
+ wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
5105
+ )
5106
+ return self._run_command(
5107
+ view.display_network_dashboard(wallet, self.initialize_chain(network))
5108
+ )
5109
+
5044
5110
  @staticmethod
5045
5111
  @utils_app.command("convert")
5046
5112
  def convert(
@@ -713,6 +713,9 @@ HELP_PANELS = {
713
713
  "IDENTITY": "Subnet Identity Management",
714
714
  },
715
715
  "WEIGHTS": {"COMMIT_REVEAL": "Commit / Reveal"},
716
+ "VIEW": {
717
+ "DASHBOARD": "Network Dashboard",
718
+ },
716
719
  }
717
720
 
718
721
  COLOR_PALETTE = {
@@ -297,17 +297,16 @@ class Balance:
297
297
  return self
298
298
 
299
299
 
300
- def fixed_to_float(fixed: dict) -> float:
301
- # Currently this is stored as a U64F64
300
+ def fixed_to_float(fixed, frac_bits: int = 64, total_bits: int = 128) -> float:
301
+ # By default, this is a U64F64
302
302
  # which is 64 bits of integer and 64 bits of fractional
303
- # uint_bits = 64
304
- frac_bits = 64
305
303
 
306
304
  data: int = fixed["bits"]
307
305
 
308
- # Shift bits to extract integer part (assuming 64 bits for integer part)
309
- integer_part = data >> frac_bits
306
+ # Logical and to get the fractional part; remaining is the integer part
310
307
  fractional_part = data & (2**frac_bits - 1)
308
+ # Shift to get the integer part from the remaining bits
309
+ integer_part = data >> (total_bits - frac_bits)
311
310
 
312
311
  frac_float = fractional_part / (2**frac_bits)
313
312
 
@@ -6,11 +6,12 @@ from typing import Optional, Any, Union
6
6
  import netaddr
7
7
  from scalecodec.utils.ss58 import ss58_encode
8
8
 
9
- from bittensor_cli.src.bittensor.balances import Balance
9
+ from bittensor_cli.src.bittensor.balances import Balance, fixed_to_float
10
10
  from bittensor_cli.src.bittensor.networking import int_to_ip
11
11
  from bittensor_cli.src.bittensor.utils import (
12
12
  SS58_FORMAT,
13
- u16_normalized_float,
13
+ u16_normalized_float as u16tf,
14
+ u64_normalized_float as u64tf,
14
15
  decode_account_id,
15
16
  )
16
17
 
@@ -57,6 +58,31 @@ def process_stake_data(stake_data, netuid):
57
58
  return decoded_stake_data
58
59
 
59
60
 
61
+ def _tbwu(val: int, netuid: Optional[int] = 0) -> Balance:
62
+ """Returns a Balance object from a value and unit."""
63
+ return Balance.from_rao(val).set_unit(netuid)
64
+
65
+
66
+ def _chr_str(codes: tuple[int]) -> str:
67
+ """Converts a tuple of integer Unicode code points into a string."""
68
+ return "".join(map(chr, codes))
69
+
70
+
71
+ def process_nested(data: Union[tuple, dict], chr_transform):
72
+ """Processes nested data structures by applying a transformation function to their elements."""
73
+ if isinstance(data, (list, tuple)):
74
+ if len(data) > 0 and isinstance(data[0], dict):
75
+ return [
76
+ {k: chr_transform(v) for k, v in item.items()}
77
+ if item is not None
78
+ else None
79
+ for item in data
80
+ ]
81
+ return {}
82
+ elif isinstance(data, dict):
83
+ return {k: chr_transform(v) for k, v in data.items()}
84
+
85
+
60
86
  @dataclass
61
87
  class AxonInfo:
62
88
  version: int
@@ -312,13 +338,13 @@ class NeuronInfo(InfoBase):
312
338
  stake=total_stake,
313
339
  stake_dict=stake_dict,
314
340
  total_stake=total_stake,
315
- rank=u16_normalized_float(decoded.get("rank")),
341
+ rank=u16tf(decoded.get("rank")),
316
342
  emission=decoded.get("emission") / 1e9,
317
- incentive=u16_normalized_float(decoded.get("incentive")),
318
- consensus=u16_normalized_float(decoded.get("consensus")),
319
- trust=u16_normalized_float(decoded.get("trust")),
320
- validator_trust=u16_normalized_float(decoded.get("validator_trust")),
321
- dividends=u16_normalized_float(decoded.get("dividends")),
343
+ incentive=u16tf(decoded.get("incentive")),
344
+ consensus=u16tf(decoded.get("consensus")),
345
+ trust=u16tf(decoded.get("trust")),
346
+ validator_trust=u16tf(decoded.get("validator_trust")),
347
+ dividends=u16tf(decoded.get("dividends")),
322
348
  last_update=decoded.get("last_update"),
323
349
  validator_permit=decoded.get("validator_permit"),
324
350
  weights=[[e[0], e[1]] for e in decoded.get("weights")],
@@ -426,22 +452,22 @@ class NeuronInfoLite(InfoBase):
426
452
  coldkey=coldkey,
427
453
  ),
428
454
  coldkey=coldkey,
429
- consensus=u16_normalized_float(consensus),
430
- dividends=u16_normalized_float(dividends),
455
+ consensus=u16tf(consensus),
456
+ dividends=u16tf(dividends),
431
457
  emission=emission / 1e9,
432
458
  hotkey=hotkey,
433
- incentive=u16_normalized_float(incentive),
459
+ incentive=u16tf(incentive),
434
460
  last_update=last_update,
435
461
  netuid=netuid,
436
462
  pruning_score=pruning_score,
437
- rank=u16_normalized_float(rank),
463
+ rank=u16tf(rank),
438
464
  stake_dict=stake_dict,
439
465
  stake=stake,
440
466
  total_stake=stake,
441
- trust=u16_normalized_float(trust),
467
+ trust=u16tf(trust),
442
468
  uid=uid,
443
469
  validator_permit=validator_permit,
444
- validator_trust=u16_normalized_float(validator_trust),
470
+ validator_trust=u16tf(validator_trust),
445
471
  )
446
472
 
447
473
  return neuron
@@ -492,7 +518,7 @@ class DelegateInfo(InfoBase):
492
518
  total_stake=total_stake,
493
519
  nominators=nominators,
494
520
  owner_ss58=owner,
495
- take=u16_normalized_float(decoded.get("take")),
521
+ take=u16tf(decoded.get("take")),
496
522
  validator_permits=decoded.get("validator_permits"),
497
523
  registrations=decoded.get("registrations"),
498
524
  return_per_1000=Balance.from_rao(decoded.get("return_per_1000")),
@@ -528,7 +554,7 @@ class DelegateInfoLite(InfoBase):
528
554
  if decoded_take == 65535:
529
555
  fixed_take = None
530
556
  else:
531
- fixed_take = u16_normalized_float(decoded_take)
557
+ fixed_take = u16tf(decoded_take)
532
558
 
533
559
  return cls(
534
560
  hotkey_ss58=ss58_encode(decoded.get("delegate_ss58"), SS58_FORMAT),
@@ -581,7 +607,7 @@ class SubnetInfo(InfoBase):
581
607
  tempo=decoded.get("tempo"),
582
608
  modality=decoded.get("network_modality"),
583
609
  connection_requirements={
584
- str(int(netuid)): u16_normalized_float(int(req))
610
+ str(int(netuid)): u16tf(int(req))
585
611
  for (netuid, req) in decoded.get("network_connect")
586
612
  },
587
613
  emission_value=decoded.get("emission_value"),
@@ -844,19 +870,17 @@ class SubnetState(InfoBase):
844
870
  coldkeys=[decode_account_id(val) for val in decoded.get("coldkeys")],
845
871
  active=decoded.get("active"),
846
872
  validator_permit=decoded.get("validator_permit"),
847
- pruning_score=[
848
- u16_normalized_float(val) for val in decoded.get("pruning_score")
849
- ],
873
+ pruning_score=[u16tf(val) for val in decoded.get("pruning_score")],
850
874
  last_update=decoded.get("last_update"),
851
875
  emission=[
852
876
  Balance.from_rao(val).set_unit(netuid)
853
877
  for val in decoded.get("emission")
854
878
  ],
855
- dividends=[u16_normalized_float(val) for val in decoded.get("dividends")],
856
- incentives=[u16_normalized_float(val) for val in decoded.get("incentives")],
857
- consensus=[u16_normalized_float(val) for val in decoded.get("consensus")],
858
- trust=[u16_normalized_float(val) for val in decoded.get("trust")],
859
- rank=[u16_normalized_float(val) for val in decoded.get("rank")],
879
+ dividends=[u16tf(val) for val in decoded.get("dividends")],
880
+ incentives=[u16tf(val) for val in decoded.get("incentives")],
881
+ consensus=[u16tf(val) for val in decoded.get("consensus")],
882
+ trust=[u16tf(val) for val in decoded.get("trust")],
883
+ rank=[u16tf(val) for val in decoded.get("rank")],
860
884
  block_at_registration=decoded.get("block_at_registration"),
861
885
  alpha_stake=[
862
886
  Balance.from_rao(val).set_unit(netuid)
@@ -871,3 +895,241 @@ class SubnetState(InfoBase):
871
895
  ],
872
896
  emission_history=decoded.get("emission_history"),
873
897
  )
898
+
899
+
900
+ @dataclass
901
+ class ChainIdentity(InfoBase):
902
+ """Dataclass for chain identity information."""
903
+
904
+ name: str
905
+ url: str
906
+ github: str
907
+ image: str
908
+ discord: str
909
+ description: str
910
+ additional: str
911
+
912
+ @classmethod
913
+ def _from_dict(cls, decoded: dict) -> "ChainIdentity":
914
+ """Returns a ChainIdentity object from decoded chain data."""
915
+ return cls(
916
+ name=decoded["name"],
917
+ url=decoded["url"],
918
+ github=decoded["github_repo"],
919
+ image=decoded["image"],
920
+ discord=decoded["discord"],
921
+ description=decoded["description"],
922
+ additional=decoded["additional"],
923
+ )
924
+
925
+
926
+ @dataclass
927
+ class MetagraphInfo(InfoBase):
928
+ # Subnet index
929
+ netuid: int
930
+
931
+ # Name and symbol
932
+ name: str
933
+ symbol: str
934
+ identity: Optional[SubnetIdentity]
935
+ network_registered_at: int
936
+
937
+ # Keys for owner.
938
+ owner_hotkey: str # hotkey
939
+ owner_coldkey: str # coldkey
940
+
941
+ # Tempo terms.
942
+ block: int # block at call.
943
+ tempo: int # epoch tempo
944
+ last_step: int
945
+ blocks_since_last_step: int
946
+
947
+ # Subnet emission terms
948
+ subnet_emission: Balance # subnet emission via tao
949
+ alpha_in: Balance # amount of alpha in reserve
950
+ alpha_out: Balance # amount of alpha outstanding
951
+ tao_in: Balance # amount of tao injected per block
952
+ alpha_out_emission: Balance # amount injected in alpha reserves per block
953
+ alpha_in_emission: Balance # amount injected outstanding per block
954
+ tao_in_emission: Balance # amount of tao injected per block
955
+ pending_alpha_emission: Balance # pending alpha to be distributed
956
+ pending_root_emission: Balance # pending tao for root divs to be distributed
957
+ subnet_volume: Balance # volume of the subnet in TAO
958
+ moving_price: Balance # subnet moving price.
959
+
960
+ # Hparams for epoch
961
+ rho: int # subnet rho param
962
+ kappa: float # subnet kappa param
963
+
964
+ # Validator params
965
+ min_allowed_weights: float # min allowed weights per val
966
+ max_weights_limit: float # max allowed weights per val
967
+ weights_version: int # allowed weights version
968
+ weights_rate_limit: int # rate limit on weights.
969
+ activity_cutoff: int # validator weights cut off period in blocks
970
+ max_validators: int # max allowed validators.
971
+
972
+ # Registration
973
+ num_uids: int
974
+ max_uids: int
975
+ burn: Balance # current burn cost.
976
+ difficulty: float # current difficulty.
977
+ registration_allowed: bool # allows registrations.
978
+ pow_registration_allowed: bool # pow registration enabled.
979
+ immunity_period: int # subnet miner immunity period
980
+ min_difficulty: float # min pow difficulty
981
+ max_difficulty: float # max pow difficulty
982
+ min_burn: Balance # min tao burn
983
+ max_burn: Balance # max tao burn
984
+ adjustment_alpha: float # adjustment speed for registration params.
985
+ adjustment_interval: int # pow and burn adjustment interval
986
+ target_regs_per_interval: int # target registrations per interval
987
+ max_regs_per_block: int # max registrations per block.
988
+ serving_rate_limit: int # axon serving rate limit
989
+
990
+ # CR
991
+ commit_reveal_weights_enabled: bool # Is CR enabled.
992
+ commit_reveal_period: int # Commit reveal interval
993
+
994
+ # Bonds
995
+ liquid_alpha_enabled: bool # Bonds liquid enabled.
996
+ alpha_high: float # Alpha param high
997
+ alpha_low: float # Alpha param low
998
+ bonds_moving_avg: float # Bonds moving avg
999
+
1000
+ # Metagraph info.
1001
+ hotkeys: list[str] # hotkey per UID
1002
+ coldkeys: list[str] # coldkey per UID
1003
+ identities: list[Optional[ChainIdentity]] # coldkeys identities
1004
+ axons: list[AxonInfo] # UID axons.
1005
+ active: list[bool] # Active per UID
1006
+ validator_permit: list[bool] # Val permit per UID
1007
+ pruning_score: list[float] # Pruning per UID
1008
+ last_update: list[int] # Last update per UID
1009
+ emission: list[Balance] # Emission per UID
1010
+ dividends: list[float] # Dividends per UID
1011
+ incentives: list[float] # Mining incentives per UID
1012
+ consensus: list[float] # Consensus per UID
1013
+ trust: list[float] # Trust per UID
1014
+ rank: list[float] # Rank per UID
1015
+ block_at_registration: list[int] # Reg block per UID
1016
+ alpha_stake: list[Balance] # Alpha staked per UID
1017
+ tao_stake: list[Balance] # TAO staked per UID
1018
+ total_stake: list[Balance] # Total stake per UID
1019
+
1020
+ # Dividend break down.
1021
+ tao_dividends_per_hotkey: list[
1022
+ tuple[str, Balance]
1023
+ ] # List of dividend payouts in tao via root.
1024
+ alpha_dividends_per_hotkey: list[
1025
+ tuple[str, Balance]
1026
+ ] # List of dividend payout in alpha via subnet.
1027
+
1028
+ @classmethod
1029
+ def _fix_decoded(cls, decoded: dict) -> "MetagraphInfo":
1030
+ """Returns a MetagraphInfo object from decoded chain data."""
1031
+ # Subnet index
1032
+ _netuid = decoded["netuid"]
1033
+
1034
+ # Name and symbol
1035
+ decoded.update({"name": bytes(decoded.get("name")).decode()})
1036
+ decoded.update({"symbol": bytes(decoded.get("symbol")).decode()})
1037
+ for key in ["identities", "identity"]:
1038
+ raw_data = decoded.get(key)
1039
+ processed = process_nested(raw_data, _chr_str)
1040
+ decoded.update({key: processed})
1041
+
1042
+ return cls(
1043
+ # Subnet index
1044
+ netuid=_netuid,
1045
+ # Name and symbol
1046
+ name=decoded["name"],
1047
+ symbol=decoded["symbol"],
1048
+ identity=decoded["identity"],
1049
+ network_registered_at=decoded["network_registered_at"],
1050
+ # Keys for owner.
1051
+ owner_hotkey=decoded["owner_hotkey"],
1052
+ owner_coldkey=decoded["owner_coldkey"],
1053
+ # Tempo terms.
1054
+ block=decoded["block"],
1055
+ tempo=decoded["tempo"],
1056
+ last_step=decoded["last_step"],
1057
+ blocks_since_last_step=decoded["blocks_since_last_step"],
1058
+ # Subnet emission terms
1059
+ subnet_emission=_tbwu(decoded["subnet_emission"]),
1060
+ alpha_in=_tbwu(decoded["alpha_in"], _netuid),
1061
+ alpha_out=_tbwu(decoded["alpha_out"], _netuid),
1062
+ tao_in=_tbwu(decoded["tao_in"]),
1063
+ alpha_out_emission=_tbwu(decoded["alpha_out_emission"], _netuid),
1064
+ alpha_in_emission=_tbwu(decoded["alpha_in_emission"], _netuid),
1065
+ tao_in_emission=_tbwu(decoded["tao_in_emission"]),
1066
+ pending_alpha_emission=_tbwu(decoded["pending_alpha_emission"], _netuid),
1067
+ pending_root_emission=_tbwu(decoded["pending_root_emission"]),
1068
+ subnet_volume=_tbwu(decoded["subnet_volume"], _netuid),
1069
+ moving_price=Balance.from_tao(
1070
+ fixed_to_float(decoded.get("moving_price"), 32)
1071
+ ),
1072
+ # Hparams for epoch
1073
+ rho=decoded["rho"],
1074
+ kappa=decoded["kappa"],
1075
+ # Validator params
1076
+ min_allowed_weights=u16tf(decoded["min_allowed_weights"]),
1077
+ max_weights_limit=u16tf(decoded["max_weights_limit"]),
1078
+ weights_version=decoded["weights_version"],
1079
+ weights_rate_limit=decoded["weights_rate_limit"],
1080
+ activity_cutoff=decoded["activity_cutoff"],
1081
+ max_validators=decoded["max_validators"],
1082
+ # Registration
1083
+ num_uids=decoded["num_uids"],
1084
+ max_uids=decoded["max_uids"],
1085
+ burn=_tbwu(decoded["burn"]),
1086
+ difficulty=u64tf(decoded["difficulty"]),
1087
+ registration_allowed=decoded["registration_allowed"],
1088
+ pow_registration_allowed=decoded["pow_registration_allowed"],
1089
+ immunity_period=decoded["immunity_period"],
1090
+ min_difficulty=u64tf(decoded["min_difficulty"]),
1091
+ max_difficulty=u64tf(decoded["max_difficulty"]),
1092
+ min_burn=_tbwu(decoded["min_burn"]),
1093
+ max_burn=_tbwu(decoded["max_burn"]),
1094
+ adjustment_alpha=u64tf(decoded["adjustment_alpha"]),
1095
+ adjustment_interval=decoded["adjustment_interval"],
1096
+ target_regs_per_interval=decoded["target_regs_per_interval"],
1097
+ max_regs_per_block=decoded["max_regs_per_block"],
1098
+ serving_rate_limit=decoded["serving_rate_limit"],
1099
+ # CR
1100
+ commit_reveal_weights_enabled=decoded["commit_reveal_weights_enabled"],
1101
+ commit_reveal_period=decoded["commit_reveal_period"],
1102
+ # Bonds
1103
+ liquid_alpha_enabled=decoded["liquid_alpha_enabled"],
1104
+ alpha_high=u16tf(decoded["alpha_high"]),
1105
+ alpha_low=u16tf(decoded["alpha_low"]),
1106
+ bonds_moving_avg=u64tf(decoded["bonds_moving_avg"]),
1107
+ # Metagraph info.
1108
+ hotkeys=[decode_account_id(ck) for ck in decoded.get("hotkeys", [])],
1109
+ coldkeys=[decode_account_id(hk) for hk in decoded.get("coldkeys", [])],
1110
+ identities=decoded["identities"],
1111
+ axons=decoded.get("axons", []),
1112
+ active=decoded["active"],
1113
+ validator_permit=decoded["validator_permit"],
1114
+ pruning_score=[u16tf(ps) for ps in decoded.get("pruning_score", [])],
1115
+ last_update=decoded["last_update"],
1116
+ emission=[_tbwu(em, _netuid) for em in decoded.get("emission", [])],
1117
+ dividends=[u16tf(dv) for dv in decoded.get("dividends", [])],
1118
+ incentives=[u16tf(ic) for ic in decoded.get("incentives", [])],
1119
+ consensus=[u16tf(cs) for cs in decoded.get("consensus", [])],
1120
+ trust=[u16tf(tr) for tr in decoded.get("trust", [])],
1121
+ rank=[u16tf(rk) for rk in decoded.get("rank", [])],
1122
+ block_at_registration=decoded["block_at_registration"],
1123
+ alpha_stake=[_tbwu(ast, _netuid) for ast in decoded["alpha_stake"]],
1124
+ tao_stake=[_tbwu(ts) for ts in decoded["tao_stake"]],
1125
+ total_stake=[_tbwu(ts, _netuid) for ts in decoded["total_stake"]],
1126
+ # Dividend break down
1127
+ tao_dividends_per_hotkey=[
1128
+ (decode_account_id(alpha[0]), _tbwu(alpha[1]))
1129
+ for alpha in decoded["tao_dividends_per_hotkey"]
1130
+ ],
1131
+ alpha_dividends_per_hotkey=[
1132
+ (decode_account_id(adphk[0]), _tbwu(adphk[1], _netuid))
1133
+ for adphk in decoded["alpha_dividends_per_hotkey"]
1134
+ ],
1135
+ )