bittensor-cli 9.0.1__py3-none-any.whl → 9.0.2__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.
@@ -49,26 +49,36 @@ async def unstake(
49
49
  f"Retrieving subnet data & identities from {subtensor.network}...",
50
50
  spinner="earth",
51
51
  ):
52
- all_sn_dynamic_info_, ck_hk_identities, old_identities = await asyncio.gather(
53
- subtensor.all_subnets(),
54
- subtensor.fetch_coldkey_hotkey_identities(),
55
- subtensor.get_delegate_identities(),
52
+ chain_head = await subtensor.substrate.get_chain_head()
53
+ (
54
+ all_sn_dynamic_info_,
55
+ ck_hk_identities,
56
+ old_identities,
57
+ stake_infos,
58
+ ) = await asyncio.gather(
59
+ subtensor.all_subnets(block_hash=chain_head),
60
+ subtensor.fetch_coldkey_hotkey_identities(block_hash=chain_head),
61
+ subtensor.get_delegate_identities(block_hash=chain_head),
62
+ subtensor.get_stake_for_coldkey(
63
+ wallet.coldkeypub.ss58_address, block_hash=chain_head
64
+ ),
56
65
  )
57
66
  all_sn_dynamic_info = {info.netuid: info for info in all_sn_dynamic_info_}
58
67
 
59
68
  if interactive:
60
69
  hotkeys_to_unstake_from, unstake_all_from_hk = await _unstake_selection(
61
- subtensor,
62
- wallet,
63
70
  all_sn_dynamic_info,
64
71
  ck_hk_identities,
65
72
  old_identities,
73
+ stake_infos,
66
74
  netuid=netuid,
67
75
  )
68
76
  if unstake_all_from_hk:
69
77
  hotkey_to_unstake_all = hotkeys_to_unstake_from[0]
70
78
  unstake_all_alpha = Confirm.ask(
71
- "\nUnstake [blue]all alpha stakes[/blue] and stake back to [blue]root[/blue]? (No will unstake everything)",
79
+ "\nDo you want to:\n"
80
+ "[blue]Yes[/blue]: Unstake from all subnets and automatically restake to subnet 0 (root)\n"
81
+ "[blue]No[/blue]: Unstake everything (including subnet 0)",
72
82
  default=True,
73
83
  )
74
84
  return await unstake_all(
@@ -96,20 +106,17 @@ async def unstake(
96
106
  all_hotkeys=all_hotkeys,
97
107
  include_hotkeys=include_hotkeys,
98
108
  exclude_hotkeys=exclude_hotkeys,
109
+ stake_infos=stake_infos,
110
+ identities=ck_hk_identities,
111
+ old_identities=old_identities,
99
112
  )
100
113
 
101
114
  with console.status(
102
115
  f"Retrieving stake data from {subtensor.network}...",
103
116
  spinner="earth",
104
117
  ):
105
- # Fetch stake balances
106
- chain_head = await subtensor.substrate.get_chain_head()
107
- stake_info_list = await subtensor.get_stake_for_coldkey(
108
- coldkey_ss58=wallet.coldkeypub.ss58_address,
109
- block_hash=chain_head,
110
- )
111
118
  stake_in_netuids = {}
112
- for stake_info in stake_info_list:
119
+ for stake_info in stake_infos:
113
120
  if stake_info.hotkey_ss58 not in stake_in_netuids:
114
121
  stake_in_netuids[stake_info.hotkey_ss58] = {}
115
122
  stake_in_netuids[stake_info.hotkey_ss58][stake_info.netuid] = (
@@ -313,6 +320,9 @@ async def unstake_all(
313
320
  subtensor: "SubtensorInterface",
314
321
  hotkey_ss58_address: str,
315
322
  unstake_all_alpha: bool = False,
323
+ all_hotkeys: bool = False,
324
+ include_hotkeys: list[str] = [],
325
+ exclude_hotkeys: list[str] = [],
316
326
  prompt: bool = True,
317
327
  ) -> bool:
318
328
  """Unstakes all stakes from all hotkeys in all subnets."""
@@ -334,10 +344,27 @@ async def unstake_all(
334
344
  subtensor.all_subnets(),
335
345
  subtensor.get_balance(wallet.coldkeypub.ss58_address),
336
346
  )
337
- if not hotkey_ss58_address:
338
- hotkey_ss58_address = wallet.hotkey.ss58_address
347
+
348
+ if all_hotkeys:
349
+ hotkeys = _get_hotkeys_to_unstake(
350
+ wallet,
351
+ hotkey_ss58_address=hotkey_ss58_address,
352
+ all_hotkeys=all_hotkeys,
353
+ include_hotkeys=include_hotkeys,
354
+ exclude_hotkeys=exclude_hotkeys,
355
+ stake_infos=stake_info,
356
+ identities=ck_hk_identities,
357
+ old_identities=old_identities,
358
+ )
359
+ elif not hotkey_ss58_address:
360
+ hotkeys = [(wallet.hotkey_str, wallet.hotkey.ss58_address)]
361
+ else:
362
+ hotkeys = [(None, hotkey_ss58_address)]
363
+
364
+ hotkey_names = {ss58: name for name, ss58 in hotkeys if name is not None}
365
+ hotkey_ss58s = [ss58 for _, ss58 in hotkeys]
339
366
  stake_info = [
340
- stake for stake in stake_info if stake.hotkey_ss58 == hotkey_ss58_address
367
+ stake for stake in stake_info if stake.hotkey_ss58 in hotkey_ss58s
341
368
  ]
342
369
 
343
370
  if unstake_all_alpha:
@@ -403,18 +430,7 @@ async def unstake_all(
403
430
  if stake.stake.rao == 0:
404
431
  continue
405
432
 
406
- # Get hotkey identity
407
- if hk_identity := ck_hk_identities["hotkeys"].get(stake.hotkey_ss58):
408
- hotkey_name = hk_identity.get("identity", {}).get(
409
- "name", ""
410
- ) or hk_identity.get("display", "~")
411
- hotkey_display = f"{hotkey_name}"
412
- elif old_identity := old_identities.get(stake.hotkey_ss58):
413
- hotkey_name = old_identity.display
414
- hotkey_display = f"{hotkey_name}"
415
- else:
416
- hotkey_display = stake.hotkey_ss58
417
-
433
+ hotkey_display = hotkey_names.get(stake.hotkey_ss58, stake.hotkey_ss58)
418
434
  subnet_info = all_sn_dynamic_info.get(stake.netuid)
419
435
  stake_amount = stake.stake
420
436
  received_amount, slippage_pct, slippage_pct_float = _calculate_slippage(
@@ -455,56 +471,16 @@ async def unstake_all(
455
471
  err_console.print("Error decrypting coldkey (possibly incorrect password)")
456
472
  return False
457
473
 
458
- console_status = (
459
- ":satellite: Unstaking all Alpha stakes..."
460
- if unstake_all_alpha
461
- else ":satellite: Unstaking all stakes..."
462
- )
463
- previous_root_stake = await subtensor.get_stake(
464
- hotkey_ss58=hotkey_ss58_address,
465
- coldkey_ss58=wallet.coldkeypub.ss58_address,
466
- netuid=0,
467
- )
468
- with console.status(console_status):
469
- call_function = "unstake_all_alpha" if unstake_all_alpha else "unstake_all"
470
- call = await subtensor.substrate.compose_call(
471
- call_module="SubtensorModule",
472
- call_function=call_function,
473
- call_params={"hotkey": hotkey_ss58_address},
474
- )
475
- success, error_message = await subtensor.sign_and_send_extrinsic(
476
- call=call,
477
- wallet=wallet,
478
- wait_for_inclusion=True,
479
- wait_for_finalization=False,
480
- )
481
-
482
- if success:
483
- success_message = (
484
- ":white_heavy_check_mark: [green]Successfully unstaked all stakes[/green]"
485
- if not unstake_all_alpha
486
- else ":white_heavy_check_mark: [green]Successfully unstaked all Alpha stakes[/green]"
487
- )
488
- console.print(success_message)
489
- new_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
490
- console.print(
491
- f"Balance:\n [blue]{current_wallet_balance}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
492
- )
493
- if unstake_all_alpha:
494
- root_stake = await subtensor.get_stake(
495
- hotkey_ss58=hotkey_ss58_address,
496
- coldkey_ss58=wallet.coldkeypub.ss58_address,
497
- netuid=0,
498
- )
499
- console.print(
500
- f"Root Stake:\n [blue]{previous_root_stake}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{root_stake}"
501
- )
502
- return True
503
- else:
504
- err_console.print(
505
- f":cross_mark: [red]Failed to unstake[/red]: {error_message}"
474
+ with console.status("Unstaking all stakes...") as status:
475
+ for hotkey_ss58 in hotkey_ss58s:
476
+ await _unstake_all_extrinsic(
477
+ wallet=wallet,
478
+ subtensor=subtensor,
479
+ hotkey_ss58=hotkey_ss58,
480
+ hotkey_name=hotkey_names.get(hotkey_ss58, hotkey_ss58),
481
+ unstake_all_alpha=unstake_all_alpha,
482
+ status=status,
506
483
  )
507
- return False
508
484
 
509
485
 
510
486
  # Extrinsics
@@ -666,9 +642,7 @@ async def _safe_unstake_extrinsic(
666
642
  )
667
643
  return
668
644
  else:
669
- err_out(
670
- f"\n{failure_prelude} with error: {format_error_message(e)}"
671
- )
645
+ err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
672
646
  return
673
647
 
674
648
  await response.process_events()
@@ -709,6 +683,115 @@ async def _safe_unstake_extrinsic(
709
683
  )
710
684
 
711
685
 
686
+ async def _unstake_all_extrinsic(
687
+ wallet: Wallet,
688
+ subtensor: "SubtensorInterface",
689
+ hotkey_ss58: str,
690
+ hotkey_name: str,
691
+ unstake_all_alpha: bool,
692
+ status=None,
693
+ ) -> None:
694
+ """Execute an unstake all extrinsic.
695
+
696
+ Args:
697
+ wallet: Wallet instance
698
+ subtensor: Subtensor interface
699
+ hotkey_ss58: Hotkey SS58 address
700
+ hotkey_name: Display name of the hotkey
701
+ unstake_all_alpha: Whether to unstake only alpha stakes
702
+ status: Optional status for console updates
703
+ """
704
+ err_out = partial(print_error, status=status)
705
+ failure_prelude = (
706
+ f":cross_mark: [red]Failed[/red] to unstake all from {hotkey_name}"
707
+ )
708
+
709
+ if status:
710
+ status.update(
711
+ f"\n:satellite: {'Unstaking all Alpha stakes' if unstake_all_alpha else 'Unstaking all stakes'} from {hotkey_name} ..."
712
+ )
713
+
714
+ block_hash = await subtensor.substrate.get_chain_head()
715
+ if unstake_all_alpha:
716
+ previous_root_stake, current_balance = await asyncio.gather(
717
+ subtensor.get_stake(
718
+ hotkey_ss58=hotkey_ss58,
719
+ coldkey_ss58=wallet.coldkeypub.ss58_address,
720
+ netuid=0,
721
+ block_hash=block_hash,
722
+ ),
723
+ subtensor.get_balance(
724
+ wallet.coldkeypub.ss58_address, block_hash=block_hash
725
+ ),
726
+ )
727
+ else:
728
+ current_balance = await subtensor.get_balance(
729
+ wallet.coldkeypub.ss58_address, block_hash=block_hash
730
+ )
731
+
732
+ call_function = "unstake_all_alpha" if unstake_all_alpha else "unstake_all"
733
+ call = await subtensor.substrate.compose_call(
734
+ call_module="SubtensorModule",
735
+ call_function=call_function,
736
+ call_params={"hotkey": hotkey_ss58},
737
+ )
738
+
739
+ try:
740
+ response = await subtensor.substrate.submit_extrinsic(
741
+ extrinsic=await subtensor.substrate.create_signed_extrinsic(
742
+ call=call,
743
+ keypair=wallet.coldkey,
744
+ ),
745
+ wait_for_inclusion=True,
746
+ wait_for_finalization=False,
747
+ )
748
+ await response.process_events()
749
+
750
+ if not await response.is_success:
751
+ err_out(
752
+ f"{failure_prelude} with error: "
753
+ f"{format_error_message(await response.error_message)}"
754
+ )
755
+ return
756
+
757
+ # Fetch latest balance and stake
758
+ block_hash = await subtensor.substrate.get_chain_head()
759
+ if unstake_all_alpha:
760
+ new_root_stake, new_balance = await asyncio.gather(
761
+ subtensor.get_stake(
762
+ hotkey_ss58=hotkey_ss58,
763
+ coldkey_ss58=wallet.coldkeypub.ss58_address,
764
+ netuid=0,
765
+ block_hash=block_hash,
766
+ ),
767
+ subtensor.get_balance(
768
+ wallet.coldkeypub.ss58_address, block_hash=block_hash
769
+ ),
770
+ )
771
+ else:
772
+ new_balance = await subtensor.get_balance(
773
+ wallet.coldkeypub.ss58_address, block_hash=block_hash
774
+ )
775
+
776
+ success_message = (
777
+ ":white_heavy_check_mark: [green]Finalized: Successfully unstaked all stakes[/green]"
778
+ if not unstake_all_alpha
779
+ else ":white_heavy_check_mark: [green]Finalized: Successfully unstaked all Alpha stakes[/green]"
780
+ )
781
+ console.print(f"{success_message} from {hotkey_name}")
782
+ console.print(
783
+ f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
784
+ )
785
+
786
+ if unstake_all_alpha:
787
+ console.print(
788
+ f"Root Stake for {hotkey_name}:\n [blue]{previous_root_stake}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_root_stake}"
789
+ )
790
+
791
+ except Exception as e:
792
+ err_out(f"{failure_prelude} with error: {str(e)}")
793
+
794
+
712
795
  # Helpers
713
796
  def _calculate_slippage(subnet_info, amount: Balance) -> tuple[Balance, str, float]:
714
797
  """Calculate slippage and received amount for unstaking operation.
@@ -737,17 +820,12 @@ def _calculate_slippage(subnet_info, amount: Balance) -> tuple[Balance, str, flo
737
820
 
738
821
 
739
822
  async def _unstake_selection(
740
- subtensor: "SubtensorInterface",
741
- wallet: Wallet,
742
823
  dynamic_info,
743
824
  identities,
744
825
  old_identities,
826
+ stake_infos,
745
827
  netuid: Optional[int] = None,
746
828
  ):
747
- stake_infos = await subtensor.get_stake_for_coldkey(
748
- coldkey_ss58=wallet.coldkeypub.ss58_address
749
- )
750
-
751
829
  if not stake_infos:
752
830
  print_error("You have no stakes to unstake.")
753
831
  raise typer.Exit()
@@ -771,16 +849,11 @@ async def _unstake_selection(
771
849
 
772
850
  hotkeys_info = []
773
851
  for idx, (hotkey_ss58, netuid_stakes) in enumerate(hotkey_stakes.items()):
774
- if hk_identity := identities["hotkeys"].get(hotkey_ss58):
775
- hotkey_name = hk_identity.get("identity", {}).get(
776
- "name", ""
777
- ) or hk_identity.get("display", "~")
778
- elif old_identity := old_identities.get(hotkey_ss58):
779
- hotkey_name = old_identity.display
780
- else:
781
- hotkey_name = "~"
782
- # TODO: Add wallet ids here.
783
-
852
+ hotkey_name = get_hotkey_identity(
853
+ hotkey_ss58=hotkey_ss58,
854
+ identities=identities,
855
+ old_identities=old_identities,
856
+ )
784
857
  hotkeys_info.append(
785
858
  {
786
859
  "index": idx,
@@ -983,6 +1056,9 @@ def _get_hotkeys_to_unstake(
983
1056
  all_hotkeys: bool,
984
1057
  include_hotkeys: list[str],
985
1058
  exclude_hotkeys: list[str],
1059
+ stake_infos: list,
1060
+ identities: dict,
1061
+ old_identities: dict,
986
1062
  ) -> list[tuple[Optional[str], str]]:
987
1063
  """Get list of hotkeys to unstake from based on input parameters.
988
1064
 
@@ -1002,13 +1078,27 @@ def _get_hotkeys_to_unstake(
1002
1078
 
1003
1079
  if all_hotkeys:
1004
1080
  print_verbose("Unstaking from all hotkeys")
1005
- all_hotkeys_: list[Wallet] = get_hotkey_wallets_for_wallet(wallet=wallet)
1006
- return [
1081
+ all_hotkeys_ = get_hotkey_wallets_for_wallet(wallet=wallet)
1082
+ wallet_hotkeys = [
1007
1083
  (wallet.hotkey_str, wallet.hotkey.ss58_address)
1008
1084
  for wallet in all_hotkeys_
1009
1085
  if wallet.hotkey_str not in exclude_hotkeys
1010
1086
  ]
1011
1087
 
1088
+ wallet_hotkey_addresses = {addr for _, addr in wallet_hotkeys}
1089
+ chain_hotkeys = [
1090
+ (
1091
+ get_hotkey_identity(stake_info.hotkey_ss58, identities, old_identities),
1092
+ stake_info.hotkey_ss58,
1093
+ )
1094
+ for stake_info in stake_infos
1095
+ if (
1096
+ stake_info.hotkey_ss58 not in wallet_hotkey_addresses
1097
+ and stake_info.hotkey_ss58 not in exclude_hotkeys
1098
+ )
1099
+ ]
1100
+ return wallet_hotkeys + chain_hotkeys
1101
+
1012
1102
  if include_hotkeys:
1013
1103
  print_verbose("Unstaking from included hotkeys")
1014
1104
  result = []
@@ -1144,3 +1234,28 @@ The columns are as follows:
1144
1234
  - [bold white]Partial unstaking[/bold white]: If True, allows unstaking up to the rate tolerance limit. If False, the entire transaction will fail if rate tolerance is exceeded.\n"""
1145
1235
 
1146
1236
  console.print(base_description + (safe_staking_description if safe_staking else ""))
1237
+
1238
+
1239
+ def get_hotkey_identity(
1240
+ hotkey_ss58: str,
1241
+ identities: dict,
1242
+ old_identities: dict,
1243
+ ) -> str:
1244
+ """Get identity name for a hotkey from identities or old_identities.
1245
+
1246
+ Args:
1247
+ hotkey_ss58 (str): The hotkey SS58 address
1248
+ identities (dict): Current identities from fetch_coldkey_hotkey_identities
1249
+ old_identities (dict): Old identities from get_delegate_identities
1250
+
1251
+ Returns:
1252
+ str: Identity name or truncated address
1253
+ """
1254
+ if hk_identity := identities["hotkeys"].get(hotkey_ss58):
1255
+ return hk_identity.get("identity", {}).get("name", "") or hk_identity.get(
1256
+ "display", "~"
1257
+ )
1258
+ elif old_identity := old_identities.get(hotkey_ss58):
1259
+ return old_identity.display
1260
+ else:
1261
+ return f"{hotkey_ss58[:4]}...{hotkey_ss58[-4:]}"
@@ -889,8 +889,8 @@ async def show(
889
889
  total_emission_per_block = 0
890
890
  for netuid_ in range(len(all_subnets)):
891
891
  subnet = all_subnets[netuid_]
892
- emission_on_subnet = (
893
- root_state.emission_history[netuid_][idx] / (subnet.tempo or 1)
892
+ emission_on_subnet = root_state.emission_history[netuid_][idx] / (
893
+ subnet.tempo or 1
894
894
  )
895
895
  total_emission_per_block += subnet.alpha_to_tao(
896
896
  Balance.from_rao(emission_on_subnet)
@@ -2135,9 +2135,7 @@ async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str
2135
2135
  title = "Subnet Identity"
2136
2136
 
2137
2137
  if not await subtensor.subnet_exists(netuid):
2138
- print_error(
2139
- f"Subnet {netuid} does not exist."
2140
- )
2138
+ print_error(f"Subnet {netuid} does not exist.")
2141
2139
  raise typer.Exit()
2142
2140
 
2143
2141
  with console.status(
@@ -18,6 +18,8 @@ from bittensor_cli.src.bittensor.utils import (
18
18
  normalize_hyperparameters,
19
19
  unlock_key,
20
20
  blocks_to_duration,
21
+ float_to_u64,
22
+ float_to_u16,
21
23
  )
22
24
 
23
25
  if TYPE_CHECKING:
@@ -70,12 +72,76 @@ def allowed_value(
70
72
  return True, value
71
73
 
72
74
 
75
+ def search_metadata(
76
+ param_name: str, value: Union[str, bool, float, list[float]], netuid: int, metadata
77
+ ) -> tuple[bool, Optional[dict]]:
78
+ """
79
+ Searches the substrate metadata AdminUtils pallet for a given parameter name. Crafts a response dict to be used
80
+ as call parameters for setting this hyperparameter.
81
+
82
+ Args:
83
+ param_name: the name of the hyperparameter
84
+ value: the value to set the hyperparameter
85
+ netuid: the specified netuid
86
+ metadata: the subtensor.substrate.metadata
87
+
88
+ Returns:
89
+ (success, dict of call params)
90
+
91
+ """
92
+
93
+ def string_to_bool(val) -> bool:
94
+ try:
95
+ return {"true": True, "1": True, "0": False, "false": False}[val.lower()]
96
+ except KeyError:
97
+ return ValueError
98
+
99
+ def type_converter_with_retry(type_, val, arg_name):
100
+ try:
101
+ if val is None:
102
+ val = input(
103
+ f"Enter a value for field '{arg_name}' with type '{arg_type_output[type_]}': "
104
+ )
105
+ return arg_types[type_](val)
106
+ except ValueError:
107
+ return type_converter_with_retry(type_, None, arg_name)
108
+
109
+ arg_types = {"bool": string_to_bool, "u16": float_to_u16, "u64": float_to_u64}
110
+ arg_type_output = {"bool": "bool", "u16": "float", "u64": "float"}
111
+
112
+ call_crafter = {"netuid": netuid}
113
+
114
+ for pallet in metadata.pallets:
115
+ if pallet.name == "AdminUtils":
116
+ for call in pallet.calls:
117
+ if call.name == param_name:
118
+ if "netuid" not in [x.name for x in call.args]:
119
+ return False, None
120
+ call_args = [
121
+ arg for arg in call.args if arg.value["name"] != "netuid"
122
+ ]
123
+ if len(call_args) == 1:
124
+ arg = call_args[0].value
125
+ call_crafter[arg["name"]] = type_converter_with_retry(
126
+ arg["typeName"], value, arg["name"]
127
+ )
128
+ else:
129
+ for arg_ in call_args:
130
+ arg = arg_.value
131
+ call_crafter[arg["name"]] = type_converter_with_retry(
132
+ arg["typeName"], None, arg["name"]
133
+ )
134
+ return True, call_crafter
135
+ else:
136
+ return False, None
137
+
138
+
73
139
  async def set_hyperparameter_extrinsic(
74
140
  subtensor: "SubtensorInterface",
75
141
  wallet: "Wallet",
76
142
  netuid: int,
77
143
  parameter: str,
78
- value: Union[str, bool, float, list[float]],
144
+ value: Optional[Union[str, bool, float, list[float]]],
79
145
  wait_for_inclusion: bool = False,
80
146
  wait_for_finalization: bool = True,
81
147
  ) -> bool:
@@ -110,44 +176,58 @@ async def set_hyperparameter_extrinsic(
110
176
  if not unlock_key(wallet).success:
111
177
  return False
112
178
 
179
+ arbitrary_extrinsic = False
180
+
113
181
  extrinsic, sudo_ = HYPERPARAMS.get(parameter, ("", False))
114
- if extrinsic is None:
115
- err_console.print(":cross_mark: [red]Invalid hyperparameter specified.[/red]")
116
- return False
182
+ if not extrinsic:
183
+ arbitrary_extrinsic, call_params = search_metadata(
184
+ parameter, value, netuid, subtensor.substrate.metadata
185
+ )
186
+ extrinsic = parameter
187
+ if not arbitrary_extrinsic:
188
+ err_console.print(
189
+ ":cross_mark: [red]Invalid hyperparameter specified.[/red]"
190
+ )
191
+ return False
117
192
 
193
+ substrate = subtensor.substrate
194
+ msg_value = value if not arbitrary_extrinsic else call_params
118
195
  with console.status(
119
- f":satellite: Setting hyperparameter [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{parameter}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] to [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{value}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] on subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] ...",
196
+ f":satellite: Setting hyperparameter [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{parameter}"
197
+ f"[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] to [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{msg_value}"
198
+ f"[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] on subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
199
+ f"{netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] ...",
120
200
  spinner="earth",
121
201
  ):
122
- substrate = subtensor.substrate
123
- extrinsic_params = await substrate.get_metadata_call_function(
124
- "AdminUtils", extrinsic
125
- )
126
- call_params: dict[str, Union[str, bool, float]] = {"netuid": netuid}
127
-
128
- # if input value is a list, iterate through the list and assign values
129
- if isinstance(value, list):
130
- # Ensure that there are enough values for all non-netuid parameters
131
- non_netuid_fields = [
132
- param["name"]
133
- for param in extrinsic_params["fields"]
134
- if "netuid" not in param["name"]
135
- ]
136
-
137
- if len(value) < len(non_netuid_fields):
138
- raise ValueError(
139
- "Not enough values provided in the list for all parameters"
140
- )
141
-
142
- call_params.update(
143
- {str(name): val for name, val in zip(non_netuid_fields, value)}
202
+ if not arbitrary_extrinsic:
203
+ extrinsic_params = await substrate.get_metadata_call_function(
204
+ "AdminUtils", extrinsic
144
205
  )
206
+ call_params = {"netuid": netuid}
207
+
208
+ # if input value is a list, iterate through the list and assign values
209
+ if isinstance(value, list):
210
+ # Ensure that there are enough values for all non-netuid parameters
211
+ non_netuid_fields = [
212
+ param["name"]
213
+ for param in extrinsic_params["fields"]
214
+ if "netuid" not in param["name"]
215
+ ]
216
+
217
+ if len(value) < len(non_netuid_fields):
218
+ raise ValueError(
219
+ "Not enough values provided in the list for all parameters"
220
+ )
145
221
 
146
- else:
147
- value_argument = extrinsic_params["fields"][
148
- len(extrinsic_params["fields"]) - 1
149
- ]
150
- call_params[str(value_argument["name"])] = value
222
+ call_params.update(
223
+ {str(name): val for name, val in zip(non_netuid_fields, value)}
224
+ )
225
+
226
+ else:
227
+ value_argument = extrinsic_params["fields"][
228
+ len(extrinsic_params["fields"]) - 1
229
+ ]
230
+ call_params[str(value_argument["name"])] = value
151
231
 
152
232
  # create extrinsic call
153
233
  call_ = await substrate.compose_call(
@@ -167,11 +247,16 @@ async def set_hyperparameter_extrinsic(
167
247
  if not success:
168
248
  err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}")
169
249
  await asyncio.sleep(0.5)
170
-
250
+ elif arbitrary_extrinsic:
251
+ console.print(
252
+ f":white_heavy_check_mark: "
253
+ f"[dark_sea_green3]Hyperparameter {parameter} values changed to {call_params}[/dark_sea_green3]"
254
+ )
171
255
  # Successful registration, final check for membership
172
256
  else:
173
257
  console.print(
174
- f":white_heavy_check_mark: [dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
258
+ f":white_heavy_check_mark: "
259
+ f"[dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
175
260
  )
176
261
  return True
177
262
 
@@ -470,7 +555,7 @@ async def sudo_set_hyperparameter(
470
555
  subtensor: "SubtensorInterface",
471
556
  netuid: int,
472
557
  param_name: str,
473
- param_value: str,
558
+ param_value: Optional[str],
474
559
  ):
475
560
  """Set subnet hyperparameters."""
476
561
 
@@ -481,7 +566,12 @@ async def sudo_set_hyperparameter(
481
566
  "commit_reveal_weights_enabled",
482
567
  "liquid_alpha_enabled",
483
568
  ]:
484
- normalized_value = param_value.lower() in ["true", "True", "1"]
569
+ normalized_value = param_value.lower() in ["true", "1"]
570
+ elif param_value in ("True", "False"):
571
+ normalized_value = {
572
+ "True": True,
573
+ "False": False,
574
+ }[param_value]
485
575
  else:
486
576
  normalized_value = param_value
487
577
 
@@ -492,7 +582,6 @@ async def sudo_set_hyperparameter(
492
582
  f"Value is {normalized_value} but must be {value}"
493
583
  )
494
584
  return
495
-
496
585
  success = await set_hyperparameter_extrinsic(
497
586
  subtensor, wallet, netuid, param_name, value
498
587
  )