bittensor-cli 8.4.3__py3-none-any.whl → 9.0.0rc2__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.
Files changed (30) hide show
  1. bittensor_cli/__init__.py +2 -2
  2. bittensor_cli/cli.py +1508 -1385
  3. bittensor_cli/src/__init__.py +627 -197
  4. bittensor_cli/src/bittensor/balances.py +41 -8
  5. bittensor_cli/src/bittensor/chain_data.py +557 -428
  6. bittensor_cli/src/bittensor/extrinsics/registration.py +161 -47
  7. bittensor_cli/src/bittensor/extrinsics/root.py +14 -8
  8. bittensor_cli/src/bittensor/extrinsics/transfer.py +14 -21
  9. bittensor_cli/src/bittensor/minigraph.py +46 -8
  10. bittensor_cli/src/bittensor/subtensor_interface.py +572 -253
  11. bittensor_cli/src/bittensor/utils.py +326 -75
  12. bittensor_cli/src/commands/stake/__init__.py +154 -0
  13. bittensor_cli/src/commands/stake/children_hotkeys.py +121 -87
  14. bittensor_cli/src/commands/stake/move.py +1000 -0
  15. bittensor_cli/src/commands/stake/stake.py +1637 -1264
  16. bittensor_cli/src/commands/subnets/__init__.py +0 -0
  17. bittensor_cli/src/commands/subnets/price.py +867 -0
  18. bittensor_cli/src/commands/subnets/subnets.py +2055 -0
  19. bittensor_cli/src/commands/sudo.py +529 -26
  20. bittensor_cli/src/commands/wallets.py +234 -544
  21. bittensor_cli/src/commands/weights.py +15 -11
  22. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/METADATA +7 -4
  23. bittensor_cli-9.0.0rc2.dist-info/RECORD +32 -0
  24. bittensor_cli/src/bittensor/async_substrate_interface.py +0 -2748
  25. bittensor_cli/src/commands/root.py +0 -1752
  26. bittensor_cli/src/commands/subnets.py +0 -897
  27. bittensor_cli-8.4.3.dist-info/RECORD +0 -31
  28. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/WHEEL +0 -0
  29. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/entry_points.txt +0 -0
  30. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/top_level.txt +0 -0
@@ -1,39 +1,31 @@
1
1
  import asyncio
2
- import binascii
3
2
  import itertools
4
3
  import os
5
- import sys
6
4
  from collections import defaultdict
7
- from functools import partial
8
- from sys import getsizeof
9
- from typing import Collection, Generator, Optional
5
+ from typing import Generator, Optional
10
6
 
11
7
  import aiohttp
12
- from bittensor_wallet import Wallet
8
+ from bittensor_wallet import Wallet, Keypair
13
9
  from bittensor_wallet.errors import KeyFileError
14
10
  from bittensor_wallet.keyfile import Keyfile
15
11
  from fuzzywuzzy import fuzz
16
12
  from rich import box
17
13
  from rich.align import Align
18
- from rich.prompt import Confirm
19
14
  from rich.table import Column, Table
20
15
  from rich.tree import Tree
21
16
  from rich.padding import Padding
22
- from rich.prompt import IntPrompt
23
17
  import typer
24
18
 
19
+ from bittensor_cli.src import COLOR_PALETTE
25
20
  from bittensor_cli.src.bittensor import utils
26
21
  from bittensor_cli.src.bittensor.balances import Balance
27
22
  from bittensor_cli.src.bittensor.chain_data import (
28
23
  DelegateInfo,
29
24
  NeuronInfoLite,
30
- StakeInfo,
31
- decode_account_id,
32
25
  )
33
26
  from bittensor_cli.src.bittensor.extrinsics.registration import (
34
27
  run_faucet_extrinsic,
35
28
  swap_hotkey_extrinsic,
36
- is_hotkey_registered,
37
29
  )
38
30
  from bittensor_cli.src.bittensor.extrinsics.transfer import transfer_extrinsic
39
31
  from bittensor_cli.src.bittensor.networking import int_to_ip
@@ -49,9 +41,8 @@ from bittensor_cli.src.bittensor.utils import (
49
41
  get_hotkey_wallets_for_wallet,
50
42
  is_valid_ss58_address,
51
43
  validate_coldkey_presence,
52
- retry_prompt,
53
- unlock_key,
54
- hex_to_bytes,
44
+ get_subnet_name,
45
+ millify_tao,
55
46
  )
56
47
 
57
48
 
@@ -69,7 +60,6 @@ async def regen_coldkey(
69
60
  json_path: Optional[str] = None,
70
61
  json_password: Optional[str] = "",
71
62
  use_password: Optional[bool] = True,
72
- overwrite: Optional[bool] = False,
73
63
  ):
74
64
  """Creates a new coldkey under this wallet"""
75
65
  json_str: Optional[str] = None
@@ -79,21 +69,13 @@ async def regen_coldkey(
79
69
  with open(json_path, "r") as f:
80
70
  json_str = f.read()
81
71
  try:
82
- new_wallet = wallet.regenerate_coldkey(
72
+ wallet.regenerate_coldkey(
83
73
  mnemonic=mnemonic,
84
74
  seed=seed,
85
75
  json=(json_str, json_password) if all([json_str, json_password]) else None,
86
76
  use_password=use_password,
87
- overwrite=overwrite,
77
+ overwrite=False,
88
78
  )
89
-
90
- if isinstance(new_wallet, Wallet):
91
- console.print(
92
- "\n✅ [dark_sea_green]Regenerated coldkey successfully!\n",
93
- f"[dark_sea_green]Wallet name: ({new_wallet.name}), path: ({new_wallet.path}), coldkey ss58: ({new_wallet.coldkeypub.ss58_address})",
94
- )
95
- except ValueError:
96
- print_error("Mnemonic phrase is invalid")
97
79
  except KeyFileError:
98
80
  print_error("KeyFileError: File is not writable")
99
81
 
@@ -102,20 +84,14 @@ async def regen_coldkey_pub(
102
84
  wallet: Wallet,
103
85
  ss58_address: str,
104
86
  public_key_hex: str,
105
- overwrite: Optional[bool] = False,
106
87
  ):
107
88
  """Creates a new coldkeypub under this wallet."""
108
89
  try:
109
- new_coldkeypub = wallet.regenerate_coldkeypub(
90
+ wallet.regenerate_coldkeypub(
110
91
  ss58_address=ss58_address,
111
92
  public_key=public_key_hex,
112
- overwrite=overwrite,
93
+ overwrite=False,
113
94
  )
114
- if isinstance(new_coldkeypub, Wallet):
115
- console.print(
116
- "\n✅ [dark_sea_green]Regenerated coldkeypub successfully!\n",
117
- f"[dark_sea_green]Wallet name: ({new_coldkeypub.name}), path: ({new_coldkeypub.path}), coldkey ss58: ({new_coldkeypub.coldkeypub.ss58_address})",
118
- )
119
95
  except KeyFileError:
120
96
  print_error("KeyFileError: File is not writable")
121
97
 
@@ -127,7 +103,6 @@ async def regen_hotkey(
127
103
  json_path: Optional[str],
128
104
  json_password: Optional[str] = "",
129
105
  use_password: Optional[bool] = False,
130
- overwrite: Optional[bool] = False,
131
106
  ):
132
107
  """Creates a new hotkey under this wallet."""
133
108
  json_str: Optional[str] = None
@@ -139,20 +114,13 @@ async def regen_hotkey(
139
114
  json_str = f.read()
140
115
 
141
116
  try:
142
- new_hotkey = wallet.regenerate_hotkey(
117
+ wallet.regenerate_hotkey(
143
118
  mnemonic=mnemonic,
144
119
  seed=seed,
145
120
  json=(json_str, json_password) if all([json_str, json_password]) else None,
146
121
  use_password=use_password,
147
- overwrite=overwrite,
122
+ overwrite=False,
148
123
  )
149
- if isinstance(new_hotkey, Wallet):
150
- console.print(
151
- "\n✅ [dark_sea_green]Regenerated hotkey successfully!\n",
152
- f"[dark_sea_green]Wallet name: ({new_hotkey.name}), path: ({new_hotkey.path}), hotkey ss58: ({new_hotkey.hotkey.ss58_address})",
153
- )
154
- except ValueError:
155
- print_error("Mnemonic phrase is invalid")
156
124
  except KeyFileError:
157
125
  print_error("KeyFileError: File is not writable")
158
126
 
@@ -161,15 +129,26 @@ async def new_hotkey(
161
129
  wallet: Wallet,
162
130
  n_words: int,
163
131
  use_password: bool,
164
- overwrite: Optional[bool] = False,
132
+ uri: Optional[str] = None,
165
133
  ):
166
134
  """Creates a new hotkey under this wallet."""
167
135
  try:
168
- wallet.create_new_hotkey(
169
- n_words=n_words,
170
- use_password=use_password,
171
- overwrite=overwrite,
172
- )
136
+ if uri:
137
+ try:
138
+ keypair = Keypair.create_from_uri(uri)
139
+ except Exception as e:
140
+ print_error(f"Failed to create keypair from URI {uri}: {str(e)}")
141
+ wallet.set_hotkey(keypair=keypair, encrypt=use_password)
142
+ console.print(
143
+ f"[dark_sea_green]Hotkey created from URI: {uri}[/dark_sea_green]"
144
+ )
145
+ else:
146
+ wallet.create_new_hotkey(
147
+ n_words=n_words,
148
+ use_password=use_password,
149
+ overwrite=False,
150
+ )
151
+ console.print("[dark_sea_green]Hotkey created[/dark_sea_green]")
173
152
  except KeyFileError:
174
153
  print_error("KeyFileError: File is not writable")
175
154
 
@@ -178,15 +157,27 @@ async def new_coldkey(
178
157
  wallet: Wallet,
179
158
  n_words: int,
180
159
  use_password: bool,
181
- overwrite: Optional[bool] = False,
160
+ uri: Optional[str] = None,
182
161
  ):
183
162
  """Creates a new coldkey under this wallet."""
184
163
  try:
185
- wallet.create_new_coldkey(
186
- n_words=n_words,
187
- use_password=use_password,
188
- overwrite=overwrite,
189
- )
164
+ if uri:
165
+ try:
166
+ keypair = Keypair.create_from_uri(uri)
167
+ except Exception as e:
168
+ print_error(f"Failed to create keypair from URI {uri}: {str(e)}")
169
+ wallet.set_coldkey(keypair=keypair, encrypt=False, overwrite=False)
170
+ wallet.set_coldkeypub(keypair=keypair, encrypt=False, overwrite=False)
171
+ console.print(
172
+ f"[dark_sea_green]Coldkey created from URI: {uri}[/dark_sea_green]"
173
+ )
174
+ else:
175
+ wallet.create_new_coldkey(
176
+ n_words=n_words,
177
+ use_password=use_password,
178
+ overwrite=False,
179
+ )
180
+ console.print("[dark_sea_green]Coldkey created[/dark_sea_green]")
190
181
  except KeyFileError:
191
182
  print_error("KeyFileError: File is not writable")
192
183
 
@@ -195,26 +186,40 @@ async def wallet_create(
195
186
  wallet: Wallet,
196
187
  n_words: int = 12,
197
188
  use_password: bool = True,
198
- overwrite: Optional[bool] = False,
189
+ uri: Optional[str] = None,
199
190
  ):
200
191
  """Creates a new wallet."""
201
- try:
202
- wallet.create_new_coldkey(
203
- n_words=n_words,
204
- use_password=use_password,
205
- overwrite=overwrite,
192
+ if uri:
193
+ try:
194
+ keypair = Keypair.create_from_uri(uri)
195
+ wallet.set_coldkey(keypair=keypair, encrypt=False, overwrite=False)
196
+ wallet.set_coldkeypub(keypair=keypair, encrypt=False, overwrite=False)
197
+ wallet.set_hotkey(keypair=keypair, encrypt=False, overwrite=False)
198
+ except Exception as e:
199
+ print_error(f"Failed to create keypair from URI: {str(e)}")
200
+ console.print(
201
+ f"[dark_sea_green]Wallet created from URI: {uri}[/dark_sea_green]"
206
202
  )
207
- except KeyFileError:
208
- print_error("KeyFileError: File is not writable")
203
+ else:
204
+ try:
205
+ wallet.create_new_coldkey(
206
+ n_words=n_words,
207
+ use_password=use_password,
208
+ overwrite=False,
209
+ )
210
+ console.print("[dark_sea_green]Coldkey created[/dark_sea_green]")
211
+ except KeyFileError:
212
+ print_error("KeyFileError: File is not writable")
209
213
 
210
- try:
211
- wallet.create_new_hotkey(
212
- n_words=n_words,
213
- use_password=False,
214
- overwrite=overwrite,
215
- )
216
- except KeyFileError:
217
- print_error("KeyFileError: File is not writable")
214
+ try:
215
+ wallet.create_new_hotkey(
216
+ n_words=n_words,
217
+ use_password=False,
218
+ overwrite=False,
219
+ )
220
+ console.print("[dark_sea_green]Hotkey created[/dark_sea_green]")
221
+ except KeyFileError:
222
+ print_error("KeyFileError: File is not writable")
218
223
 
219
224
 
220
225
  def get_coldkey_wallets_for_path(path: str) -> list[Wallet]:
@@ -258,7 +263,11 @@ async def wallet_balance(
258
263
  """Retrieves the current balance of the specified wallet"""
259
264
  if ss58_addresses:
260
265
  coldkeys = ss58_addresses
261
- wallet_names = [f"Provided Address {i + 1}" for i in range(len(ss58_addresses))]
266
+ identities = await subtensor.query_all_identities()
267
+ wallet_names = [
268
+ f"{identities.get(coldkey, {'name': f'Provided address {i}'})['name']}"
269
+ for i, coldkey in enumerate(coldkeys)
270
+ ]
262
271
 
263
272
  elif not all_balances:
264
273
  if not wallet.coldkeypub_file.exists_on_device():
@@ -278,7 +287,7 @@ async def wallet_balance(
278
287
 
279
288
  block_hash = await subtensor.substrate.get_chain_head()
280
289
  free_balances, staked_balances = await asyncio.gather(
281
- subtensor.get_balance(*coldkeys, block_hash=block_hash),
290
+ subtensor.get_balances(*coldkeys, block_hash=block_hash),
282
291
  subtensor.get_total_stake_for_coldkey(*coldkeys, block_hash=block_hash),
283
292
  )
284
293
 
@@ -298,28 +307,28 @@ async def wallet_balance(
298
307
  ),
299
308
  Column(
300
309
  "[white]Coldkey Address",
301
- style="bright_magenta",
310
+ style=COLOR_PALETTE["GENERAL"]["COLDKEY"],
302
311
  no_wrap=True,
303
312
  ),
304
313
  Column(
305
314
  "[white]Free Balance",
306
315
  justify="right",
307
- style="light_goldenrod2",
316
+ style=COLOR_PALETTE["GENERAL"]["BALANCE"],
308
317
  no_wrap=True,
309
318
  ),
310
319
  Column(
311
320
  "[white]Staked Balance",
312
321
  justify="right",
313
- style="orange1",
322
+ style=COLOR_PALETTE["STAKE"]["STAKE_AMOUNT"],
314
323
  no_wrap=True,
315
324
  ),
316
325
  Column(
317
326
  "[white]Total Balance",
318
327
  justify="right",
319
- style="green",
328
+ style=COLOR_PALETTE["GENERAL"]["BALANCE"],
320
329
  no_wrap=True,
321
330
  ),
322
- title=f"[underline dark_orange]Wallet Coldkey Balance[/underline dark_orange]\n[dark_orange]Network: {subtensor.network}",
331
+ title=f"\n [{COLOR_PALETTE['GENERAL']['HEADER']}]Wallet Coldkey Balance\nNetwork: {subtensor.network}",
323
332
  show_footer=True,
324
333
  show_edge=False,
325
334
  border_style="bright_black",
@@ -347,6 +356,7 @@ async def wallet_balance(
347
356
  )
348
357
  console.print(Padding(table, (0, 0, 0, 4)))
349
358
  await subtensor.substrate.close()
359
+ return total_free_balance, total_staked_balance
350
360
 
351
361
 
352
362
  async def get_wallet_transfers(wallet_address: str) -> list[dict]:
@@ -541,7 +551,7 @@ async def _get_total_balance(
541
551
  ]
542
552
  total_balance += sum(
543
553
  (
544
- await subtensor.get_balance(
554
+ await subtensor.get_balances(
545
555
  *(x.coldkeypub.ss58_address for x in _balance_cold_wallets),
546
556
  block_hash=block_hash,
547
557
  )
@@ -563,7 +573,7 @@ async def _get_total_balance(
563
573
  ):
564
574
  total_balance = sum(
565
575
  (
566
- await subtensor.get_balance(
576
+ await subtensor.get_balances(
567
577
  coldkey_wallet.coldkeypub.ss58_address, block_hash=block_hash
568
578
  )
569
579
  ).values()
@@ -587,17 +597,19 @@ async def overview(
587
597
  include_hotkeys: Optional[list[str]] = None,
588
598
  exclude_hotkeys: Optional[list[str]] = None,
589
599
  netuids_filter: Optional[list[int]] = None,
600
+ verbose: bool = False,
590
601
  ):
591
602
  """Prints an overview for the wallet's coldkey."""
592
603
 
593
604
  total_balance = Balance(0)
594
605
 
595
606
  # We are printing for every coldkey.
596
- print_verbose("Fetching total balance for coldkey/s")
597
607
  block_hash = await subtensor.substrate.get_chain_head()
598
608
  all_hotkeys, total_balance = await _get_total_balance(
599
609
  total_balance, subtensor, wallet, all_wallets, block_hash=block_hash
600
610
  )
611
+ _dynamic_info = await subtensor.all_subnets()
612
+ dynamic_info = {info.netuid: info for info in _dynamic_info}
601
613
 
602
614
  with console.status(
603
615
  f":satellite: Synchronizing with chain [white]{subtensor.network}[/white]",
@@ -605,9 +617,6 @@ async def overview(
605
617
  ) as status:
606
618
  # We are printing for a select number of hotkeys from all_hotkeys.
607
619
  if include_hotkeys or exclude_hotkeys:
608
- print_verbose(
609
- "Fetching for select hotkeys passed in 'include_hotkeys'", status
610
- )
611
620
  all_hotkeys = _get_hotkeys(include_hotkeys, exclude_hotkeys, all_hotkeys)
612
621
 
613
622
  # Check we have keys to display.
@@ -617,17 +626,14 @@ async def overview(
617
626
 
618
627
  # Pull neuron info for all keys.
619
628
  neurons: dict[str, list[NeuronInfoLite]] = {}
620
- print_verbose("Fetching subnet netuids", status)
621
629
  block, all_netuids = await asyncio.gather(
622
630
  subtensor.substrate.get_block_number(None),
623
631
  subtensor.get_all_subnet_netuids(),
624
632
  )
625
633
 
626
- print_verbose("Filtering netuids by registered hotkeys", status)
627
634
  netuids = await subtensor.filter_netuids_by_registered_hotkeys(
628
635
  all_netuids, netuids_filter, all_hotkeys, reuse_block=True
629
636
  )
630
- # bittensor.logging.debug(f"Netuids to check: {netuids}")
631
637
 
632
638
  for netuid in netuids:
633
639
  neurons[str(netuid)] = []
@@ -648,122 +654,17 @@ async def overview(
648
654
  )
649
655
  all_hotkeys, _ = validate_coldkey_presence(all_hotkeys)
650
656
 
651
- print_verbose("Fetching key addresses", status)
652
657
  all_hotkey_addresses, hotkey_coldkey_to_hotkey_wallet = _get_key_address(
653
658
  all_hotkeys
654
659
  )
655
660
 
656
- print_verbose("Pulling and processing neuron information for all keys", status)
657
661
  results = await _get_neurons_for_netuids(
658
662
  subtensor, netuids, all_hotkey_addresses
659
663
  )
660
664
  neurons = _process_neuron_results(results, neurons, netuids)
661
- total_coldkey_stake_from_metagraph = await _calculate_total_coldkey_stake(
662
- neurons
663
- )
664
-
665
- has_alerts = False
666
- alerts_table = Table(show_header=True, header_style="bold magenta")
667
- alerts_table.add_column("🥩 alert!")
668
- alerts_table.add_row(
669
- "[bold]Detected the following stake(s) associated with coldkey(s) that are not linked to any local hotkeys:[/bold]"
670
- )
671
- alerts_table.add_row("")
672
-
673
- coldkeys_to_check = []
674
- ck_stakes = await subtensor.get_total_stake_for_coldkey(
675
- *(
676
- coldkey_wallet.coldkeypub.ss58_address
677
- for coldkey_wallet in all_coldkey_wallets
678
- if coldkey_wallet.coldkeypub
679
- ),
680
- block_hash=block_hash,
681
- )
682
- for coldkey_wallet in all_coldkey_wallets:
683
- if coldkey_wallet.coldkeypub:
684
- # Check if we have any stake with hotkeys that are not registered.
685
- difference = (
686
- ck_stakes[coldkey_wallet.coldkeypub.ss58_address]
687
- - total_coldkey_stake_from_metagraph[
688
- coldkey_wallet.coldkeypub.ss58_address
689
- ]
690
- )
691
- if difference == 0:
692
- continue # We have all our stake registered.
693
-
694
- has_alerts = True
695
- coldkeys_to_check.append(coldkey_wallet)
696
- alerts_table.add_row(
697
- "[light_goldenrod2]{}[/light_goldenrod2] stake associated with coldkey [bright_magenta]{}[/bright_magenta] (ss58: [bright_magenta]{}[/bright_magenta])".format(
698
- abs(difference),
699
- coldkey_wallet.name,
700
- coldkey_wallet.coldkeypub.ss58_address,
701
- )
702
- )
703
- if has_alerts:
704
- alerts_table.add_row("")
705
- alerts_table.add_row(
706
- "[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."
707
- )
708
- alerts_table.add_row(
709
- "You can find out more by executing `[bold]btcli wallet inspect[/bold]` command."
710
- )
711
-
712
- if coldkeys_to_check:
713
- # We have some stake that is not with a registered hotkey.
714
- if "-1" not in neurons:
715
- neurons["-1"] = []
716
-
717
- print_verbose("Checking coldkeys for de-registered stake", status)
718
- results = await asyncio.gather(
719
- *[
720
- _get_de_registered_stake_for_coldkey_wallet(
721
- subtensor, all_hotkey_addresses, coldkey_wallet
722
- )
723
- for coldkey_wallet in coldkeys_to_check
724
- ]
725
- )
726
-
727
- for result in results:
728
- coldkey_wallet, de_registered_stake, err_msg = result
729
- if err_msg is not None:
730
- err_console.print(err_msg)
731
-
732
- if len(de_registered_stake) == 0:
733
- continue # We have no de-registered stake with this coldkey.
734
-
735
- de_registered_neurons = []
736
- for hotkey_addr, our_stake in de_registered_stake:
737
- # Make a neuron info lite for this hotkey and coldkey.
738
- de_registered_neuron = NeuronInfoLite.get_null_neuron()
739
- de_registered_neuron.hotkey = hotkey_addr
740
- de_registered_neuron.coldkey = coldkey_wallet.coldkeypub.ss58_address
741
- de_registered_neuron.total_stake = Balance(our_stake)
742
- de_registered_neurons.append(de_registered_neuron)
743
-
744
- # Add this hotkey to the wallets dict
745
- wallet_ = WalletLike(
746
- name=wallet.name,
747
- hotkey_ss58=hotkey_addr,
748
- hotkey_str=hotkey_addr[:5],
749
- )
750
- # Indicates a hotkey not on local machine but exists in stake_info obj on-chain
751
- if hotkey_coldkey_to_hotkey_wallet.get(hotkey_addr) is None:
752
- hotkey_coldkey_to_hotkey_wallet[hotkey_addr] = {}
753
- hotkey_coldkey_to_hotkey_wallet[hotkey_addr][
754
- coldkey_wallet.coldkeypub.ss58_address
755
- ] = wallet_
756
-
757
- # Add neurons to overview.
758
- neurons["-1"].extend(de_registered_neurons)
759
-
760
665
  # Setup outer table.
761
666
  grid = Table.grid(pad_edge=True)
762
667
 
763
- # If there are any alerts, add them to the grid
764
- if has_alerts:
765
- grid.add_row(alerts_table)
766
-
767
668
  # Add title
768
669
  if not all_wallets:
769
670
  title = "[underline dark_orange]Wallet[/underline dark_orange]\n"
@@ -782,9 +683,6 @@ async def overview(
782
683
  )
783
684
  )
784
685
  # Generate rows per netuid
785
- hotkeys_seen = set()
786
- total_neurons = 0
787
- total_stake = 0.0
788
686
  tempos = await asyncio.gather(
789
687
  *[
790
688
  subtensor.get_hyperparameter("Tempo", netuid, block_hash)
@@ -792,7 +690,6 @@ async def overview(
792
690
  ]
793
691
  )
794
692
  for netuid, subnet_tempo in zip(netuids, tempos):
795
- last_subnet = netuid == netuids[-1]
796
693
  table_data = []
797
694
  total_rank = 0.0
798
695
  total_trust = 0.0
@@ -801,6 +698,8 @@ async def overview(
801
698
  total_incentive = 0.0
802
699
  total_dividends = 0.0
803
700
  total_emission = 0
701
+ total_stake = 0
702
+ total_neurons = 0
804
703
 
805
704
  for nn in neurons[str(netuid)]:
806
705
  hotwallet = hotkey_coldkey_to_hotkey_wallet.get(nn.hotkey, {}).get(
@@ -821,7 +720,7 @@ async def overview(
821
720
  validator_trust = nn.validator_trust
822
721
  incentive = nn.incentive
823
722
  dividends = nn.dividends
824
- emission = int(nn.emission / (subnet_tempo + 1) * 1e9)
723
+ emission = int(nn.emission / (subnet_tempo + 1) * 1e9) # Per block
825
724
  last_update = int(block - nn.last_update)
826
725
  validator_permit = nn.validator_permit
827
726
  row = [
@@ -829,14 +728,14 @@ async def overview(
829
728
  hotwallet.hotkey_str,
830
729
  str(uid),
831
730
  str(active),
832
- "{:.5f}".format(stake),
833
- "{:.5f}".format(rank),
834
- "{:.5f}".format(trust),
835
- "{:.5f}".format(consensus),
836
- "{:.5f}".format(incentive),
837
- "{:.5f}".format(dividends),
838
- "{:_}".format(emission),
839
- "{:.5f}".format(validator_trust),
731
+ f"{stake:.4f}" if verbose else millify_tao(stake),
732
+ f"{rank:.4f}" if verbose else millify_tao(rank),
733
+ f"{trust:.4f}" if verbose else millify_tao(trust),
734
+ f"{consensus:.4f}" if verbose else millify_tao(consensus),
735
+ f"{incentive:.4f}" if verbose else millify_tao(incentive),
736
+ f"{dividends:.4f}" if verbose else millify_tao(dividends),
737
+ f"{emission:.4f}",
738
+ f"{validator_trust:.4f}" if verbose else millify_tao(validator_trust),
840
739
  "*" if validator_permit else "",
841
740
  str(last_update),
842
741
  (
@@ -854,23 +753,15 @@ async def overview(
854
753
  total_dividends += dividends
855
754
  total_emission += emission
856
755
  total_validator_trust += validator_trust
857
-
858
- if (nn.hotkey, nn.coldkey) not in hotkeys_seen:
859
- # Don't double count stake on hotkey-coldkey pairs.
860
- hotkeys_seen.add((nn.hotkey, nn.coldkey))
861
- total_stake += stake
862
-
863
- # netuid -1 are neurons that are de-registered.
864
- if netuid != "-1":
865
- total_neurons += 1
756
+ total_stake += stake
757
+ total_neurons += 1
866
758
 
867
759
  table_data.append(row)
868
760
 
869
761
  # Add subnet header
870
- if netuid == "-1":
871
- grid.add_row("Deregistered Neurons")
872
- else:
873
- grid.add_row(f"Subnet: [dark_orange]{netuid}[/dark_orange]")
762
+ grid.add_row(
763
+ f"Subnet: [dark_orange]{netuid}: {get_subnet_name(dynamic_info[netuid])} {dynamic_info[netuid].symbol}[/dark_orange]"
764
+ )
874
765
  width = console.width
875
766
  table = Table(
876
767
  show_footer=False,
@@ -879,45 +770,34 @@ async def overview(
879
770
  expand=True,
880
771
  width=width - 5,
881
772
  )
882
- if last_subnet:
883
- table.add_column(
884
- "[white]COLDKEY", str(total_neurons), style="bold bright_cyan", ratio=2
885
- )
886
- table.add_column(
887
- "[white]HOTKEY", str(total_neurons), style="bright_cyan", ratio=2
888
- )
889
- else:
890
- # No footer for non-last subnet.
891
- table.add_column("[white]COLDKEY", style="bold bright_cyan", ratio=2)
892
- table.add_column("[white]HOTKEY", style="bright_cyan", ratio=2)
773
+
774
+ table.add_column("[white]COLDKEY", style="bold bright_cyan", ratio=2)
775
+ table.add_column("[white]HOTKEY", style="bright_cyan", ratio=2)
893
776
  table.add_column(
894
777
  "[white]UID", str(total_neurons), style="rgb(42,161,152)", ratio=1
895
778
  )
896
779
  table.add_column(
897
780
  "[white]ACTIVE", justify="right", style="#8787ff", no_wrap=True, ratio=1
898
781
  )
899
- if last_subnet:
900
- table.add_column(
901
- "[white]STAKE(\u03c4)",
902
- "\u03c4{:.5f}".format(total_stake),
903
- footer_style="bold white",
904
- justify="right",
905
- style="dark_orange",
906
- no_wrap=True,
907
- ratio=1,
908
- )
909
- else:
910
- # No footer for non-last subnet.
911
- table.add_column(
912
- "[white]STAKE(\u03c4)",
913
- justify="right",
914
- style="dark_orange",
915
- no_wrap=True,
916
- ratio=1.5,
917
- )
782
+
783
+ _total_stake_formatted = (
784
+ f"{total_stake:.4f}" if verbose else millify_tao(total_stake)
785
+ )
786
+ table.add_column(
787
+ "[white]STAKE(\u03c4)"
788
+ if netuid == 0
789
+ else f"[white]STAKE({Balance.get_unit(netuid)})",
790
+ f"{_total_stake_formatted} {Balance.get_unit(netuid)}"
791
+ if netuid != 0
792
+ else f"{Balance.get_unit(netuid)} {_total_stake_formatted}",
793
+ justify="right",
794
+ style="dark_orange",
795
+ no_wrap=True,
796
+ ratio=1.5,
797
+ )
918
798
  table.add_column(
919
799
  "[white]RANK",
920
- "{:.5f}".format(total_rank),
800
+ f"{total_rank:.4f}",
921
801
  justify="right",
922
802
  style="medium_purple",
923
803
  no_wrap=True,
@@ -925,7 +805,7 @@ async def overview(
925
805
  )
926
806
  table.add_column(
927
807
  "[white]TRUST",
928
- "{:.5f}".format(total_trust),
808
+ f"{total_trust:.4f}",
929
809
  justify="right",
930
810
  style="green",
931
811
  no_wrap=True,
@@ -933,7 +813,7 @@ async def overview(
933
813
  )
934
814
  table.add_column(
935
815
  "[white]CONSENSUS",
936
- "{:.5f}".format(total_consensus),
816
+ f"{total_consensus:.4f}",
937
817
  justify="right",
938
818
  style="rgb(42,161,152)",
939
819
  no_wrap=True,
@@ -941,7 +821,7 @@ async def overview(
941
821
  )
942
822
  table.add_column(
943
823
  "[white]INCENTIVE",
944
- "{:.5f}".format(total_incentive),
824
+ f"{total_incentive:.4f}",
945
825
  justify="right",
946
826
  style="#5fd7ff",
947
827
  no_wrap=True,
@@ -949,7 +829,7 @@ async def overview(
949
829
  )
950
830
  table.add_column(
951
831
  "[white]DIVIDENDS",
952
- "{:.5f}".format(total_dividends),
832
+ f"{total_dividends:.4f}",
953
833
  justify="right",
954
834
  style="#8787d7",
955
835
  no_wrap=True,
@@ -957,7 +837,7 @@ async def overview(
957
837
  )
958
838
  table.add_column(
959
839
  "[white]EMISSION(\u03c1)",
960
- "\u03c1{:_}".format(total_emission),
840
+ f"\u03c1{total_emission}",
961
841
  justify="right",
962
842
  style="#d7d7ff",
963
843
  no_wrap=True,
@@ -965,7 +845,7 @@ async def overview(
965
845
  )
966
846
  table.add_column(
967
847
  "[white]VTRUST",
968
- "{:.5f}".format(total_validator_trust),
848
+ f"{total_validator_trust:.4f}",
969
849
  justify="right",
970
850
  style="magenta",
971
851
  no_wrap=True,
@@ -1148,7 +1028,7 @@ def _map_hotkey_to_neurons(
1148
1028
 
1149
1029
  async def _fetch_neuron_for_netuid(
1150
1030
  netuid: int, subtensor: SubtensorInterface
1151
- ) -> tuple[int, Optional[str]]:
1031
+ ) -> tuple[int, list[NeuronInfoLite]]:
1152
1032
  """
1153
1033
  Retrieves all neurons for a specified netuid
1154
1034
 
@@ -1157,25 +1037,13 @@ async def _fetch_neuron_for_netuid(
1157
1037
 
1158
1038
  :return: the original netuid, and a mapping of the neurons to their NeuronInfoLite objects
1159
1039
  """
1160
-
1161
- async def neurons_lite_for_uid(uid: int) -> Optional[str]:
1162
- block_hash = subtensor.substrate.last_block_hash
1163
- hex_bytes_result = await subtensor.query_runtime_api(
1164
- runtime_api="NeuronInfoRuntimeApi",
1165
- method="get_neurons_lite",
1166
- params=[uid],
1167
- block_hash=block_hash,
1168
- )
1169
-
1170
- return hex_bytes_result
1171
-
1172
- neurons = await neurons_lite_for_uid(uid=netuid)
1040
+ neurons = await subtensor.neurons_lite(netuid=netuid)
1173
1041
  return netuid, neurons
1174
1042
 
1175
1043
 
1176
1044
  async def _fetch_all_neurons(
1177
1045
  netuids: list[int], subtensor
1178
- ) -> list[tuple[int, Optional[str]]]:
1046
+ ) -> list[tuple[int, list[NeuronInfoLite]]]:
1179
1047
  """Retrieves all neurons for each of the specified netuids"""
1180
1048
  return list(
1181
1049
  await asyncio.gather(
@@ -1184,101 +1052,26 @@ async def _fetch_all_neurons(
1184
1052
  )
1185
1053
 
1186
1054
 
1187
- def _process_neurons_for_netuids(
1188
- netuids_with_all_neurons_hex_bytes: list[tuple[int, Optional[str]]],
1189
- ) -> list[tuple[int, list[NeuronInfoLite]]]:
1190
- """
1191
- Decode a list of hex-bytes neurons with their respective netuid
1192
-
1193
- :param netuids_with_all_neurons_hex_bytes: netuids with hex-bytes neurons
1194
- :return: netuids mapped to decoded neurons
1195
- """
1196
- all_results = [
1197
- (netuid, NeuronInfoLite.list_from_vec_u8(hex_to_bytes(result)))
1198
- if result
1199
- else (netuid, [])
1200
- for netuid, result in netuids_with_all_neurons_hex_bytes
1201
- ]
1202
- return all_results
1203
-
1204
-
1205
1055
  async def _get_neurons_for_netuids(
1206
1056
  subtensor: SubtensorInterface, netuids: list[int], hot_wallets: list[str]
1207
1057
  ) -> list[tuple[int, list["NeuronInfoLite"], Optional[str]]]:
1208
- all_neurons_hex_bytes = await _fetch_all_neurons(netuids, subtensor)
1209
-
1210
- all_processed_neurons = _process_neurons_for_netuids(all_neurons_hex_bytes)
1058
+ all_neurons = await _fetch_all_neurons(netuids, subtensor)
1211
1059
  return [
1212
1060
  _map_hotkey_to_neurons(neurons, hot_wallets, netuid)
1213
- for netuid, neurons in all_processed_neurons
1061
+ for netuid, neurons in all_neurons
1214
1062
  ]
1215
1063
 
1216
1064
 
1217
- async def _get_de_registered_stake_for_coldkey_wallet(
1218
- subtensor: SubtensorInterface,
1219
- all_hotkey_addresses: Collection[str],
1220
- coldkey_wallet: Wallet,
1221
- ) -> tuple[Wallet, list[tuple[str, float]], Optional[str]]:
1222
- """
1223
- Looks at the total stake of a coldkey, then filters this based on the supplied hotkey addresses
1224
- depending on whether the hotkey is a delegate
1225
-
1226
- :param subtensor: SubtensorInterface to make queries with
1227
- :param all_hotkey_addresses: collection of hotkey SS58 addresses
1228
- :param coldkey_wallet: Wallet containing coldkey
1229
-
1230
- :return: (original wallet, [(hotkey SS58, stake in TAO), ...], error message)
1231
- """
1232
- # Pull all stake for our coldkey
1233
- all_stake_info_for_coldkey = await subtensor.get_stake_info_for_coldkey(
1234
- coldkey_ss58=coldkey_wallet.coldkeypub.ss58_address, reuse_block=True
1235
- )
1236
-
1237
- # Filter out hotkeys that are in our wallets
1238
- # Filter out hotkeys that are delegates.
1239
- async def _filter_stake_info(stake_info: StakeInfo) -> bool:
1240
- if stake_info.stake == 0:
1241
- return False # Skip hotkeys that we have no stake with.
1242
- if stake_info.hotkey_ss58 in all_hotkey_addresses:
1243
- return False # Skip hotkeys that are in our wallets.
1244
- return not await subtensor.is_hotkey_delegate(
1245
- hotkey_ss58=stake_info.hotkey_ss58, reuse_block=True
1246
- )
1247
-
1248
- all_staked = await asyncio.gather(
1249
- *[_filter_stake_info(stake_info) for stake_info in all_stake_info_for_coldkey]
1250
- )
1251
-
1252
- # Collecting all filtered stake info using async for loop
1253
- all_staked_hotkeys = []
1254
- for stake_info, staked in zip(all_stake_info_for_coldkey, all_staked):
1255
- if staked:
1256
- all_staked_hotkeys.append(
1257
- (
1258
- stake_info.hotkey_ss58,
1259
- stake_info.stake.tao,
1260
- )
1261
- )
1262
-
1263
- return coldkey_wallet, all_staked_hotkeys, None
1264
-
1265
-
1266
1065
  async def transfer(
1267
1066
  wallet: Wallet,
1268
1067
  subtensor: SubtensorInterface,
1269
1068
  destination: str,
1270
1069
  amount: float,
1271
- transfer_all: bool,
1272
1070
  prompt: bool,
1273
1071
  ):
1274
1072
  """Transfer token of amount to destination."""
1275
1073
  await transfer_extrinsic(
1276
- subtensor,
1277
- wallet,
1278
- destination,
1279
- Balance.from_tao(amount),
1280
- transfer_all,
1281
- prompt=prompt,
1074
+ subtensor, wallet, destination, Balance.from_tao(amount), prompt=prompt
1282
1075
  )
1283
1076
 
1284
1077
 
@@ -1292,6 +1085,8 @@ async def inspect(
1292
1085
  delegates_: list[tuple[DelegateInfo, Balance]],
1293
1086
  ) -> Generator[list[str], None, None]:
1294
1087
  for d_, staked in delegates_:
1088
+ if not staked.tao > 0:
1089
+ continue
1295
1090
  if d_.hotkey_ss58 in registered_delegate_info:
1296
1091
  delegate_name = registered_delegate_info[d_.hotkey_ss58].display
1297
1092
  else:
@@ -1301,7 +1096,11 @@ async def inspect(
1301
1096
  + [
1302
1097
  str(delegate_name),
1303
1098
  str(staked),
1304
- str(d_.total_daily_return.tao * (staked.tao / d_.total_stake.tao)),
1099
+ str(
1100
+ d_.total_daily_return.tao * (staked.tao / d_.total_stake.tao)
1101
+ if d_.total_stake.tao != 0
1102
+ else 0
1103
+ ),
1305
1104
  ]
1306
1105
  + [""] * 4
1307
1106
  )
@@ -1381,7 +1180,7 @@ async def inspect(
1381
1180
  all_delegates: list[list[tuple[DelegateInfo, Balance]]]
1382
1181
  with console.status("Pulling balance data...", spinner="aesthetic"):
1383
1182
  balances, all_neurons, all_delegates = await asyncio.gather(
1384
- subtensor.get_balance(
1183
+ subtensor.get_balances(
1385
1184
  *[w.coldkeypub.ss58_address for w in wallets_with_ckp_file],
1386
1185
  block_hash=block_hash,
1387
1186
  ),
@@ -1432,14 +1231,13 @@ async def faucet(
1432
1231
  output_in_place: bool,
1433
1232
  log_verbose: bool,
1434
1233
  max_successes: int = 3,
1435
- prompt: bool = True,
1436
1234
  ):
1437
1235
  # TODO: - work out prompts to be passed through the cli
1438
1236
  success = await run_faucet_extrinsic(
1439
1237
  subtensor,
1440
1238
  wallet,
1441
1239
  tpb=threads_per_block,
1442
- prompt=prompt,
1240
+ prompt=False,
1443
1241
  update_interval=update_interval,
1444
1242
  num_processes=processes,
1445
1243
  cuda=use_cuda,
@@ -1467,210 +1265,97 @@ async def swap_hotkey(
1467
1265
  )
1468
1266
 
1469
1267
 
1470
- def set_id_prompts(
1471
- validator: bool,
1472
- ) -> tuple[str, str, str, str, str, str, str, str, str, bool, int]:
1473
- """
1474
- Used to prompt the user to input their info for setting the ID
1475
- :return: (display_name, legal_name, web_url, riot_handle, email,pgp_fingerprint, image_url, info_, twitter_url,
1476
- validator_id)
1477
- """
1478
- text_rejection = partial(
1479
- retry_prompt,
1480
- rejection=lambda x: sys.getsizeof(x) > 113,
1481
- rejection_text="[red]Error:[/red] Identity field must be <= 64 raw bytes.",
1482
- )
1268
+ def create_identity_table(title: str = None):
1269
+ if not title:
1270
+ title = "On-Chain Identity"
1483
1271
 
1484
- def pgp_check(s: str):
1485
- try:
1486
- if s.startswith("0x"):
1487
- s = s[2:] # Strip '0x'
1488
- pgp_fingerprint_encoded = binascii.unhexlify(s.replace(" ", ""))
1489
- except Exception:
1490
- return True
1491
- return True if len(pgp_fingerprint_encoded) != 20 else False
1492
-
1493
- display_name = text_rejection("Display name")
1494
- legal_name = text_rejection("Legal name")
1495
- web_url = text_rejection("Web URL")
1496
- riot_handle = text_rejection("Riot handle")
1497
- email = text_rejection("Email address")
1498
- pgp_fingerprint = retry_prompt(
1499
- "PGP fingerprint (Eg: A1B2 C3D4 E5F6 7890 1234 5678 9ABC DEF0 1234 5678)",
1500
- lambda s: False if not s else pgp_check(s),
1501
- "[red]Error:[/red] PGP Fingerprint must be exactly 20 bytes.",
1502
- )
1503
- image_url = text_rejection("Image URL")
1504
- info_ = text_rejection("Enter info")
1505
- twitter_url = text_rejection("𝕏 (Twitter) URL")
1506
-
1507
- subnet_netuid = None
1508
- if validator is False:
1509
- subnet_netuid = IntPrompt.ask("Enter the netuid of the subnet you own")
1510
-
1511
- return (
1512
- display_name,
1513
- legal_name,
1514
- web_url,
1515
- pgp_fingerprint,
1516
- riot_handle,
1517
- email,
1518
- image_url,
1519
- twitter_url,
1520
- info_,
1521
- validator,
1522
- subnet_netuid,
1272
+ table = Table(
1273
+ Column(
1274
+ "Item",
1275
+ justify="right",
1276
+ style=COLOR_PALETTE["GENERAL"]["SUBHEADING_MAIN"],
1277
+ no_wrap=True,
1278
+ ),
1279
+ Column("Value", style=COLOR_PALETTE["GENERAL"]["SUBHEADING"]),
1280
+ title=f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]{title}",
1281
+ show_footer=True,
1282
+ show_edge=False,
1283
+ header_style="bold white",
1284
+ border_style="bright_black",
1285
+ style="bold",
1286
+ title_justify="center",
1287
+ show_lines=False,
1288
+ pad_edge=True,
1523
1289
  )
1290
+ return table
1524
1291
 
1525
1292
 
1526
1293
  async def set_id(
1527
1294
  wallet: Wallet,
1528
1295
  subtensor: SubtensorInterface,
1529
- display_name: str,
1530
- legal_name: str,
1296
+ name: str,
1531
1297
  web_url: str,
1532
- pgp_fingerprint: str,
1533
- riot_handle: str,
1534
- email: str,
1535
- image: str,
1536
- twitter: str,
1537
- info_: str,
1538
- validator_id: bool,
1539
- subnet_netuid: int,
1298
+ image_url: str,
1299
+ discord: str,
1300
+ description: str,
1301
+ additional: str,
1302
+ github_repo: str,
1540
1303
  prompt: bool,
1541
1304
  ):
1542
1305
  """Create a new or update existing identity on-chain."""
1543
1306
 
1544
- id_dict = {
1545
- "additional": [[]],
1546
- "display": display_name,
1547
- "legal": legal_name,
1548
- "web": web_url,
1549
- "pgp_fingerprint": pgp_fingerprint,
1550
- "riot": riot_handle,
1551
- "email": email,
1552
- "image": image,
1553
- "twitter": twitter,
1554
- "info": info_,
1307
+ identity_data = {
1308
+ "name": name.encode(),
1309
+ "url": web_url.encode(),
1310
+ "image": image_url.encode(),
1311
+ "discord": discord.encode(),
1312
+ "description": description.encode(),
1313
+ "additional": additional.encode(),
1314
+ "github_repo": github_repo.encode(),
1555
1315
  }
1556
1316
 
1557
- try:
1558
- pgp_fingerprint_encoded = binascii.unhexlify(pgp_fingerprint.replace(" ", ""))
1559
- except Exception as e:
1560
- print_error(f"The PGP is not in the correct format: {e}")
1561
- raise typer.Exit()
1562
-
1563
- for field, string in id_dict.items():
1564
- if (
1565
- field == "pgp_fingerprint"
1566
- and pgp_fingerprint
1567
- and len(pgp_fingerprint_encoded) != 20
1568
- ):
1569
- err_console.print(
1570
- "[red]Error:[/red] PGP Fingerprint must be exactly 20 bytes."
1571
- )
1572
- return False
1573
- elif (size := getsizeof(string)) > 113: # 64 + 49 overhead bytes for string
1317
+ for field, value in identity_data.items():
1318
+ max_size = 64 # bytes
1319
+ if len(value) > max_size:
1574
1320
  err_console.print(
1575
- f"[red]Error:[/red] Identity field [white]{field}[/white] must be <= 64 raw bytes.\n"
1576
- f"Value: '{string}' currently [white]{size} bytes[/white]."
1321
+ f"[red]Error:[/red] Identity field [white]{field}[/white] must be <= {max_size} bytes.\n"
1322
+ f"Value '{value.decode()}' is {len(value)} bytes."
1577
1323
  )
1578
1324
  return False
1579
1325
 
1580
- identified = (
1581
- wallet.hotkey.ss58_address if validator_id else wallet.coldkey.ss58_address
1582
- )
1583
- encoded_id_dict = {
1584
- "info": {
1585
- "additional": [[]],
1586
- "display": {f"Raw{len(display_name.encode())}": display_name.encode()},
1587
- "legal": {f"Raw{len(legal_name.encode())}": legal_name.encode()},
1588
- "web": {f"Raw{len(web_url.encode())}": web_url.encode()},
1589
- "riot": {f"Raw{len(riot_handle.encode())}": riot_handle.encode()},
1590
- "email": {f"Raw{len(email.encode())}": email.encode()},
1591
- "pgp_fingerprint": pgp_fingerprint_encoded if pgp_fingerprint else None,
1592
- "image": {f"Raw{len(image.encode())}": image.encode()},
1593
- "info": {f"Raw{len(info_.encode())}": info_.encode()},
1594
- "twitter": {f"Raw{len(twitter.encode())}": twitter.encode()},
1595
- },
1596
- "identified": identified,
1597
- }
1598
-
1599
- if prompt:
1600
- if not Confirm.ask(
1601
- "Cost to register an Identity is [bold white italic]0.1 Tao[/bold white italic],"
1602
- " are you sure you wish to continue?"
1603
- ):
1604
- console.print(":cross_mark: Aborted!")
1605
- raise typer.Exit()
1606
-
1607
- if validator_id:
1608
- block_hash = await subtensor.substrate.get_chain_head()
1609
-
1610
- is_registered_on_root, hotkey_owner = await asyncio.gather(
1611
- is_hotkey_registered(
1612
- subtensor, netuid=0, hotkey_ss58=wallet.hotkey.ss58_address
1613
- ),
1614
- subtensor.get_hotkey_owner(
1615
- hotkey_ss58=wallet.hotkey.ss58_address, block_hash=block_hash
1616
- ),
1617
- )
1618
-
1619
- if not is_registered_on_root:
1620
- print_error("The hotkey is not registered on root. Aborting.")
1621
- return False
1622
-
1623
- own_hotkey = wallet.coldkeypub.ss58_address == hotkey_owner
1624
- if not own_hotkey:
1625
- print_error("The hotkey doesn't belong to the coldkey wallet. Aborting.")
1626
- return False
1627
- else:
1628
- subnet_owner_ = await subtensor.substrate.query(
1629
- module="SubtensorModule",
1630
- storage_function="SubnetOwner",
1631
- params=[subnet_netuid],
1632
- )
1633
- subnet_owner = decode_account_id(subnet_owner_[0])
1634
- if subnet_owner != wallet.coldkeypub.ss58_address:
1635
- print_error(f":cross_mark: This wallet doesn't own subnet {subnet_netuid}.")
1636
- return False
1637
-
1638
- if not unlock_key(wallet).success:
1326
+ try:
1327
+ wallet.unlock_coldkey()
1328
+ except KeyFileError:
1329
+ err_console.print("Error decrypting coldkey (possibly incorrect password)")
1639
1330
  return False
1640
1331
 
1332
+ call = await subtensor.substrate.compose_call(
1333
+ call_module="SubtensorModule",
1334
+ call_function="set_identity",
1335
+ call_params=identity_data,
1336
+ )
1337
+
1641
1338
  with console.status(
1642
- ":satellite: [bold green]Updating identity on-chain...", spinner="earth"
1339
+ " :satellite: [dark_sea_green3]Updating identity on-chain...", spinner="earth"
1643
1340
  ):
1644
- call = await subtensor.substrate.compose_call(
1645
- call_module="Registry",
1646
- call_function="set_identity",
1647
- call_params=encoded_id_dict,
1648
- )
1649
1341
  success, err_msg = await subtensor.sign_and_send_extrinsic(call, wallet)
1650
1342
 
1651
1343
  if not success:
1652
1344
  err_console.print(f"[red]:cross_mark: Failed![/red] {err_msg}")
1653
1345
  return
1654
1346
 
1655
- console.print(":white_heavy_check_mark: Success!")
1656
- identity = await subtensor.query_identity(
1657
- identified or wallet.coldkey.ss58_address
1658
- )
1659
-
1660
- table = Table(
1661
- Column("Key", justify="right", style="cyan", no_wrap=True),
1662
- Column("Value", style="magenta"),
1663
- title="[bold white italic]Updated On-Chain Identity",
1664
- )
1347
+ console.print(":white_heavy_check_mark: [dark_sea_green3]Success!")
1348
+ identity = await subtensor.query_identity(wallet.coldkeypub.ss58_address)
1665
1349
 
1666
- table.add_row("Address", identified or wallet.coldkey.ss58_address)
1350
+ table = create_identity_table(title="New on-chain Identity")
1351
+ table.add_row("Address", wallet.coldkeypub.ss58_address)
1667
1352
  for key, value in identity.items():
1668
- table.add_row(key, str(value) if value is not None else "~")
1353
+ table.add_row(key, str(value) if value else "~")
1669
1354
 
1670
1355
  return console.print(table)
1671
1356
 
1672
1357
 
1673
- async def get_id(subtensor: SubtensorInterface, ss58_address: str):
1358
+ async def get_id(subtensor: SubtensorInterface, ss58_address: str, title: str = None):
1674
1359
  with console.status(
1675
1360
  ":satellite: [bold green]Querying chain identity...", spinner="earth"
1676
1361
  ):
@@ -1678,40 +1363,37 @@ async def get_id(subtensor: SubtensorInterface, ss58_address: str):
1678
1363
 
1679
1364
  if not identity:
1680
1365
  err_console.print(
1681
- f"[red]Identity not found[/red]"
1682
- f" for [light_goldenrod3]{ss58_address}[/light_goldenrod3]"
1683
- f" on [white]{subtensor}[/white]"
1366
+ f"[blue]Existing identity not found[/blue]"
1367
+ f" for [{COLOR_PALETTE['GENERAL']['COLDKEY']}]{ss58_address}[/{COLOR_PALETTE['GENERAL']['COLDKEY']}]"
1368
+ f" on {subtensor}"
1684
1369
  )
1685
- return
1686
- table = Table(
1687
- Column("Item", justify="right", style="cyan", no_wrap=True),
1688
- Column("Value", style="magenta"),
1689
- title="[bold white italic]On-Chain Identity",
1690
- )
1370
+ return {}
1691
1371
 
1372
+ table = create_identity_table(title)
1692
1373
  table.add_row("Address", ss58_address)
1693
1374
  for key, value in identity.items():
1694
- table.add_row(key, str(value) if value is not None else "~")
1375
+ table.add_row(key, str(value) if value else "~")
1695
1376
 
1696
- return console.print(table)
1377
+ console.print(table)
1378
+ return identity
1697
1379
 
1698
1380
 
1699
1381
  async def check_coldkey_swap(wallet: Wallet, subtensor: SubtensorInterface):
1700
- arbitration_check = len(
1382
+ arbitration_check = len( # TODO verify this works
1701
1383
  (
1702
- await subtensor.substrate.query(
1384
+ await subtensor.query(
1703
1385
  module="SubtensorModule",
1704
1386
  storage_function="ColdkeySwapDestinations",
1705
1387
  params=[wallet.coldkeypub.ss58_address],
1706
1388
  )
1707
- ).decode()
1389
+ )
1708
1390
  )
1709
1391
  if arbitration_check == 0:
1710
1392
  console.print(
1711
1393
  "[green]There has been no previous key swap initiated for your coldkey.[/green]"
1712
1394
  )
1713
1395
  elif arbitration_check == 1:
1714
- arbitration_block = await subtensor.substrate.query(
1396
+ arbitration_block = await subtensor.query(
1715
1397
  module="SubtensorModule",
1716
1398
  storage_function="ColdkeyArbitrationBlock",
1717
1399
  params=[wallet.coldkeypub.ss58_address],
@@ -1735,17 +1417,25 @@ async def check_coldkey_swap(wallet: Wallet, subtensor: SubtensorInterface):
1735
1417
 
1736
1418
  async def sign(wallet: Wallet, message: str, use_hotkey: str):
1737
1419
  """Sign a message using the provided wallet or hotkey."""
1420
+
1421
+ try:
1422
+ wallet.unlock_coldkey()
1423
+ except KeyFileError:
1424
+ err_console.print(
1425
+ ":cross_mark: [red]Keyfile is corrupt, non-writable, non-readable or the password used to decrypt is "
1426
+ "invalid[/red]:[bold white]\n [/bold white]"
1427
+ )
1738
1428
  if not use_hotkey:
1739
- if not unlock_key(wallet).success:
1740
- return False
1741
1429
  keypair = wallet.coldkey
1742
- print_verbose(f"Signing using coldkey: {wallet.name}")
1430
+ print_verbose(
1431
+ f"Signing using [{COLOR_PALETTE['GENERAL']['COLDKEY']}]coldkey: {wallet.name}"
1432
+ )
1743
1433
  else:
1744
- if not unlock_key(wallet, "hot").success:
1745
- return False
1746
1434
  keypair = wallet.hotkey
1747
- print_verbose(f"Signing using hotkey: {wallet.hotkey_str}")
1435
+ print_verbose(
1436
+ f"Signing using [{COLOR_PALETTE['GENERAL']['HOTKEY']}]hotkey: {wallet.hotkey_str}"
1437
+ )
1748
1438
 
1749
1439
  signed_message = keypair.sign(message.encode("utf-8")).hex()
1750
- console.print("[bold green]Message signed successfully:")
1440
+ console.print("[dark_sea_green3]Message signed successfully:")
1751
1441
  console.print(signed_message)