bittensor-cli 8.3.0__py3-none-any.whl → 8.4.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/__init__.py CHANGED
@@ -18,6 +18,6 @@
18
18
  from .cli import CLIManager
19
19
 
20
20
 
21
- __version__ = "8.3.0"
21
+ __version__ = "8.4.0"
22
22
 
23
23
  __all__ = ["CLIManager", "__version__"]
bittensor_cli/cli.py CHANGED
@@ -7,6 +7,7 @@ import os.path
7
7
  import re
8
8
  import ssl
9
9
  import sys
10
+ import traceback
10
11
  from pathlib import Path
11
12
  from typing import Coroutine, Optional
12
13
  from dataclasses import fields
@@ -57,7 +58,7 @@ except ImportError:
57
58
  pass
58
59
 
59
60
 
60
- __version__ = "8.3.0"
61
+ __version__ = "8.4.0"
61
62
 
62
63
 
63
64
  _core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0)
@@ -126,8 +127,6 @@ class Options:
126
127
  use_password = typer.Option(
127
128
  True,
128
129
  help="Set this to `True` to protect the generated Bittensor key with a password.",
129
- is_flag=True,
130
- flag_value=False,
131
130
  )
132
131
  public_hex_key = typer.Option(None, help="The public key in hex format.")
133
132
  ss58_address = typer.Option(
@@ -840,6 +839,7 @@ class CLIManager:
840
839
  return result
841
840
  except (ConnectionRefusedError, ssl.SSLError):
842
841
  err_console.print(f"Unable to connect to the chain: {self.subtensor}")
842
+ verbose_console.print(traceback.format_exc())
843
843
  except (
844
844
  ConnectionClosed,
845
845
  SubstrateRequestException,
@@ -847,6 +847,10 @@ class CLIManager:
847
847
  ) as e:
848
848
  if isinstance(e, SubstrateRequestException):
849
849
  err_console.print(str(e))
850
+ verbose_console.print(traceback.format_exc())
851
+ except Exception as e:
852
+ err_console.print(f"An unknown error has occurred: {e}")
853
+ verbose_console.print(traceback.format_exc())
850
854
  finally:
851
855
  if initiated is False:
852
856
  asyncio.create_task(cmd).cancel()
@@ -1837,8 +1841,6 @@ class CLIManager:
1837
1841
  use_password: bool = typer.Option(
1838
1842
  False, # Overriden to False
1839
1843
  help="Set to 'True' to protect the generated Bittensor key with a password.",
1840
- is_flag=True,
1841
- flag_value=True,
1842
1844
  ),
1843
1845
  quiet: bool = Options.quiet,
1844
1846
  verbose: bool = Options.verbose,
@@ -1895,8 +1897,6 @@ class CLIManager:
1895
1897
  use_password: bool = typer.Option(
1896
1898
  False, # Overriden to False
1897
1899
  help="Set to 'True' to protect the generated Bittensor key with a password.",
1898
- is_flag=True,
1899
- flag_value=True,
1900
1900
  ),
1901
1901
  quiet: bool = Options.quiet,
1902
1902
  verbose: bool = Options.verbose,
@@ -3904,6 +3904,16 @@ class CLIManager:
3904
3904
  )
3905
3905
  param_name = hyperparam_list[choice - 1]
3906
3906
 
3907
+ if param_name in ["alpha_high", "alpha_low"]:
3908
+ param_name = "alpha_values"
3909
+ low_val = FloatPrompt.ask(
3910
+ "Enter the new value for [dark_orange]alpha_low[/dark_orange]"
3911
+ )
3912
+ high_val = FloatPrompt.ask(
3913
+ "Enter the new value for [dark_orange]alpha_high[/dark_orange]"
3914
+ )
3915
+ param_value = f"{low_val},{high_val}"
3916
+
3907
3917
  if not param_value:
3908
3918
  param_value = Prompt.ask(
3909
3919
  f"Enter the new value for [dark_orange]{param_name}[/dark_orange] in the VALUE column format"
@@ -318,28 +318,32 @@ NETWORK_EXPLORER_MAP = {
318
318
 
319
319
 
320
320
  HYPERPARAMS = {
321
- "serving_rate_limit": "sudo_set_serving_rate_limit",
321
+ "rho": "sudo_set_rho",
322
+ "kappa": "sudo_set_kappa",
323
+ "immunity_period": "sudo_set_immunity_period",
324
+ "min_allowed_weights": "sudo_set_min_allowed_weights",
325
+ "max_weights_limit": "sudo_set_max_weight_limit",
326
+ "tempo": "sudo_set_tempo",
322
327
  "min_difficulty": "sudo_set_min_difficulty",
323
328
  "max_difficulty": "sudo_set_max_difficulty",
324
329
  "weights_version": "sudo_set_weights_version_key",
325
330
  "weights_rate_limit": "sudo_set_weights_set_rate_limit",
326
- "max_weight_limit": "sudo_set_max_weight_limit",
327
- "immunity_period": "sudo_set_immunity_period",
328
- "min_allowed_weights": "sudo_set_min_allowed_weights",
331
+ "adjustment_interval": "sudo_set_adjustment_interval",
329
332
  "activity_cutoff": "sudo_set_activity_cutoff",
330
- "network_registration_allowed": "sudo_set_network_registration_allowed",
331
- "network_pow_registration_allowed": "sudo_set_network_pow_registration_allowed",
333
+ "target_regs_per_interval": "sudo_set_target_registrations_per_interval",
332
334
  "min_burn": "sudo_set_min_burn",
333
335
  "max_burn": "sudo_set_max_burn",
336
+ "bonds_moving_avg": "sudo_set_bonds_moving_average",
337
+ "max_regs_per_block": "sudo_set_max_registrations_per_block",
338
+ "serving_rate_limit": "sudo_set_serving_rate_limit",
339
+ "max_validators": "sudo_set_max_allowed_validators",
334
340
  "adjustment_alpha": "sudo_set_adjustment_alpha",
335
- "rho": "sudo_set_rho",
336
- "kappa": "sudo_set_kappa",
337
341
  "difficulty": "sudo_set_difficulty",
338
- "bonds_moving_avg": "sudo_set_bonds_moving_average",
339
342
  "commit_reveal_weights_interval": "sudo_set_commit_reveal_weights_interval",
340
343
  "commit_reveal_weights_enabled": "sudo_set_commit_reveal_weights_enabled",
341
344
  "alpha_values": "sudo_set_alpha_values",
342
345
  "liquid_alpha_enabled": "sudo_set_liquid_alpha_enabled",
346
+ "registration_allowed": "sudo_set_network_registration_allowed",
343
347
  }
344
348
 
345
349
  # Help Panels for cli help
@@ -4,22 +4,28 @@ import random
4
4
  from collections import defaultdict
5
5
  from dataclasses import dataclass
6
6
  from hashlib import blake2b
7
- from typing import Optional, Any, Union, Callable, Awaitable, cast
7
+ from typing import Optional, Any, Union, Callable, Awaitable, cast, TYPE_CHECKING
8
8
 
9
- from bt_decode import PortableRegistry, decode as decode_by_type_string, MetadataV15
10
9
  from async_property import async_property
10
+ from bt_decode import PortableRegistry, decode as decode_by_type_string, MetadataV15
11
+ from bittensor_wallet import Keypair
11
12
  from scalecodec import GenericExtrinsic
12
13
  from scalecodec.base import ScaleBytes, ScaleType, RuntimeConfigurationObject
13
14
  from scalecodec.type_registry import load_type_registry_preset
14
15
  from scalecodec.types import GenericCall
15
- from bittensor_wallet import Keypair
16
16
  from substrateinterface.exceptions import (
17
17
  SubstrateRequestException,
18
18
  ExtrinsicNotFound,
19
19
  BlockNotFound,
20
20
  )
21
21
  from substrateinterface.storage import StorageKey
22
- import websockets
22
+ from websockets.asyncio.client import connect
23
+ from websockets.exceptions import ConnectionClosed
24
+
25
+ from bittensor_cli.src.bittensor.utils import hex_to_bytes
26
+
27
+ if TYPE_CHECKING:
28
+ from websockets.asyncio.client import ClientConnection
23
29
 
24
30
  ResultHandler = Callable[[dict, Any], Awaitable[tuple[dict, bool]]]
25
31
 
@@ -433,7 +439,7 @@ class RuntimeCache:
433
439
  self.block_hashes[block_hash] = runtime
434
440
 
435
441
  def retrieve(
436
- self, block: Optional[int], block_hash: Optional[str]
442
+ self, block: Optional[int] = None, block_hash: Optional[str] = None
437
443
  ) -> Optional["Runtime"]:
438
444
  if block is not None:
439
445
  return self.blocks.get(block)
@@ -624,7 +630,7 @@ class Websocket:
624
630
  # TODO allow setting max concurrent connections and rpc subscriptions per connection
625
631
  # TODO reconnection logic
626
632
  self.ws_url = ws_url
627
- self.ws: Optional[websockets.WebSocketClientProtocol] = None
633
+ self.ws: Optional["ClientConnection"] = None
628
634
  self.id = 0
629
635
  self.max_subscriptions = max_subscriptions
630
636
  self.max_connections = max_connections
@@ -646,15 +652,12 @@ class Websocket:
646
652
  self._exit_task.cancel()
647
653
  if not self._initialized:
648
654
  self._initialized = True
649
- await self._connect()
655
+ self.ws = await asyncio.wait_for(
656
+ connect(self.ws_url, **self._options), timeout=10
657
+ )
650
658
  self._receiving_task = asyncio.create_task(self._start_receiving())
651
659
  return self
652
660
 
653
- async def _connect(self):
654
- self.ws = await asyncio.wait_for(
655
- websockets.connect(self.ws_url, **self._options), timeout=10
656
- )
657
-
658
661
  async def __aexit__(self, exc_type, exc_val, exc_tb):
659
662
  async with self._lock:
660
663
  self._in_use -= 1
@@ -695,9 +698,7 @@ class Websocket:
695
698
 
696
699
  async def _recv(self) -> None:
697
700
  try:
698
- response = json.loads(
699
- await cast(websockets.WebSocketClientProtocol, self.ws).recv()
700
- )
701
+ response = json.loads(await self.ws.recv())
701
702
  async with self._lock:
702
703
  self._open_subscriptions -= 1
703
704
  if "id" in response:
@@ -706,7 +707,7 @@ class Websocket:
706
707
  self._received[response["params"]["subscription"]] = response
707
708
  else:
708
709
  raise KeyError(response)
709
- except websockets.ConnectionClosed:
710
+ except ConnectionClosed:
710
711
  raise
711
712
  except KeyError as e:
712
713
  raise e
@@ -717,7 +718,7 @@ class Websocket:
717
718
  await self._recv()
718
719
  except asyncio.CancelledError:
719
720
  pass
720
- except websockets.ConnectionClosed:
721
+ except ConnectionClosed:
721
722
  # TODO try reconnect, but only if it's needed
722
723
  raise
723
724
 
@@ -734,7 +735,7 @@ class Websocket:
734
735
  try:
735
736
  await self.ws.send(json.dumps({**payload, **{"id": original_id}}))
736
737
  return original_id
737
- except websockets.ConnectionClosed:
738
+ except ConnectionClosed:
738
739
  raise
739
740
 
740
741
  async def retrieve(self, item_id: int) -> Optional[dict]:
@@ -775,7 +776,6 @@ class AsyncSubstrateInterface:
775
776
  chain_endpoint,
776
777
  options={
777
778
  "max_size": 2**32,
778
- "read_limit": 2**16,
779
779
  "write_limit": 2**16,
780
780
  },
781
781
  )
@@ -1135,7 +1135,7 @@ class AsyncSubstrateInterface:
1135
1135
  -------
1136
1136
  StorageKey
1137
1137
  """
1138
- runtime = await self.init_runtime(block_hash=block_hash)
1138
+ await self.init_runtime(block_hash=block_hash)
1139
1139
 
1140
1140
  return StorageKey.create_from_storage_function(
1141
1141
  pallet,
@@ -1555,7 +1555,7 @@ class AsyncSubstrateInterface:
1555
1555
  self,
1556
1556
  response: dict,
1557
1557
  subscription_id: Union[int, str],
1558
- value_scale_type: Optional[str],
1558
+ value_scale_type: Optional[str] = None,
1559
1559
  storage_item: Optional[ScaleType] = None,
1560
1560
  runtime: Optional[Runtime] = None,
1561
1561
  result_handler: Optional[ResultHandler] = None,
@@ -1769,7 +1769,6 @@ class AsyncSubstrateInterface:
1769
1769
  call_params = {}
1770
1770
 
1771
1771
  await self.init_runtime(block_hash=block_hash)
1772
-
1773
1772
  call = self.runtime_config.create_scale_object(
1774
1773
  type_string="Call", metadata=self.metadata
1775
1774
  )
@@ -2087,7 +2086,8 @@ class AsyncSubstrateInterface:
2087
2086
 
2088
2087
  :return: The signed Extrinsic
2089
2088
  """
2090
- await self.init_runtime()
2089
+ if not self.metadata:
2090
+ await self.init_runtime()
2091
2091
 
2092
2092
  # Check requirements
2093
2093
  if not isinstance(call, GenericCall):
@@ -2140,7 +2140,6 @@ class AsyncSubstrateInterface:
2140
2140
  extrinsic = self.runtime_config.create_scale_object(
2141
2141
  type_string="Extrinsic", metadata=self.metadata
2142
2142
  )
2143
-
2144
2143
  value = {
2145
2144
  "account_id": f"0x{keypair.public_key.hex()}",
2146
2145
  "signature": f"0x{signature.hex()}",
@@ -2158,9 +2157,7 @@ class AsyncSubstrateInterface:
2158
2157
  signature_cls = self.runtime_config.get_decoder_class("ExtrinsicSignature")
2159
2158
  if issubclass(signature_cls, self.runtime_config.get_decoder_class("Enum")):
2160
2159
  value["signature_version"] = signature_version
2161
-
2162
2160
  extrinsic.encode(value)
2163
-
2164
2161
  return extrinsic
2165
2162
 
2166
2163
  async def get_chain_finalised_head(self):
@@ -2564,10 +2561,7 @@ class AsyncSubstrateInterface:
2564
2561
  item_key = None
2565
2562
 
2566
2563
  try:
2567
- try:
2568
- item_bytes = bytes.fromhex(item[1][2:])
2569
- except ValueError:
2570
- item_bytes = bytes.fromhex(item[1])
2564
+ item_bytes = hex_to_bytes(item[1])
2571
2565
 
2572
2566
  item_value = await self.decode_scale(
2573
2567
  type_string=value_type,
@@ -18,9 +18,7 @@ import typing
18
18
  from typing import Optional
19
19
  import subprocess
20
20
 
21
- import backoff
22
21
  from bittensor_wallet import Wallet
23
- from bittensor_wallet.errors import KeyFileError
24
22
  from Crypto.Hash import keccak
25
23
  import numpy as np
26
24
  from rich.prompt import Confirm
@@ -37,6 +35,8 @@ from bittensor_cli.src.bittensor.utils import (
37
35
  get_human_readable,
38
36
  print_verbose,
39
37
  print_error,
38
+ unlock_key,
39
+ hex_to_bytes,
40
40
  )
41
41
 
42
42
  if typing.TYPE_CHECKING:
@@ -687,7 +687,7 @@ async def run_faucet_extrinsic(
687
687
  tpb: int = 256,
688
688
  num_processes: Optional[int] = None,
689
689
  update_interval: Optional[int] = None,
690
- log_verbose: bool = False,
690
+ log_verbose: bool = True,
691
691
  max_successes: int = 3,
692
692
  ) -> tuple[bool, str]:
693
693
  r"""Runs a continual POW to get a faucet of TAO on the test net.
@@ -726,10 +726,8 @@ async def run_faucet_extrinsic(
726
726
  return False, "Requires torch"
727
727
 
728
728
  # Unlock coldkey
729
- try:
730
- wallet.unlock_coldkey()
731
- except KeyFileError:
732
- return False, "There was an error unlocking your coldkey"
729
+ if not (unlock_status := unlock_key(wallet, print_out=False)).success:
730
+ return False, unlock_status.message
733
731
 
734
732
  # Get previous balance.
735
733
  old_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
@@ -737,8 +735,12 @@ async def run_faucet_extrinsic(
737
735
  # Attempt rolling registration.
738
736
  attempts = 1
739
737
  successes = 1
738
+ pow_result: Optional[POWSolution]
740
739
  while True:
741
740
  try:
741
+ account_nonce = await subtensor.substrate.get_account_nonce(
742
+ wallet.coldkey.ss58_address
743
+ )
742
744
  pow_result = None
743
745
  while pow_result is None or await pow_result.is_stale(subtensor=subtensor):
744
746
  # Solve latest POW.
@@ -747,7 +749,7 @@ async def run_faucet_extrinsic(
747
749
  if prompt:
748
750
  err_console.print("CUDA is not available.")
749
751
  return False, "CUDA is not available."
750
- pow_result: Optional[POWSolution] = await create_pow(
752
+ pow_result = await create_pow(
751
753
  subtensor,
752
754
  wallet,
753
755
  -1,
@@ -760,7 +762,7 @@ async def run_faucet_extrinsic(
760
762
  log_verbose=log_verbose,
761
763
  )
762
764
  else:
763
- pow_result: Optional[POWSolution] = await create_pow(
765
+ pow_result = await create_pow(
764
766
  subtensor,
765
767
  wallet,
766
768
  -1,
@@ -780,7 +782,7 @@ async def run_faucet_extrinsic(
780
782
  },
781
783
  )
782
784
  extrinsic = await subtensor.substrate.create_signed_extrinsic(
783
- call=call, keypair=wallet.coldkey
785
+ call=call, keypair=wallet.coldkey, nonce=account_nonce
784
786
  )
785
787
  response = await subtensor.substrate.submit_extrinsic(
786
788
  extrinsic,
@@ -865,7 +867,7 @@ async def _check_for_newest_block_and_update(
865
867
  block_number, difficulty, block_hash = await _get_block_with_retry(
866
868
  subtensor=subtensor, netuid=netuid
867
869
  )
868
- block_bytes = bytes.fromhex(block_hash[2:])
870
+ block_bytes = hex_to_bytes(block_hash)
869
871
 
870
872
  update_curr_block(
871
873
  curr_diff,
@@ -972,7 +974,7 @@ async def _block_solver(
972
974
  subtensor=subtensor, netuid=netuid
973
975
  )
974
976
 
975
- block_bytes = bytes.fromhex(block_hash[2:])
977
+ block_bytes = hex_to_bytes(block_hash)
976
978
  old_block_number = block_number
977
979
  # Set to current block
978
980
  _update_curr_block(
@@ -1247,11 +1249,9 @@ def _terminate_workers_and_wait_for_exit(
1247
1249
  worker.terminate()
1248
1250
 
1249
1251
 
1250
- # TODO verify this works with async
1251
- @backoff.on_exception(backoff.constant, Exception, interval=1, max_tries=3)
1252
1252
  async def _get_block_with_retry(
1253
1253
  subtensor: "SubtensorInterface", netuid: int
1254
- ) -> tuple[int, int, bytes]:
1254
+ ) -> tuple[int, int, str]:
1255
1255
  """
1256
1256
  Gets the current block number, difficulty, and block hash from the substrate node.
1257
1257
 
@@ -1263,10 +1263,9 @@ async def _get_block_with_retry(
1263
1263
  :raises Exception: If the block hash is None.
1264
1264
  :raises ValueError: If the difficulty is None.
1265
1265
  """
1266
- block_number = await subtensor.substrate.get_block_number(None)
1267
- block_hash = await subtensor.substrate.get_block_hash(
1268
- block_number
1269
- ) # TODO check if I need to do all this
1266
+ block = await subtensor.substrate.get_block()
1267
+ block_hash = block["header"]["hash"]
1268
+ block_number = block["header"]["number"]
1270
1269
  try:
1271
1270
  difficulty = (
1272
1271
  1_000_000
@@ -1639,10 +1638,7 @@ async def swap_hotkey_extrinsic(
1639
1638
  )
1640
1639
  return False
1641
1640
 
1642
- try:
1643
- wallet.unlock_coldkey()
1644
- except KeyFileError:
1645
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
1641
+ if not unlock_key(wallet).success:
1646
1642
  return False
1647
1643
 
1648
1644
  if prompt:
@@ -21,7 +21,6 @@ import time
21
21
  from typing import Union, List, TYPE_CHECKING
22
22
 
23
23
  from bittensor_wallet import Wallet, Keypair
24
- from bittensor_wallet.errors import KeyFileError
25
24
  import numpy as np
26
25
  from numpy.typing import NDArray
27
26
  from rich.prompt import Confirm
@@ -37,6 +36,7 @@ from bittensor_cli.src.bittensor.utils import (
37
36
  u16_normalized_float,
38
37
  print_verbose,
39
38
  format_error_message,
39
+ unlock_key,
40
40
  )
41
41
 
42
42
  if TYPE_CHECKING:
@@ -306,10 +306,7 @@ async def root_register_extrinsic(
306
306
  the response is `True`.
307
307
  """
308
308
 
309
- try:
310
- wallet.unlock_coldkey()
311
- except KeyFileError:
312
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
309
+ if not unlock_key(wallet).success:
313
310
  return False
314
311
 
315
312
  print_verbose(f"Checking if hotkey ({wallet.hotkey_str}) is registered on root")
@@ -427,10 +424,7 @@ async def set_root_weights_extrinsic(
427
424
  err_console.print("Your hotkey is not registered to the root network")
428
425
  return False
429
426
 
430
- try:
431
- wallet.unlock_coldkey()
432
- except KeyFileError:
433
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
427
+ if not unlock_key(wallet).success:
434
428
  return False
435
429
 
436
430
  # First convert types.
@@ -1,7 +1,6 @@
1
1
  import asyncio
2
2
 
3
3
  from bittensor_wallet import Wallet
4
- from bittensor_wallet.errors import KeyFileError
5
4
  from rich.prompt import Confirm
6
5
  from substrateinterface.exceptions import SubstrateRequestException
7
6
 
@@ -16,6 +15,7 @@ from bittensor_cli.src.bittensor.utils import (
16
15
  get_explorer_url_for_network,
17
16
  is_valid_bittensor_address_or_public_key,
18
17
  print_error,
18
+ unlock_key,
19
19
  )
20
20
 
21
21
 
@@ -115,10 +115,7 @@ async def transfer_extrinsic(
115
115
  return False
116
116
  console.print(f"[dark_orange]Initiating transfer on network: {subtensor.network}")
117
117
  # Unlock wallet coldkey.
118
- try:
119
- wallet.unlock_coldkey()
120
- except KeyFileError:
121
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
118
+ if not unlock_key(wallet).success:
122
119
  return False
123
120
 
124
121
  # Check balance.
@@ -35,6 +35,7 @@ from bittensor_cli.src.bittensor.utils import (
35
35
  err_console,
36
36
  decode_hex_identity_dict,
37
37
  validate_chain_endpoint,
38
+ hex_to_bytes,
38
39
  )
39
40
 
40
41
 
@@ -213,12 +214,7 @@ class SubtensorInterface:
213
214
  block_hash=block_hash,
214
215
  )
215
216
  if hex_bytes_result is not None:
216
- try:
217
- bytes_result = bytes.fromhex(hex_bytes_result[2:])
218
- except ValueError:
219
- bytes_result = bytes.fromhex(hex_bytes_result)
220
-
221
- return DelegateInfo.list_from_vec_u8(bytes_result)
217
+ return DelegateInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result))
222
218
  else:
223
219
  return []
224
220
 
@@ -254,12 +250,7 @@ class SubtensorInterface:
254
250
  if hex_bytes_result is None:
255
251
  return []
256
252
 
257
- try:
258
- bytes_result = bytes.fromhex(hex_bytes_result[2:])
259
- except ValueError:
260
- bytes_result = bytes.fromhex(hex_bytes_result)
261
-
262
- return StakeInfo.list_from_vec_u8(bytes_result)
253
+ return StakeInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result))
263
254
 
264
255
  async def get_stake_for_coldkey_and_hotkey(
265
256
  self, hotkey_ss58: str, coldkey_ss58: str, block_hash: Optional[str]
@@ -654,12 +645,7 @@ class SubtensorInterface:
654
645
  if hex_bytes_result is None:
655
646
  return []
656
647
 
657
- try:
658
- bytes_result = bytes.fromhex(hex_bytes_result[2:])
659
- except ValueError:
660
- bytes_result = bytes.fromhex(hex_bytes_result)
661
-
662
- return NeuronInfoLite.list_from_vec_u8(bytes_result)
648
+ return NeuronInfoLite.list_from_vec_u8(hex_to_bytes(hex_bytes_result))
663
649
 
664
650
  async def neuron_for_uid(
665
651
  self, uid: Optional[int], netuid: int, block_hash: Optional[str] = None
@@ -988,12 +974,7 @@ class SubtensorInterface:
988
974
  if hex_bytes_result is None:
989
975
  return []
990
976
 
991
- if hex_bytes_result.startswith("0x"):
992
- bytes_result = bytes.fromhex(hex_bytes_result[2:])
993
- else:
994
- bytes_result = bytes.fromhex(hex_bytes_result)
995
-
996
- return SubnetHyperparameters.from_vec_u8(bytes_result)
977
+ return SubnetHyperparameters.from_vec_u8(hex_to_bytes(hex_bytes_result))
997
978
 
998
979
  async def get_vote_data(
999
980
  self,
@@ -1,4 +1,5 @@
1
1
  import ast
2
+ from collections import namedtuple
2
3
  import math
3
4
  import os
4
5
  import sqlite3
@@ -9,7 +10,7 @@ from urllib.parse import urlparse
9
10
 
10
11
  from bittensor_wallet import Wallet, Keypair
11
12
  from bittensor_wallet.utils import SS58_FORMAT
12
- from bittensor_wallet.errors import KeyFileError
13
+ from bittensor_wallet.errors import KeyFileError, PasswordError
13
14
  from bittensor_wallet import utils
14
15
  from jinja2 import Template
15
16
  from markupsafe import Markup
@@ -35,6 +36,8 @@ console = Console()
35
36
  err_console = Console(stderr=True)
36
37
  verbose_console = Console(quiet=True)
37
38
 
39
+ UnlockStatus = namedtuple("UnlockStatus", ["success", "message"])
40
+
38
41
 
39
42
  def print_console(message: str, colour: str, title: str, console: Console):
40
43
  console.print(
@@ -238,11 +241,14 @@ def get_hotkey_wallets_for_wallet(
238
241
  def get_coldkey_wallets_for_path(path: str) -> list[Wallet]:
239
242
  """Gets all wallets with coldkeys from a given path"""
240
243
  wallet_path = Path(path).expanduser()
241
- wallets = [
242
- Wallet(name=directory.name, path=path)
243
- for directory in wallet_path.iterdir()
244
- if directory.is_dir()
245
- ]
244
+ try:
245
+ wallets = [
246
+ Wallet(name=directory.name, path=path)
247
+ for directory in wallet_path.iterdir()
248
+ if directory.is_dir()
249
+ ]
250
+ except FileNotFoundError:
251
+ wallets = []
246
252
  return wallets
247
253
 
248
254
 
@@ -575,7 +581,7 @@ def decode_hex_identity_dict(info_dictionary) -> dict[str, Any]:
575
581
  def get_decoded(data: str) -> str:
576
582
  """Decodes a hex-encoded string."""
577
583
  try:
578
- return bytes.fromhex(data[2:]).decode()
584
+ return hex_to_bytes(data).decode()
579
585
  except UnicodeDecodeError:
580
586
  print(f"Could not decode: {key}: {item}")
581
587
 
@@ -974,3 +980,50 @@ def retry_prompt(
974
980
  return var
975
981
  else:
976
982
  err_console.print(rejection_text)
983
+
984
+
985
+ def unlock_key(
986
+ wallet: Wallet, unlock_type="cold", print_out: bool = True
987
+ ) -> "UnlockStatus":
988
+ """
989
+ Attempts to decrypt a wallet's coldkey or hotkey
990
+ Args:
991
+ wallet: a Wallet object
992
+ unlock_type: the key type, 'cold' or 'hot'
993
+ print_out: whether to print out the error message to the err_console
994
+
995
+ Returns: UnlockStatus for success status of unlock, with error message if unsuccessful
996
+
997
+ """
998
+ if unlock_type == "cold":
999
+ unlocker = "unlock_coldkey"
1000
+ elif unlock_type == "hot":
1001
+ unlocker = "unlock_hotkey"
1002
+ else:
1003
+ raise ValueError(
1004
+ f"Invalid unlock type provided: {unlock_type}. Must be 'cold' or 'hot'."
1005
+ )
1006
+ try:
1007
+ getattr(wallet, unlocker)()
1008
+ return UnlockStatus(True, "")
1009
+ except PasswordError:
1010
+ err_msg = f"The password used to decrypt your {unlock_type.capitalize()}key Keyfile is invalid."
1011
+ if print_out:
1012
+ err_console.print(f":cross_mark: [red]{err_msg}[/red]")
1013
+ return UnlockStatus(False, err_msg)
1014
+ except KeyFileError:
1015
+ err_msg = f"{unlock_type.capitalize()}key Keyfile is corrupt, non-writable, or non-readable, or non-existent."
1016
+ if print_out:
1017
+ err_console.print(f":cross_mark: [red]{err_msg}[/red]")
1018
+ return UnlockStatus(False, err_msg)
1019
+
1020
+
1021
+ def hex_to_bytes(hex_str: str) -> bytes:
1022
+ """
1023
+ Converts a hex-encoded string into bytes. Handles 0x-prefixed and non-prefixed hex-encoded strings.
1024
+ """
1025
+ if hex_str.startswith("0x"):
1026
+ bytes_result = bytes.fromhex(hex_str[2:])
1027
+ else:
1028
+ bytes_result = bytes.fromhex(hex_str)
1029
+ return bytes_result
@@ -3,7 +3,6 @@ import json
3
3
  from typing import Optional, TYPE_CHECKING
4
4
 
5
5
  from bittensor_wallet import Wallet
6
- from bittensor_wallet.errors import KeyFileError
7
6
  import numpy as np
8
7
  from numpy.typing import NDArray
9
8
  from rich import box
@@ -42,6 +41,7 @@ from bittensor_cli.src.bittensor.utils import (
42
41
  ss58_to_vec_u8,
43
42
  update_metadata_table,
44
43
  group_subnets,
44
+ unlock_key,
45
45
  )
46
46
 
47
47
  if TYPE_CHECKING:
@@ -280,10 +280,7 @@ async def burned_register_extrinsic(
280
280
  finalization/inclusion, the response is `True`.
281
281
  """
282
282
 
283
- try:
284
- wallet.unlock_coldkey()
285
- except KeyFileError:
286
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
283
+ if not unlock_key(wallet).success:
287
284
  return False
288
285
 
289
286
  with console.status(
@@ -537,10 +534,7 @@ async def delegate_extrinsic(
537
534
  delegate_string = "delegate" if delegate else "undelegate"
538
535
 
539
536
  # Decrypt key
540
- try:
541
- wallet.unlock_coldkey()
542
- except KeyFileError:
543
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
537
+ if not unlock_key(wallet).success:
544
538
  return False
545
539
 
546
540
  print_verbose("Checking if hotkey is a delegate")
@@ -1098,11 +1092,7 @@ async def senate_vote(
1098
1092
  return False
1099
1093
 
1100
1094
  # Unlock the wallet.
1101
- try:
1102
- wallet.unlock_hotkey()
1103
- wallet.unlock_coldkey()
1104
- except KeyFileError:
1105
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
1095
+ if not unlock_key(wallet).success and unlock_key(wallet, "hot").success:
1106
1096
  return False
1107
1097
 
1108
1098
  console.print(f"Fetching proposals in [dark_orange]network: {subtensor.network}")
@@ -1322,11 +1312,7 @@ async def set_take(wallet: Wallet, subtensor: SubtensorInterface, take: float) -
1322
1312
 
1323
1313
  console.print(f"Setting take on [dark_orange]network: {subtensor.network}")
1324
1314
  # Unlock the wallet.
1325
- try:
1326
- wallet.unlock_hotkey()
1327
- wallet.unlock_coldkey()
1328
- except KeyFileError:
1329
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
1315
+ if not unlock_key(wallet).success and unlock_key(wallet, "hot").success:
1330
1316
  return False
1331
1317
 
1332
1318
  result_ = await _do_set_take()
@@ -1724,11 +1710,7 @@ async def nominate(wallet: Wallet, subtensor: SubtensorInterface, prompt: bool):
1724
1710
 
1725
1711
  console.print(f"Nominating on [dark_orange]network: {subtensor.network}")
1726
1712
  # Unlock the wallet.
1727
- try:
1728
- wallet.unlock_hotkey()
1729
- wallet.unlock_coldkey()
1730
- except KeyFileError:
1731
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
1713
+ if not unlock_key(wallet).success and unlock_key(wallet, "hot").success:
1732
1714
  return False
1733
1715
 
1734
1716
  print_verbose(f"Checking hotkey ({wallet.hotkey_str}) is a delegate")
@@ -2,7 +2,6 @@ import asyncio
2
2
  from typing import Optional
3
3
 
4
4
  from bittensor_wallet import Wallet
5
- from bittensor_wallet.errors import KeyFileError
6
5
  from rich.prompt import Confirm, Prompt, IntPrompt
7
6
  from rich.table import Table
8
7
  from rich.text import Text
@@ -19,6 +18,7 @@ from bittensor_cli.src.bittensor.utils import (
19
18
  u64_to_float,
20
19
  is_valid_ss58_address,
21
20
  format_error_message,
21
+ unlock_key,
22
22
  )
23
23
 
24
24
 
@@ -72,10 +72,8 @@ async def set_children_extrinsic(
72
72
  return False, "Operation Cancelled"
73
73
 
74
74
  # Decrypt coldkey.
75
- try:
76
- wallet.unlock_coldkey()
77
- except KeyFileError:
78
- return False, "There was an error unlocking your coldkey."
75
+ if not (unlock_status := unlock_key(wallet, print_out=False)).success:
76
+ return False, unlock_status.message
79
77
 
80
78
  with console.status(
81
79
  f":satellite: {operation} on [white]{subtensor.network}[/white] ..."
@@ -158,10 +156,8 @@ async def set_childkey_take_extrinsic(
158
156
  return False, "Operation Cancelled"
159
157
 
160
158
  # Decrypt coldkey.
161
- try:
162
- wallet.unlock_coldkey()
163
- except KeyFileError:
164
- return False, "There was an error unlocking your coldkey."
159
+ if not (unlock_status := unlock_key(wallet, print_out=False)).success:
160
+ return False, unlock_status.message
165
161
 
166
162
  with console.status(
167
163
  f":satellite: Setting childkey take on [white]{subtensor.network}[/white] ..."
@@ -7,7 +7,6 @@ from contextlib import suppress
7
7
  from typing import TYPE_CHECKING, Optional, Sequence, Union, cast
8
8
 
9
9
  from bittensor_wallet import Wallet
10
- from bittensor_wallet.errors import KeyFileError
11
10
  from rich.prompt import Confirm
12
11
  from rich.table import Table, Column
13
12
  import typer
@@ -28,6 +27,7 @@ from bittensor_cli.src.bittensor.utils import (
28
27
  render_tree,
29
28
  u16_normalized_float,
30
29
  validate_coldkey_presence,
30
+ unlock_key,
31
31
  )
32
32
 
33
33
  if TYPE_CHECKING:
@@ -103,10 +103,7 @@ async def add_stake_extrinsic(
103
103
  """
104
104
 
105
105
  # Decrypt keys,
106
- try:
107
- wallet.unlock_coldkey()
108
- except KeyFileError:
109
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
106
+ if not unlock_key(wallet).success:
110
107
  return False
111
108
 
112
109
  # Default to wallet's own hotkey if the value is not passed.
@@ -310,10 +307,7 @@ async def add_stake_multiple_extrinsic(
310
307
  return True
311
308
 
312
309
  # Decrypt coldkey.
313
- try:
314
- wallet.unlock_coldkey()
315
- except KeyFileError:
316
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
310
+ if not unlock_key(wallet).success:
317
311
  return False
318
312
 
319
313
  with console.status(
@@ -491,11 +485,8 @@ async def unstake_extrinsic(
491
485
  :return: success: `True` if extrinsic was finalized or included in the block. If we did not wait for
492
486
  finalization/inclusion, the response is `True`.
493
487
  """
494
- # Decrypt keys,
495
- try:
496
- wallet.unlock_coldkey()
497
- except KeyFileError:
498
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
488
+ # Decrypt coldkey
489
+ if not unlock_key(wallet).success:
499
490
  return False
500
491
 
501
492
  if hotkey_ss58 is None:
@@ -663,10 +654,7 @@ async def unstake_multiple_extrinsic(
663
654
  return True
664
655
 
665
656
  # Unlock coldkey.
666
- try:
667
- wallet.unlock_coldkey()
668
- except KeyFileError:
669
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
657
+ if not unlock_key(wallet).success:
670
658
  return False
671
659
 
672
660
  with console.status(
@@ -5,7 +5,6 @@ from textwrap import dedent
5
5
  from typing import TYPE_CHECKING, Optional, cast
6
6
 
7
7
  from bittensor_wallet import Wallet
8
- from bittensor_wallet.errors import KeyFileError
9
8
  from rich.prompt import Confirm
10
9
  from rich.table import Column, Table
11
10
 
@@ -28,6 +27,8 @@ from bittensor_cli.src.bittensor.utils import (
28
27
  millify,
29
28
  render_table,
30
29
  update_metadata_table,
30
+ unlock_key,
31
+ hex_to_bytes,
31
32
  )
32
33
 
33
34
  if TYPE_CHECKING:
@@ -100,10 +101,7 @@ async def register_subnetwork_extrinsic(
100
101
  ):
101
102
  return False
102
103
 
103
- try:
104
- wallet.unlock_coldkey()
105
- except KeyFileError:
106
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
104
+ if not unlock_key(wallet).success:
107
105
  return False
108
106
 
109
107
  with console.status(":satellite: Registering subnet...", spinner="earth"):
@@ -158,12 +156,8 @@ async def subnets_list(
158
156
  hex_bytes_result = await subtensor.query_runtime_api(
159
157
  runtime_api="SubnetInfoRuntimeApi", method="get_subnets_info", params=[]
160
158
  )
161
- try:
162
- bytes_result = bytes.fromhex(hex_bytes_result[2:])
163
- except ValueError:
164
- bytes_result = bytes.fromhex(hex_bytes_result)
165
159
 
166
- return SubnetInfo.list_from_vec_u8(bytes_result)
160
+ return SubnetInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result))
167
161
 
168
162
  if not reuse_last:
169
163
  subnets: list[SubnetInfo]
@@ -2,7 +2,6 @@ import asyncio
2
2
  from typing import TYPE_CHECKING, Union
3
3
 
4
4
  from bittensor_wallet import Wallet
5
- from bittensor_wallet.errors import KeyFileError
6
5
  from rich import box
7
6
  from rich.table import Column, Table
8
7
 
@@ -14,6 +13,7 @@ from bittensor_cli.src.bittensor.utils import (
14
13
  print_error,
15
14
  print_verbose,
16
15
  normalize_hyperparameters,
16
+ unlock_key,
17
17
  )
18
18
 
19
19
  if TYPE_CHECKING:
@@ -101,10 +101,7 @@ async def set_hyperparameter_extrinsic(
101
101
  )
102
102
  return False
103
103
 
104
- try:
105
- wallet.unlock_coldkey()
106
- except KeyFileError:
107
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
104
+ if not unlock_key(wallet).success:
108
105
  return False
109
106
 
110
107
  extrinsic = HYPERPARAMS.get(parameter)
@@ -181,19 +178,20 @@ async def sudo_set_hyperparameter(
181
178
 
182
179
  normalized_value: Union[str, bool]
183
180
  if param_name in [
184
- "network_registration_allowed",
181
+ "registration_allowed",
185
182
  "network_pow_registration_allowed",
186
183
  "commit_reveal_weights_enabled",
187
184
  "liquid_alpha_enabled",
188
185
  ]:
189
- normalized_value = param_value.lower() in ["true", "1"]
186
+ normalized_value = param_value.lower() in ["true", "True", "1"]
190
187
  else:
191
188
  normalized_value = param_value
192
189
 
193
190
  is_allowed_value, value = allowed_value(param_name, normalized_value)
194
191
  if not is_allowed_value:
195
192
  err_console.print(
196
- f"Hyperparameter {param_name} value is not within bounds. Value is {normalized_value} but must be {value}"
193
+ f"Hyperparameter [dark_orange]{param_name}[/dark_orange] value is not within bounds. "
194
+ f"Value is {normalized_value} but must be {value}"
197
195
  )
198
196
  return
199
197
 
@@ -15,23 +15,19 @@ from bittensor_wallet.keyfile import Keyfile
15
15
  from fuzzywuzzy import fuzz
16
16
  from rich import box
17
17
  from rich.align import Align
18
- from rich.prompt import Confirm, Prompt
18
+ from rich.prompt import Confirm
19
19
  from rich.table import Column, Table
20
20
  from rich.tree import Tree
21
21
  from rich.padding import Padding
22
22
  from rich.prompt import IntPrompt
23
- from scalecodec import ScaleBytes
24
- import scalecodec
25
23
  import typer
26
24
 
27
- from bittensor_cli.src import TYPE_REGISTRY
28
25
  from bittensor_cli.src.bittensor import utils
29
26
  from bittensor_cli.src.bittensor.balances import Balance
30
27
  from bittensor_cli.src.bittensor.chain_data import (
31
28
  DelegateInfo,
32
29
  NeuronInfoLite,
33
30
  StakeInfo,
34
- custom_rpc_type_registry,
35
31
  decode_account_id,
36
32
  )
37
33
  from bittensor_cli.src.bittensor.extrinsics.registration import (
@@ -46,7 +42,6 @@ from bittensor_cli.src.bittensor.utils import (
46
42
  RAO_PER_TAO,
47
43
  console,
48
44
  convert_blocks_to_time,
49
- decode_scale_bytes,
50
45
  err_console,
51
46
  print_error,
52
47
  print_verbose,
@@ -55,6 +50,8 @@ from bittensor_cli.src.bittensor.utils import (
55
50
  is_valid_ss58_address,
56
51
  validate_coldkey_presence,
57
52
  retry_prompt,
53
+ unlock_key,
54
+ hex_to_bytes,
58
55
  )
59
56
 
60
57
 
@@ -659,8 +656,13 @@ async def overview(
659
656
  neurons
660
657
  )
661
658
 
659
+ has_alerts = False
662
660
  alerts_table = Table(show_header=True, header_style="bold magenta")
663
661
  alerts_table.add_column("🥩 alert!")
662
+ alerts_table.add_row(
663
+ "[bold]Detected the following stake(s) associated with coldkey(s) that are not linked to any local hotkeys:[/bold]"
664
+ )
665
+ alerts_table.add_row("")
664
666
 
665
667
  coldkeys_to_check = []
666
668
  ck_stakes = await subtensor.get_total_stake_for_coldkey(
@@ -683,12 +685,23 @@ async def overview(
683
685
  if difference == 0:
684
686
  continue # We have all our stake registered.
685
687
 
688
+ has_alerts = True
686
689
  coldkeys_to_check.append(coldkey_wallet)
687
690
  alerts_table.add_row(
688
- "Found [light_goldenrod2]{}[/light_goldenrod2] stake with coldkey [bright_magenta]{}[/bright_magenta] that is not registered.".format(
689
- abs(difference), coldkey_wallet.coldkeypub.ss58_address
691
+ "[light_goldenrod2]{}[/light_goldenrod2] stake associated with coldkey [bright_magenta]{}[/bright_magenta] (ss58: [bright_magenta]{}[/bright_magenta])".format(
692
+ abs(difference),
693
+ coldkey_wallet.name,
694
+ coldkey_wallet.coldkeypub.ss58_address,
690
695
  )
691
696
  )
697
+ if has_alerts:
698
+ alerts_table.add_row("")
699
+ alerts_table.add_row(
700
+ "[bold yellow]Note:[/bold yellow] This stake might be delegated, staked to another user's hotkey, or associated with a hotkey not present in your wallet."
701
+ )
702
+ alerts_table.add_row(
703
+ "You can find out more by executing `[bold]btcli wallet inspect[/bold]` command."
704
+ )
692
705
 
693
706
  if coldkeys_to_check:
694
707
  # We have some stake that is not with a registered hotkey.
@@ -742,7 +755,7 @@ async def overview(
742
755
  grid = Table.grid(pad_edge=True)
743
756
 
744
757
  # If there are any alerts, add them to the grid
745
- if len(alerts_table.rows) > 0:
758
+ if has_alerts:
746
759
  grid.add_row(alerts_table)
747
760
 
748
761
  # Add title
@@ -1175,7 +1188,7 @@ def _process_neurons_for_netuids(
1175
1188
  :return: netuids mapped to decoded neurons
1176
1189
  """
1177
1190
  all_results = [
1178
- (netuid, NeuronInfoLite.list_from_vec_u8(bytes.fromhex(result[2:])))
1191
+ (netuid, NeuronInfoLite.list_from_vec_u8(hex_to_bytes(result)))
1179
1192
  if result
1180
1193
  else (netuid, [])
1181
1194
  for netuid, result in netuids_with_all_neurons_hex_bytes
@@ -1616,10 +1629,7 @@ async def set_id(
1616
1629
  print_error(f":cross_mark: This wallet doesn't own subnet {subnet_netuid}.")
1617
1630
  return False
1618
1631
 
1619
- try:
1620
- wallet.unlock_coldkey()
1621
- except KeyFileError:
1622
- err_console.print("Error decrypting coldkey (possibly incorrect password)")
1632
+ if not unlock_key(wallet).success:
1623
1633
  return False
1624
1634
 
1625
1635
  with console.status(
@@ -1719,18 +1729,14 @@ async def check_coldkey_swap(wallet: Wallet, subtensor: SubtensorInterface):
1719
1729
 
1720
1730
  async def sign(wallet: Wallet, message: str, use_hotkey: str):
1721
1731
  """Sign a message using the provided wallet or hotkey."""
1722
-
1723
- try:
1724
- wallet.unlock_coldkey()
1725
- except KeyFileError:
1726
- err_console.print(
1727
- ":cross_mark: [red]Keyfile is corrupt, non-writable, non-readable or the password used to decrypt is "
1728
- "invalid[/red]:[bold white]\n [/bold white]"
1729
- )
1730
1732
  if not use_hotkey:
1733
+ if not unlock_key(wallet).success:
1734
+ return False
1731
1735
  keypair = wallet.coldkey
1732
1736
  print_verbose(f"Signing using coldkey: {wallet.name}")
1733
1737
  else:
1738
+ if not unlock_key(wallet, "hot").success:
1739
+ return False
1734
1740
  keypair = wallet.hotkey
1735
1741
  print_verbose(f"Signing using hotkey: {wallet.hotkey_str}")
1736
1742
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bittensor-cli
3
- Version: 8.3.0
3
+ Version: 8.4.0
4
4
  Summary: Bittensor CLI
5
5
  Home-page: https://github.com/opentensor/btcli
6
6
  Author: bittensor.com
@@ -40,8 +40,8 @@ Requires-Dist: rich~=13.7
40
40
  Requires-Dist: scalecodec==1.2.11
41
41
  Requires-Dist: substrate-interface~=1.7.9
42
42
  Requires-Dist: typer~=0.12
43
- Requires-Dist: websockets>=12.0
44
- Requires-Dist: bittensor-wallet>=2.0.2
43
+ Requires-Dist: websockets>=14.1
44
+ Requires-Dist: bittensor-wallet>=2.1.3
45
45
  Requires-Dist: bt-decode==0.2.0a0
46
46
  Provides-Extra: cuda
47
47
  Requires-Dist: cubit>=1.1.0; extra == "cuda"
@@ -0,0 +1,31 @@
1
+ bittensor_cli/__init__.py,sha256=0dDE_gb7wXMgoxy5mCs0B4IjiojCNSEiBmyJTyKwCTg,1217
2
+ bittensor_cli/cli.py,sha256=1C9xRsNq3CZHEsYcvw50IemjLxQ7olSljX6wK1WwK6g,170025
3
+ bittensor_cli/doc_generation_helper.py,sha256=GexqjEIKulWg84hpNBEchJ840oOgOi7DWpt447nsdNI,91
4
+ bittensor_cli/src/__init__.py,sha256=1_hTPLBqA6gV8HTL-v0_RVTPt7TQJEJEv-TIw9f79OE,12055
5
+ bittensor_cli/src/bittensor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ bittensor_cli/src/bittensor/async_substrate_interface.py,sha256=o7Pe_Nxsys8aPm_xsih2xR8ArhZrUu9yYobf8qBvT5s,103185
7
+ bittensor_cli/src/bittensor/balances.py,sha256=102mg1iiliLSLx-EocQseWGHiWzRqcBBM-MRoObOdKo,10075
8
+ bittensor_cli/src/bittensor/chain_data.py,sha256=IsHWjmhJbTvud2i3IM1sfmBHP82VxNHC1iFDAtlLgXc,26490
9
+ bittensor_cli/src/bittensor/minigraph.py,sha256=17AjEA75MO7ez_NekOJSaAz6ARjPt99QG_7E1RJ_u_k,8891
10
+ bittensor_cli/src/bittensor/networking.py,sha256=pZLMs8YXpZzDMLXWMBb_Bj6TVkm_q9khyY-lnbwVMuE,462
11
+ bittensor_cli/src/bittensor/subtensor_interface.py,sha256=_99AjukDm7ijEwQUA6TXctZFrj9IRuOzJdheKNmbZ5s,42775
12
+ bittensor_cli/src/bittensor/utils.py,sha256=60h45hRVTaLhhOOTHmNurY3wHb0Jpt9pIhS3joVM7d4,35505
13
+ bittensor_cli/src/bittensor/extrinsics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ bittensor_cli/src/bittensor/extrinsics/registration.py,sha256=87L7xs64beu0htRaiykaJcYLyRmxoFzF5PFNumNuhcw,59010
15
+ bittensor_cli/src/bittensor/extrinsics/root.py,sha256=huycqHbSTFBNIhQ846MuBqwBEtQCSVDW3y3yPAqPzeU,19121
16
+ bittensor_cli/src/bittensor/extrinsics/transfer.py,sha256=yC5oKgoKAXszMzfrof3GbeGppESUMgSqJFFGOMMALuc,8686
17
+ bittensor_cli/src/bittensor/templates/table.j2,sha256=P2EFiksnO1cQsB8zjK6hVJwUryHTsLslzRE0YtobAV8,10601
18
+ bittensor_cli/src/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ bittensor_cli/src/commands/root.py,sha256=hohGfh7w9Lu7z264rbmFkwRCStyZrtdBZVMt20RwiqA,62186
20
+ bittensor_cli/src/commands/subnets.py,sha256=_M2EJLdHaLBN04C22A-Xn6weN-3j5dU5frLe6W5Q2rs,33175
21
+ bittensor_cli/src/commands/sudo.py,sha256=sr4hW27EwW_O7lz0fwPLN3xRpVKNsdBasETIbGDhkb0,8209
22
+ bittensor_cli/src/commands/wallets.py,sha256=BuPJiEDOpHuGRx3zekU2QkFQjFpCUP-Kdk4opS5YfWo,60678
23
+ bittensor_cli/src/commands/weights.py,sha256=UHakAMTNqRkg_fkiyebbZAT9T3UEf93MmdbFgPSbqUw,16520
24
+ bittensor_cli/src/commands/stake/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ bittensor_cli/src/commands/stake/children_hotkeys.py,sha256=j239HdawvHp9rTbIx9MI9v9hkaKbA5OaN_cIQISkHdw,28606
26
+ bittensor_cli/src/commands/stake/stake.py,sha256=7TyFtL5wnXvGvD-GckNrNTRdcu3RewAfx_JfEekugFU,56147
27
+ bittensor_cli-8.4.0.dist-info/METADATA,sha256=XJctL-W1oJCDVKEvsDOrEG_oh6t8ycRPeXudbVaQ174,6788
28
+ bittensor_cli-8.4.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
29
+ bittensor_cli-8.4.0.dist-info/entry_points.txt,sha256=hBTLGLbVxmAKy69XSKaUZvjTCmyEzDGZKq4S8UOto8I,49
30
+ bittensor_cli-8.4.0.dist-info/top_level.txt,sha256=DvgvXpmTtI_Q1BbDZMlK90LFcGFCreN1daViEPV2iFw,14
31
+ bittensor_cli-8.4.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.44.0)
2
+ Generator: bdist_wheel (0.45.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,31 +0,0 @@
1
- bittensor_cli/__init__.py,sha256=O5T0sSkvfCnlXbdjLguIp-4w1jd6Bmb-TXgQINZD1uo,1217
2
- bittensor_cli/cli.py,sha256=tMJBqFba9L267Ghl8Af228_MIR8h7nHfYrmN1Tz3xR8,169461
3
- bittensor_cli/doc_generation_helper.py,sha256=GexqjEIKulWg84hpNBEchJ840oOgOi7DWpt447nsdNI,91
4
- bittensor_cli/src/__init__.py,sha256=9hFSqapIynZbrjc9YHl2wARkPdk4pV5P5zLSvn-EbqM,11856
5
- bittensor_cli/src/bittensor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- bittensor_cli/src/bittensor/async_substrate_interface.py,sha256=EcvAoQcyDa_Sm8Ne-SNtMm8lUkZmkzDto1VUvqG0rlg,103271
7
- bittensor_cli/src/bittensor/balances.py,sha256=102mg1iiliLSLx-EocQseWGHiWzRqcBBM-MRoObOdKo,10075
8
- bittensor_cli/src/bittensor/chain_data.py,sha256=IsHWjmhJbTvud2i3IM1sfmBHP82VxNHC1iFDAtlLgXc,26490
9
- bittensor_cli/src/bittensor/minigraph.py,sha256=17AjEA75MO7ez_NekOJSaAz6ARjPt99QG_7E1RJ_u_k,8891
10
- bittensor_cli/src/bittensor/networking.py,sha256=pZLMs8YXpZzDMLXWMBb_Bj6TVkm_q9khyY-lnbwVMuE,462
11
- bittensor_cli/src/bittensor/subtensor_interface.py,sha256=cwbRhS5qV0Jmref5Qe7rsuDy8ssrRqdObKHvaeGeoOc,43373
12
- bittensor_cli/src/bittensor/utils.py,sha256=cvtej2aKix_EEU5FBeBCd3vIEZSt44R0dCidny7zyoA,33663
13
- bittensor_cli/src/bittensor/extrinsics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- bittensor_cli/src/bittensor/extrinsics/registration.py,sha256=xrEdN_gbL6fFNh-tZRwgB-Xpb8fUer1nSd3Xr5f7x9g,59202
15
- bittensor_cli/src/bittensor/extrinsics/root.py,sha256=RZEQv6QVDAQDjuX_vgjOMsatYvHpA3MW8zueiL6jxlE,19376
16
- bittensor_cli/src/bittensor/extrinsics/transfer.py,sha256=ZqbUcaGVENFP0nviLj914lJXcQ_bHpUpyudPlrmSCzw,8830
17
- bittensor_cli/src/bittensor/templates/table.j2,sha256=P2EFiksnO1cQsB8zjK6hVJwUryHTsLslzRE0YtobAV8,10601
18
- bittensor_cli/src/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- bittensor_cli/src/commands/root.py,sha256=MiNdEg2SCPYv4Q_8aSgGn_9Giotv-k5JEnwgjrDA09A,62753
20
- bittensor_cli/src/commands/subnets.py,sha256=0tf3DhdCmvIQA_64gFTfhk9spOA9PHSn4NUsswjbY0U,33445
21
- bittensor_cli/src/commands/sudo.py,sha256=lpmZBT2xoAcERQNjJN__6nBmFUNcbXFTdNvl3S_T5Cg,8310
22
- bittensor_cli/src/commands/wallets.py,sha256=lHuChXL9n4esIktENZjffdVnNKaFQaBhtuIHvunqrvs,60286
23
- bittensor_cli/src/commands/weights.py,sha256=UHakAMTNqRkg_fkiyebbZAT9T3UEf93MmdbFgPSbqUw,16520
24
- bittensor_cli/src/commands/stake/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- bittensor_cli/src/commands/stake/children_hotkeys.py,sha256=3FapotpWGbE_i6RELt0Sqlk5Bvao4Sd3tQibLS13nKQ,28667
26
- bittensor_cli/src/commands/stake/stake.py,sha256=lGLMWdE3RVmYcr57pMwKljQI8vRX3WFRltmXWHdnKy8,56622
27
- bittensor_cli-8.3.0.dist-info/METADATA,sha256=5SilMKuTyLT2Y6r_zi1Gh3kFJWSzWUQvidQQADezkfs,6788
28
- bittensor_cli-8.3.0.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
29
- bittensor_cli-8.3.0.dist-info/entry_points.txt,sha256=hBTLGLbVxmAKy69XSKaUZvjTCmyEzDGZKq4S8UOto8I,49
30
- bittensor_cli-8.3.0.dist-info/top_level.txt,sha256=DvgvXpmTtI_Q1BbDZMlK90LFcGFCreN1daViEPV2iFw,14
31
- bittensor_cli-8.3.0.dist-info/RECORD,,