bittensor-cli 9.9.0__py3-none-any.whl → 9.10.1__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
@@ -58,6 +58,7 @@ from bittensor_cli.src.bittensor.utils import (
58
58
  validate_uri,
59
59
  prompt_for_subnet_identity,
60
60
  validate_rate_tolerance,
61
+ get_hotkey_pub_ss58,
61
62
  )
62
63
  from bittensor_cli.src.commands import sudo, wallets, view
63
64
  from bittensor_cli.src.commands import weights as weights_cmds
@@ -250,7 +251,7 @@ class Options:
250
251
  True,
251
252
  "--prompt/--no-prompt",
252
253
  " /--yes",
253
- "--prompt/--no_prompt",
254
+ " /--no_prompt",
254
255
  " /-y",
255
256
  help="Enable or disable interactive prompts.",
256
257
  )
@@ -409,10 +410,15 @@ def get_optional_netuid(netuid: Optional[int], all_netuids: bool) -> Optional[in
409
410
  )
410
411
  if answer is None:
411
412
  return None
413
+ answer = answer.strip()
412
414
  if answer.lower() == "all":
413
415
  return None
414
416
  else:
415
- return int(answer)
417
+ try:
418
+ return int(answer)
419
+ except ValueError:
420
+ err_console.print(f"Invalid netuid: {answer}")
421
+ return get_optional_netuid(None, False)
416
422
  else:
417
423
  return netuid
418
424
 
@@ -643,8 +649,21 @@ class CLIManager:
643
649
  # },
644
650
  }
645
651
  self.subtensor = None
652
+
653
+ if sys.version_info < (3, 10):
654
+ # For Python 3.9 or lower
655
+ self.event_loop = asyncio.new_event_loop()
656
+ else:
657
+ try:
658
+ uvloop = importlib.import_module("uvloop")
659
+ self.event_loop = uvloop.new_event_loop()
660
+ except ModuleNotFoundError:
661
+ self.event_loop = asyncio.new_event_loop()
662
+
646
663
  self.config_base_path = os.path.expanduser(defaults.config.base_path)
647
- self.config_path = os.path.expanduser(defaults.config.path)
664
+ self.config_path = os.getenv("BTCLI_CONFIG_PATH") or os.path.expanduser(
665
+ defaults.config.path
666
+ )
648
667
 
649
668
  self.app = typer.Typer(
650
669
  rich_markup_mode="rich",
@@ -652,7 +671,12 @@ class CLIManager:
652
671
  epilog=_epilog,
653
672
  no_args_is_help=True,
654
673
  )
655
- self.config_app = typer.Typer(epilog=_epilog)
674
+ self.config_app = typer.Typer(
675
+ epilog=_epilog,
676
+ help=f"Allows for getting/setting the config. "
677
+ f"Default path for the config file is [{COLORS.G.ARG}]{defaults.config.path}[/{COLORS.G.ARG}]. "
678
+ f"You can set your own with the env var [{COLORS.G.ARG}]BTCLI_CONFIG_PATH[/{COLORS.G.ARG}]",
679
+ )
656
680
  self.wallet_app = typer.Typer(epilog=_epilog)
657
681
  self.stake_app = typer.Typer(epilog=_epilog)
658
682
  self.sudo_app = typer.Typer(epilog=_epilog)
@@ -773,6 +797,9 @@ class CLIManager:
773
797
  self.wallet_app.command(
774
798
  "regen-hotkey", rich_help_panel=HELP_PANELS["WALLET"]["SECURITY"]
775
799
  )(self.wallet_regen_hotkey)
800
+ self.wallet_app.command(
801
+ "regen-hotkeypub", rich_help_panel=HELP_PANELS["WALLET"]["SECURITY"]
802
+ )(self.wallet_regen_hotkey_pub)
776
803
  self.wallet_app.command(
777
804
  "new-hotkey", rich_help_panel=HELP_PANELS["WALLET"]["MANAGEMENT"]
778
805
  )(self.wallet_new_hotkey)
@@ -955,6 +982,10 @@ class CLIManager:
955
982
  "regen_hotkey",
956
983
  hidden=True,
957
984
  )(self.wallet_regen_hotkey)
985
+ self.wallet_app.command(
986
+ "regen_hotkeypub",
987
+ hidden=True,
988
+ )(self.wallet_regen_hotkey_pub)
958
989
  self.wallet_app.command(
959
990
  "new_hotkey",
960
991
  hidden=True,
@@ -1079,11 +1110,11 @@ class CLIManager:
1079
1110
 
1080
1111
  self.subtensor = SubtensorInterface(network_)
1081
1112
  elif self.config["network"]:
1082
- self.subtensor = SubtensorInterface(self.config["network"])
1083
1113
  console.print(
1084
1114
  f"Using the specified network [{COLORS.G.LINKS}]{self.config['network']}"
1085
1115
  f"[/{COLORS.G.LINKS}] from config"
1086
1116
  )
1117
+ self.subtensor = SubtensorInterface(self.config["network"])
1087
1118
  else:
1088
1119
  self.subtensor = SubtensorInterface(defaults.subtensor.network)
1089
1120
  return self.subtensor
@@ -1097,12 +1128,9 @@ class CLIManager:
1097
1128
  initiated = False
1098
1129
  try:
1099
1130
  if self.subtensor:
1100
- async with self.subtensor:
1101
- initiated = True
1102
- result = await cmd
1103
- else:
1104
- initiated = True
1105
- result = await cmd
1131
+ await self.subtensor.substrate.initialize()
1132
+ initiated = True
1133
+ result = await cmd
1106
1134
  return result
1107
1135
  except (ConnectionRefusedError, ssl.SSLError, InvalidHandshake):
1108
1136
  err_console.print(f"Unable to connect to the chain: {self.subtensor}")
@@ -1128,12 +1156,14 @@ class CLIManager:
1128
1156
  exit_early is True
1129
1157
  ): # temporarily to handle multiple run commands in one session
1130
1158
  try:
1159
+ if self.subtensor:
1160
+ await self.subtensor.substrate.close()
1131
1161
  raise typer.Exit()
1132
1162
  except Exception as e: # ensures we always exit cleanly
1133
1163
  if not isinstance(e, (typer.Exit, RuntimeError)):
1134
1164
  err_console.print(f"An unknown error has occurred: {e}")
1135
1165
 
1136
- return self.asyncio_runner(_run())
1166
+ return self.event_loop.run_until_complete(_run())
1137
1167
 
1138
1168
  def main_callback(
1139
1169
  self,
@@ -1184,20 +1214,6 @@ class CLIManager:
1184
1214
  if k in self.config.keys():
1185
1215
  self.config[k] = v
1186
1216
 
1187
- if sys.version_info < (3, 10):
1188
- # For Python 3.9 or lower
1189
- self.asyncio_runner = asyncio.get_event_loop().run_until_complete
1190
- else:
1191
- try:
1192
- uvloop = importlib.import_module("uvloop")
1193
- if sys.version_info >= (3, 11):
1194
- self.asyncio_runner = uvloop.run
1195
- else:
1196
- uvloop.install()
1197
- self.asyncio_runner = asyncio.run
1198
- except ModuleNotFoundError:
1199
- self.asyncio_runner = asyncio.run
1200
-
1201
1217
  def verbosity_handler(
1202
1218
  self, quiet: bool, verbose: bool, json_output: bool = False
1203
1219
  ) -> None:
@@ -1253,7 +1269,7 @@ class CLIManager:
1253
1269
  use_cache: Optional[bool] = typer.Option(
1254
1270
  None,
1255
1271
  "--cache/--no-cache",
1256
- "--cache/--no_cache",
1272
+ " /--no_cache",
1257
1273
  help="Disable caching of some commands. This will disable the `--reuse-last` and `--html` flags on "
1258
1274
  "commands such as `subnets metagraph`, `stake show` and `subnets list`.",
1259
1275
  ),
@@ -1502,6 +1518,8 @@ class CLIManager:
1502
1518
  Column("[bold white]Value", style="gold1"),
1503
1519
  Column("", style="medium_purple"),
1504
1520
  box=box.SIMPLE_HEAD,
1521
+ title=f"[{COLORS.G.HEADER}]BTCLI Config[/{COLORS.G.HEADER}]: "
1522
+ f"[{COLORS.G.ARG}]{self.config_path}[/{COLORS.G.ARG}]",
1505
1523
  )
1506
1524
 
1507
1525
  for key, value in self.config.items():
@@ -1722,7 +1740,7 @@ class CLIManager:
1722
1740
  if return_wallet_and_hotkey:
1723
1741
  valid = utils.is_valid_wallet(wallet)
1724
1742
  if valid[1]:
1725
- return wallet, wallet.hotkey.ss58_address
1743
+ return wallet, get_hotkey_pub_ss58(wallet)
1726
1744
  else:
1727
1745
  if wallet_hotkey and is_valid_ss58_address(wallet_hotkey):
1728
1746
  return wallet, wallet_hotkey
@@ -2229,14 +2247,15 @@ class CLIManager:
2229
2247
 
2230
2248
  if not wallet_path:
2231
2249
  wallet_path = Prompt.ask(
2232
- "Enter the path for the wallets directory", default=defaults.wallet.path
2250
+ "Enter the path for the wallets directory",
2251
+ default=self.config.get("wallet_path") or defaults.wallet.path,
2233
2252
  )
2234
2253
  wallet_path = os.path.expanduser(wallet_path)
2235
2254
 
2236
2255
  if not wallet_name:
2237
2256
  wallet_name = Prompt.ask(
2238
2257
  f"Enter the name of the [{COLORS.G.CK}]new wallet (coldkey)",
2239
- default=defaults.wallet.name,
2258
+ default=self.config.get("wallet_name") or defaults.wallet.name,
2240
2259
  )
2241
2260
 
2242
2261
  wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
@@ -2280,7 +2299,7 @@ class CLIManager:
2280
2299
 
2281
2300
  EXAMPLE
2282
2301
 
2283
- [green]$[/green] btcli wallet regen_coldkeypub --ss58_address 5DkQ4...
2302
+ [green]$[/green] btcli wallet regen-coldkeypub --ss58_address 5DkQ4...
2284
2303
 
2285
2304
  [bold]Note[/bold]: This command is particularly useful for users who need to regenerate their coldkeypub, perhaps due to file corruption or loss. You will need either ss58 address or public hex key from your old coldkeypub.txt for the wallet. It is a recovery-focused utility that ensures continued access to your wallet functionalities.
2286
2305
  """
@@ -2288,13 +2307,14 @@ class CLIManager:
2288
2307
 
2289
2308
  if not wallet_path:
2290
2309
  wallet_path = Prompt.ask(
2291
- "Enter the path to the wallets directory", default=defaults.wallet.path
2310
+ "Enter the path to the wallets directory",
2311
+ default=self.config.get("wallet_path") or defaults.wallet.path,
2292
2312
  )
2293
2313
  wallet_path = os.path.expanduser(wallet_path)
2294
2314
 
2295
2315
  if not wallet_name:
2296
2316
  wallet_name = Prompt.ask(
2297
- f"Enter the name of the [{COLORS.G.CK}]new wallet (coldkey)",
2317
+ f"Enter the name of the [{COLORS.G.CK}]wallet for the new coldkeypub",
2298
2318
  default=defaults.wallet.name,
2299
2319
  )
2300
2320
  wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
@@ -2311,7 +2331,7 @@ class CLIManager:
2311
2331
  address=ss58_address if ss58_address else public_key_hex
2312
2332
  ):
2313
2333
  rich.print("[red]Error: Invalid SS58 address or public key![/red]")
2314
- raise typer.Exit()
2334
+ return
2315
2335
  return self._run_command(
2316
2336
  wallets.regen_coldkey_pub(
2317
2337
  wallet, ss58_address, public_key_hex, overwrite, json_output
@@ -2377,6 +2397,68 @@ class CLIManager:
2377
2397
  )
2378
2398
  )
2379
2399
 
2400
+ def wallet_regen_hotkey_pub(
2401
+ self,
2402
+ wallet_name: Optional[str] = Options.wallet_name,
2403
+ wallet_path: Optional[str] = Options.wallet_path,
2404
+ wallet_hotkey: Optional[str] = Options.wallet_hotkey,
2405
+ public_key_hex: Optional[str] = Options.public_hex_key,
2406
+ ss58_address: Optional[str] = Options.ss58_address,
2407
+ overwrite: bool = Options.overwrite,
2408
+ quiet: bool = Options.quiet,
2409
+ verbose: bool = Options.verbose,
2410
+ json_output: bool = Options.json_output,
2411
+ ):
2412
+ """
2413
+ Regenerates the public part of a hotkey (hotkeypub.txt) for a wallet.
2414
+
2415
+ Use this command when you need to move machine for subnet mining. Use the public key or SS58 address from your hotkeypub.txt that you have on another machine to regenerate the hotkeypub.txt on this new machine.
2416
+
2417
+ USAGE
2418
+
2419
+ The command requires either a public key in hexadecimal format or an ``SS58`` address from the existing hotkeypub.txt from old machine to regenerate the coldkeypub on the new machine.
2420
+
2421
+ EXAMPLE
2422
+
2423
+ [green]$[/green] btcli wallet regen-hotkeypub --ss58_address 5DkQ4...
2424
+
2425
+ [bold]Note[/bold]: This command is particularly useful for users who need to regenerate their hotkeypub, perhaps due to file corruption or loss. You will need either ss58 address or public hex key from your old hotkeypub.txt for the wallet. It is a recovery-focused utility that ensures continued access to your wallet functionalities.
2426
+ """
2427
+ self.verbosity_handler(quiet, verbose, json_output)
2428
+
2429
+ if not wallet_path:
2430
+ wallet_path = Prompt.ask(
2431
+ "Enter the path to the wallets directory",
2432
+ default=self.config.get("wallet_path") or defaults.wallet.path,
2433
+ )
2434
+ wallet_path = os.path.expanduser(wallet_path)
2435
+
2436
+ if not wallet_name:
2437
+ wallet_name = Prompt.ask(
2438
+ f"Enter the name of the [{COLORS.G.CK}]wallet for the new hotkeypub",
2439
+ default=defaults.wallet.name,
2440
+ )
2441
+ wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
2442
+
2443
+ if not ss58_address and not public_key_hex:
2444
+ prompt_answer = typer.prompt(
2445
+ "Enter the ss58_address or the public key in hex"
2446
+ )
2447
+ if prompt_answer.startswith("0x"):
2448
+ public_key_hex = prompt_answer
2449
+ else:
2450
+ ss58_address = prompt_answer
2451
+ if not utils.is_valid_bittensor_address_or_public_key(
2452
+ address=ss58_address if ss58_address else public_key_hex
2453
+ ):
2454
+ rich.print("[red]Error: Invalid SS58 address or public key![/red]")
2455
+ return False
2456
+ return self._run_command(
2457
+ wallets.regen_hotkey_pub(
2458
+ wallet, ss58_address, public_key_hex, overwrite, json_output
2459
+ )
2460
+ )
2461
+
2380
2462
  def wallet_new_hotkey(
2381
2463
  self,
2382
2464
  wallet_name: Optional[str] = Options.wallet_name,
@@ -2417,7 +2499,7 @@ class CLIManager:
2417
2499
  if not wallet_name:
2418
2500
  wallet_name = Prompt.ask(
2419
2501
  f"Enter the [{COLORS.G.CK}]wallet name",
2420
- default=defaults.wallet.name,
2502
+ default=self.config.get("wallet_name") or defaults.wallet.name,
2421
2503
  )
2422
2504
 
2423
2505
  if not wallet_hotkey:
@@ -2472,11 +2554,11 @@ class CLIManager:
2472
2554
  if not wallet_hotkey:
2473
2555
  wallet_hotkey = Prompt.ask(
2474
2556
  "Enter the [blue]hotkey[/blue] name or "
2475
- "[blue]hotkey ss58 address[/blue] [dim](to associate with your coldkey)[/dim]"
2557
+ "[blue]hotkey ss58 address[/blue] [dim](to associate with your coldkey)[/dim]",
2558
+ default=self.config.get("wallet_hotkey") or defaults.wallet.hotkey,
2476
2559
  )
2477
2560
 
2478
- hotkey_display = None
2479
- if is_valid_ss58_address(wallet_hotkey):
2561
+ if wallet_hotkey and is_valid_ss58_address(wallet_hotkey):
2480
2562
  hotkey_ss58 = wallet_hotkey
2481
2563
  wallet = self.wallet_ask(
2482
2564
  wallet_name,
@@ -2496,8 +2578,11 @@ class CLIManager:
2496
2578
  ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
2497
2579
  validate=WV.WALLET_AND_HOTKEY,
2498
2580
  )
2499
- hotkey_ss58 = wallet.hotkey.ss58_address
2500
- hotkey_display = f"hotkey [blue]{wallet_hotkey}[/blue] [{COLORS.GENERAL.HK}]({hotkey_ss58})[/{COLORS.GENERAL.HK}]"
2581
+ hotkey_ss58 = get_hotkey_pub_ss58(wallet)
2582
+ hotkey_display = (
2583
+ f"hotkey [blue]{wallet_hotkey}[/blue] "
2584
+ f"[{COLORS.GENERAL.HK}]({hotkey_ss58})[/{COLORS.GENERAL.HK}]"
2585
+ )
2501
2586
 
2502
2587
  return self._run_command(
2503
2588
  wallets.associate_hotkey(
@@ -2544,13 +2629,14 @@ class CLIManager:
2544
2629
 
2545
2630
  if not wallet_path:
2546
2631
  wallet_path = Prompt.ask(
2547
- "Enter the path to the wallets directory", default=defaults.wallet.path
2632
+ "Enter the path to the wallets directory",
2633
+ default=self.config.get("wallet_path") or defaults.wallet.path,
2548
2634
  )
2549
2635
 
2550
2636
  if not wallet_name:
2551
2637
  wallet_name = Prompt.ask(
2552
2638
  f"Enter the name of the [{COLORS.G.CK}]new wallet (coldkey)",
2553
- default=defaults.wallet.name,
2639
+ default=self.config.get("wallet_name") or defaults.wallet.name,
2554
2640
  )
2555
2641
 
2556
2642
  wallet = self.wallet_ask(
@@ -2623,7 +2709,8 @@ class CLIManager:
2623
2709
 
2624
2710
  if not wallet_ss58_address:
2625
2711
  wallet_ss58_address = Prompt.ask(
2626
- "Enter [blue]wallet name[/blue] or [blue]SS58 address[/blue] [dim](leave blank to show all pending swaps)[/dim]"
2712
+ "Enter [blue]wallet name[/blue] or [blue]SS58 address[/blue] [dim]"
2713
+ "(leave blank to show all pending swaps)[/dim]"
2627
2714
  )
2628
2715
  if not wallet_ss58_address:
2629
2716
  return self._run_command(
@@ -2687,18 +2774,18 @@ class CLIManager:
2687
2774
  self.verbosity_handler(quiet, verbose, json_output)
2688
2775
  if not wallet_path:
2689
2776
  wallet_path = Prompt.ask(
2690
- "Enter the path of wallets directory", default=defaults.wallet.path
2777
+ "Enter the path of wallets directory",
2778
+ default=self.config.get("wallet_path") or defaults.wallet.path,
2691
2779
  )
2692
2780
 
2693
2781
  if not wallet_name:
2694
2782
  wallet_name = Prompt.ask(
2695
2783
  f"Enter the name of the [{COLORS.G.CK}]new wallet (coldkey)",
2696
- default=defaults.wallet.name,
2697
2784
  )
2698
2785
  if not wallet_hotkey:
2699
2786
  wallet_hotkey = Prompt.ask(
2700
2787
  f"Enter the the name of the [{COLORS.G.HK}]new hotkey",
2701
- default=defaults.wallet.hotkey,
2788
+ default=self.config.get("wallet_hotkey") or defaults.wallet.hotkey,
2702
2789
  )
2703
2790
 
2704
2791
  wallet = self.wallet_ask(
@@ -3507,7 +3594,7 @@ class CLIManager:
3507
3594
  ask_for=[WO.NAME, WO.HOTKEY, WO.PATH],
3508
3595
  validate=WV.WALLET_AND_HOTKEY,
3509
3596
  )
3510
- include_hotkeys = wallet.hotkey.ss58_address
3597
+ include_hotkeys = get_hotkey_pub_ss58(wallet)
3511
3598
 
3512
3599
  elif all_hotkeys or include_hotkeys or exclude_hotkeys:
3513
3600
  wallet = self.wallet_ask(
@@ -3971,7 +4058,7 @@ class CLIManager:
3971
4058
  ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
3972
4059
  validate=WV.WALLET_AND_HOTKEY,
3973
4060
  )
3974
- destination_hotkey = destination_wallet.hotkey.ss58_address
4061
+ destination_hotkey = get_hotkey_pub_ss58(destination_wallet)
3975
4062
  else:
3976
4063
  if is_valid_ss58_address(destination_hotkey):
3977
4064
  destination_hotkey = destination_hotkey
@@ -4010,7 +4097,7 @@ class CLIManager:
4010
4097
  ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
4011
4098
  validate=WV.WALLET_AND_HOTKEY,
4012
4099
  )
4013
- origin_hotkey = wallet.hotkey.ss58_address
4100
+ origin_hotkey = get_hotkey_pub_ss58(wallet)
4014
4101
  else:
4015
4102
  if is_valid_ss58_address(wallet_hotkey):
4016
4103
  origin_hotkey = wallet_hotkey
@@ -4022,7 +4109,7 @@ class CLIManager:
4022
4109
  ask_for=[],
4023
4110
  validate=WV.WALLET_AND_HOTKEY,
4024
4111
  )
4025
- origin_hotkey = wallet.hotkey.ss58_address
4112
+ origin_hotkey = get_hotkey_pub_ss58(wallet)
4026
4113
 
4027
4114
  if not interactive_selection:
4028
4115
  if origin_netuid is None:
@@ -4158,7 +4245,8 @@ class CLIManager:
4158
4245
  interactive_selection = False
4159
4246
  if not wallet_hotkey:
4160
4247
  origin_hotkey = Prompt.ask(
4161
- "Enter the [blue]origin hotkey[/blue] name or ss58 address [bold](stake will be transferred FROM here)[/bold] "
4248
+ "Enter the [blue]origin hotkey[/blue] name or ss58 address [bold]"
4249
+ "(stake will be transferred FROM here)[/bold] "
4162
4250
  "[dim](or press Enter to select from existing stakes)[/dim]"
4163
4251
  )
4164
4252
  if origin_hotkey == "":
@@ -4174,7 +4262,7 @@ class CLIManager:
4174
4262
  ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
4175
4263
  validate=WV.WALLET_AND_HOTKEY,
4176
4264
  )
4177
- origin_hotkey = wallet.hotkey.ss58_address
4265
+ origin_hotkey = get_hotkey_pub_ss58(wallet)
4178
4266
  else:
4179
4267
  if is_valid_ss58_address(wallet_hotkey):
4180
4268
  origin_hotkey = wallet_hotkey
@@ -4186,7 +4274,7 @@ class CLIManager:
4186
4274
  ask_for=[],
4187
4275
  validate=WV.WALLET_AND_HOTKEY,
4188
4276
  )
4189
- origin_hotkey = wallet.hotkey.ss58_address
4277
+ origin_hotkey = get_hotkey_pub_ss58(wallet)
4190
4278
 
4191
4279
  if not interactive_selection:
4192
4280
  if origin_netuid is None:
@@ -4733,7 +4821,7 @@ class CLIManager:
4733
4821
  wallet = self.wallet_ask(
4734
4822
  wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
4735
4823
  )
4736
- result = self._run_command(
4824
+ result, err_msg = self._run_command(
4737
4825
  sudo.sudo_set_hyperparameter(
4738
4826
  wallet,
4739
4827
  self.initialize_chain(network),
@@ -4745,7 +4833,7 @@ class CLIManager:
4745
4833
  )
4746
4834
  )
4747
4835
  if json_output:
4748
- json_console.print(json.dumps({"success": result}))
4836
+ json_console.print(json.dumps({"success": result, "err_msg": err_msg}))
4749
4837
  return result
4750
4838
 
4751
4839
  def sudo_get(
@@ -5009,7 +5097,7 @@ class CLIManager:
5009
5097
  "Netuids to show the price for. Separate multiple netuids with a comma, for example: `-n 0,1,2`.",
5010
5098
  ),
5011
5099
  interval_hours: int = typer.Option(
5012
- 24,
5100
+ 4,
5013
5101
  "--interval-hours",
5014
5102
  "--interval",
5015
5103
  help="The number of hours to show the historical price for.",
@@ -5026,6 +5114,11 @@ class CLIManager:
5026
5114
  "--log",
5027
5115
  help="Show the price in log scale.",
5028
5116
  ),
5117
+ current_only: bool = typer.Option(
5118
+ False,
5119
+ "--current",
5120
+ help="Show only the current data, and no historical data.",
5121
+ ),
5029
5122
  html_output: bool = Options.html_output,
5030
5123
  quiet: bool = Options.quiet,
5031
5124
  verbose: bool = Options.verbose,
@@ -5048,9 +5141,31 @@ class CLIManager:
5048
5141
  [green]$[/green] btcli subnets price --netuids 1,2,3,4 --html
5049
5142
  """
5050
5143
  if json_output and html_output:
5051
- print_error("Cannot specify both `--json-output` and `--html`")
5144
+ print_error(
5145
+ f"Cannot specify both [{COLORS.G.ARG}]--json-output[/{COLORS.G.ARG}] "
5146
+ f"and [{COLORS.G.ARG}]--html[/{COLORS.G.ARG}]"
5147
+ )
5148
+ return
5149
+ if current_only and html_output:
5150
+ print_error(
5151
+ f"Cannot specify both [{COLORS.G.ARG}]--current[/{COLORS.G.ARG}] "
5152
+ f"and [{COLORS.G.ARG}]--html[/{COLORS.G.ARG}]"
5153
+ )
5052
5154
  return
5053
5155
  self.verbosity_handler(quiet=quiet, verbose=verbose, json_output=json_output)
5156
+
5157
+ subtensor = self.initialize_chain(network)
5158
+ non_archives = ["finney", "latent-lite", "subvortex"]
5159
+ if not current_only and subtensor.network in non_archives + [
5160
+ Constants.network_map[x] for x in non_archives
5161
+ ]:
5162
+ err_console.print(
5163
+ f"[red]Error[/red] Running this command without [{COLORS.G.ARG}]--current[/{COLORS.G.ARG}] requires "
5164
+ "use of an archive node. "
5165
+ f"Try running again with the [{COLORS.G.ARG}]--network archive[/{COLORS.G.ARG}] flag."
5166
+ )
5167
+ return False
5168
+
5054
5169
  if netuids:
5055
5170
  netuids = parse_to_list(
5056
5171
  netuids,
@@ -5080,10 +5195,11 @@ class CLIManager:
5080
5195
 
5081
5196
  return self._run_command(
5082
5197
  price.price(
5083
- self.initialize_chain(network),
5198
+ subtensor,
5084
5199
  netuids,
5085
5200
  all_netuids,
5086
5201
  interval_hours,
5202
+ current_only,
5087
5203
  html_output,
5088
5204
  log_scale,
5089
5205
  json_output,
@@ -631,10 +631,10 @@ HYPERPARAMS = {
631
631
  "min_allowed_weights": ("sudo_set_min_allowed_weights", False),
632
632
  "max_weights_limit": ("sudo_set_max_weight_limit", False),
633
633
  "tempo": ("sudo_set_tempo", True),
634
- "min_difficulty": ("sudo_set_min_difficulty", False),
634
+ "min_difficulty": ("sudo_set_min_difficulty", True),
635
635
  "max_difficulty": ("sudo_set_max_difficulty", False),
636
636
  "weights_version": ("sudo_set_weights_version_key", False),
637
- "weights_rate_limit": ("sudo_set_weights_set_rate_limit", False),
637
+ "weights_rate_limit": ("sudo_set_weights_set_rate_limit", True),
638
638
  "adjustment_interval": ("sudo_set_adjustment_interval", True),
639
639
  "activity_cutoff": ("sudo_set_activity_cutoff", False),
640
640
  "target_regs_per_interval": ("sudo_set_target_registrations_per_interval", True),
@@ -645,7 +645,7 @@ HYPERPARAMS = {
645
645
  "serving_rate_limit": ("sudo_set_serving_rate_limit", False),
646
646
  "max_validators": ("sudo_set_max_allowed_validators", True),
647
647
  "adjustment_alpha": ("sudo_set_adjustment_alpha", False),
648
- "difficulty": ("sudo_set_difficulty", False),
648
+ "difficulty": ("sudo_set_difficulty", True),
649
649
  "commit_reveal_period": (
650
650
  "sudo_set_commit_reveal_weights_interval",
651
651
  False,
@@ -653,7 +653,7 @@ HYPERPARAMS = {
653
653
  "commit_reveal_weights_enabled": ("sudo_set_commit_reveal_weights_enabled", False),
654
654
  "alpha_values": ("sudo_set_alpha_values", False),
655
655
  "liquid_alpha_enabled": ("sudo_set_liquid_alpha_enabled", False),
656
- "registration_allowed": ("sudo_set_network_registration_allowed", False),
656
+ "registration_allowed": ("sudo_set_network_registration_allowed", True),
657
657
  "network_pow_registration_allowed": (
658
658
  "sudo_set_network_pow_registration_allowed",
659
659
  False,
@@ -718,6 +718,7 @@ class DynamicInfo(InfoBase):
718
718
  network_registered_at: int
719
719
  subnet_identity: Optional[SubnetIdentity]
720
720
  subnet_volume: Balance
721
+ moving_price: float
721
722
 
722
723
  @classmethod
723
724
  def _fix_decoded(cls, decoded: Any) -> "DynamicInfo":
@@ -786,6 +787,7 @@ class DynamicInfo(InfoBase):
786
787
  network_registered_at=int(decoded.get("network_registered_at")),
787
788
  subnet_identity=subnet_identity,
788
789
  subnet_volume=subnet_volume,
790
+ moving_price=fixed_to_float(decoded["moving_price"], 32),
789
791
  )
790
792
 
791
793
  def tao_to_alpha(self, tao: Balance) -> Balance: