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