bittensor-cli 9.4.0__tar.gz → 9.4.2__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 (40) hide show
  1. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/PKG-INFO +3 -2
  2. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/README.md +1 -1
  3. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/cli.py +75 -40
  4. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/__init__.py +1 -2
  5. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/extrinsics/registration.py +0 -1
  6. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/extrinsics/root.py +0 -1
  7. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/subtensor_interface.py +19 -19
  8. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/utils.py +4 -1
  9. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/subnets/subnets.py +20 -9
  10. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/sudo.py +4 -2
  11. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/wallets.py +4 -6
  12. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli.egg-info/PKG-INFO +3 -2
  13. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli.egg-info/requires.txt +1 -0
  14. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/pyproject.toml +2 -1
  15. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/__init__.py +0 -0
  16. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/doc_generation_helper.py +0 -0
  17. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/__init__.py +0 -0
  18. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/balances.py +0 -0
  19. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/chain_data.py +0 -0
  20. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/extrinsics/__init__.py +0 -0
  21. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/extrinsics/transfer.py +0 -0
  22. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/minigraph.py +0 -0
  23. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/bittensor/networking.py +0 -0
  24. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/__init__.py +0 -0
  25. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/stake/__init__.py +0 -0
  26. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/stake/add.py +0 -0
  27. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/stake/children_hotkeys.py +0 -0
  28. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/stake/list.py +0 -0
  29. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/stake/move.py +0 -0
  30. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/stake/remove.py +0 -0
  31. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/subnets/__init__.py +0 -0
  32. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/subnets/price.py +0 -0
  33. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/view.py +0 -0
  34. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/src/commands/weights.py +0 -0
  35. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli/version.py +0 -0
  36. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli.egg-info/SOURCES.txt +0 -0
  37. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli.egg-info/dependency_links.txt +0 -0
  38. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli.egg-info/entry_points.txt +0 -0
  39. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/bittensor_cli.egg-info/top_level.txt +0 -0
  40. {bittensor_cli-9.4.0 → bittensor_cli-9.4.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bittensor-cli
3
- Version: 9.4.0
3
+ Version: 9.4.2
4
4
  Summary: Bittensor CLI
5
5
  Author: bittensor.com
6
6
  Project-URL: homepage, https://github.com/opentensor/btcli
@@ -12,6 +12,7 @@ Requires-Dist: async-property==0.2.2
12
12
  Requires-Dist: async-substrate-interface>=1.1.0
13
13
  Requires-Dist: aiohttp~=3.10.2
14
14
  Requires-Dist: backoff~=2.2.1
15
+ Requires-Dist: click<8.2.0
15
16
  Requires-Dist: GitPython>=3.0.0
16
17
  Requires-Dist: fuzzywuzzy~=0.18.0
17
18
  Requires-Dist: netaddr~=1.3.0
@@ -72,7 +73,7 @@ Installation steps are described below. For a full documentation on how to use `
72
73
 
73
74
  ## Install on macOS and Linux
74
75
 
75
- You can install `btcli` on your local machine directly from source, or from from PyPI. **Make sure you verify your installation after you install**:
76
+ You can install `btcli` on your local machine directly from source, or from PyPI. **Make sure you verify your installation after you install**:
76
77
 
77
78
 
78
79
  ### Install from PyPI
@@ -39,7 +39,7 @@ Installation steps are described below. For a full documentation on how to use `
39
39
 
40
40
  ## Install on macOS and Linux
41
41
 
42
- You can install `btcli` on your local machine directly from source, or from from PyPI. **Make sure you verify your installation after you install**:
42
+ You can install `btcli` on your local machine directly from source, or from PyPI. **Make sure you verify your installation after you install**:
43
43
 
44
44
 
45
45
  ### Install from PyPI
@@ -293,8 +293,11 @@ class Options:
293
293
  "--json-out",
294
294
  help="Outputs the result of the command as JSON.",
295
295
  )
296
- era: int = typer.Option(
297
- 3, help="Length (in blocks) for which the transaction should be valid."
296
+ period: int = typer.Option(
297
+ 16,
298
+ "--period",
299
+ "--era",
300
+ help="Length (in blocks) for which the transaction should be valid.",
298
301
  )
299
302
 
300
303
 
@@ -436,36 +439,49 @@ def parse_mnemonic(mnemonic: str) -> str:
436
439
  def get_creation_data(
437
440
  mnemonic: Optional[str],
438
441
  seed: Optional[str],
439
- json: Optional[str],
442
+ json_path: Optional[str],
440
443
  json_password: Optional[str],
441
444
  ) -> tuple[str, str, str, str]:
442
445
  """
443
446
  Determines which of the key creation elements have been supplied, if any. If None have been supplied,
444
447
  prompts to user, and determines what they've supplied. Returns all elements in a tuple.
445
448
  """
446
- if not mnemonic and not seed and not json:
447
- prompt_answer = Prompt.ask(
448
- "Enter the mnemonic, or the seed hex string, or the location of the JSON file."
449
+ if not mnemonic and not seed and not json_path:
450
+ choices = {
451
+ 1: "mnemonic",
452
+ 2: "seed hex string",
453
+ 3: "path to JSON File",
454
+ }
455
+ type_answer = IntPrompt.ask(
456
+ "Select one of the following to enter\n"
457
+ f"[{COLORS.G.HINT}][1][/{COLORS.G.HINT}] Mnemonic\n"
458
+ f"[{COLORS.G.HINT}][2][/{COLORS.G.HINT}] Seed hex string\n"
459
+ f"[{COLORS.G.HINT}][3][/{COLORS.G.HINT}] Path to JSON File\n",
460
+ choices=["1", "2", "3"],
461
+ show_choices=False,
449
462
  )
450
- if prompt_answer.startswith("0x"):
463
+ prompt_answer = Prompt.ask(f"Please enter your {choices[type_answer]}")
464
+ if type_answer == 1:
465
+ mnemonic = prompt_answer
466
+ elif type_answer == 2:
451
467
  seed = prompt_answer
452
- elif len(prompt_answer.split(" ")) > 1:
453
- mnemonic = parse_mnemonic(prompt_answer)
454
- else:
455
- json = prompt_answer
468
+ if seed.startswith("0x"):
469
+ seed = seed[2:]
470
+ elif type_answer == 3:
471
+ json_path = prompt_answer
456
472
  elif mnemonic:
457
473
  mnemonic = parse_mnemonic(mnemonic)
458
474
 
459
- if json:
460
- if not os.path.exists(json):
461
- print_error(f"The JSON file '{json}' does not exist.")
475
+ if json_path:
476
+ if not os.path.exists(json_path):
477
+ print_error(f"The JSON file '{json_path}' does not exist.")
462
478
  raise typer.Exit()
463
479
 
464
- if json and not json_password:
480
+ if json_path and not json_password:
465
481
  json_password = Prompt.ask(
466
482
  "Enter the backup password for JSON file.", password=True
467
483
  )
468
- return mnemonic, seed, json, json_password
484
+ return mnemonic, seed, json_path, json_password
469
485
 
470
486
 
471
487
  def config_selector(conf: dict, title: str):
@@ -1792,7 +1808,7 @@ class CLIManager:
1792
1808
  transfer_all: bool = typer.Option(
1793
1809
  False, "--all", prompt=False, help="Transfer all available balance."
1794
1810
  ),
1795
- era: int = Options.era,
1811
+ period: int = Options.period,
1796
1812
  wallet_name: str = Options.wallet_name,
1797
1813
  wallet_path: str = Options.wallet_path,
1798
1814
  wallet_hotkey: str = Options.wallet_hotkey,
@@ -1847,7 +1863,7 @@ class CLIManager:
1847
1863
  destination=destination_ss58_address,
1848
1864
  amount=amount,
1849
1865
  transfer_all=transfer_all,
1850
- era=era,
1866
+ era=period,
1851
1867
  prompt=prompt,
1852
1868
  json_output=json_output,
1853
1869
  )
@@ -2090,7 +2106,7 @@ class CLIManager:
2090
2106
  wallet_hotkey: Optional[str] = Options.wallet_hotkey,
2091
2107
  mnemonic: Optional[str] = Options.mnemonic,
2092
2108
  seed: Optional[str] = Options.seed,
2093
- json: Optional[str] = Options.json,
2109
+ json_path: Optional[str] = Options.json,
2094
2110
  json_password: Optional[str] = Options.json_password,
2095
2111
  use_password: Optional[bool] = Options.use_password,
2096
2112
  overwrite: bool = Options.overwrite,
@@ -2130,15 +2146,15 @@ class CLIManager:
2130
2146
 
2131
2147
  wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
2132
2148
 
2133
- mnemonic, seed, json, json_password = get_creation_data(
2134
- mnemonic, seed, json, json_password
2149
+ mnemonic, seed, json_path, json_password = get_creation_data(
2150
+ mnemonic, seed, json_path, json_password
2135
2151
  )
2136
2152
  return self._run_command(
2137
2153
  wallets.regen_coldkey(
2138
2154
  wallet,
2139
2155
  mnemonic,
2140
2156
  seed,
2141
- json,
2157
+ json_path,
2142
2158
  json_password,
2143
2159
  use_password,
2144
2160
  overwrite,
@@ -2214,7 +2230,7 @@ class CLIManager:
2214
2230
  wallet_hotkey: Optional[str] = Options.wallet_hotkey,
2215
2231
  mnemonic: Optional[str] = Options.mnemonic,
2216
2232
  seed: Optional[str] = Options.seed,
2217
- json: Optional[str] = Options.json,
2233
+ json_path: Optional[str] = Options.json,
2218
2234
  json_password: Optional[str] = Options.json_password,
2219
2235
  use_password: bool = typer.Option(
2220
2236
  False, # Overriden to False
@@ -2250,15 +2266,15 @@ class CLIManager:
2250
2266
  ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
2251
2267
  validate=WV.WALLET,
2252
2268
  )
2253
- mnemonic, seed, json, json_password = get_creation_data(
2254
- mnemonic, seed, json, json_password
2269
+ mnemonic, seed, json_path, json_password = get_creation_data(
2270
+ mnemonic, seed, json_path, json_password
2255
2271
  )
2256
2272
  return self._run_command(
2257
2273
  wallets.regen_hotkey(
2258
2274
  wallet,
2259
2275
  mnemonic,
2260
2276
  seed,
2261
- json,
2277
+ json_path,
2262
2278
  json_password,
2263
2279
  use_password,
2264
2280
  overwrite,
@@ -3190,7 +3206,7 @@ class CLIManager:
3190
3206
  rate_tolerance: Optional[float] = Options.rate_tolerance,
3191
3207
  safe_staking: Optional[bool] = Options.safe_staking,
3192
3208
  allow_partial_stake: Optional[bool] = Options.allow_partial_stake,
3193
- era: int = Options.era,
3209
+ period: int = Options.period,
3194
3210
  prompt: bool = Options.prompt,
3195
3211
  quiet: bool = Options.quiet,
3196
3212
  verbose: bool = Options.verbose,
@@ -3386,7 +3402,7 @@ class CLIManager:
3386
3402
  rate_tolerance,
3387
3403
  allow_partial_stake,
3388
3404
  json_output,
3389
- era,
3405
+ period,
3390
3406
  )
3391
3407
  )
3392
3408
 
@@ -3438,7 +3454,7 @@ class CLIManager:
3438
3454
  rate_tolerance: Optional[float] = Options.rate_tolerance,
3439
3455
  safe_staking: Optional[bool] = Options.safe_staking,
3440
3456
  allow_partial_stake: Optional[bool] = Options.allow_partial_stake,
3441
- era: int = Options.era,
3457
+ period: int = Options.period,
3442
3458
  prompt: bool = Options.prompt,
3443
3459
  interactive: bool = typer.Option(
3444
3460
  False,
@@ -3631,7 +3647,7 @@ class CLIManager:
3631
3647
  exclude_hotkeys=exclude_hotkeys,
3632
3648
  prompt=prompt,
3633
3649
  json_output=json_output,
3634
- era=era,
3650
+ era=period,
3635
3651
  )
3636
3652
  )
3637
3653
  elif (
@@ -3687,7 +3703,7 @@ class CLIManager:
3687
3703
  rate_tolerance=rate_tolerance,
3688
3704
  allow_partial_stake=allow_partial_stake,
3689
3705
  json_output=json_output,
3690
- era=era,
3706
+ era=period,
3691
3707
  )
3692
3708
  )
3693
3709
 
@@ -3715,7 +3731,7 @@ class CLIManager:
3715
3731
  stake_all: bool = typer.Option(
3716
3732
  False, "--stake-all", "--all", help="Stake all", prompt=False
3717
3733
  ),
3718
- era: int = Options.era,
3734
+ period: int = Options.period,
3719
3735
  prompt: bool = Options.prompt,
3720
3736
  quiet: bool = Options.quiet,
3721
3737
  verbose: bool = Options.verbose,
@@ -3845,7 +3861,7 @@ class CLIManager:
3845
3861
  destination_hotkey=destination_hotkey,
3846
3862
  amount=amount,
3847
3863
  stake_all=stake_all,
3848
- era=era,
3864
+ era=period,
3849
3865
  interactive_selection=interactive_selection,
3850
3866
  prompt=prompt,
3851
3867
  )
@@ -3886,7 +3902,7 @@ class CLIManager:
3886
3902
  stake_all: bool = typer.Option(
3887
3903
  False, "--stake-all", "--all", help="Stake all", prompt=False
3888
3904
  ),
3889
- era: int = Options.era,
3905
+ period: int = Options.period,
3890
3906
  prompt: bool = Options.prompt,
3891
3907
  quiet: bool = Options.quiet,
3892
3908
  verbose: bool = Options.verbose,
@@ -4008,7 +4024,7 @@ class CLIManager:
4008
4024
  dest_netuid=dest_netuid,
4009
4025
  dest_coldkey_ss58=dest_ss58,
4010
4026
  amount=amount,
4011
- era=era,
4027
+ era=period,
4012
4028
  interactive_selection=interactive_selection,
4013
4029
  stake_all=stake_all,
4014
4030
  prompt=prompt,
@@ -4050,7 +4066,7 @@ class CLIManager:
4050
4066
  "--all",
4051
4067
  help="Swap all available stake",
4052
4068
  ),
4053
- era: int = Options.era,
4069
+ period: int = Options.period,
4054
4070
  prompt: bool = Options.prompt,
4055
4071
  wait_for_inclusion: bool = Options.wait_for_inclusion,
4056
4072
  wait_for_finalization: bool = Options.wait_for_finalization,
@@ -4115,7 +4131,7 @@ class CLIManager:
4115
4131
  destination_netuid=dest_netuid,
4116
4132
  amount=amount,
4117
4133
  swap_all=swap_all,
4118
- era=era,
4134
+ era=period,
4119
4135
  interactive_selection=interactive_selection,
4120
4136
  prompt=prompt,
4121
4137
  wait_for_inclusion=wait_for_inclusion,
@@ -4430,6 +4446,7 @@ class CLIManager:
4430
4446
  param_value: Optional[str] = typer.Option(
4431
4447
  "", "--value", help="Value to set the hyperparameter to."
4432
4448
  ),
4449
+ prompt: bool = Options.prompt,
4433
4450
  quiet: bool = Options.quiet,
4434
4451
  verbose: bool = Options.verbose,
4435
4452
  json_output: bool = Options.json_output,
@@ -4454,6 +4471,11 @@ class CLIManager:
4454
4471
  raise typer.Exit()
4455
4472
 
4456
4473
  if not param_name:
4474
+ if not prompt:
4475
+ err_console.print(
4476
+ "Param name not supplied with `--no-prompt` flag. Cannot continue"
4477
+ )
4478
+ return False
4457
4479
  hyperparam_list = [field.name for field in fields(SubnetHyperparameters)]
4458
4480
  console.print("Available hyperparameters:\n")
4459
4481
  for idx, param in enumerate(hyperparam_list, start=1):
@@ -4467,6 +4489,11 @@ class CLIManager:
4467
4489
  param_name = hyperparam_list[choice - 1]
4468
4490
 
4469
4491
  if param_name in ["alpha_high", "alpha_low"]:
4492
+ if not prompt:
4493
+ err_console.print(
4494
+ "`alpha_high` and `alpha_low` values cannot be set with `--no-prompt`"
4495
+ )
4496
+ return False
4470
4497
  param_name = "alpha_values"
4471
4498
  low_val = FloatPrompt.ask(
4472
4499
  "Enter the new value for [dark_orange]alpha_low[/dark_orange]"
@@ -4477,6 +4504,11 @@ class CLIManager:
4477
4504
  param_value = f"{low_val},{high_val}"
4478
4505
 
4479
4506
  if not param_value:
4507
+ if not prompt:
4508
+ err_console.print(
4509
+ "Param value not supplied with `--no-prompt` flag. Cannot continue."
4510
+ )
4511
+ return False
4480
4512
  if HYPERPARAMS.get(param_name):
4481
4513
  param_value = Prompt.ask(
4482
4514
  f"Enter the new value for [{COLORS.G.SUBHEAD}]{param_name}[/{COLORS.G.SUBHEAD}] "
@@ -4495,6 +4527,7 @@ class CLIManager:
4495
4527
  netuid,
4496
4528
  param_name,
4497
4529
  param_value,
4530
+ prompt,
4498
4531
  json_output,
4499
4532
  )
4500
4533
  )
@@ -5258,10 +5291,12 @@ class CLIManager:
5258
5291
  wallet_hotkey: str = Options.wallet_hotkey,
5259
5292
  network: Optional[list[str]] = Options.network,
5260
5293
  netuid: int = Options.netuid,
5261
- era: Optional[
5294
+ period: Optional[
5262
5295
  int
5263
- ] = typer.Option( # Should not be Options.era bc this needs to be an Optional[int]
5296
+ ] = typer.Option( # Should not be Options.period bc this needs to be an Optional[int]
5264
5297
  None,
5298
+ "--period",
5299
+ "--era",
5265
5300
  help="Length (in blocks) for which the transaction should be valid. Note that it is possible that if you "
5266
5301
  "use an era for this transaction that you may pay a different fee to register than the one stated.",
5267
5302
  ),
@@ -5294,7 +5329,7 @@ class CLIManager:
5294
5329
  wallet,
5295
5330
  self.initialize_chain(network),
5296
5331
  netuid,
5297
- era,
5332
+ period,
5298
5333
  json_output,
5299
5334
  prompt,
5300
5335
  )
@@ -38,7 +38,6 @@ class Constants:
38
38
  "test": "0x8f9cf856bf558a14440e75569c9e58594757048d7b3a84b5d25f6bd978263105",
39
39
  }
40
40
  delegates_detail_url = "https://raw.githubusercontent.com/opentensor/bittensor-delegates/main/public/delegates.json"
41
- emission_start_schedule = 7 * 24 * 60 * 60 / 12 # 7 days
42
41
 
43
42
 
44
43
  @dataclass
@@ -640,7 +639,7 @@ HYPERPARAMS = {
640
639
  "activity_cutoff": ("sudo_set_activity_cutoff", False),
641
640
  "target_regs_per_interval": ("sudo_set_target_registrations_per_interval", True),
642
641
  "min_burn": ("sudo_set_min_burn", True),
643
- "max_burn": ("sudo_set_max_burn", False),
642
+ "max_burn": ("sudo_set_max_burn", True),
644
643
  "bonds_moving_avg": ("sudo_set_bonds_moving_average", False),
645
644
  "max_regs_per_block": ("sudo_set_max_registrations_per_block", True),
646
645
  "serving_rate_limit": ("sudo_set_serving_rate_limit", False),
@@ -678,7 +678,6 @@ async def burned_register_extrinsic(
678
678
  wait_for_inclusion: bool = True,
679
679
  wait_for_finalization: bool = True,
680
680
  era: Optional[int] = None,
681
- prompt: bool = False,
682
681
  ) -> tuple[bool, str]:
683
682
  """Registers the wallet to chain by recycling TAO.
684
683
 
@@ -290,7 +290,6 @@ async def root_register_extrinsic(
290
290
  wallet: Wallet,
291
291
  wait_for_inclusion: bool = True,
292
292
  wait_for_finalization: bool = True,
293
- prompt: bool = False,
294
293
  ) -> tuple[bool, str]:
295
294
  r"""Registers the wallet to root network.
296
295
 
@@ -238,25 +238,25 @@ class SubtensorInterface:
238
238
 
239
239
  :return: Balance: The stake under the coldkey - hotkey pairing.
240
240
  """
241
- alpha_shares = await self.query(
242
- module="SubtensorModule",
243
- storage_function="Alpha",
244
- params=[hotkey_ss58, coldkey_ss58, netuid],
245
- block_hash=block_hash,
246
- )
247
-
248
- hotkey_alpha = await self.query(
249
- module="SubtensorModule",
250
- storage_function="TotalHotkeyAlpha",
251
- params=[hotkey_ss58, netuid],
252
- block_hash=block_hash,
253
- )
254
-
255
- hotkey_shares = await self.query(
256
- module="SubtensorModule",
257
- storage_function="TotalHotkeyShares",
258
- params=[hotkey_ss58, netuid],
259
- block_hash=block_hash,
241
+ alpha_shares, hotkey_alpha, hotkey_shares = await asyncio.gather(
242
+ self.query(
243
+ module="SubtensorModule",
244
+ storage_function="Alpha",
245
+ params=[hotkey_ss58, coldkey_ss58, netuid],
246
+ block_hash=block_hash,
247
+ ),
248
+ self.query(
249
+ module="SubtensorModule",
250
+ storage_function="TotalHotkeyAlpha",
251
+ params=[hotkey_ss58, netuid],
252
+ block_hash=block_hash,
253
+ ),
254
+ self.query(
255
+ module="SubtensorModule",
256
+ storage_function="TotalHotkeyShares",
257
+ params=[hotkey_ss58, netuid],
258
+ block_hash=block_hash,
259
+ ),
260
260
  )
261
261
 
262
262
  alpha_shares_as_float = fixed_to_float(alpha_shares or 0)
@@ -558,7 +558,10 @@ def format_error_message(error_message: Union[dict, Exception]) -> str:
558
558
  err_type = error_message.get("type", err_type)
559
559
  err_name = error_message.get("name", err_name)
560
560
  err_docs = error_message.get("docs", [err_description])
561
- err_description = err_docs[0] if err_docs else err_description
561
+ if isinstance(err_docs, list):
562
+ err_description = " ".join(err_docs)
563
+ else:
564
+ err_description = err_docs
562
565
 
563
566
  return f"Subtensor returned `{err_name}({err_type})` error. This means: `{err_description}`."
564
567
 
@@ -1662,12 +1662,14 @@ async def register(
1662
1662
  subtensor,
1663
1663
  wallet=wallet,
1664
1664
  netuid=netuid,
1665
- prompt=False,
1666
1665
  old_balance=balance,
1667
1666
  era=era,
1668
1667
  )
1669
1668
  if json_output:
1670
1669
  json_console.print(json.dumps({"success": success, "msg": msg}))
1670
+ else:
1671
+ if not success:
1672
+ err_console.print(f"Failure: {msg}")
1671
1673
 
1672
1674
 
1673
1675
  # TODO: Confirm emissions, incentive, Dividends are to be fetched from subnet_state or keep NeuronInfo
@@ -2320,14 +2322,21 @@ async def get_start_schedule(
2320
2322
  if not await subtensor.subnet_exists(netuid):
2321
2323
  print_error(f"Subnet {netuid} does not exist.")
2322
2324
  return None
2323
-
2324
- registration_block = await subtensor.query(
2325
- module="SubtensorModule",
2326
- storage_function="NetworkRegisteredAt",
2327
- params=[netuid],
2325
+ block_hash = await subtensor.substrate.get_chain_head()
2326
+ registration_block, min_blocks_to_start, current_block = await asyncio.gather(
2327
+ subtensor.query(
2328
+ module="SubtensorModule",
2329
+ storage_function="NetworkRegisteredAt",
2330
+ params=[netuid],
2331
+ block_hash=block_hash,
2332
+ ),
2333
+ subtensor.substrate.get_constant(
2334
+ module_name="SubtensorModule",
2335
+ constant_name="DurationOfStartCall",
2336
+ block_hash=block_hash,
2337
+ ),
2338
+ subtensor.substrate.get_block_number(block_hash=block_hash),
2328
2339
  )
2329
- min_blocks_to_start = Constants.emission_start_schedule
2330
- current_block = await subtensor.substrate.get_block_number()
2331
2340
 
2332
2341
  potential_start_block = registration_block + min_blocks_to_start
2333
2342
  if current_block < potential_start_block:
@@ -2412,7 +2421,9 @@ async def start_subnet(
2412
2421
  else:
2413
2422
  error_msg = format_error_message(await response.error_message)
2414
2423
  if "FirstEmissionBlockNumberAlreadySet" in error_msg:
2415
- console.print(f"[dark_sea_green3]Subnet {netuid} already has an emission schedule.[/dark_sea_green3]")
2424
+ console.print(
2425
+ f"[dark_sea_green3]Subnet {netuid} already has an emission schedule.[/dark_sea_green3]"
2426
+ )
2416
2427
  return True
2417
2428
 
2418
2429
  await get_start_schedule(subtensor, netuid)
@@ -145,6 +145,7 @@ async def set_hyperparameter_extrinsic(
145
145
  value: Optional[Union[str, bool, float, list[float]]],
146
146
  wait_for_inclusion: bool = False,
147
147
  wait_for_finalization: bool = True,
148
+ prompt: bool = True,
148
149
  ) -> bool:
149
150
  """Sets a hyperparameter for a specific subnetwork.
150
151
 
@@ -190,7 +191,7 @@ async def set_hyperparameter_extrinsic(
190
191
  ":cross_mark: [red]Invalid hyperparameter specified.[/red]"
191
192
  )
192
193
  return False
193
- if sudo_:
194
+ if sudo_ and prompt:
194
195
  if not Confirm.ask(
195
196
  "This hyperparam is only settable by root sudo users. If you are not, this will fail. Please confirm"
196
197
  ):
@@ -574,6 +575,7 @@ async def sudo_set_hyperparameter(
574
575
  netuid: int,
575
576
  param_name: str,
576
577
  param_value: Optional[str],
578
+ prompt: bool,
577
579
  json_output: bool,
578
580
  ):
579
581
  """Set subnet hyperparameters."""
@@ -602,7 +604,7 @@ async def sudo_set_hyperparameter(
602
604
  )
603
605
  return False
604
606
  success = await set_hyperparameter_extrinsic(
605
- subtensor, wallet, netuid, param_name, value
607
+ subtensor, wallet, netuid, param_name, value, prompt=prompt
606
608
  )
607
609
  if json_output:
608
610
  return success
@@ -438,11 +438,10 @@ async def wallet_create(
438
438
  "name": wallet.name,
439
439
  "path": wallet.path,
440
440
  "hotkey": wallet.hotkey_str,
441
- "hotkey_ss58": wallet.hotkey.ss58_address,
442
441
  "coldkey_ss58": wallet.coldkeypub.ss58_address,
443
442
  }
444
- except KeyFileError:
445
- err = "KeyFileError: File is not writable"
443
+ except KeyFileError as error:
444
+ err = str(error)
446
445
  print_error(err)
447
446
  output_dict["error"] = err
448
447
  try:
@@ -458,10 +457,9 @@ async def wallet_create(
458
457
  "path": wallet.path,
459
458
  "hotkey": wallet.hotkey_str,
460
459
  "hotkey_ss58": wallet.hotkey.ss58_address,
461
- "coldkey_ss58": wallet.coldkeypub.ss58_address,
462
460
  }
463
- except KeyFileError:
464
- err = "KeyFileError: File is not writable"
461
+ except KeyFileError as error:
462
+ err = str(error)
465
463
  print_error(err)
466
464
  output_dict["error"] = err
467
465
  if json_output:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bittensor-cli
3
- Version: 9.4.0
3
+ Version: 9.4.2
4
4
  Summary: Bittensor CLI
5
5
  Author: bittensor.com
6
6
  Project-URL: homepage, https://github.com/opentensor/btcli
@@ -12,6 +12,7 @@ Requires-Dist: async-property==0.2.2
12
12
  Requires-Dist: async-substrate-interface>=1.1.0
13
13
  Requires-Dist: aiohttp~=3.10.2
14
14
  Requires-Dist: backoff~=2.2.1
15
+ Requires-Dist: click<8.2.0
15
16
  Requires-Dist: GitPython>=3.0.0
16
17
  Requires-Dist: fuzzywuzzy~=0.18.0
17
18
  Requires-Dist: netaddr~=1.3.0
@@ -72,7 +73,7 @@ Installation steps are described below. For a full documentation on how to use `
72
73
 
73
74
  ## Install on macOS and Linux
74
75
 
75
- You can install `btcli` on your local machine directly from source, or from from PyPI. **Make sure you verify your installation after you install**:
76
+ You can install `btcli` on your local machine directly from source, or from PyPI. **Make sure you verify your installation after you install**:
76
77
 
77
78
 
78
79
  ### Install from PyPI
@@ -3,6 +3,7 @@ async-property==0.2.2
3
3
  async-substrate-interface>=1.1.0
4
4
  aiohttp~=3.10.2
5
5
  backoff~=2.2.1
6
+ click<8.2.0
6
7
  GitPython>=3.0.0
7
8
  fuzzywuzzy~=0.18.0
8
9
  netaddr~=1.3.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "bittensor-cli"
7
- version = "9.4.0"
7
+ version = "9.4.2"
8
8
  description = "Bittensor CLI"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -19,6 +19,7 @@ dependencies = [
19
19
  "async-substrate-interface>=1.1.0",
20
20
  "aiohttp~=3.10.2",
21
21
  "backoff~=2.2.1",
22
+ "click<8.2.0", # typer.testing.CliRunner(mix_stderr=) is broken in click 8.2.0+
22
23
  "GitPython>=3.0.0",
23
24
  "fuzzywuzzy~=0.18.0",
24
25
  "netaddr~=1.3.0",
File without changes