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.
- bittensor_cli/__init__.py +2 -2
- bittensor_cli/cli.py +1508 -1385
- bittensor_cli/src/__init__.py +627 -197
- bittensor_cli/src/bittensor/balances.py +41 -8
- bittensor_cli/src/bittensor/chain_data.py +557 -428
- bittensor_cli/src/bittensor/extrinsics/registration.py +161 -47
- bittensor_cli/src/bittensor/extrinsics/root.py +14 -8
- bittensor_cli/src/bittensor/extrinsics/transfer.py +14 -21
- bittensor_cli/src/bittensor/minigraph.py +46 -8
- bittensor_cli/src/bittensor/subtensor_interface.py +572 -253
- bittensor_cli/src/bittensor/utils.py +326 -75
- bittensor_cli/src/commands/stake/__init__.py +154 -0
- bittensor_cli/src/commands/stake/children_hotkeys.py +121 -87
- bittensor_cli/src/commands/stake/move.py +1000 -0
- bittensor_cli/src/commands/stake/stake.py +1637 -1264
- bittensor_cli/src/commands/subnets/__init__.py +0 -0
- bittensor_cli/src/commands/subnets/price.py +867 -0
- bittensor_cli/src/commands/subnets/subnets.py +2055 -0
- bittensor_cli/src/commands/sudo.py +529 -26
- bittensor_cli/src/commands/wallets.py +234 -544
- bittensor_cli/src/commands/weights.py +15 -11
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/METADATA +7 -4
- bittensor_cli-9.0.0rc2.dist-info/RECORD +32 -0
- bittensor_cli/src/bittensor/async_substrate_interface.py +0 -2748
- bittensor_cli/src/commands/root.py +0 -1752
- bittensor_cli/src/commands/subnets.py +0 -897
- bittensor_cli-8.4.3.dist-info/RECORD +0 -31
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/WHEEL +0 -0
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/top_level.txt +0 -0
bittensor_cli/cli.py
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
import asyncio
|
3
|
-
import binascii
|
4
3
|
import curses
|
5
|
-
from functools import partial
|
6
4
|
import os.path
|
7
5
|
import re
|
8
6
|
import ssl
|
@@ -19,21 +17,22 @@ from bittensor_wallet import Wallet
|
|
19
17
|
from rich import box
|
20
18
|
from rich.prompt import Confirm, FloatPrompt, Prompt, IntPrompt
|
21
19
|
from rich.table import Column, Table
|
20
|
+
from rich.tree import Tree
|
22
21
|
from bittensor_cli.src import (
|
23
22
|
defaults,
|
24
23
|
HELP_PANELS,
|
25
24
|
WalletOptions as WO,
|
26
25
|
WalletValidationTypes as WV,
|
27
26
|
Constants,
|
27
|
+
COLOR_PALETTE,
|
28
28
|
)
|
29
29
|
from bittensor_cli.src.bittensor import utils
|
30
30
|
from bittensor_cli.src.bittensor.balances import Balance
|
31
|
-
from
|
32
|
-
|
33
|
-
)
|
34
|
-
from bittensor_cli.src.commands import root, subnets, sudo, wallets
|
31
|
+
from async_substrate_interface.errors import SubstrateRequestException
|
32
|
+
from bittensor_cli.src.commands import sudo, wallets
|
35
33
|
from bittensor_cli.src.commands import weights as weights_cmds
|
36
|
-
from bittensor_cli.src.commands.
|
34
|
+
from bittensor_cli.src.commands.subnets import price, subnets
|
35
|
+
from bittensor_cli.src.commands.stake import children_hotkeys, stake, move
|
37
36
|
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
|
38
37
|
from bittensor_cli.src.bittensor.chain_data import SubnetHyperparameters
|
39
38
|
from bittensor_cli.src.bittensor.utils import (
|
@@ -43,22 +42,30 @@ from bittensor_cli.src.bittensor.utils import (
|
|
43
42
|
is_valid_ss58_address,
|
44
43
|
print_error,
|
45
44
|
validate_chain_endpoint,
|
46
|
-
|
45
|
+
validate_netuid,
|
46
|
+
is_rao_network,
|
47
|
+
get_effective_network,
|
48
|
+
prompt_for_identity,
|
49
|
+
validate_uri,
|
50
|
+
prompt_for_subnet_identity,
|
51
|
+
print_linux_dependency_message,
|
52
|
+
is_linux,
|
47
53
|
)
|
48
54
|
from typing_extensions import Annotated
|
49
55
|
from textwrap import dedent
|
50
|
-
from websockets import ConnectionClosed
|
56
|
+
from websockets import ConnectionClosed, InvalidHandshake
|
51
57
|
from yaml import safe_dump, safe_load
|
52
58
|
|
53
59
|
try:
|
54
60
|
from git import Repo, GitError
|
55
61
|
except ImportError:
|
62
|
+
Repo = None
|
56
63
|
|
57
64
|
class GitError(Exception):
|
58
65
|
pass
|
59
66
|
|
60
67
|
|
61
|
-
__version__ = "
|
68
|
+
__version__ = "9.0.0rc2"
|
62
69
|
|
63
70
|
|
64
71
|
_core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0)
|
@@ -127,15 +134,22 @@ class Options:
|
|
127
134
|
use_password = typer.Option(
|
128
135
|
True,
|
129
136
|
help="Set this to `True` to protect the generated Bittensor key with a password.",
|
137
|
+
is_flag=True,
|
138
|
+
flag_value=False,
|
130
139
|
)
|
131
140
|
public_hex_key = typer.Option(None, help="The public key in hex format.")
|
132
141
|
ss58_address = typer.Option(
|
133
142
|
None, "--ss58", "--ss58-address", help="The SS58 address of the coldkey."
|
134
143
|
)
|
135
|
-
|
144
|
+
overwrite_coldkey = typer.Option(
|
145
|
+
False,
|
146
|
+
help="Overwrite the old coldkey with the newly generated coldkey.",
|
147
|
+
prompt=True,
|
148
|
+
)
|
149
|
+
overwrite_hotkey = typer.Option(
|
136
150
|
False,
|
137
|
-
"
|
138
|
-
|
151
|
+
help="Overwrite the old hotkey with the newly generated hotkey.",
|
152
|
+
prompt=True,
|
139
153
|
)
|
140
154
|
network = typer.Option(
|
141
155
|
None,
|
@@ -157,6 +171,17 @@ class Options:
|
|
157
171
|
None,
|
158
172
|
help="The netuid of the subnet in the root network, (e.g. 1).",
|
159
173
|
prompt=True,
|
174
|
+
callback=validate_netuid,
|
175
|
+
)
|
176
|
+
netuid_not_req = typer.Option(
|
177
|
+
None,
|
178
|
+
help="The netuid of the subnet in the root network, (e.g. 1).",
|
179
|
+
prompt=False,
|
180
|
+
)
|
181
|
+
all_netuids = typer.Option(
|
182
|
+
False,
|
183
|
+
help="Use all netuids",
|
184
|
+
prompt=False,
|
160
185
|
)
|
161
186
|
weights = typer.Option(
|
162
187
|
None,
|
@@ -202,6 +227,17 @@ class Options:
|
|
202
227
|
"--quiet",
|
203
228
|
help="Display only critical information on the console.",
|
204
229
|
)
|
230
|
+
live = typer.Option(
|
231
|
+
False,
|
232
|
+
"--live",
|
233
|
+
help="Display live view of the table",
|
234
|
+
)
|
235
|
+
uri = typer.Option(
|
236
|
+
None,
|
237
|
+
"--uri",
|
238
|
+
help="Create wallet from uri (e.g. 'Alice', 'Bob', 'Charlie', 'Dave', 'Eve')",
|
239
|
+
callback=validate_uri,
|
240
|
+
)
|
205
241
|
|
206
242
|
|
207
243
|
def list_prompt(init_var: list, list_type: type, help_text: str) -> list:
|
@@ -244,7 +280,8 @@ def parse_to_list(
|
|
244
280
|
def verbosity_console_handler(verbosity_level: int = 1) -> None:
|
245
281
|
"""
|
246
282
|
Sets verbosity level of console output
|
247
|
-
:param verbosity_level: int corresponding to verbosity level of console output (0 is quiet, 1 is normal, 2 is
|
283
|
+
:param verbosity_level: int corresponding to verbosity level of console output (0 is quiet, 1 is normal, 2 is
|
284
|
+
verbose)
|
248
285
|
"""
|
249
286
|
if verbosity_level not in range(3):
|
250
287
|
raise ValueError(
|
@@ -264,6 +301,32 @@ def verbosity_console_handler(verbosity_level: int = 1) -> None:
|
|
264
301
|
verbose_console.quiet = False
|
265
302
|
|
266
303
|
|
304
|
+
def get_optional_netuid(netuid: Optional[int], all_netuids: bool) -> Optional[int]:
|
305
|
+
"""
|
306
|
+
Parses options to determine if the user wants to use a specific netuid or all netuids (None)
|
307
|
+
|
308
|
+
Returns:
|
309
|
+
None if using all netuids, otherwise int for the netuid to use
|
310
|
+
"""
|
311
|
+
if netuid is None and all_netuids is True:
|
312
|
+
return None
|
313
|
+
elif netuid is None and all_netuids is False:
|
314
|
+
answer = Prompt.ask(
|
315
|
+
f"Enter the [{COLOR_PALETTE['GENERAL']['SUBHEADING_MAIN']}]netuid"
|
316
|
+
f"[/{COLOR_PALETTE['GENERAL']['SUBHEADING_MAIN']}] to use. Leave blank for all netuids",
|
317
|
+
default=None,
|
318
|
+
show_default=False,
|
319
|
+
)
|
320
|
+
if answer is None:
|
321
|
+
return None
|
322
|
+
if answer.lower() == "all":
|
323
|
+
return None
|
324
|
+
else:
|
325
|
+
return int(answer)
|
326
|
+
else:
|
327
|
+
return netuid
|
328
|
+
|
329
|
+
|
267
330
|
def get_n_words(n_words: Optional[int]) -> int:
|
268
331
|
"""
|
269
332
|
Prompts the user to select the number of words used in the mnemonic if not supplied or not within the
|
@@ -413,12 +476,21 @@ def version_callback(value: bool):
|
|
413
476
|
raise typer.Exit()
|
414
477
|
|
415
478
|
|
479
|
+
def commands_callback(value: bool):
|
480
|
+
"""
|
481
|
+
Prints a tree of commands for the app
|
482
|
+
"""
|
483
|
+
if value:
|
484
|
+
cli = CLIManager()
|
485
|
+
console.print(cli.generate_command_tree())
|
486
|
+
raise typer.Exit()
|
487
|
+
|
488
|
+
|
416
489
|
class CLIManager:
|
417
490
|
"""
|
418
491
|
:var app: the main CLI Typer app
|
419
492
|
:var config_app: the Typer app as it relates to config commands
|
420
493
|
:var wallet_app: the Typer app as it relates to wallet commands
|
421
|
-
:var root_app: the Typer app as it relates to root commands
|
422
494
|
:var stake_app: the Typer app as it relates to stake commands
|
423
495
|
:var sudo_app: the Typer app as it relates to sudo commands
|
424
496
|
:var subnets_app: the Typer app as it relates to subnets commands
|
@@ -429,7 +501,6 @@ class CLIManager:
|
|
429
501
|
app: typer.Typer
|
430
502
|
config_app: typer.Typer
|
431
503
|
wallet_app: typer.Typer
|
432
|
-
root_app: typer.Typer
|
433
504
|
subnets_app: typer.Typer
|
434
505
|
weights_app: typer.Typer
|
435
506
|
utils_app = typer.Typer(epilog=_epilog)
|
@@ -443,7 +514,9 @@ class CLIManager:
|
|
443
514
|
"use_cache": True,
|
444
515
|
"metagraph_cols": {
|
445
516
|
"UID": True,
|
446
|
-
"
|
517
|
+
"GLOBAL_STAKE": True,
|
518
|
+
"LOCAL_STAKE": True,
|
519
|
+
"STAKE_WEIGHT": True,
|
447
520
|
"RANK": True,
|
448
521
|
"TRUST": True,
|
449
522
|
"CONSENSUS": True,
|
@@ -471,7 +544,6 @@ class CLIManager:
|
|
471
544
|
)
|
472
545
|
self.config_app = typer.Typer(epilog=_epilog)
|
473
546
|
self.wallet_app = typer.Typer(epilog=_epilog)
|
474
|
-
self.root_app = typer.Typer(epilog=_epilog)
|
475
547
|
self.stake_app = typer.Typer(epilog=_epilog)
|
476
548
|
self.sudo_app = typer.Typer(epilog=_epilog)
|
477
549
|
self.subnets_app = typer.Typer(epilog=_epilog)
|
@@ -501,15 +573,6 @@ class CLIManager:
|
|
501
573
|
self.wallet_app, name="wallets", hidden=True, no_args_is_help=True
|
502
574
|
)
|
503
575
|
|
504
|
-
# root aliases
|
505
|
-
self.app.add_typer(
|
506
|
-
self.root_app,
|
507
|
-
name="root",
|
508
|
-
short_help="Root commands, alias: `r`",
|
509
|
-
no_args_is_help=True,
|
510
|
-
)
|
511
|
-
self.app.add_typer(self.root_app, name="r", hidden=True, no_args_is_help=True)
|
512
|
-
|
513
576
|
# stake aliases
|
514
577
|
self.app.add_typer(
|
515
578
|
self.stake_app,
|
@@ -558,7 +621,9 @@ class CLIManager:
|
|
558
621
|
)
|
559
622
|
|
560
623
|
# utils app
|
561
|
-
self.app.add_typer(
|
624
|
+
self.app.add_typer(
|
625
|
+
self.utils_app, name="utils", no_args_is_help=True, hidden=True
|
626
|
+
)
|
562
627
|
|
563
628
|
# config commands
|
564
629
|
self.config_app.command("set")(self.set_config)
|
@@ -595,16 +660,21 @@ class CLIManager:
|
|
595
660
|
"balance", rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"]
|
596
661
|
)(self.wallet_balance)
|
597
662
|
self.wallet_app.command(
|
598
|
-
"history",
|
663
|
+
"history",
|
664
|
+
rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
|
665
|
+
hidden=True,
|
599
666
|
)(self.wallet_history)
|
600
667
|
self.wallet_app.command(
|
601
|
-
"overview",
|
668
|
+
"overview",
|
669
|
+
rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
|
602
670
|
)(self.wallet_overview)
|
603
671
|
self.wallet_app.command(
|
604
672
|
"transfer", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
|
605
673
|
)(self.wallet_transfer)
|
606
674
|
self.wallet_app.command(
|
607
|
-
"inspect",
|
675
|
+
"inspect",
|
676
|
+
rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
|
677
|
+
hidden=True,
|
608
678
|
)(self.wallet_inspect)
|
609
679
|
self.wallet_app.command(
|
610
680
|
"faucet", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
|
@@ -619,59 +689,25 @@ class CLIManager:
|
|
619
689
|
"sign", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
|
620
690
|
)(self.wallet_sign)
|
621
691
|
|
622
|
-
# root commands
|
623
|
-
self.root_app.command("list")(self.root_list)
|
624
|
-
self.root_app.command(
|
625
|
-
"set-weights", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
626
|
-
)(self.root_set_weights)
|
627
|
-
self.root_app.command(
|
628
|
-
"get-weights", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
629
|
-
)(self.root_get_weights)
|
630
|
-
self.root_app.command(
|
631
|
-
"boost", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
632
|
-
)(self.root_boost)
|
633
|
-
self.root_app.command(
|
634
|
-
"slash", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
635
|
-
)(self.root_slash)
|
636
|
-
self.root_app.command(
|
637
|
-
"senate", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
638
|
-
)(self.root_senate)
|
639
|
-
self.root_app.command(
|
640
|
-
"senate-vote", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
641
|
-
)(self.root_senate_vote)
|
642
|
-
self.root_app.command("register")(self.root_register)
|
643
|
-
self.root_app.command(
|
644
|
-
"proposals", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
645
|
-
)(self.root_proposals)
|
646
|
-
self.root_app.command(
|
647
|
-
"set-take", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
648
|
-
)(self.root_set_take)
|
649
|
-
self.root_app.command(
|
650
|
-
"delegate-stake", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
651
|
-
)(self.root_delegate_stake)
|
652
|
-
self.root_app.command(
|
653
|
-
"undelegate-stake", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
654
|
-
)(self.root_undelegate_stake)
|
655
|
-
self.root_app.command(
|
656
|
-
"my-delegates", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
657
|
-
)(self.root_my_delegates)
|
658
|
-
self.root_app.command(
|
659
|
-
"list-delegates", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
660
|
-
)(self.root_list_delegates)
|
661
|
-
self.root_app.command(
|
662
|
-
"nominate", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
663
|
-
)(self.root_nominate)
|
664
|
-
|
665
692
|
# stake commands
|
666
|
-
self.stake_app.command(
|
667
|
-
"show", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
668
|
-
)(self.stake_show)
|
669
693
|
self.stake_app.command(
|
670
694
|
"add", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
671
695
|
)(self.stake_add)
|
672
696
|
self.stake_app.command(
|
673
697
|
"remove", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
674
698
|
)(self.stake_remove)
|
699
|
+
self.stake_app.command(
|
700
|
+
"list", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
701
|
+
)(self.stake_list)
|
702
|
+
self.stake_app.command(
|
703
|
+
"move", rich_help_panel=HELP_PANELS["STAKE"]["MOVEMENT"]
|
704
|
+
)(self.stake_move)
|
705
|
+
self.stake_app.command(
|
706
|
+
"transfer", rich_help_panel=HELP_PANELS["STAKE"]["MOVEMENT"]
|
707
|
+
)(self.stake_transfer)
|
708
|
+
self.stake_app.command(
|
709
|
+
"swap", rich_help_panel=HELP_PANELS["STAKE"]["MOVEMENT"]
|
710
|
+
)(self.stake_swap)
|
675
711
|
|
676
712
|
# stake-children commands
|
677
713
|
children_app = typer.Typer()
|
@@ -697,6 +733,21 @@ class CLIManager:
|
|
697
733
|
self.sudo_app.command("get", rich_help_panel=HELP_PANELS["SUDO"]["CONFIG"])(
|
698
734
|
self.sudo_get
|
699
735
|
)
|
736
|
+
self.sudo_app.command(
|
737
|
+
"senate", rich_help_panel=HELP_PANELS["SUDO"]["GOVERNANCE"]
|
738
|
+
)(self.sudo_senate)
|
739
|
+
self.sudo_app.command(
|
740
|
+
"proposals", rich_help_panel=HELP_PANELS["SUDO"]["GOVERNANCE"]
|
741
|
+
)(self.sudo_proposals)
|
742
|
+
self.sudo_app.command(
|
743
|
+
"senate-vote", rich_help_panel=HELP_PANELS["SUDO"]["GOVERNANCE"]
|
744
|
+
)(self.sudo_senate_vote)
|
745
|
+
self.sudo_app.command("set-take", rich_help_panel=HELP_PANELS["SUDO"]["TAKE"])(
|
746
|
+
self.sudo_set_take
|
747
|
+
)
|
748
|
+
self.sudo_app.command("get-take", rich_help_panel=HELP_PANELS["SUDO"]["TAKE"])(
|
749
|
+
self.sudo_get_take
|
750
|
+
)
|
700
751
|
|
701
752
|
# subnets commands
|
702
753
|
self.subnets_app.command(
|
@@ -706,8 +757,8 @@ class CLIManager:
|
|
706
757
|
"list", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
|
707
758
|
)(self.subnets_list)
|
708
759
|
self.subnets_app.command(
|
709
|
-
"
|
710
|
-
)(self.
|
760
|
+
"burn-cost", rich_help_panel=HELP_PANELS["SUBNETS"]["CREATION"]
|
761
|
+
)(self.subnets_burn_cost)
|
711
762
|
self.subnets_app.command(
|
712
763
|
"create", rich_help_panel=HELP_PANELS["SUBNETS"]["CREATION"]
|
713
764
|
)(self.subnets_create)
|
@@ -718,8 +769,14 @@ class CLIManager:
|
|
718
769
|
"register", rich_help_panel=HELP_PANELS["SUBNETS"]["REGISTER"]
|
719
770
|
)(self.subnets_register)
|
720
771
|
self.subnets_app.command(
|
721
|
-
"metagraph", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
|
722
|
-
)(self.
|
772
|
+
"metagraph", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"], hidden=True
|
773
|
+
)(self.subnets_show) # Aliased to `s show` for now
|
774
|
+
self.subnets_app.command(
|
775
|
+
"show", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
|
776
|
+
)(self.subnets_show)
|
777
|
+
self.subnets_app.command(
|
778
|
+
"price", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
|
779
|
+
)(self.subnets_price)
|
723
780
|
|
724
781
|
# weights commands
|
725
782
|
self.weights_app.command(
|
@@ -764,22 +821,49 @@ class CLIManager:
|
|
764
821
|
hidden=True,
|
765
822
|
)(self.wallet_get_id)
|
766
823
|
|
767
|
-
# Root
|
768
|
-
self.root_app.command("set_weights", hidden=True)(self.root_set_weights)
|
769
|
-
self.root_app.command("get_weights", hidden=True)(self.root_get_weights)
|
770
|
-
self.root_app.command("senate_vote", hidden=True)(self.root_senate_vote)
|
771
|
-
self.root_app.command("set_take", hidden=True)(self.root_set_take)
|
772
|
-
self.root_app.command("delegate_stake", hidden=True)(self.root_delegate_stake)
|
773
|
-
self.root_app.command("undelegate_stake", hidden=True)(
|
774
|
-
self.root_undelegate_stake
|
775
|
-
)
|
776
|
-
self.root_app.command("my_delegates", hidden=True)(self.root_my_delegates)
|
777
|
-
self.root_app.command("list_delegates", hidden=True)(self.root_list_delegates)
|
778
|
-
|
779
824
|
# Subnets
|
780
|
-
self.subnets_app.command("
|
825
|
+
self.subnets_app.command("burn_cost", hidden=True)(self.subnets_burn_cost)
|
781
826
|
self.subnets_app.command("pow_register", hidden=True)(self.subnets_pow_register)
|
782
827
|
|
828
|
+
# Sudo
|
829
|
+
self.sudo_app.command("senate_vote", hidden=True)(self.sudo_senate_vote)
|
830
|
+
self.sudo_app.command("get_take", hidden=True)(self.sudo_get_take)
|
831
|
+
self.sudo_app.command("set_take", hidden=True)(self.sudo_set_take)
|
832
|
+
|
833
|
+
def generate_command_tree(self) -> Tree:
|
834
|
+
"""
|
835
|
+
Generates a rich.Tree of the commands, subcommands, and groups of this app
|
836
|
+
"""
|
837
|
+
|
838
|
+
def build_rich_tree(data: dict, parent: Tree):
|
839
|
+
for group, content in data.get("groups", {}).items():
|
840
|
+
group_node = parent.add(
|
841
|
+
f"[bold cyan]{group}[/]"
|
842
|
+
) # Add group to the tree
|
843
|
+
for command in content.get("commands", []):
|
844
|
+
group_node.add(f"[green]{command}[/]") # Add commands to the group
|
845
|
+
build_rich_tree(content, group_node) # Recurse for subgroups
|
846
|
+
|
847
|
+
def traverse_group(group: typer.Typer) -> dict:
|
848
|
+
tree = {}
|
849
|
+
if commands := [
|
850
|
+
cmd.name for cmd in group.registered_commands if not cmd.hidden
|
851
|
+
]:
|
852
|
+
tree["commands"] = commands
|
853
|
+
for group in group.registered_groups:
|
854
|
+
if "groups" not in tree:
|
855
|
+
tree["groups"] = {}
|
856
|
+
if not group.hidden:
|
857
|
+
if group_transversal := traverse_group(group.typer_instance):
|
858
|
+
tree["groups"][group.name] = group_transversal
|
859
|
+
|
860
|
+
return tree
|
861
|
+
|
862
|
+
groups_and_commands = traverse_group(self.app)
|
863
|
+
root = Tree("[bold magenta]BTCLI Commands[/]") # Root node
|
864
|
+
build_rich_tree(groups_and_commands, root)
|
865
|
+
return root
|
866
|
+
|
783
867
|
def initialize_chain(
|
784
868
|
self,
|
785
869
|
network: Optional[list[str]] = None,
|
@@ -810,13 +894,13 @@ class CLIManager:
|
|
810
894
|
elif self.config["network"]:
|
811
895
|
self.subtensor = SubtensorInterface(self.config["network"])
|
812
896
|
console.print(
|
813
|
-
f"Using the specified network [
|
897
|
+
f"Using the specified network [{COLOR_PALETTE['GENERAL']['LINKS']}]{self.config['network']}[/{COLOR_PALETTE['GENERAL']['LINKS']}] from config"
|
814
898
|
)
|
815
899
|
else:
|
816
900
|
self.subtensor = SubtensorInterface(defaults.subtensor.network)
|
817
901
|
return self.subtensor
|
818
902
|
|
819
|
-
def _run_command(self, cmd: Coroutine):
|
903
|
+
def _run_command(self, cmd: Coroutine, exit_early: bool = True):
|
820
904
|
"""
|
821
905
|
Runs the supplied coroutine with `asyncio.run`
|
822
906
|
"""
|
@@ -832,7 +916,7 @@ class CLIManager:
|
|
832
916
|
initiated = True
|
833
917
|
result = await cmd
|
834
918
|
return result
|
835
|
-
except (ConnectionRefusedError, ssl.SSLError):
|
919
|
+
except (ConnectionRefusedError, ssl.SSLError, InvalidHandshake):
|
836
920
|
err_console.print(f"Unable to connect to the chain: {self.subtensor}")
|
837
921
|
verbose_console.print(traceback.format_exc())
|
838
922
|
except (
|
@@ -849,7 +933,12 @@ class CLIManager:
|
|
849
933
|
finally:
|
850
934
|
if initiated is False:
|
851
935
|
asyncio.create_task(cmd).cancel()
|
852
|
-
|
936
|
+
if exit_early is True:
|
937
|
+
try:
|
938
|
+
raise typer.Exit()
|
939
|
+
except Exception as e: # ensures we always exit cleanly
|
940
|
+
if not isinstance(e, (typer.Exit, RuntimeError)): # temporarily to handle multiple run commands in one session
|
941
|
+
err_console.print(f"An unknown error has occurred: {e}")
|
853
942
|
|
854
943
|
if sys.version_info < (3, 10):
|
855
944
|
# For Python 3.9 or lower
|
@@ -861,11 +950,21 @@ class CLIManager:
|
|
861
950
|
def main_callback(
|
862
951
|
self,
|
863
952
|
version: Annotated[
|
864
|
-
Optional[bool],
|
953
|
+
Optional[bool],
|
954
|
+
typer.Option(
|
955
|
+
"--version", callback=version_callback, help="Show BTCLI version"
|
956
|
+
),
|
957
|
+
] = None,
|
958
|
+
commands: Annotated[
|
959
|
+
Optional[bool],
|
960
|
+
typer.Option(
|
961
|
+
"--commands", callback=commands_callback, help="Show BTCLI commands"
|
962
|
+
),
|
865
963
|
] = None,
|
866
964
|
):
|
867
965
|
"""
|
868
|
-
Command line interface (CLI) for Bittensor. Uses the values in the configuration file. These values can be
|
966
|
+
Command line interface (CLI) for Bittensor. Uses the values in the configuration file. These values can be
|
967
|
+
overriden by passing them explicitly in the command line.
|
869
968
|
"""
|
870
969
|
# Load or create the config file
|
871
970
|
if os.path.exists(self.config_path):
|
@@ -1173,39 +1272,16 @@ class CLIManager:
|
|
1173
1272
|
:return: created Wallet object
|
1174
1273
|
"""
|
1175
1274
|
# Prompt for missing attributes specified in ask_for
|
1176
|
-
|
1177
|
-
if wallet_path:
|
1178
|
-
if wallet_path == "default":
|
1179
|
-
wallet_path = defaults.wallet.path
|
1180
|
-
|
1181
|
-
elif self.config.get("wallet_path"):
|
1182
|
-
wallet_path = self.config.get("wallet_path")
|
1183
|
-
console.print(
|
1184
|
-
f"Using the wallet path from config:[bold magenta] {wallet_path}"
|
1185
|
-
)
|
1186
|
-
|
1187
|
-
if WO.PATH in ask_for and not wallet_path:
|
1188
|
-
wallet_path = Prompt.ask(
|
1189
|
-
"Enter the [blue]wallet path[/blue]"
|
1190
|
-
+ " [dark_sea_green3 italic](Hint: You can set this with `btcli config set --wallet-path`)[/dark_sea_green3 italic]",
|
1191
|
-
default=defaults.wallet.path,
|
1192
|
-
)
|
1193
|
-
if wallet_path:
|
1194
|
-
wallet_path = os.path.expanduser(wallet_path)
|
1195
|
-
else:
|
1196
|
-
wallet_path = os.path.expanduser(defaults.wallet.path)
|
1197
|
-
console.print(f"Using default wallet path: ({defaults.wallet.path})")
|
1198
|
-
|
1199
1275
|
if WO.NAME in ask_for and not wallet_name:
|
1200
1276
|
if self.config.get("wallet_name"):
|
1201
1277
|
wallet_name = self.config.get("wallet_name")
|
1202
1278
|
console.print(
|
1203
|
-
f"Using the wallet name from config:[bold cyan] {wallet_name}"
|
1279
|
+
f"Using the [blue]wallet name[/blue] from config:[bold cyan] {wallet_name}"
|
1204
1280
|
)
|
1205
1281
|
else:
|
1206
1282
|
wallet_name = Prompt.ask(
|
1207
1283
|
"Enter the [blue]wallet name[/blue]"
|
1208
|
-
+ " [
|
1284
|
+
+ f" [{COLOR_PALETTE['GENERAL']['HINT']} italic](Hint: You can set this with `btcli config set --wallet-name`)",
|
1209
1285
|
default=defaults.wallet.name,
|
1210
1286
|
)
|
1211
1287
|
|
@@ -1213,7 +1289,7 @@ class CLIManager:
|
|
1213
1289
|
if self.config.get("wallet_hotkey"):
|
1214
1290
|
wallet_hotkey = self.config.get("wallet_hotkey")
|
1215
1291
|
console.print(
|
1216
|
-
f"Using the wallet hotkey from config:[bold cyan] {wallet_hotkey}"
|
1292
|
+
f"Using the [blue]wallet hotkey[/blue] from config:[bold cyan] {wallet_hotkey}"
|
1217
1293
|
)
|
1218
1294
|
else:
|
1219
1295
|
wallet_hotkey = Prompt.ask(
|
@@ -1221,8 +1297,27 @@ class CLIManager:
|
|
1221
1297
|
+ " [dark_sea_green3 italic](Hint: You can set this with `btcli config set --wallet-hotkey`)[/dark_sea_green3 italic]",
|
1222
1298
|
default=defaults.wallet.hotkey,
|
1223
1299
|
)
|
1300
|
+
if wallet_path:
|
1301
|
+
if wallet_path == "default":
|
1302
|
+
wallet_path = defaults.wallet.path
|
1303
|
+
|
1304
|
+
elif self.config.get("wallet_path"):
|
1305
|
+
wallet_path = self.config.get("wallet_path")
|
1306
|
+
console.print(
|
1307
|
+
f"Using the [blue]wallet path[/blue] from config:[bold magenta] {wallet_path}"
|
1308
|
+
)
|
1309
|
+
else:
|
1310
|
+
wallet_path = defaults.wallet.path
|
1224
1311
|
|
1312
|
+
if WO.PATH in ask_for and not wallet_path:
|
1313
|
+
wallet_path = Prompt.ask(
|
1314
|
+
"Enter the [blue]wallet path[/blue]"
|
1315
|
+
+ " [dark_sea_green3 italic](Hint: You can set this with `btcli config set --wallet-path`)[/dark_sea_green3 italic]",
|
1316
|
+
default=defaults.wallet.path,
|
1317
|
+
)
|
1225
1318
|
# Create the Wallet object
|
1319
|
+
if wallet_path:
|
1320
|
+
wallet_path = os.path.expanduser(wallet_path)
|
1226
1321
|
wallet = Wallet(name=wallet_name, path=wallet_path, hotkey=wallet_hotkey)
|
1227
1322
|
|
1228
1323
|
# Validate the wallet if required
|
@@ -1378,7 +1473,7 @@ class CLIManager:
|
|
1378
1473
|
"Netuids must be a comma-separated list of ints, e.g., `--netuids 1,2,3,4`.",
|
1379
1474
|
)
|
1380
1475
|
|
1381
|
-
ask_for = [WO.NAME] if not all_wallets else []
|
1476
|
+
ask_for = [WO.NAME, WO.PATH] if not all_wallets else [WO.PATH]
|
1382
1477
|
validate = WV.WALLET if not all_wallets else WV.NONE
|
1383
1478
|
wallet = self.wallet_ask(
|
1384
1479
|
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
|
@@ -1408,6 +1503,7 @@ class CLIManager:
|
|
1408
1503
|
include_hotkeys,
|
1409
1504
|
exclude_hotkeys,
|
1410
1505
|
netuids_filter=netuids,
|
1506
|
+
verbose=verbose,
|
1411
1507
|
)
|
1412
1508
|
)
|
1413
1509
|
|
@@ -1425,12 +1521,9 @@ class CLIManager:
|
|
1425
1521
|
None,
|
1426
1522
|
"--amount",
|
1427
1523
|
"-a",
|
1428
|
-
prompt=
|
1524
|
+
prompt=True,
|
1429
1525
|
help="Amount (in TAO) to transfer.",
|
1430
1526
|
),
|
1431
|
-
transfer_all: bool = typer.Option(
|
1432
|
-
False, "--all", prompt=False, help="Transfer all available balance."
|
1433
|
-
),
|
1434
1527
|
wallet_name: str = Options.wallet_name,
|
1435
1528
|
wallet_path: str = Options.wallet_path,
|
1436
1529
|
wallet_hotkey: str = Options.wallet_hotkey,
|
@@ -1466,25 +1559,20 @@ class CLIManager:
|
|
1466
1559
|
wallet_name,
|
1467
1560
|
wallet_path,
|
1468
1561
|
wallet_hotkey,
|
1469
|
-
ask_for=[WO.NAME],
|
1562
|
+
ask_for=[WO.NAME, WO.PATH],
|
1470
1563
|
validate=WV.WALLET,
|
1471
1564
|
)
|
1565
|
+
|
1566
|
+
# For Rao games - temporarily commented out
|
1567
|
+
# effective_network = get_effective_network(self.config, network)
|
1568
|
+
# if is_rao_network(effective_network):
|
1569
|
+
# print_error("This command is disabled on the 'rao' network.")
|
1570
|
+
# raise typer.Exit()
|
1571
|
+
|
1472
1572
|
subtensor = self.initialize_chain(network)
|
1473
|
-
if transfer_all and amount:
|
1474
|
-
print_error("Cannot specify an amount and '--all' flag.")
|
1475
|
-
raise typer.Exit()
|
1476
|
-
elif transfer_all:
|
1477
|
-
amount = 0
|
1478
|
-
elif not amount:
|
1479
|
-
amount = FloatPrompt.ask("Enter amount (in TAO) to transfer.")
|
1480
1573
|
return self._run_command(
|
1481
1574
|
wallets.transfer(
|
1482
|
-
wallet,
|
1483
|
-
subtensor,
|
1484
|
-
destination_ss58_address,
|
1485
|
-
amount,
|
1486
|
-
transfer_all,
|
1487
|
-
prompt,
|
1575
|
+
wallet, subtensor, destination_ss58_address, amount, prompt
|
1488
1576
|
)
|
1489
1577
|
)
|
1490
1578
|
|
@@ -1523,7 +1611,7 @@ class CLIManager:
|
|
1523
1611
|
wallet_name,
|
1524
1612
|
wallet_path,
|
1525
1613
|
wallet_hotkey,
|
1526
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
1614
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
1527
1615
|
validate=WV.WALLET_AND_HOTKEY,
|
1528
1616
|
)
|
1529
1617
|
if not destination_hotkey_name:
|
@@ -1535,7 +1623,7 @@ class CLIManager:
|
|
1535
1623
|
wallet_name,
|
1536
1624
|
wallet_path,
|
1537
1625
|
destination_hotkey_name,
|
1538
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
1626
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
1539
1627
|
validate=WV.WALLET_AND_HOTKEY,
|
1540
1628
|
)
|
1541
1629
|
self.initialize_chain(network)
|
@@ -1591,6 +1679,8 @@ class CLIManager:
|
|
1591
1679
|
|
1592
1680
|
[bold]Note[/bold]: The `inspect` command is for displaying information only and does not perform any transactions or state changes on the blockchain. It is intended to be used with Bittensor CLI and not as a standalone function in user code.
|
1593
1681
|
"""
|
1682
|
+
print_error("This command is disabled on the 'rao' network.")
|
1683
|
+
raise typer.Exit()
|
1594
1684
|
self.verbosity_handler(quiet, verbose)
|
1595
1685
|
|
1596
1686
|
if netuids:
|
@@ -1601,11 +1691,12 @@ class CLIManager:
|
|
1601
1691
|
)
|
1602
1692
|
|
1603
1693
|
# if all-wallets is entered, ask for path
|
1604
|
-
ask_for = [WO.NAME] if not all_wallets else []
|
1694
|
+
ask_for = [WO.NAME, WO.PATH] if not all_wallets else [WO.PATH]
|
1605
1695
|
validate = WV.WALLET if not all_wallets else WV.NONE
|
1606
1696
|
wallet = self.wallet_ask(
|
1607
1697
|
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
|
1608
1698
|
)
|
1699
|
+
|
1609
1700
|
self.initialize_chain(network)
|
1610
1701
|
return self._run_command(
|
1611
1702
|
wallets.inspect(
|
@@ -1667,7 +1758,6 @@ class CLIManager:
|
|
1667
1758
|
"--max-successes",
|
1668
1759
|
help="Set the maximum number of times to successfully run the faucet for this command.",
|
1669
1760
|
),
|
1670
|
-
prompt: bool = Options.prompt,
|
1671
1761
|
):
|
1672
1762
|
"""
|
1673
1763
|
Obtain test TAO tokens by performing Proof of Work (PoW).
|
@@ -1691,7 +1781,7 @@ class CLIManager:
|
|
1691
1781
|
wallet_name,
|
1692
1782
|
wallet_path,
|
1693
1783
|
wallet_hotkey,
|
1694
|
-
ask_for=[WO.NAME],
|
1784
|
+
ask_for=[WO.NAME, WO.PATH],
|
1695
1785
|
validate=WV.WALLET,
|
1696
1786
|
)
|
1697
1787
|
return self._run_command(
|
@@ -1706,7 +1796,6 @@ class CLIManager:
|
|
1706
1796
|
output_in_place,
|
1707
1797
|
verbose,
|
1708
1798
|
max_successes,
|
1709
|
-
prompt,
|
1710
1799
|
)
|
1711
1800
|
)
|
1712
1801
|
|
@@ -1720,7 +1809,6 @@ class CLIManager:
|
|
1720
1809
|
json: Optional[str] = Options.json,
|
1721
1810
|
json_password: Optional[str] = Options.json_password,
|
1722
1811
|
use_password: Optional[bool] = Options.use_password,
|
1723
|
-
overwrite: bool = Options.overwrite,
|
1724
1812
|
quiet: bool = Options.quiet,
|
1725
1813
|
verbose: bool = Options.verbose,
|
1726
1814
|
):
|
@@ -1750,7 +1838,8 @@ class CLIManager:
|
|
1750
1838
|
|
1751
1839
|
if not wallet_name:
|
1752
1840
|
wallet_name = Prompt.ask(
|
1753
|
-
"Enter the name of the new wallet",
|
1841
|
+
f"Enter the name of the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]new wallet (coldkey)",
|
1842
|
+
default=defaults.wallet.name,
|
1754
1843
|
)
|
1755
1844
|
|
1756
1845
|
wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
|
@@ -1766,7 +1855,6 @@ class CLIManager:
|
|
1766
1855
|
json,
|
1767
1856
|
json_password,
|
1768
1857
|
use_password,
|
1769
|
-
overwrite,
|
1770
1858
|
)
|
1771
1859
|
)
|
1772
1860
|
|
@@ -1777,7 +1865,6 @@ class CLIManager:
|
|
1777
1865
|
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
1778
1866
|
public_key_hex: Optional[str] = Options.public_hex_key,
|
1779
1867
|
ss58_address: Optional[str] = Options.ss58_address,
|
1780
|
-
overwrite: bool = Options.overwrite,
|
1781
1868
|
quiet: bool = Options.quiet,
|
1782
1869
|
verbose: bool = Options.verbose,
|
1783
1870
|
):
|
@@ -1806,7 +1893,8 @@ class CLIManager:
|
|
1806
1893
|
|
1807
1894
|
if not wallet_name:
|
1808
1895
|
wallet_name = Prompt.ask(
|
1809
|
-
"Enter the name of the new wallet",
|
1896
|
+
f"Enter the name of the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]new wallet (coldkey)",
|
1897
|
+
default=defaults.wallet.name,
|
1810
1898
|
)
|
1811
1899
|
wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
|
1812
1900
|
|
@@ -1824,7 +1912,7 @@ class CLIManager:
|
|
1824
1912
|
rich.print("[red]Error: Invalid SS58 address or public key![/red]")
|
1825
1913
|
raise typer.Exit()
|
1826
1914
|
return self._run_command(
|
1827
|
-
wallets.regen_coldkey_pub(wallet, ss58_address, public_key_hex
|
1915
|
+
wallets.regen_coldkey_pub(wallet, ss58_address, public_key_hex)
|
1828
1916
|
)
|
1829
1917
|
|
1830
1918
|
def wallet_regen_hotkey(
|
@@ -1839,8 +1927,9 @@ class CLIManager:
|
|
1839
1927
|
use_password: bool = typer.Option(
|
1840
1928
|
False, # Overriden to False
|
1841
1929
|
help="Set to 'True' to protect the generated Bittensor key with a password.",
|
1930
|
+
is_flag=True,
|
1931
|
+
flag_value=True,
|
1842
1932
|
),
|
1843
|
-
overwrite: bool = Options.overwrite,
|
1844
1933
|
quiet: bool = Options.quiet,
|
1845
1934
|
verbose: bool = Options.verbose,
|
1846
1935
|
):
|
@@ -1879,7 +1968,6 @@ class CLIManager:
|
|
1879
1968
|
json,
|
1880
1969
|
json_password,
|
1881
1970
|
use_password,
|
1882
|
-
overwrite,
|
1883
1971
|
)
|
1884
1972
|
)
|
1885
1973
|
|
@@ -1897,8 +1985,10 @@ class CLIManager:
|
|
1897
1985
|
use_password: bool = typer.Option(
|
1898
1986
|
False, # Overriden to False
|
1899
1987
|
help="Set to 'True' to protect the generated Bittensor key with a password.",
|
1988
|
+
is_flag=True,
|
1989
|
+
flag_value=True,
|
1900
1990
|
),
|
1901
|
-
|
1991
|
+
uri: Optional[str] = Options.uri,
|
1902
1992
|
quiet: bool = Options.quiet,
|
1903
1993
|
verbose: bool = Options.verbose,
|
1904
1994
|
):
|
@@ -1920,12 +2010,14 @@ class CLIManager:
|
|
1920
2010
|
|
1921
2011
|
if not wallet_name:
|
1922
2012
|
wallet_name = Prompt.ask(
|
1923
|
-
"Enter the wallet name",
|
2013
|
+
f"Enter the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]wallet name",
|
2014
|
+
default=defaults.wallet.name,
|
1924
2015
|
)
|
1925
2016
|
|
1926
2017
|
if not wallet_hotkey:
|
1927
2018
|
wallet_hotkey = Prompt.ask(
|
1928
|
-
"Enter the name of the new hotkey",
|
2019
|
+
f"Enter the name of the [{COLOR_PALETTE['GENERAL']['HOTKEY']}]new hotkey",
|
2020
|
+
default=defaults.wallet.hotkey,
|
1929
2021
|
)
|
1930
2022
|
|
1931
2023
|
wallet = self.wallet_ask(
|
@@ -1935,10 +2027,9 @@ class CLIManager:
|
|
1935
2027
|
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
1936
2028
|
validate=WV.WALLET,
|
1937
2029
|
)
|
1938
|
-
|
1939
|
-
|
1940
|
-
|
1941
|
-
)
|
2030
|
+
if not uri:
|
2031
|
+
n_words = get_n_words(n_words)
|
2032
|
+
return self._run_command(wallets.new_hotkey(wallet, n_words, use_password, uri))
|
1942
2033
|
|
1943
2034
|
def wallet_new_coldkey(
|
1944
2035
|
self,
|
@@ -1952,7 +2043,7 @@ class CLIManager:
|
|
1952
2043
|
help="The number of words used in the mnemonic. Options: [12, 15, 18, 21, 24]",
|
1953
2044
|
),
|
1954
2045
|
use_password: Optional[bool] = Options.use_password,
|
1955
|
-
|
2046
|
+
uri: Optional[str] = Options.uri,
|
1956
2047
|
quiet: bool = Options.quiet,
|
1957
2048
|
verbose: bool = Options.verbose,
|
1958
2049
|
):
|
@@ -1978,7 +2069,8 @@ class CLIManager:
|
|
1978
2069
|
|
1979
2070
|
if not wallet_name:
|
1980
2071
|
wallet_name = Prompt.ask(
|
1981
|
-
"Enter the name of the new wallet",
|
2072
|
+
f"Enter the name of the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]new wallet (coldkey)",
|
2073
|
+
default=defaults.wallet.name,
|
1982
2074
|
)
|
1983
2075
|
|
1984
2076
|
wallet = self.wallet_ask(
|
@@ -1988,9 +2080,10 @@ class CLIManager:
|
|
1988
2080
|
ask_for=[WO.NAME, WO.PATH],
|
1989
2081
|
validate=WV.NONE,
|
1990
2082
|
)
|
1991
|
-
|
2083
|
+
if not uri:
|
2084
|
+
n_words = get_n_words(n_words)
|
1992
2085
|
return self._run_command(
|
1993
|
-
wallets.new_coldkey(wallet, n_words, use_password,
|
2086
|
+
wallets.new_coldkey(wallet, n_words, use_password, uri)
|
1994
2087
|
)
|
1995
2088
|
|
1996
2089
|
def wallet_check_ck_swap(
|
@@ -2025,7 +2118,7 @@ class CLIManager:
|
|
2025
2118
|
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2026
2119
|
n_words: Optional[int] = None,
|
2027
2120
|
use_password: bool = Options.use_password,
|
2028
|
-
|
2121
|
+
uri: Optional[str] = Options.uri,
|
2029
2122
|
quiet: bool = Options.quiet,
|
2030
2123
|
verbose: bool = Options.verbose,
|
2031
2124
|
):
|
@@ -2049,12 +2142,13 @@ class CLIManager:
|
|
2049
2142
|
|
2050
2143
|
if not wallet_name:
|
2051
2144
|
wallet_name = Prompt.ask(
|
2052
|
-
"Enter the name of the new wallet (coldkey)",
|
2145
|
+
f"Enter the name of the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]new wallet (coldkey)",
|
2053
2146
|
default=defaults.wallet.name,
|
2054
2147
|
)
|
2055
2148
|
if not wallet_hotkey:
|
2056
2149
|
wallet_hotkey = Prompt.ask(
|
2057
|
-
"Enter the the name of the new hotkey",
|
2150
|
+
f"Enter the the name of the [{COLOR_PALETTE['GENERAL']['HOTKEY']}]new hotkey",
|
2151
|
+
default=defaults.wallet.hotkey,
|
2058
2152
|
)
|
2059
2153
|
|
2060
2154
|
self.verbosity_handler(quiet, verbose)
|
@@ -2065,13 +2159,14 @@ class CLIManager:
|
|
2065
2159
|
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
2066
2160
|
validate=WV.NONE,
|
2067
2161
|
)
|
2068
|
-
|
2162
|
+
if not uri:
|
2163
|
+
n_words = get_n_words(n_words)
|
2069
2164
|
return self._run_command(
|
2070
2165
|
wallets.wallet_create(
|
2071
2166
|
wallet,
|
2072
2167
|
n_words,
|
2073
2168
|
use_password,
|
2074
|
-
|
2169
|
+
uri,
|
2075
2170
|
)
|
2076
2171
|
)
|
2077
2172
|
|
@@ -2116,8 +2211,18 @@ class CLIManager:
|
|
2116
2211
|
|
2117
2212
|
"""
|
2118
2213
|
self.verbosity_handler(quiet, verbose)
|
2119
|
-
|
2120
|
-
if
|
2214
|
+
wallet = None
|
2215
|
+
if all_balances:
|
2216
|
+
ask_for = [WO.PATH]
|
2217
|
+
validate = WV.NONE
|
2218
|
+
wallet = self.wallet_ask(
|
2219
|
+
wallet_name,
|
2220
|
+
wallet_path,
|
2221
|
+
wallet_hotkey,
|
2222
|
+
ask_for=ask_for,
|
2223
|
+
validate=validate,
|
2224
|
+
)
|
2225
|
+
elif ss58_addresses:
|
2121
2226
|
valid_ss58s = [
|
2122
2227
|
ss58 for ss58 in set(ss58_addresses) if is_valid_ss58_address(ss58)
|
2123
2228
|
]
|
@@ -2127,20 +2232,45 @@ class CLIManager:
|
|
2127
2232
|
print_error(f"Incorrect ss58 address: {invalid_ss58}. Skipping.")
|
2128
2233
|
|
2129
2234
|
if valid_ss58s:
|
2130
|
-
wallet = None
|
2131
2235
|
ss58_addresses = valid_ss58s
|
2132
2236
|
else:
|
2133
2237
|
raise typer.Exit()
|
2134
2238
|
else:
|
2135
|
-
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2239
|
+
if wallet_name:
|
2240
|
+
coldkey_or_ss58 = wallet_name
|
2241
|
+
else:
|
2242
|
+
coldkey_or_ss58 = Prompt.ask(
|
2243
|
+
"Enter the [blue]wallet name[/blue] or [blue]coldkey ss58 addresses[/blue] (comma-separated)",
|
2244
|
+
default=self.config.get("wallet_name") or defaults.wallet.name,
|
2245
|
+
)
|
2246
|
+
|
2247
|
+
# Split and validate ss58 addresses
|
2248
|
+
coldkey_or_ss58_list = [x.strip() for x in coldkey_or_ss58.split(",")]
|
2249
|
+
if any(is_valid_ss58_address(x) for x in coldkey_or_ss58_list):
|
2250
|
+
valid_ss58s = [
|
2251
|
+
ss58 for ss58 in coldkey_or_ss58_list if is_valid_ss58_address(ss58)
|
2252
|
+
]
|
2253
|
+
invalid_ss58s = set(coldkey_or_ss58_list) - set(valid_ss58s)
|
2254
|
+
for invalid_ss58 in invalid_ss58s:
|
2255
|
+
print_error(f"Incorrect ss58 address: {invalid_ss58}. Skipping.")
|
2256
|
+
|
2257
|
+
if valid_ss58s:
|
2258
|
+
ss58_addresses = valid_ss58s
|
2259
|
+
else:
|
2260
|
+
raise typer.Exit()
|
2261
|
+
else:
|
2262
|
+
wallet_name = (
|
2263
|
+
coldkey_or_ss58_list[0] if coldkey_or_ss58_list else wallet_name
|
2264
|
+
)
|
2265
|
+
ask_for = [WO.NAME, WO.PATH]
|
2266
|
+
validate = WV.WALLET
|
2267
|
+
wallet = self.wallet_ask(
|
2268
|
+
wallet_name,
|
2269
|
+
wallet_path,
|
2270
|
+
wallet_hotkey,
|
2271
|
+
ask_for=ask_for,
|
2272
|
+
validate=validate,
|
2273
|
+
)
|
2144
2274
|
subtensor = self.initialize_chain(network)
|
2145
2275
|
return self._run_command(
|
2146
2276
|
wallets.wallet_balance(wallet, subtensor, all_balances, ss58_addresses)
|
@@ -2166,19 +2296,23 @@ class CLIManager:
|
|
2166
2296
|
[green]$[/green] btcli wallet history
|
2167
2297
|
|
2168
2298
|
"""
|
2299
|
+
# TODO: Fetch effective network and redirect users accordingly - this only works on finney
|
2300
|
+
# no_use_config_str = "Using the network [dark_orange]finney[/dark_orange] and ignoring network/chain configs"
|
2169
2301
|
|
2170
|
-
|
2302
|
+
# if self.config.get("network"):
|
2303
|
+
# if self.config.get("network") != "finney":
|
2304
|
+
# console.print(no_use_config_str)
|
2171
2305
|
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2306
|
+
# For Rao games
|
2307
|
+
print_error("This command is disabled on the 'rao' network.")
|
2308
|
+
raise typer.Exit()
|
2175
2309
|
|
2176
2310
|
self.verbosity_handler(quiet, verbose)
|
2177
2311
|
wallet = self.wallet_ask(
|
2178
2312
|
wallet_name,
|
2179
2313
|
wallet_path,
|
2180
2314
|
wallet_hotkey,
|
2181
|
-
ask_for=[WO.NAME],
|
2315
|
+
ask_for=[WO.NAME, WO.PATH],
|
2182
2316
|
validate=WV.WALLET,
|
2183
2317
|
)
|
2184
2318
|
return self._run_command(wallets.wallet_history(wallet))
|
@@ -2189,69 +2323,42 @@ class CLIManager:
|
|
2189
2323
|
wallet_path: Optional[str] = Options.wallet_path,
|
2190
2324
|
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2191
2325
|
network: Optional[list[str]] = Options.network,
|
2192
|
-
|
2326
|
+
name: str = typer.Option(
|
2193
2327
|
"",
|
2194
|
-
"--
|
2195
|
-
"--display",
|
2328
|
+
"--name",
|
2196
2329
|
help="The display name for the identity.",
|
2197
2330
|
),
|
2198
|
-
legal_name: str = typer.Option(
|
2199
|
-
"",
|
2200
|
-
"--legal-name",
|
2201
|
-
"--legal",
|
2202
|
-
help="The legal name for the identity.",
|
2203
|
-
),
|
2204
2331
|
web_url: str = typer.Option(
|
2205
2332
|
"",
|
2206
2333
|
"--web-url",
|
2207
2334
|
"--web",
|
2208
2335
|
help="The web URL for the identity.",
|
2209
2336
|
),
|
2210
|
-
riot_handle: str = typer.Option(
|
2211
|
-
"",
|
2212
|
-
"--riot-handle",
|
2213
|
-
"--riot",
|
2214
|
-
help="The Riot handle for the identity.",
|
2215
|
-
),
|
2216
|
-
email: str = typer.Option(
|
2217
|
-
"",
|
2218
|
-
help="The email address for the identity.",
|
2219
|
-
),
|
2220
|
-
pgp_fingerprint: str = typer.Option(
|
2221
|
-
"",
|
2222
|
-
"--pgp-fingerprint",
|
2223
|
-
"--pgp",
|
2224
|
-
help="The PGP fingerprint for the identity.",
|
2225
|
-
),
|
2226
2337
|
image_url: str = typer.Option(
|
2227
2338
|
"",
|
2228
2339
|
"--image-url",
|
2229
2340
|
"--image",
|
2230
2341
|
help="The image URL for the identity.",
|
2231
2342
|
),
|
2232
|
-
|
2343
|
+
discord: str = typer.Option(
|
2233
2344
|
"",
|
2234
|
-
"--
|
2235
|
-
"
|
2236
|
-
help="The info for the identity.",
|
2345
|
+
"--discord",
|
2346
|
+
help="The Discord handle for the identity.",
|
2237
2347
|
),
|
2238
|
-
|
2348
|
+
description: str = typer.Option(
|
2239
2349
|
"",
|
2240
|
-
"
|
2241
|
-
"
|
2242
|
-
"--twitter-url",
|
2243
|
-
"--twitter",
|
2244
|
-
help="The 𝕏 (Twitter) URL for the identity.",
|
2350
|
+
"--description",
|
2351
|
+
help="The description for the identity.",
|
2245
2352
|
),
|
2246
|
-
|
2247
|
-
|
2248
|
-
"--
|
2249
|
-
help="
|
2353
|
+
additional: str = typer.Option(
|
2354
|
+
"",
|
2355
|
+
"--additional",
|
2356
|
+
help="Additional details for the identity.",
|
2250
2357
|
),
|
2251
|
-
|
2252
|
-
|
2253
|
-
"--
|
2254
|
-
help="
|
2358
|
+
github_repo: str = typer.Option(
|
2359
|
+
"",
|
2360
|
+
"--github",
|
2361
|
+
help="The GitHub repository for the identity.",
|
2255
2362
|
),
|
2256
2363
|
quiet: bool = Options.quiet,
|
2257
2364
|
verbose: bool = Options.verbose,
|
@@ -2279,94 +2386,67 @@ class CLIManager:
|
|
2279
2386
|
wallet_name,
|
2280
2387
|
wallet_path,
|
2281
2388
|
wallet_hotkey,
|
2282
|
-
ask_for=[WO.
|
2283
|
-
validate=WV.
|
2389
|
+
ask_for=[WO.NAME],
|
2390
|
+
validate=WV.WALLET,
|
2284
2391
|
)
|
2285
2392
|
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
image_url,
|
2295
|
-
info_,
|
2296
|
-
twitter_url,
|
2297
|
-
]
|
2298
|
-
):
|
2299
|
-
console.print(
|
2300
|
-
"[yellow]All fields are optional. Press Enter to skip a field.[/yellow]"
|
2301
|
-
)
|
2302
|
-
text_rejection = partial(
|
2303
|
-
retry_prompt,
|
2304
|
-
rejection=lambda x: sys.getsizeof(x) > 113,
|
2305
|
-
rejection_text="[red]Error:[/red] Identity field must be <= 64 raw bytes.",
|
2306
|
-
)
|
2393
|
+
current_identity = self._run_command(
|
2394
|
+
wallets.get_id(
|
2395
|
+
self.initialize_chain(network),
|
2396
|
+
wallet.coldkeypub.ss58_address,
|
2397
|
+
"Current on-chain identity",
|
2398
|
+
),
|
2399
|
+
exit_early=False,
|
2400
|
+
)
|
2307
2401
|
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
return True if len(pgp_fingerprint_encoded) != 20 else False
|
2316
|
-
|
2317
|
-
display_name = display_name or text_rejection("Display name")
|
2318
|
-
legal_name = legal_name or text_rejection("Legal name")
|
2319
|
-
web_url = web_url or text_rejection("Web URL")
|
2320
|
-
riot_handle = riot_handle or text_rejection("Riot handle")
|
2321
|
-
email = email or text_rejection("Email address")
|
2322
|
-
pgp_fingerprint = pgp_fingerprint or retry_prompt(
|
2323
|
-
"PGP fingerprint (Eg: A1B2 C3D4 E5F6 7890 1234 5678 9ABC DEF0 1234 5678)",
|
2324
|
-
lambda s: False if not s else pgp_check(s),
|
2325
|
-
"[red]Error:[/red] PGP Fingerprint must be exactly 20 bytes.",
|
2326
|
-
)
|
2327
|
-
image_url = image_url or text_rejection("Image URL")
|
2328
|
-
info_ = info_ or text_rejection("Enter info")
|
2329
|
-
twitter_url = twitter_url or text_rejection("𝕏 (Twitter) URL")
|
2330
|
-
|
2331
|
-
validator_id = validator_id or Confirm.ask(
|
2332
|
-
"Are you updating a [bold blue]validator hotkey[/bold blue] identity or a [bold blue]subnet "
|
2333
|
-
"owner[/bold blue] identity?\n"
|
2334
|
-
"Enter [bold green]Y[/bold green] for [bold]validator hotkey[/bold] or [bold red]N[/bold red] for "
|
2335
|
-
"[bold]subnet owner[/bold]",
|
2336
|
-
show_choices=True,
|
2337
|
-
)
|
2402
|
+
if prompt:
|
2403
|
+
if not Confirm.ask(
|
2404
|
+
"Cost to register an [blue]Identity[/blue] is [blue]0.1 TAO[/blue],"
|
2405
|
+
" are you sure you wish to continue?"
|
2406
|
+
):
|
2407
|
+
console.print(":cross_mark: Aborted!")
|
2408
|
+
raise typer.Exit()
|
2338
2409
|
|
2339
|
-
|
2340
|
-
|
2410
|
+
identity = prompt_for_identity(
|
2411
|
+
current_identity,
|
2412
|
+
name,
|
2413
|
+
web_url,
|
2414
|
+
image_url,
|
2415
|
+
discord,
|
2416
|
+
description,
|
2417
|
+
additional,
|
2418
|
+
github_repo,
|
2419
|
+
)
|
2341
2420
|
|
2342
2421
|
return self._run_command(
|
2343
2422
|
wallets.set_id(
|
2344
2423
|
wallet,
|
2345
2424
|
self.initialize_chain(network),
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
twitter_url,
|
2354
|
-
info_,
|
2355
|
-
validator_id,
|
2356
|
-
subnet_netuid,
|
2425
|
+
identity["name"],
|
2426
|
+
identity["url"],
|
2427
|
+
identity["image"],
|
2428
|
+
identity["discord"],
|
2429
|
+
identity["description"],
|
2430
|
+
identity["additional"],
|
2431
|
+
identity["github_repo"],
|
2357
2432
|
prompt,
|
2358
2433
|
)
|
2359
2434
|
)
|
2360
2435
|
|
2361
2436
|
def wallet_get_id(
|
2362
2437
|
self,
|
2363
|
-
|
2438
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
2439
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2440
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
2441
|
+
coldkey_ss58=typer.Option(
|
2364
2442
|
None,
|
2443
|
+
"--ss58",
|
2444
|
+
"--coldkey_ss58",
|
2445
|
+
"--coldkey.ss58_address",
|
2446
|
+
"--coldkey.ss58",
|
2365
2447
|
"--key",
|
2366
2448
|
"-k",
|
2367
|
-
"
|
2368
|
-
help="The coldkey or hotkey ss58 address to query.",
|
2369
|
-
prompt=True,
|
2449
|
+
help="Coldkey address of the wallet",
|
2370
2450
|
),
|
2371
2451
|
network: Optional[list[str]] = Options.network,
|
2372
2452
|
quiet: bool = Options.quiet,
|
@@ -2389,13 +2469,28 @@ class CLIManager:
|
|
2389
2469
|
|
2390
2470
|
[bold]Note[/bold]: This command is primarily used for informational purposes and has no side effects on the blockchain network state.
|
2391
2471
|
"""
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2472
|
+
wallet = None
|
2473
|
+
if coldkey_ss58:
|
2474
|
+
if not is_valid_ss58_address(coldkey_ss58):
|
2475
|
+
print_error("You entered an invalid ss58 address")
|
2476
|
+
raise typer.Exit()
|
2477
|
+
else:
|
2478
|
+
coldkey_or_ss58 = Prompt.ask(
|
2479
|
+
"Enter the [blue]wallet name[/blue] or [blue]coldkey ss58 address[/blue]",
|
2480
|
+
default=self.config.get("wallet_name") or defaults.wallet.name,
|
2481
|
+
)
|
2482
|
+
if is_valid_ss58_address(coldkey_or_ss58):
|
2483
|
+
coldkey_ss58 = coldkey_or_ss58
|
2484
|
+
else:
|
2485
|
+
wallet_name = coldkey_or_ss58 if coldkey_or_ss58 else wallet_name
|
2486
|
+
wallet = self.wallet_ask(
|
2487
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2488
|
+
)
|
2489
|
+
coldkey_ss58 = wallet.coldkeypub.ss58_address
|
2395
2490
|
|
2396
2491
|
self.verbosity_handler(quiet, verbose)
|
2397
2492
|
return self._run_command(
|
2398
|
-
wallets.get_id(self.initialize_chain(network),
|
2493
|
+
wallets.get_id(self.initialize_chain(network), coldkey_ss58)
|
2399
2494
|
)
|
2400
2495
|
|
2401
2496
|
def wallet_sign(
|
@@ -2429,872 +2524,117 @@ class CLIManager:
|
|
2429
2524
|
self.verbosity_handler(quiet, verbose)
|
2430
2525
|
if use_hotkey is None:
|
2431
2526
|
use_hotkey = Confirm.ask(
|
2432
|
-
"Would you like to sign the transaction using your [
|
2433
|
-
"\n[Type [
|
2434
|
-
"(default is [
|
2527
|
+
f"Would you like to sign the transaction using your [{COLOR_PALETTE['GENERAL']['HOTKEY']}]hotkey[/{COLOR_PALETTE['GENERAL']['HOTKEY']}]?"
|
2528
|
+
f"\n[Type [{COLOR_PALETTE['GENERAL']['HOTKEY']}]y[/{COLOR_PALETTE['GENERAL']['HOTKEY']}] for [{COLOR_PALETTE['GENERAL']['HOTKEY']}]hotkey[/{COLOR_PALETTE['GENERAL']['HOTKEY']}]"
|
2529
|
+
f" and [{COLOR_PALETTE['GENERAL']['COLDKEY']}]n[/{COLOR_PALETTE['GENERAL']['COLDKEY']}] for [{COLOR_PALETTE['GENERAL']['COLDKEY']}]coldkey[/{COLOR_PALETTE['GENERAL']['COLDKEY']}]] (default is [{COLOR_PALETTE['GENERAL']['COLDKEY']}]coldkey[/{COLOR_PALETTE['GENERAL']['COLDKEY']}])",
|
2435
2530
|
default=False,
|
2436
2531
|
)
|
2437
2532
|
|
2438
|
-
ask_for = [WO.HOTKEY, WO.NAME] if use_hotkey else [WO.NAME]
|
2533
|
+
ask_for = [WO.HOTKEY, WO.PATH, WO.NAME] if use_hotkey else [WO.NAME, WO.PATH]
|
2439
2534
|
validate = WV.WALLET_AND_HOTKEY if use_hotkey else WV.WALLET
|
2440
2535
|
|
2441
2536
|
wallet = self.wallet_ask(
|
2442
2537
|
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
|
2443
2538
|
)
|
2444
2539
|
if not message:
|
2445
|
-
message =
|
2540
|
+
message = Prompt.ask("Enter the [blue]message[/blue] to encode and sign")
|
2446
2541
|
|
2447
2542
|
return self._run_command(wallets.sign(wallet, message, use_hotkey))
|
2448
2543
|
|
2449
|
-
def
|
2544
|
+
def stake_list(
|
2450
2545
|
self,
|
2451
2546
|
network: Optional[list[str]] = Options.network,
|
2547
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
2548
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2549
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
2550
|
+
coldkey_ss58=typer.Option(
|
2551
|
+
None,
|
2552
|
+
"--ss58",
|
2553
|
+
"--coldkey_ss58",
|
2554
|
+
"--coldkey.ss58_address",
|
2555
|
+
"--coldkey.ss58",
|
2556
|
+
help="Coldkey address of the wallet",
|
2557
|
+
),
|
2558
|
+
live: bool = Options.live,
|
2452
2559
|
quiet: bool = Options.quiet,
|
2453
2560
|
verbose: bool = Options.verbose,
|
2561
|
+
no_prompt: bool = Options.prompt,
|
2562
|
+
# TODO add: all-wallets, reuse_last, html_output
|
2454
2563
|
):
|
2455
|
-
"""
|
2456
|
-
|
2457
|
-
|
2458
|
-
USAGE
|
2459
|
-
|
2460
|
-
The command fetches and lists the neurons (root network validators) in the root network, showing their unique identifiers (UIDs), names, addresses, stakes, and whether they are part of the senate (network governance body).
|
2461
|
-
|
2462
|
-
This command is useful for understanding the composition and governance structure of the Bittensor network's root network. It provides insights into which neurons hold significant influence and responsibility within the Bittensor network.
|
2564
|
+
"""List all stake accounts for wallet."""
|
2565
|
+
self.verbosity_handler(quiet, verbose)
|
2463
2566
|
|
2464
|
-
|
2567
|
+
wallet = None
|
2568
|
+
if coldkey_ss58:
|
2569
|
+
if not is_valid_ss58_address(coldkey_ss58):
|
2570
|
+
print_error("You entered an invalid ss58 address")
|
2571
|
+
raise typer.Exit()
|
2572
|
+
else:
|
2573
|
+
if wallet_name:
|
2574
|
+
coldkey_or_ss58 = wallet_name
|
2575
|
+
else:
|
2576
|
+
coldkey_or_ss58 = Prompt.ask(
|
2577
|
+
"Enter the [blue]wallet name[/blue] or [blue]coldkey ss58 address[/blue]",
|
2578
|
+
default=self.config.get("wallet_name") or defaults.wallet.name,
|
2579
|
+
)
|
2580
|
+
if is_valid_ss58_address(coldkey_or_ss58):
|
2581
|
+
coldkey_ss58 = coldkey_or_ss58
|
2582
|
+
else:
|
2583
|
+
wallet_name = coldkey_or_ss58 if coldkey_or_ss58 else wallet_name
|
2584
|
+
wallet = self.wallet_ask(
|
2585
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
2586
|
+
)
|
2465
2587
|
|
2466
|
-
[green]$[/green] btcli root list
|
2467
|
-
"""
|
2468
|
-
self.verbosity_handler(quiet, verbose)
|
2469
2588
|
return self._run_command(
|
2470
|
-
|
2589
|
+
stake.stake_list(
|
2590
|
+
wallet,
|
2591
|
+
coldkey_ss58,
|
2592
|
+
self.initialize_chain(network),
|
2593
|
+
live,
|
2594
|
+
verbose,
|
2595
|
+
no_prompt,
|
2596
|
+
)
|
2471
2597
|
)
|
2472
2598
|
|
2473
|
-
def
|
2599
|
+
def stake_add(
|
2474
2600
|
self,
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2482
|
-
|
2483
|
-
"
|
2484
|
-
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2510
|
-
|
2511
|
-
|
2512
|
-
if netuids:
|
2513
|
-
netuids = parse_to_list(
|
2514
|
-
netuids,
|
2515
|
-
int,
|
2516
|
-
"Netuids must be a comma-separated list of ints, e.g., `--netuid 1,2,3,4`.",
|
2517
|
-
)
|
2518
|
-
else:
|
2519
|
-
netuids = list_prompt(netuids, int, "Enter netuids (e.g: 1, 4, 6)")
|
2520
|
-
|
2521
|
-
if weights:
|
2522
|
-
weights = parse_to_list(
|
2523
|
-
weights,
|
2524
|
-
float,
|
2525
|
-
"Weights must be a comma-separated list of floats, e.g., `--weights 0.3,0.4,0.3`.",
|
2526
|
-
)
|
2527
|
-
else:
|
2528
|
-
weights = list_prompt(
|
2529
|
-
weights, float, "Enter weights (e.g. 0.02, 0.03, 0.01)"
|
2530
|
-
)
|
2531
|
-
|
2532
|
-
if len(netuids) != len(weights):
|
2533
|
-
raise typer.BadParameter(
|
2534
|
-
"The number of netuids and weights must be the same."
|
2535
|
-
)
|
2536
|
-
|
2537
|
-
wallet = self.wallet_ask(
|
2538
|
-
wallet_name,
|
2539
|
-
wallet_path,
|
2540
|
-
wallet_hotkey,
|
2541
|
-
ask_for=[WO.HOTKEY, WO.NAME],
|
2542
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2543
|
-
)
|
2544
|
-
self._run_command(
|
2545
|
-
root.set_weights(
|
2546
|
-
wallet, self.initialize_chain(network), netuids, weights, prompt
|
2547
|
-
)
|
2548
|
-
)
|
2549
|
-
|
2550
|
-
def root_get_weights(
|
2551
|
-
self,
|
2552
|
-
network: Optional[list[str]] = Options.network,
|
2553
|
-
limit_min_col: Optional[int] = typer.Option(
|
2554
|
-
None,
|
2555
|
-
"--limit-min-col",
|
2556
|
-
"--min",
|
2557
|
-
help="Limit the left display of the table to this column.",
|
2558
|
-
),
|
2559
|
-
limit_max_col: Optional[int] = typer.Option(
|
2560
|
-
None,
|
2561
|
-
"--limit-max-col",
|
2562
|
-
"--max",
|
2563
|
-
help="Limit the right display of the table to this column.",
|
2564
|
-
),
|
2565
|
-
reuse_last: bool = Options.reuse_last,
|
2566
|
-
html_output: bool = Options.html_output,
|
2567
|
-
quiet: bool = Options.quiet,
|
2568
|
-
verbose: bool = Options.verbose,
|
2569
|
-
):
|
2570
|
-
"""
|
2571
|
-
Shows a table listing the weights assigned to each subnet in the root network.
|
2572
|
-
|
2573
|
-
This command provides visibility into how network responsibilities and rewards are distributed among various subnets. This information is crucial for understanding the current influence and reward distribution across different subnets. Use this command if you are interested in the governance and operational dynamics of the Bittensor network.
|
2574
|
-
|
2575
|
-
EXAMPLE
|
2576
|
-
|
2577
|
-
[green]$[/green] btcli root get_weights
|
2578
|
-
"""
|
2579
|
-
self.verbosity_handler(quiet, verbose)
|
2580
|
-
if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
2581
|
-
err_console.print(
|
2582
|
-
"Unable to use `--reuse-last` or `--html` when config 'no-cache' is set to 'True'."
|
2583
|
-
"Change it to 'False' using `btcli config set`."
|
2584
|
-
)
|
2585
|
-
raise typer.Exit()
|
2586
|
-
if not reuse_last:
|
2587
|
-
subtensor = self.initialize_chain(network)
|
2588
|
-
else:
|
2589
|
-
subtensor = None
|
2590
|
-
return self._run_command(
|
2591
|
-
root.get_weights(
|
2592
|
-
subtensor,
|
2593
|
-
limit_min_col,
|
2594
|
-
limit_max_col,
|
2595
|
-
reuse_last,
|
2596
|
-
html_output,
|
2597
|
-
not self.config.get("use_cache", True),
|
2598
|
-
)
|
2599
|
-
)
|
2600
|
-
|
2601
|
-
def root_boost(
|
2602
|
-
self,
|
2603
|
-
network: Optional[list[str]] = Options.network,
|
2604
|
-
wallet_name: str = Options.wallet_name,
|
2605
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2606
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2607
|
-
netuid: int = Options.netuid,
|
2608
|
-
amount: float = typer.Option(
|
2609
|
-
None,
|
2610
|
-
"--amount",
|
2611
|
-
"--increase",
|
2612
|
-
"-a",
|
2613
|
-
prompt="Enter the boost amount (added to existing weight)",
|
2614
|
-
help="Amount (float) to boost (added to the existing weight), (e.g. 0.01)",
|
2615
|
-
),
|
2616
|
-
prompt: bool = Options.prompt,
|
2617
|
-
quiet: bool = Options.quiet,
|
2618
|
-
verbose: bool = Options.verbose,
|
2619
|
-
):
|
2620
|
-
"""
|
2621
|
-
Increase (boost) the weights for a specific subnet in the root network. Any amount provided will be added to the subnet's existing weight.
|
2622
|
-
|
2623
|
-
EXAMPLE
|
2624
|
-
|
2625
|
-
[green]$[/green] btcli root boost --netuid 1 --increase 0.01
|
2626
|
-
"""
|
2627
|
-
self.verbosity_handler(quiet, verbose)
|
2628
|
-
wallet = self.wallet_ask(
|
2629
|
-
wallet_name,
|
2630
|
-
wallet_path,
|
2631
|
-
wallet_hotkey,
|
2632
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2633
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2634
|
-
)
|
2635
|
-
return self._run_command(
|
2636
|
-
root.set_boost(
|
2637
|
-
wallet, self.initialize_chain(network), netuid, amount, prompt
|
2638
|
-
)
|
2639
|
-
)
|
2640
|
-
|
2641
|
-
def root_slash(
|
2642
|
-
self,
|
2643
|
-
network: Optional[list[str]] = Options.network,
|
2644
|
-
wallet_name: str = Options.wallet_name,
|
2645
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2646
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2647
|
-
netuid: int = Options.netuid,
|
2648
|
-
amount: float = typer.Option(
|
2649
|
-
None,
|
2650
|
-
"--amount",
|
2651
|
-
"--decrease",
|
2652
|
-
"-a",
|
2653
|
-
prompt="Enter the slash amount (subtracted from the existing weight)",
|
2654
|
-
help="Amount (float) to slash (subtract from the existing weight), (e.g. 0.01)",
|
2655
|
-
),
|
2656
|
-
prompt: bool = Options.prompt,
|
2657
|
-
quiet: bool = Options.quiet,
|
2658
|
-
verbose: bool = Options.verbose,
|
2659
|
-
):
|
2660
|
-
"""
|
2661
|
-
Decrease (slash) the weights for a specific subnet in the root network. Any amount provided will be subtracted from the subnet's existing weight.
|
2662
|
-
|
2663
|
-
EXAMPLE
|
2664
|
-
|
2665
|
-
[green]$[/green] btcli root slash --netuid 1 --decrease 0.01
|
2666
|
-
|
2667
|
-
"""
|
2668
|
-
self.verbosity_handler(quiet, verbose)
|
2669
|
-
wallet = self.wallet_ask(
|
2670
|
-
wallet_name,
|
2671
|
-
wallet_path,
|
2672
|
-
wallet_hotkey,
|
2673
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2674
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2675
|
-
)
|
2676
|
-
return self._run_command(
|
2677
|
-
root.set_slash(
|
2678
|
-
wallet, self.initialize_chain(network), netuid, amount, prompt
|
2679
|
-
)
|
2680
|
-
)
|
2681
|
-
|
2682
|
-
def root_senate_vote(
|
2683
|
-
self,
|
2684
|
-
network: Optional[list[str]] = Options.network,
|
2685
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2686
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2687
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2688
|
-
proposal: str = typer.Option(
|
2689
|
-
None,
|
2690
|
-
"--proposal",
|
2691
|
-
"--proposal-hash",
|
2692
|
-
prompt="Enter the proposal hash",
|
2693
|
-
help="The hash of the proposal to vote on.",
|
2694
|
-
),
|
2695
|
-
prompt: bool = Options.prompt,
|
2696
|
-
quiet: bool = Options.quiet,
|
2697
|
-
verbose: bool = Options.verbose,
|
2698
|
-
vote: bool = typer.Option(
|
2699
|
-
None,
|
2700
|
-
"--vote-aye/--vote-nay",
|
2701
|
-
prompt="Enter y to vote Aye, or enter n to vote Nay",
|
2702
|
-
help="The vote casted on the proposal",
|
2703
|
-
),
|
2704
|
-
):
|
2705
|
-
"""
|
2706
|
-
Cast a vote on an active proposal in Bittensor's governance protocol.
|
2707
|
-
|
2708
|
-
This command is used by Senate members to vote on various proposals that shape the network's future. Use `btcli root proposals` to see the active proposals and their hashes.
|
2709
|
-
|
2710
|
-
USAGE
|
2711
|
-
|
2712
|
-
The user must specify the hash of the proposal they want to vote on. The command then allows the Senate member to cast a 'Yes' or 'No' vote, contributing to the decision-making process on the proposal. This command is crucial for Senate members to exercise their voting rights on key proposals. It plays a vital role in the governance and evolution of the Bittensor network.
|
2713
|
-
|
2714
|
-
EXAMPLE
|
2715
|
-
|
2716
|
-
[green]$[/green] btcli root senate_vote --proposal <proposal_hash>
|
2717
|
-
"""
|
2718
|
-
self.verbosity_handler(quiet, verbose)
|
2719
|
-
wallet = self.wallet_ask(
|
2720
|
-
wallet_name,
|
2721
|
-
wallet_path,
|
2722
|
-
wallet_hotkey,
|
2723
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2724
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2725
|
-
)
|
2726
|
-
return self._run_command(
|
2727
|
-
root.senate_vote(
|
2728
|
-
wallet, self.initialize_chain(network), proposal, vote, prompt
|
2729
|
-
)
|
2730
|
-
)
|
2731
|
-
|
2732
|
-
def root_senate(
|
2733
|
-
self,
|
2734
|
-
network: Optional[list[str]] = Options.network,
|
2735
|
-
quiet: bool = Options.quiet,
|
2736
|
-
verbose: bool = Options.verbose,
|
2737
|
-
):
|
2738
|
-
"""
|
2739
|
-
Shows the Senate members of the Bittensor's governance protocol.
|
2740
|
-
|
2741
|
-
This command lists the delegates involved in the decision-making process of the Bittensor network, showing their names and wallet addresses. This information is crucial for understanding who holds governance roles within the network.
|
2742
|
-
|
2743
|
-
EXAMPLE
|
2744
|
-
|
2745
|
-
[green]$[/green] btcli root senate
|
2746
|
-
"""
|
2747
|
-
self.verbosity_handler(quiet, verbose)
|
2748
|
-
return self._run_command(root.get_senate(self.initialize_chain(network)))
|
2749
|
-
|
2750
|
-
def root_register(
|
2751
|
-
self,
|
2752
|
-
network: Optional[list[str]] = Options.network,
|
2753
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2754
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2755
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2756
|
-
prompt: bool = Options.prompt,
|
2757
|
-
quiet: bool = Options.quiet,
|
2758
|
-
verbose: bool = Options.verbose,
|
2759
|
-
):
|
2760
|
-
"""
|
2761
|
-
Register a neuron to the root subnet by recycling some TAO to cover for the registration cost.
|
2762
|
-
|
2763
|
-
This command adds a new neuron as a validator on the root network. This will allow the neuron owner to set subnet weights.
|
2764
|
-
|
2765
|
-
# Usage:
|
2766
|
-
|
2767
|
-
Before registering, the command checks if the specified subnet exists and whether the TAO balance in the user's wallet is sufficient to cover the registration cost. The registration cost is determined by the current recycle amount for the specified subnet. If the balance is insufficient or the subnet does not exist, the command will exit with an appropriate error message.
|
2768
|
-
|
2769
|
-
# Example usage:
|
2770
|
-
|
2771
|
-
[green]$[/green] btcli subnets register --netuid 1
|
2772
|
-
"""
|
2773
|
-
self.verbosity_handler(quiet, verbose)
|
2774
|
-
wallet = self.wallet_ask(
|
2775
|
-
wallet_name,
|
2776
|
-
wallet_path,
|
2777
|
-
wallet_hotkey,
|
2778
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2779
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2780
|
-
)
|
2781
|
-
return self._run_command(
|
2782
|
-
root.register(wallet, self.initialize_chain(network), prompt)
|
2783
|
-
)
|
2784
|
-
|
2785
|
-
def root_proposals(
|
2786
|
-
self,
|
2787
|
-
network: Optional[list[str]] = Options.network,
|
2788
|
-
quiet: bool = Options.quiet,
|
2789
|
-
verbose: bool = Options.verbose,
|
2790
|
-
):
|
2791
|
-
"""
|
2792
|
-
View active proposals for the senate in the Bittensor's governance protocol.
|
2793
|
-
|
2794
|
-
This command displays the details of ongoing proposals, including proposal hashes, votes, thresholds, and proposal data.
|
2795
|
-
|
2796
|
-
EXAMPLE
|
2797
|
-
|
2798
|
-
[green]$[/green] btcli root proposals
|
2799
|
-
"""
|
2800
|
-
self.verbosity_handler(quiet, verbose)
|
2801
|
-
return self._run_command(root.proposals(self.initialize_chain(network)))
|
2802
|
-
|
2803
|
-
def root_set_take(
|
2804
|
-
self,
|
2805
|
-
network: Optional[list[str]] = Options.network,
|
2806
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2807
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2808
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2809
|
-
take: float = typer.Option(None, help="The new take value."),
|
2810
|
-
quiet: bool = Options.quiet,
|
2811
|
-
verbose: bool = Options.verbose,
|
2812
|
-
):
|
2813
|
-
"""
|
2814
|
-
Allows users to change their delegate take percentage.
|
2815
|
-
|
2816
|
-
This command can be used to update the delegate takes individually for every subnet. To run the command, the user must have a configured wallet with both hotkey and coldkey. The command performs the below checks:
|
2817
|
-
|
2818
|
-
1. The provided hotkey is already a delegate.
|
2819
|
-
2. The new take value is within 0-18% range.
|
2820
|
-
|
2821
|
-
EXAMPLE
|
2822
|
-
|
2823
|
-
[green]$[/green] btcli root set_take --wallet-name my_wallet --wallet-hotkey my_hotkey
|
2824
|
-
"""
|
2825
|
-
max_value = 0.18
|
2826
|
-
min_value = 0.00
|
2827
|
-
self.verbosity_handler(quiet, verbose)
|
2828
|
-
|
2829
|
-
if not take:
|
2830
|
-
max_value_style = typer.style(f"Max: {max_value}", fg="magenta")
|
2831
|
-
min_value_style = typer.style(f"Min: {min_value}", fg="magenta")
|
2832
|
-
prompt_text = typer.style(
|
2833
|
-
"Enter take value (0.18 for 18%)", fg="bright_cyan", bold=True
|
2834
|
-
)
|
2835
|
-
take = FloatPrompt.ask(f"{prompt_text} {min_value_style} {max_value_style}")
|
2836
|
-
|
2837
|
-
if not (min_value <= take <= max_value):
|
2838
|
-
print_error(
|
2839
|
-
f"Take value must be between {min_value} and {max_value}. Provided value: {take}"
|
2840
|
-
)
|
2841
|
-
raise typer.Exit()
|
2842
|
-
|
2843
|
-
wallet = self.wallet_ask(
|
2844
|
-
wallet_name,
|
2845
|
-
wallet_path,
|
2846
|
-
wallet_hotkey,
|
2847
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2848
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2849
|
-
)
|
2850
|
-
|
2851
|
-
return self._run_command(
|
2852
|
-
root.set_take(wallet, self.initialize_chain(network), take)
|
2853
|
-
)
|
2854
|
-
|
2855
|
-
def root_delegate_stake(
|
2856
|
-
self,
|
2857
|
-
delegate_ss58key: str = typer.Option(
|
2858
|
-
None,
|
2859
|
-
help="The ss58 address of the delegate hotkey to stake TAO to.",
|
2860
|
-
prompt="Enter the hotkey ss58 address you want to delegate TAO to.",
|
2861
|
-
),
|
2862
|
-
amount: Optional[float] = typer.Option(
|
2863
|
-
None, help="The amount of TAO to stake. Do no specify if using `--all`"
|
2864
|
-
),
|
2865
|
-
stake_all: Optional[bool] = typer.Option(
|
2866
|
-
False,
|
2867
|
-
"--all",
|
2868
|
-
"-a",
|
2869
|
-
help="If specified, the command stakes all available TAO. Do not specify if using"
|
2870
|
-
" `--amount`",
|
2871
|
-
),
|
2872
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2873
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2874
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2875
|
-
network: Optional[list[str]] = Options.network,
|
2876
|
-
prompt: bool = Options.prompt,
|
2877
|
-
quiet: bool = Options.quiet,
|
2878
|
-
verbose: bool = Options.verbose,
|
2879
|
-
):
|
2880
|
-
"""
|
2881
|
-
Stakes TAO to a specified delegate hotkey.
|
2882
|
-
|
2883
|
-
This command allocates the user's TAO to the specified hotkey of a delegate, potentially earning staking rewards in return. If the
|
2884
|
-
`--all` flag is used, it delegates the entire TAO balance available in the user's wallet.
|
2885
|
-
|
2886
|
-
This command should be run by a TAO holder. Compare this command with "btcli stake add" that is typically run by a subnet validator to add stake to their own delegate hotkey.
|
2887
|
-
|
2888
|
-
EXAMPLE
|
2889
|
-
|
2890
|
-
[green]$[/green] btcli root delegate-stake --delegate_ss58key <SS58_ADDRESS> --amount <AMOUNT>
|
2891
|
-
|
2892
|
-
[green]$[/green] btcli root delegate-stake --delegate_ss58key <SS58_ADDRESS> --all
|
2893
|
-
|
2894
|
-
[blue bold]Note[/blue bold]: This command modifies the blockchain state and may incur transaction fees. The user should ensure the delegate's address and the amount to be staked are correct before executing the command.
|
2895
|
-
"""
|
2896
|
-
self.verbosity_handler(quiet, verbose)
|
2897
|
-
if amount and stake_all:
|
2898
|
-
err_console.print(
|
2899
|
-
"Both `--amount` and `--all` are specified. Choose one or the other."
|
2900
|
-
)
|
2901
|
-
if not stake_all and not amount:
|
2902
|
-
while True:
|
2903
|
-
amount = FloatPrompt.ask(
|
2904
|
-
"Amount to [blue]stake (TAO τ)[/blue]", console=console
|
2905
|
-
)
|
2906
|
-
confirmation = FloatPrompt.ask(
|
2907
|
-
"Confirm the amount to stake [blue](TAO τ)[/blue]",
|
2908
|
-
console=console,
|
2909
|
-
)
|
2910
|
-
if amount == confirmation:
|
2911
|
-
break
|
2912
|
-
else:
|
2913
|
-
err_console.print(
|
2914
|
-
"[red]The amounts do not match. Please try again.[/red]"
|
2915
|
-
)
|
2916
|
-
|
2917
|
-
wallet = self.wallet_ask(
|
2918
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2919
|
-
)
|
2920
|
-
return self._run_command(
|
2921
|
-
root.delegate_stake(
|
2922
|
-
wallet,
|
2923
|
-
self.initialize_chain(network),
|
2924
|
-
amount,
|
2925
|
-
delegate_ss58key,
|
2926
|
-
prompt,
|
2927
|
-
)
|
2928
|
-
)
|
2929
|
-
|
2930
|
-
def root_undelegate_stake(
|
2931
|
-
self,
|
2932
|
-
delegate_ss58key: str = typer.Option(
|
2933
|
-
None,
|
2934
|
-
help="The ss58 address of the delegate to undelegate from.",
|
2935
|
-
prompt="Enter the hotkey ss58 address you want to undelegate from",
|
2936
|
-
),
|
2937
|
-
amount: Optional[float] = typer.Option(
|
2938
|
-
None, help="The amount of TAO to unstake. Do no specify if using `--all`"
|
2939
|
-
),
|
2940
|
-
unstake_all: Optional[bool] = typer.Option(
|
2941
|
-
False,
|
2942
|
-
"--all",
|
2943
|
-
"-a",
|
2944
|
-
help="If specified, the command undelegates all staked TAO from the delegate. Do not specify if using"
|
2945
|
-
" `--amount`",
|
2946
|
-
),
|
2947
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2948
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2949
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2950
|
-
network: Optional[list[str]] = Options.network,
|
2951
|
-
prompt: bool = Options.prompt,
|
2952
|
-
quiet: bool = Options.quiet,
|
2953
|
-
verbose: bool = Options.verbose,
|
2954
|
-
):
|
2955
|
-
"""
|
2956
|
-
Allows users to withdraw their staked TAO from a delegate.
|
2957
|
-
|
2958
|
-
The user must provide the delegate hotkey's ss58 address and the amount of TAO to undelegate. The function will then send a transaction to the blockchain to process the undelegation. This command can result in a change to the blockchain state and may incur transaction fees.
|
2959
|
-
|
2960
|
-
EXAMPLE
|
2961
|
-
|
2962
|
-
[green]$[/green] btcli undelegate --delegate_ss58key <SS58_ADDRESS> --amount <AMOUNT>
|
2963
|
-
|
2964
|
-
[green]$[/green] btcli undelegate --delegate_ss58key <SS58_ADDRESS> --all
|
2965
|
-
"""
|
2966
|
-
self.verbosity_handler(quiet, verbose)
|
2967
|
-
if amount and unstake_all:
|
2968
|
-
err_console.print(
|
2969
|
-
"Both `--amount` and `--all` are specified. Choose one or the other."
|
2970
|
-
)
|
2971
|
-
if not unstake_all and not amount:
|
2972
|
-
while True:
|
2973
|
-
amount = FloatPrompt.ask(
|
2974
|
-
"Amount to [blue]unstake (TAO τ)[/blue]", console=console
|
2975
|
-
)
|
2976
|
-
confirmation = FloatPrompt.ask(
|
2977
|
-
"Confirm the amount to unstake [blue](TAO τ)[/blue]",
|
2978
|
-
console=console,
|
2979
|
-
)
|
2980
|
-
if amount == confirmation:
|
2981
|
-
break
|
2982
|
-
else:
|
2983
|
-
err_console.print(
|
2984
|
-
"[red]The amounts do not match. Please try again.[/red]"
|
2985
|
-
)
|
2986
|
-
|
2987
|
-
wallet = self.wallet_ask(
|
2988
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2989
|
-
)
|
2990
|
-
self._run_command(
|
2991
|
-
root.delegate_unstake(
|
2992
|
-
wallet,
|
2993
|
-
self.initialize_chain(network),
|
2994
|
-
amount,
|
2995
|
-
delegate_ss58key,
|
2996
|
-
prompt,
|
2997
|
-
)
|
2998
|
-
)
|
2999
|
-
|
3000
|
-
def root_my_delegates(
|
3001
|
-
self,
|
3002
|
-
network: Optional[list[str]] = Options.network,
|
3003
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
3004
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
3005
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3006
|
-
all_wallets: bool = typer.Option(
|
3007
|
-
False,
|
3008
|
-
"--all-wallets",
|
3009
|
-
"--all",
|
3010
|
-
"-a",
|
3011
|
-
help="If specified, the command aggregates information across all the wallets.",
|
3012
|
-
),
|
3013
|
-
quiet: bool = Options.quiet,
|
3014
|
-
verbose: bool = Options.verbose,
|
3015
|
-
):
|
3016
|
-
"""
|
3017
|
-
Shows a table with the details on the user's delegates.
|
3018
|
-
|
3019
|
-
The table output includes the following columns:
|
3020
|
-
|
3021
|
-
- Wallet: The name of the user's wallet (coldkey).
|
3022
|
-
|
3023
|
-
- OWNER: The name of the delegate who owns the hotkey.
|
3024
|
-
|
3025
|
-
- SS58: The truncated SS58 address of the delegate's hotkey.
|
3026
|
-
|
3027
|
-
- Delegation: The amount of TAO staked by the user to the delegate.
|
3028
|
-
|
3029
|
-
- τ/24h: The earnings from the delegate to the user over the past 24 hours.
|
3030
|
-
|
3031
|
-
- NOMS: The number of nominators for the delegate.
|
3032
|
-
|
3033
|
-
- OWNER STAKE(τ): The stake amount owned by the delegate.
|
3034
|
-
|
3035
|
-
- TOTAL STAKE(τ): The total stake amount held by the delegate.
|
3036
|
-
|
3037
|
-
- SUBNETS: The list of subnets the delegate is a part of.
|
3038
|
-
|
3039
|
-
- VPERMIT: Validator permits held by the delegate for various subnets.
|
3040
|
-
|
3041
|
-
- 24h/kτ: Earnings per 1000 TAO staked over the last 24 hours.
|
3042
|
-
|
3043
|
-
- Desc: A description of the delegate.
|
3044
|
-
|
3045
|
-
The command also sums and prints the total amount of TAO delegated across all wallets.
|
3046
|
-
|
3047
|
-
EXAMPLE
|
3048
|
-
|
3049
|
-
[green]$[/green] btcli root my-delegates
|
3050
|
-
[green]$[/green] btcli root my-delegates --all
|
3051
|
-
[green]$[/green] btcli root my-delegates --wallet-name my_wallet
|
3052
|
-
|
3053
|
-
[blue bold]Note[/blue bold]: This command is not intended to be used directly in user code.
|
3054
|
-
"""
|
3055
|
-
self.verbosity_handler(quiet, verbose)
|
3056
|
-
wallet = self.wallet_ask(
|
3057
|
-
wallet_name,
|
3058
|
-
wallet_path,
|
3059
|
-
wallet_hotkey,
|
3060
|
-
ask_for=([WO.NAME] if not all_wallets else []),
|
3061
|
-
validate=WV.WALLET if not all_wallets else WV.NONE,
|
3062
|
-
)
|
3063
|
-
self._run_command(
|
3064
|
-
root.my_delegates(wallet, self.initialize_chain(network), all_wallets)
|
3065
|
-
)
|
3066
|
-
|
3067
|
-
def root_list_delegates(
|
3068
|
-
self,
|
3069
|
-
network: Optional[list[str]] = Options.network,
|
3070
|
-
quiet: bool = Options.quiet,
|
3071
|
-
verbose: bool = Options.verbose,
|
3072
|
-
):
|
3073
|
-
"""
|
3074
|
-
Displays a table of Bittensor network-wide delegates, providing a comprehensive overview of delegate statistics and information.
|
3075
|
-
|
3076
|
-
This table helps users make informed decisions on which delegates to allocate their TAO stake.
|
3077
|
-
|
3078
|
-
The table columns include:
|
3079
|
-
|
3080
|
-
- INDEX: The delegate's index in the sorted list.
|
3081
|
-
|
3082
|
-
- DELEGATE: The name of the delegate.
|
3083
|
-
|
3084
|
-
- SS58: The delegate's unique ss58 address (truncated for display).
|
3085
|
-
|
3086
|
-
- NOMINATORS: The count of nominators backing the delegate.
|
3087
|
-
|
3088
|
-
- OWN STAKE(τ): The amount of delegate's own stake (not the TAO delegated from any nominators).
|
3089
|
-
|
3090
|
-
- TOTAL STAKE(τ): The delegate's total stake, i.e., the sum of delegate's own stake and nominators' stakes.
|
3091
|
-
|
3092
|
-
- CHANGE/(4h): The percentage change in the delegate's stake over the last four hours.
|
3093
|
-
|
3094
|
-
- SUBNETS: The subnets in which the delegate is registered.
|
3095
|
-
|
3096
|
-
- VPERMIT: Indicates the subnets in which the delegate has validator permits.
|
3097
|
-
|
3098
|
-
- NOMINATOR/(24h)/kτ: The earnings per 1000 τ staked by nominators in the last 24 hours.
|
3099
|
-
|
3100
|
-
- DELEGATE/(24h): The total earnings of the delegate in the last 24 hours.
|
3101
|
-
|
3102
|
-
- DESCRIPTION: A brief description of the delegate's purpose and operations.
|
3103
|
-
|
3104
|
-
[blue bold]NOTES:[/blue bold]
|
3105
|
-
|
3106
|
-
- Sorting is done based on the `TOTAL STAKE` column in descending order.
|
3107
|
-
- Changes in stake are shown as: increases in green and decreases in red.
|
3108
|
-
- Entries with no previous data are marked with `NA`.
|
3109
|
-
- Each delegate's name is a hyperlink to more information, if available.
|
3110
|
-
|
3111
|
-
EXAMPLE
|
3112
|
-
|
3113
|
-
[green]$[/green] btcli root list_delegates
|
3114
|
-
|
3115
|
-
[green]$[/green] btcli root list_delegates --subtensor.network finney # can also be `test` or `local`
|
3116
|
-
|
3117
|
-
[blue bold]NOTE[/blue bold]: This command is intended for use within a
|
3118
|
-
console application. It prints directly to the console and does not return any value.
|
3119
|
-
"""
|
3120
|
-
self.verbosity_handler(quiet, verbose)
|
3121
|
-
|
3122
|
-
if network:
|
3123
|
-
if "finney" in network:
|
3124
|
-
network = ["wss://archive.chain.opentensor.ai:443"]
|
3125
|
-
elif (conf_net := self.config.get("network")) == "finney":
|
3126
|
-
network = ["wss://archive.chain.opentensor.ai:443"]
|
3127
|
-
elif conf_net:
|
3128
|
-
network = [conf_net]
|
3129
|
-
else:
|
3130
|
-
network = ["wss://archive.chain.opentensor.ai:443"]
|
3131
|
-
|
3132
|
-
sub = self.initialize_chain(network)
|
3133
|
-
return self._run_command(root.list_delegates(sub))
|
3134
|
-
|
3135
|
-
# TODO: Confirm if we need a command for this - currently registering to root auto makes u delegate
|
3136
|
-
def root_nominate(
|
3137
|
-
self,
|
3138
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
3139
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
3140
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3141
|
-
network: Optional[list[str]] = Options.network,
|
3142
|
-
prompt: bool = Options.prompt,
|
3143
|
-
quiet: bool = Options.quiet,
|
3144
|
-
verbose: bool = Options.verbose,
|
3145
|
-
):
|
3146
|
-
"""
|
3147
|
-
Enables a wallet's hotkey to become a delegate.
|
3148
|
-
|
3149
|
-
This command handles the nomination process, including wallet unlocking and verification of the hotkey's current delegate status.
|
3150
|
-
|
3151
|
-
The command performs several checks:
|
3152
|
-
|
3153
|
-
- Verifies that the hotkey is not already a delegate to prevent redundant nominations.
|
3154
|
-
|
3155
|
-
- Tries to nominate the wallet and reports success or failure.
|
3156
|
-
|
3157
|
-
Upon success, the wallet's hotkey is registered as a delegate on the network.
|
3158
|
-
|
3159
|
-
To run the command, the user must have a configured wallet with both hotkey and coldkey. If the wallet is not already nominated, this command will initiate the process.
|
3160
|
-
|
3161
|
-
EXAMPLE
|
3162
|
-
|
3163
|
-
[green]$[/green] btcli root nominate
|
3164
|
-
|
3165
|
-
[green]$[/green] btcli root nominate --wallet-name my_wallet --wallet-hotkey my_hotkey
|
3166
|
-
|
3167
|
-
[blue bold]Note[/blue bold]: This command prints the output directly to the console. It should not be called programmatically in user code due to its interactive nature and side effects on the network state.
|
3168
|
-
"""
|
3169
|
-
self.verbosity_handler(quiet, verbose)
|
3170
|
-
wallet = self.wallet_ask(
|
3171
|
-
wallet_name,
|
3172
|
-
wallet_path,
|
3173
|
-
wallet_hotkey,
|
3174
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3175
|
-
validate=WV.WALLET_AND_HOTKEY,
|
3176
|
-
)
|
3177
|
-
return self._run_command(
|
3178
|
-
root.nominate(wallet, self.initialize_chain(network), prompt)
|
3179
|
-
)
|
3180
|
-
|
3181
|
-
def stake_show(
|
3182
|
-
self,
|
3183
|
-
all_wallets: bool = typer.Option(
|
3184
|
-
False,
|
3185
|
-
"--all",
|
3186
|
-
"--all-wallets",
|
3187
|
-
"-a",
|
3188
|
-
help="When set, the command checks all the coldkey wallets of the user instead of just the specified wallet.",
|
3189
|
-
),
|
3190
|
-
network: Optional[list[str]] = Options.network,
|
3191
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
3192
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3193
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
3194
|
-
reuse_last: bool = Options.reuse_last,
|
3195
|
-
html_output: bool = Options.html_output,
|
3196
|
-
quiet: bool = Options.quiet,
|
3197
|
-
verbose: bool = Options.verbose,
|
3198
|
-
):
|
3199
|
-
"""
|
3200
|
-
Lists all the stake accounts associated with a user's wallet.
|
3201
|
-
|
3202
|
-
This command provides a comprehensive view of the stakes associated with the user's coldkeys. It shows both the user's own hotkeys and also the hotkeys of the delegates to which this user has staked.
|
3203
|
-
|
3204
|
-
The command lists all the stake accounts for a specified wallet or all wallets in the user's configuration directory. It displays the coldkey, balance, hotkey details (own hotkey and delegate hotkey), stake amount, and the rate of return.
|
3205
|
-
|
3206
|
-
The command shows a table with the below columns:
|
3207
|
-
|
3208
|
-
- Coldkey: The coldkey associated with the wallet.
|
3209
|
-
|
3210
|
-
- Balance: The balance of the coldkey.
|
3211
|
-
|
3212
|
-
- Hotkey: The names of the coldkey's own hotkeys and the delegate hotkeys to which this coldkey has staked.
|
3213
|
-
|
3214
|
-
- Stake: The amount of TAO staked to all the hotkeys.
|
3215
|
-
|
3216
|
-
- Rate: The rate of return on the stake, shown in TAO per day.
|
3217
|
-
|
3218
|
-
EXAMPLE
|
3219
|
-
|
3220
|
-
[green]$[/green] btcli stake show --all
|
3221
|
-
"""
|
3222
|
-
self.verbosity_handler(quiet, verbose)
|
3223
|
-
if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
3224
|
-
err_console.print(
|
3225
|
-
"Unable to use `--reuse-last` or `--html` when config 'no-cache' is set to 'True'. "
|
3226
|
-
"Please change the config to 'False' using `btcli config set`"
|
3227
|
-
)
|
3228
|
-
raise typer.Exit()
|
3229
|
-
if not reuse_last:
|
3230
|
-
subtensor = self.initialize_chain(network)
|
3231
|
-
else:
|
3232
|
-
subtensor = None
|
3233
|
-
|
3234
|
-
if all_wallets:
|
3235
|
-
wallet = self.wallet_ask(
|
3236
|
-
wallet_name,
|
3237
|
-
wallet_path,
|
3238
|
-
wallet_hotkey,
|
3239
|
-
ask_for=[],
|
3240
|
-
validate=WV.NONE,
|
3241
|
-
)
|
3242
|
-
else:
|
3243
|
-
wallet = self.wallet_ask(
|
3244
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
3245
|
-
)
|
3246
|
-
|
3247
|
-
return self._run_command(
|
3248
|
-
stake.show(
|
3249
|
-
wallet,
|
3250
|
-
subtensor,
|
3251
|
-
all_wallets,
|
3252
|
-
reuse_last,
|
3253
|
-
html_output,
|
3254
|
-
not self.config.get("use_cache", True),
|
3255
|
-
)
|
3256
|
-
)
|
3257
|
-
|
3258
|
-
def stake_add(
|
3259
|
-
self,
|
3260
|
-
stake_all: bool = typer.Option(
|
3261
|
-
False,
|
3262
|
-
"--all-tokens",
|
3263
|
-
"--all",
|
3264
|
-
"-a",
|
3265
|
-
help="When set, the command stakes all the available TAO from the coldkey.",
|
3266
|
-
),
|
3267
|
-
amount: float = typer.Option(
|
3268
|
-
0.0, "--amount", help="The amount of TAO to stake"
|
3269
|
-
),
|
3270
|
-
max_stake: float = typer.Option(
|
3271
|
-
0.0,
|
3272
|
-
"--max-stake",
|
3273
|
-
"-m",
|
3274
|
-
help="Stake is sent to a hotkey only until the hotkey's total stake is less than or equal to this maximum staked TAO. If a hotkey already has stake greater than this amount, then stake is not added to this hotkey.",
|
3275
|
-
),
|
3276
|
-
hotkey_ss58_address: str = typer.Option(
|
3277
|
-
"",
|
3278
|
-
help="The ss58 address of the hotkey to stake to.",
|
3279
|
-
),
|
3280
|
-
include_hotkeys: str = typer.Option(
|
3281
|
-
"",
|
3282
|
-
"--include-hotkeys",
|
3283
|
-
"-in",
|
3284
|
-
help="Specifies hotkeys by name or ss58 address to stake to. For example, `-in hk1,hk2`",
|
3285
|
-
),
|
3286
|
-
exclude_hotkeys: str = typer.Option(
|
3287
|
-
"",
|
3288
|
-
"--exclude-hotkeys",
|
3289
|
-
"-ex",
|
3290
|
-
help="Specifies hotkeys by name or ss58 address to not to stake to (use this option only with `--all-hotkeys`)"
|
3291
|
-
" i.e. `--all-hotkeys -ex hk3,hk4`",
|
3292
|
-
),
|
3293
|
-
all_hotkeys: bool = typer.Option(
|
3294
|
-
False,
|
3295
|
-
help="When set, this command stakes to all hotkeys associated with the wallet. Do not use if specifying "
|
3296
|
-
"hotkeys in `--include-hotkeys`.",
|
3297
|
-
),
|
2601
|
+
stake_all: bool = typer.Option(
|
2602
|
+
False,
|
2603
|
+
"--all-tokens",
|
2604
|
+
"--all",
|
2605
|
+
"-a",
|
2606
|
+
help="When set, the command stakes all the available TAO from the coldkey.",
|
2607
|
+
),
|
2608
|
+
amount: float = typer.Option(
|
2609
|
+
0.0, "--amount", help="The amount of TAO to stake"
|
2610
|
+
),
|
2611
|
+
max_stake: float = typer.Option(
|
2612
|
+
0.0,
|
2613
|
+
"--max-stake",
|
2614
|
+
"-m",
|
2615
|
+
help="Stake is sent to a hotkey only until the hotkey's total stake is less than or equal to this maximum staked TAO. If a hotkey already has stake greater than this amount, then stake is not added to this hotkey.",
|
2616
|
+
),
|
2617
|
+
include_hotkeys: str = typer.Option(
|
2618
|
+
"",
|
2619
|
+
"--include-hotkeys",
|
2620
|
+
"-in",
|
2621
|
+
"--hotkey-ss58-address",
|
2622
|
+
help="Specifies hotkeys by name or ss58 address to stake to. For example, `-in hk1,hk2`",
|
2623
|
+
),
|
2624
|
+
exclude_hotkeys: str = typer.Option(
|
2625
|
+
"",
|
2626
|
+
"--exclude-hotkeys",
|
2627
|
+
"-ex",
|
2628
|
+
help="Specifies hotkeys by name or ss58 address to not to stake to (use this option only with `--all-hotkeys`)"
|
2629
|
+
" i.e. `--all-hotkeys -ex hk3,hk4`",
|
2630
|
+
),
|
2631
|
+
all_hotkeys: bool = typer.Option(
|
2632
|
+
False,
|
2633
|
+
help="When set, this command stakes to all hotkeys associated with the wallet. Do not use if specifying "
|
2634
|
+
"hotkeys in `--include-hotkeys`.",
|
2635
|
+
),
|
2636
|
+
netuid: Optional[int] = Options.netuid_not_req,
|
2637
|
+
all_netuids: bool = Options.all_netuids,
|
3298
2638
|
wallet_name: str = Options.wallet_name,
|
3299
2639
|
wallet_path: str = Options.wallet_path,
|
3300
2640
|
wallet_hotkey: str = Options.wallet_hotkey,
|
@@ -3315,16 +2655,14 @@ class CLIManager:
|
|
3315
2655
|
[green]$[/green] btcli stake add --amount 100 --wallet-name <my_wallet> --wallet-hotkey <my_hotkey>
|
3316
2656
|
"""
|
3317
2657
|
self.verbosity_handler(quiet, verbose)
|
2658
|
+
netuid = get_optional_netuid(netuid, all_netuids)
|
3318
2659
|
|
3319
2660
|
if stake_all and amount:
|
3320
|
-
|
2661
|
+
err_console.print(
|
3321
2662
|
"Cannot specify an amount and 'stake-all'. Choose one or the other."
|
3322
2663
|
)
|
3323
2664
|
raise typer.Exit()
|
3324
2665
|
|
3325
|
-
if not stake_all and not amount and not max_stake:
|
3326
|
-
amount = FloatPrompt.ask("Amount to [blue]stake (TAO τ)[/blue]")
|
3327
|
-
|
3328
2666
|
if stake_all and not amount:
|
3329
2667
|
if not Confirm.ask("Stake all the available TAO tokens?", default=False):
|
3330
2668
|
raise typer.Exit()
|
@@ -3342,40 +2680,66 @@ class CLIManager:
|
|
3342
2680
|
)
|
3343
2681
|
raise typer.Exit()
|
3344
2682
|
|
3345
|
-
if
|
3346
|
-
not
|
3347
|
-
|
3348
|
-
|
3349
|
-
|
3350
|
-
|
3351
|
-
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
3355
|
-
|
2683
|
+
if not wallet_hotkey and not all_hotkeys and not include_hotkeys:
|
2684
|
+
if not wallet_name:
|
2685
|
+
wallet_name = Prompt.ask(
|
2686
|
+
"Enter the [blue]wallet name[/blue]",
|
2687
|
+
default=self.config.get("wallet_name") or defaults.wallet.name,
|
2688
|
+
)
|
2689
|
+
if netuid is not None:
|
2690
|
+
hotkey_or_ss58 = Prompt.ask(
|
2691
|
+
"Enter the [blue]wallet hotkey[/blue] name or [blue]ss58 address[/blue] to stake to [dim](or Press Enter to view delegates)[/dim]",
|
2692
|
+
)
|
2693
|
+
else:
|
2694
|
+
hotkey_or_ss58 = Prompt.ask(
|
2695
|
+
"Enter the [blue]hotkey[/blue] name or [blue]ss58 address[/blue] to stake to",
|
2696
|
+
default=self.config.get("wallet_hotkey") or defaults.wallet.hotkey,
|
2697
|
+
)
|
2698
|
+
|
2699
|
+
if hotkey_or_ss58 == "":
|
3356
2700
|
wallet = self.wallet_ask(
|
3357
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2701
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
2702
|
+
)
|
2703
|
+
selected_hotkey = self._run_command(
|
2704
|
+
subnets.show(
|
2705
|
+
subtensor=self.initialize_chain(network),
|
2706
|
+
netuid=netuid,
|
2707
|
+
max_rows=12,
|
2708
|
+
prompt=False,
|
2709
|
+
delegate_selection=True,
|
2710
|
+
),
|
2711
|
+
exit_early=False,
|
2712
|
+
)
|
2713
|
+
if selected_hotkey is None:
|
2714
|
+
print_error("No delegate selected. Exiting.")
|
2715
|
+
raise typer.Exit()
|
2716
|
+
include_hotkeys = selected_hotkey
|
2717
|
+
elif is_valid_ss58_address(hotkey_or_ss58):
|
2718
|
+
wallet = self.wallet_ask(
|
2719
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3358
2720
|
)
|
2721
|
+
include_hotkeys = hotkey_or_ss58
|
3359
2722
|
else:
|
3360
2723
|
wallet_hotkey = hotkey_or_ss58
|
3361
2724
|
wallet = self.wallet_ask(
|
3362
2725
|
wallet_name,
|
3363
2726
|
wallet_path,
|
3364
2727
|
wallet_hotkey,
|
3365
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2728
|
+
ask_for=[WO.NAME, WO.HOTKEY, WO.PATH],
|
3366
2729
|
validate=WV.WALLET_AND_HOTKEY,
|
3367
2730
|
)
|
2731
|
+
include_hotkeys = wallet.hotkey.ss58_address
|
3368
2732
|
|
3369
|
-
elif all_hotkeys or include_hotkeys or exclude_hotkeys
|
2733
|
+
elif all_hotkeys or include_hotkeys or exclude_hotkeys:
|
3370
2734
|
wallet = self.wallet_ask(
|
3371
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2735
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3372
2736
|
)
|
3373
2737
|
else:
|
3374
2738
|
wallet = self.wallet_ask(
|
3375
2739
|
wallet_name,
|
3376
2740
|
wallet_path,
|
3377
2741
|
wallet_hotkey,
|
3378
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2742
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3379
2743
|
validate=WV.WALLET_AND_HOTKEY,
|
3380
2744
|
)
|
3381
2745
|
|
@@ -3383,8 +2747,8 @@ class CLIManager:
|
|
3383
2747
|
included_hotkeys = parse_to_list(
|
3384
2748
|
include_hotkeys,
|
3385
2749
|
str,
|
3386
|
-
"Hotkeys must be a comma-separated list of ss58s
|
3387
|
-
|
2750
|
+
"Hotkeys must be a comma-separated list of ss58s, e.g., `--include-hotkeys 5Grw....,5Grw....`.",
|
2751
|
+
is_ss58=True,
|
3388
2752
|
)
|
3389
2753
|
else:
|
3390
2754
|
included_hotkeys = []
|
@@ -3393,24 +2757,54 @@ class CLIManager:
|
|
3393
2757
|
excluded_hotkeys = parse_to_list(
|
3394
2758
|
exclude_hotkeys,
|
3395
2759
|
str,
|
3396
|
-
"Hotkeys must be a comma-separated list of ss58s
|
3397
|
-
|
2760
|
+
"Hotkeys must be a comma-separated list of ss58s, e.g., `--exclude-hotkeys 5Grw....,5Grw....`.",
|
2761
|
+
is_ss58=True,
|
3398
2762
|
)
|
3399
2763
|
else:
|
3400
2764
|
excluded_hotkeys = []
|
3401
2765
|
|
2766
|
+
# TODO: Ask amount for each subnet explicitly if more than one
|
2767
|
+
if not stake_all and not amount and not max_stake:
|
2768
|
+
free_balance, staked_balance = self._run_command(
|
2769
|
+
wallets.wallet_balance(
|
2770
|
+
wallet, self.initialize_chain(network), False, None
|
2771
|
+
),
|
2772
|
+
exit_early=False,
|
2773
|
+
)
|
2774
|
+
if free_balance == Balance.from_tao(0):
|
2775
|
+
print_error("You dont have any balance to stake.")
|
2776
|
+
raise typer.Exit()
|
2777
|
+
if netuid is not None:
|
2778
|
+
amount = FloatPrompt.ask(
|
2779
|
+
f"Amount to [{COLOR_PALETTE['GENERAL']['SUBHEADING_MAIN']}]stake (TAO τ)"
|
2780
|
+
)
|
2781
|
+
else:
|
2782
|
+
amount = FloatPrompt.ask(
|
2783
|
+
f"Amount to [{COLOR_PALETTE['GENERAL']['SUBHEADING_MAIN']}]stake to each netuid (TAO τ)"
|
2784
|
+
)
|
2785
|
+
|
2786
|
+
if amount <= 0:
|
2787
|
+
print_error(f"You entered an incorrect stake amount: {amount}")
|
2788
|
+
raise typer.Exit()
|
2789
|
+
if Balance.from_tao(amount) > free_balance:
|
2790
|
+
print_error(
|
2791
|
+
f"You dont have enough balance to stake. Current free Balance: {free_balance}."
|
2792
|
+
)
|
2793
|
+
raise typer.Exit()
|
2794
|
+
|
3402
2795
|
return self._run_command(
|
3403
2796
|
stake.stake_add(
|
3404
2797
|
wallet,
|
3405
2798
|
self.initialize_chain(network),
|
3406
|
-
|
2799
|
+
netuid,
|
3407
2800
|
stake_all,
|
2801
|
+
amount,
|
2802
|
+
False,
|
2803
|
+
prompt,
|
3408
2804
|
max_stake,
|
2805
|
+
all_hotkeys,
|
3409
2806
|
included_hotkeys,
|
3410
2807
|
excluded_hotkeys,
|
3411
|
-
all_hotkeys,
|
3412
|
-
prompt,
|
3413
|
-
hotkey_ss58_address,
|
3414
2808
|
)
|
3415
2809
|
)
|
3416
2810
|
|
@@ -3420,11 +2814,21 @@ class CLIManager:
|
|
3420
2814
|
wallet_name: str = Options.wallet_name,
|
3421
2815
|
wallet_path: str = Options.wallet_path,
|
3422
2816
|
wallet_hotkey: str = Options.wallet_hotkey,
|
2817
|
+
netuid: Optional[int] = Options.netuid_not_req,
|
2818
|
+
all_netuids: bool = Options.all_netuids,
|
3423
2819
|
unstake_all: bool = typer.Option(
|
3424
2820
|
False,
|
3425
2821
|
"--unstake-all",
|
3426
2822
|
"--all",
|
3427
|
-
|
2823
|
+
hidden=True,
|
2824
|
+
help="When set, this command unstakes all staked TAO + Alpha from the all hotkeys.",
|
2825
|
+
),
|
2826
|
+
unstake_all_alpha: bool = typer.Option(
|
2827
|
+
False,
|
2828
|
+
"--unstake-all-alpha",
|
2829
|
+
"--all-alpha",
|
2830
|
+
hidden=True,
|
2831
|
+
help="When set, this command unstakes all staked Alpha from the all hotkeys.",
|
3428
2832
|
),
|
3429
2833
|
amount: float = typer.Option(
|
3430
2834
|
0.0, "--amount", "-a", help="The amount of TAO to unstake."
|
@@ -3458,6 +2862,12 @@ class CLIManager:
|
|
3458
2862
|
"hotkeys in `--include-hotkeys`.",
|
3459
2863
|
),
|
3460
2864
|
prompt: bool = Options.prompt,
|
2865
|
+
interactive: bool = typer.Option(
|
2866
|
+
False,
|
2867
|
+
"--interactive",
|
2868
|
+
"-i",
|
2869
|
+
help="Enter interactive mode for unstaking.",
|
2870
|
+
),
|
3461
2871
|
quiet: bool = Options.quiet,
|
3462
2872
|
verbose: bool = Options.verbose,
|
3463
2873
|
):
|
@@ -3473,31 +2883,45 @@ class CLIManager:
|
|
3473
2883
|
[blue bold]Note[/blue bold]: This command is for users who wish to reallocate their stake or withdraw them from the network. It allows for flexible management of TAO stake across different neurons (hotkeys) on the network.
|
3474
2884
|
"""
|
3475
2885
|
self.verbosity_handler(quiet, verbose)
|
2886
|
+
# TODO: Coldkey related unstakes need to be updated. Patching for now.
|
2887
|
+
unstake_all_alpha = False
|
2888
|
+
unstake_all = False
|
3476
2889
|
|
3477
|
-
if
|
2890
|
+
if interactive and any(
|
2891
|
+
[hotkey_ss58_address, include_hotkeys, exclude_hotkeys, all_hotkeys]
|
2892
|
+
):
|
3478
2893
|
err_console.print(
|
3479
|
-
"
|
3480
|
-
"should only be used standalone (to use all hotkeys) or with `--exclude-hotkeys`."
|
2894
|
+
"Interactive mode cannot be used with hotkey selection options like --include-hotkeys, --exclude-hotkeys, --all-hotkeys, or --hotkey."
|
3481
2895
|
)
|
3482
2896
|
raise typer.Exit()
|
3483
2897
|
|
3484
|
-
if
|
3485
|
-
err_console.print(
|
3486
|
-
"You have specified both including and excluding hotkeys options. Select one or the other."
|
3487
|
-
)
|
2898
|
+
if unstake_all and unstake_all_alpha:
|
2899
|
+
err_console.print("Cannot specify both unstake-all and unstake-all-alpha.")
|
3488
2900
|
raise typer.Exit()
|
3489
2901
|
|
3490
|
-
if unstake_all and
|
3491
|
-
|
3492
|
-
|
3493
|
-
|
3494
|
-
|
2902
|
+
if not interactive and not unstake_all and not unstake_all_alpha:
|
2903
|
+
netuid = get_optional_netuid(netuid, all_netuids)
|
2904
|
+
if all_hotkeys and include_hotkeys:
|
2905
|
+
err_console.print(
|
2906
|
+
"You have specified hotkeys to include and also the `--all-hotkeys` flag. The flag"
|
2907
|
+
" should only be used standalone (to use all hotkeys) or with `--exclude-hotkeys`."
|
2908
|
+
)
|
2909
|
+
raise typer.Exit()
|
2910
|
+
|
2911
|
+
if include_hotkeys and exclude_hotkeys:
|
2912
|
+
err_console.print(
|
2913
|
+
"You have specified both including and excluding hotkeys options. Select one or the other."
|
2914
|
+
)
|
2915
|
+
raise typer.Exit()
|
3495
2916
|
|
3496
|
-
|
3497
|
-
|
2917
|
+
if unstake_all and amount:
|
2918
|
+
err_console.print(
|
2919
|
+
"Cannot specify both a specific amount and 'unstake-all'. Choose one or the other."
|
2920
|
+
)
|
2921
|
+
raise typer.Exit()
|
3498
2922
|
|
3499
|
-
|
3500
|
-
|
2923
|
+
if amount and amount <= 0:
|
2924
|
+
print_error(f"You entered an incorrect unstake amount: {amount}")
|
3501
2925
|
raise typer.Exit()
|
3502
2926
|
|
3503
2927
|
if (
|
@@ -3505,14 +2929,27 @@ class CLIManager:
|
|
3505
2929
|
and not hotkey_ss58_address
|
3506
2930
|
and not all_hotkeys
|
3507
2931
|
and not include_hotkeys
|
2932
|
+
and not interactive
|
2933
|
+
and not unstake_all
|
2934
|
+
and not unstake_all_alpha
|
3508
2935
|
):
|
2936
|
+
if not wallet_name:
|
2937
|
+
wallet_name = Prompt.ask(
|
2938
|
+
"Enter the [blue]wallet name[/blue]",
|
2939
|
+
default=self.config.get("wallet_name") or defaults.wallet.name,
|
2940
|
+
)
|
3509
2941
|
hotkey_or_ss58 = Prompt.ask(
|
3510
|
-
"Enter the [blue]hotkey[/blue] name or [blue]ss58 address[/blue] to unstake from"
|
2942
|
+
"Enter the [blue]hotkey[/blue] name or [blue]ss58 address[/blue] to unstake from [dim](or Press Enter to view existing staked hotkeys)[/dim]",
|
3511
2943
|
)
|
3512
|
-
if
|
2944
|
+
if hotkey_or_ss58 == "":
|
2945
|
+
wallet = self.wallet_ask(
|
2946
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
2947
|
+
)
|
2948
|
+
interactive = True
|
2949
|
+
elif is_valid_ss58_address(hotkey_or_ss58):
|
3513
2950
|
hotkey_ss58_address = hotkey_or_ss58
|
3514
2951
|
wallet = self.wallet_ask(
|
3515
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2952
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3516
2953
|
)
|
3517
2954
|
else:
|
3518
2955
|
wallet_hotkey = hotkey_or_ss58
|
@@ -3520,56 +2957,436 @@ class CLIManager:
|
|
3520
2957
|
wallet_name,
|
3521
2958
|
wallet_path,
|
3522
2959
|
wallet_hotkey,
|
3523
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2960
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3524
2961
|
validate=WV.WALLET_AND_HOTKEY,
|
3525
2962
|
)
|
3526
2963
|
|
3527
|
-
elif
|
2964
|
+
elif (
|
2965
|
+
all_hotkeys
|
2966
|
+
or include_hotkeys
|
2967
|
+
or exclude_hotkeys
|
2968
|
+
or hotkey_ss58_address
|
2969
|
+
or interactive
|
2970
|
+
or unstake_all
|
2971
|
+
or unstake_all_alpha
|
2972
|
+
):
|
2973
|
+
wallet = self.wallet_ask(
|
2974
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
2975
|
+
)
|
2976
|
+
else:
|
3528
2977
|
wallet = self.wallet_ask(
|
3529
|
-
wallet_name,
|
2978
|
+
wallet_name,
|
2979
|
+
wallet_path,
|
2980
|
+
wallet_hotkey,
|
2981
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
2982
|
+
validate=WV.WALLET_AND_HOTKEY,
|
2983
|
+
)
|
2984
|
+
|
2985
|
+
if include_hotkeys:
|
2986
|
+
included_hotkeys = parse_to_list(
|
2987
|
+
include_hotkeys,
|
2988
|
+
str,
|
2989
|
+
"Hotkeys must be a comma-separated list of ss58s or names, e.g., `--include-hotkeys hk1,hk2`.",
|
2990
|
+
is_ss58=False,
|
2991
|
+
)
|
2992
|
+
else:
|
2993
|
+
included_hotkeys = []
|
2994
|
+
|
2995
|
+
if exclude_hotkeys:
|
2996
|
+
excluded_hotkeys = parse_to_list(
|
2997
|
+
exclude_hotkeys,
|
2998
|
+
str,
|
2999
|
+
"Hotkeys must be a comma-separated list of ss58s or names, e.g., `--exclude-hotkeys hk3,hk4`.",
|
3000
|
+
is_ss58=False,
|
3001
|
+
)
|
3002
|
+
else:
|
3003
|
+
excluded_hotkeys = []
|
3004
|
+
|
3005
|
+
return self._run_command(
|
3006
|
+
stake.unstake(
|
3007
|
+
wallet,
|
3008
|
+
self.initialize_chain(network),
|
3009
|
+
hotkey_ss58_address,
|
3010
|
+
all_hotkeys,
|
3011
|
+
included_hotkeys,
|
3012
|
+
excluded_hotkeys,
|
3013
|
+
amount,
|
3014
|
+
keep_stake,
|
3015
|
+
unstake_all,
|
3016
|
+
prompt,
|
3017
|
+
interactive,
|
3018
|
+
netuid=netuid,
|
3019
|
+
unstake_all_alpha=unstake_all_alpha,
|
3020
|
+
)
|
3021
|
+
)
|
3022
|
+
|
3023
|
+
def stake_move(
|
3024
|
+
self,
|
3025
|
+
network: Optional[list[str]] = Options.network,
|
3026
|
+
wallet_name=Options.wallet_name,
|
3027
|
+
wallet_path=Options.wallet_path,
|
3028
|
+
wallet_hotkey=Options.wallet_hotkey,
|
3029
|
+
origin_netuid: Optional[int] = typer.Option(
|
3030
|
+
None, "--origin-netuid", help="Origin netuid"
|
3031
|
+
),
|
3032
|
+
destination_netuid: Optional[int] = typer.Option(
|
3033
|
+
None, "--dest-netuid", help="Destination netuid"
|
3034
|
+
),
|
3035
|
+
destination_hotkey: Optional[str] = typer.Option(
|
3036
|
+
None, "--dest-ss58", "--dest", help="Destination hotkey", prompt=False
|
3037
|
+
),
|
3038
|
+
amount: float = typer.Option(
|
3039
|
+
None,
|
3040
|
+
"--amount",
|
3041
|
+
help="The amount of TAO to stake",
|
3042
|
+
prompt=False,
|
3043
|
+
),
|
3044
|
+
stake_all: bool = typer.Option(
|
3045
|
+
False, "--stake-all", "--all", help="Stake all", prompt=False
|
3046
|
+
),
|
3047
|
+
prompt: bool = Options.prompt,
|
3048
|
+
):
|
3049
|
+
"""
|
3050
|
+
Move staked TAO between hotkeys while keeping the same coldkey ownership.
|
3051
|
+
|
3052
|
+
This command allows you to:
|
3053
|
+
- Move stake from one hotkey to another hotkey
|
3054
|
+
- Move stake between different subnets
|
3055
|
+
- Keep the same coldkey ownership
|
3056
|
+
|
3057
|
+
You can specify:
|
3058
|
+
- The origin subnet (--origin-netuid)
|
3059
|
+
- The destination subnet (--dest-netuid)
|
3060
|
+
- The destination hotkey (--dest-hotkey)
|
3061
|
+
- The amount to move (--amount)
|
3062
|
+
|
3063
|
+
If no arguments are provided, an interactive selection menu will be shown.
|
3064
|
+
|
3065
|
+
EXAMPLE
|
3066
|
+
|
3067
|
+
[green]$[/green] btcli stake move
|
3068
|
+
"""
|
3069
|
+
console.print(
|
3070
|
+
"[dim]This command moves stake from one hotkey to another hotkey while keeping the same coldkey.[/dim]"
|
3071
|
+
)
|
3072
|
+
if not destination_hotkey:
|
3073
|
+
dest_wallet_or_ss58 = Prompt.ask(
|
3074
|
+
"Enter the [blue]destination wallet[/blue] where destination hotkey is located or [blue]ss58 address[/blue]"
|
3075
|
+
)
|
3076
|
+
if is_valid_ss58_address(dest_wallet_or_ss58):
|
3077
|
+
destination_hotkey = dest_wallet_or_ss58
|
3078
|
+
else:
|
3079
|
+
dest_wallet = self.wallet_ask(
|
3080
|
+
dest_wallet_or_ss58,
|
3081
|
+
wallet_path,
|
3082
|
+
None,
|
3083
|
+
ask_for=[WO.NAME, WO.PATH],
|
3084
|
+
validate=WV.WALLET,
|
3085
|
+
)
|
3086
|
+
destination_hotkey = Prompt.ask(
|
3087
|
+
"Enter the [blue]destination hotkey[/blue] name",
|
3088
|
+
default=dest_wallet.hotkey_str,
|
3089
|
+
)
|
3090
|
+
destination_wallet = self.wallet_ask(
|
3091
|
+
dest_wallet_or_ss58,
|
3092
|
+
wallet_path,
|
3093
|
+
destination_hotkey,
|
3094
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3095
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3096
|
+
)
|
3097
|
+
destination_hotkey = destination_wallet.hotkey.ss58_address
|
3098
|
+
else:
|
3099
|
+
if is_valid_ss58_address(destination_hotkey):
|
3100
|
+
destination_hotkey = destination_hotkey
|
3101
|
+
else:
|
3102
|
+
print_error(
|
3103
|
+
"Invalid destination hotkey ss58 address. Please enter a valid ss58 address or wallet name."
|
3104
|
+
)
|
3105
|
+
raise typer.Exit()
|
3106
|
+
|
3107
|
+
if not wallet_name:
|
3108
|
+
wallet_name = Prompt.ask(
|
3109
|
+
"Enter the [blue]origin wallet name[/blue]",
|
3110
|
+
default=self.config.get("wallet_name") or defaults.wallet.name,
|
3111
|
+
)
|
3112
|
+
wallet = self.wallet_ask(
|
3113
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3114
|
+
)
|
3115
|
+
|
3116
|
+
interactive_selection = False
|
3117
|
+
if not wallet_hotkey:
|
3118
|
+
origin_hotkey = Prompt.ask(
|
3119
|
+
"Enter the [blue]origin hotkey[/blue] name or "
|
3120
|
+
"[blue]ss58 address[/blue] where the stake will be moved from "
|
3121
|
+
"[dim](or Press Enter to view existing stakes)[/dim]"
|
3122
|
+
)
|
3123
|
+
if origin_hotkey == "":
|
3124
|
+
interactive_selection = True
|
3125
|
+
|
3126
|
+
elif is_valid_ss58_address(origin_hotkey):
|
3127
|
+
origin_hotkey = origin_hotkey
|
3128
|
+
else:
|
3129
|
+
wallet = self.wallet_ask(
|
3130
|
+
wallet_name,
|
3131
|
+
wallet_path,
|
3132
|
+
origin_hotkey,
|
3133
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3134
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3135
|
+
)
|
3136
|
+
origin_hotkey = wallet.hotkey.ss58_address
|
3137
|
+
else:
|
3138
|
+
if is_valid_ss58_address(wallet_hotkey):
|
3139
|
+
origin_hotkey = wallet_hotkey
|
3140
|
+
else:
|
3141
|
+
wallet = self.wallet_ask(
|
3142
|
+
wallet_name,
|
3143
|
+
wallet_path,
|
3144
|
+
wallet_hotkey,
|
3145
|
+
ask_for=[],
|
3146
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3147
|
+
)
|
3148
|
+
origin_hotkey = wallet.hotkey.ss58_address
|
3149
|
+
|
3150
|
+
if not interactive_selection:
|
3151
|
+
if origin_netuid is None:
|
3152
|
+
origin_netuid = IntPrompt.ask(
|
3153
|
+
"Enter the [blue]origin subnet[/blue] (netuid) to move stake from"
|
3154
|
+
)
|
3155
|
+
|
3156
|
+
if destination_netuid is None:
|
3157
|
+
destination_netuid = IntPrompt.ask(
|
3158
|
+
"Enter the [blue]destination subnet[/blue] (netuid) to move stake to"
|
3159
|
+
)
|
3160
|
+
|
3161
|
+
return self._run_command(
|
3162
|
+
move.move_stake(
|
3163
|
+
subtensor=self.initialize_chain(network),
|
3164
|
+
wallet=wallet,
|
3165
|
+
origin_netuid=origin_netuid,
|
3166
|
+
origin_hotkey=origin_hotkey,
|
3167
|
+
destination_netuid=destination_netuid,
|
3168
|
+
destination_hotkey=destination_hotkey,
|
3169
|
+
amount=amount,
|
3170
|
+
stake_all=stake_all,
|
3171
|
+
interactive_selection=interactive_selection,
|
3172
|
+
prompt=prompt,
|
3173
|
+
)
|
3174
|
+
)
|
3175
|
+
|
3176
|
+
def stake_transfer(
|
3177
|
+
self,
|
3178
|
+
network: Optional[list[str]] = Options.network,
|
3179
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
3180
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
3181
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3182
|
+
origin_netuid: Optional[int] = typer.Option(
|
3183
|
+
None,
|
3184
|
+
"--origin-netuid",
|
3185
|
+
help="The netuid to transfer stake from",
|
3186
|
+
),
|
3187
|
+
dest_netuid: Optional[int] = typer.Option(
|
3188
|
+
None,
|
3189
|
+
"--dest-netuid",
|
3190
|
+
help="The netuid to transfer stake to",
|
3191
|
+
),
|
3192
|
+
dest_ss58: Optional[str] = typer.Option(
|
3193
|
+
None,
|
3194
|
+
"--dest-ss58",
|
3195
|
+
"--dest",
|
3196
|
+
"--dest-coldkey",
|
3197
|
+
help="The destination wallet name or SS58 address to transfer stake to",
|
3198
|
+
),
|
3199
|
+
amount: float = typer.Option(
|
3200
|
+
None,
|
3201
|
+
"--amount",
|
3202
|
+
"-a",
|
3203
|
+
help="Amount of stake to transfer",
|
3204
|
+
),
|
3205
|
+
prompt: bool = Options.prompt,
|
3206
|
+
quiet: bool = Options.quiet,
|
3207
|
+
verbose: bool = Options.verbose,
|
3208
|
+
):
|
3209
|
+
"""
|
3210
|
+
Transfer stake between coldkeys while keeping the same hotkey ownership.
|
3211
|
+
|
3212
|
+
This command allows you to:
|
3213
|
+
- Transfer stake from one coldkey to another coldkey
|
3214
|
+
- Keep the same hotkey ownership
|
3215
|
+
- Transfer stake between different subnets
|
3216
|
+
|
3217
|
+
You can specify:
|
3218
|
+
- The origin subnet (--origin-netuid)
|
3219
|
+
- The destination subnet (--dest-netuid)
|
3220
|
+
- The destination wallet/address (--dest)
|
3221
|
+
- The amount to transfer (--amount)
|
3222
|
+
|
3223
|
+
If no arguments are provided, an interactive selection menu will be shown.
|
3224
|
+
|
3225
|
+
EXAMPLE
|
3226
|
+
|
3227
|
+
Transfer 100 TAO from subnet 1 to subnet 2:
|
3228
|
+
[green]$[/green] btcli stake transfer --origin-netuid 1 --dest-netuid 2 --dest wallet2 --amount 100
|
3229
|
+
|
3230
|
+
Using SS58 address:
|
3231
|
+
[green]$[/green] btcli stake transfer --origin-netuid 1 --dest-netuid 2 --dest 5FrLxJsyJ5x9n2rmxFwosFraxFCKcXZDngEP9H7qjkKgHLcK --amount 100
|
3232
|
+
"""
|
3233
|
+
console.print(
|
3234
|
+
"[dim]This command transfers stake from one coldkey to another while keeping the same hotkey.[/dim]"
|
3235
|
+
)
|
3236
|
+
self.verbosity_handler(quiet, verbose)
|
3237
|
+
|
3238
|
+
wallet = self.wallet_ask(
|
3239
|
+
wallet_name,
|
3240
|
+
wallet_path,
|
3241
|
+
wallet_hotkey,
|
3242
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3243
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3244
|
+
)
|
3245
|
+
|
3246
|
+
if not dest_ss58:
|
3247
|
+
dest_ss58 = Prompt.ask(
|
3248
|
+
"Enter the [blue]destination wallet name[/blue] or [blue]coldkey SS58 address[/blue]"
|
3530
3249
|
)
|
3531
3250
|
|
3251
|
+
if is_valid_ss58_address(dest_ss58):
|
3252
|
+
dest_ss58 = dest_ss58
|
3532
3253
|
else:
|
3533
|
-
|
3534
|
-
|
3254
|
+
dest_wallet = self.wallet_ask(
|
3255
|
+
dest_ss58,
|
3535
3256
|
wallet_path,
|
3536
|
-
|
3537
|
-
ask_for=[WO.NAME, WO.
|
3538
|
-
validate=WV.
|
3257
|
+
None,
|
3258
|
+
ask_for=[WO.NAME, WO.PATH],
|
3259
|
+
validate=WV.WALLET,
|
3539
3260
|
)
|
3261
|
+
dest_ss58 = dest_wallet.coldkeypub.ss58_address
|
3540
3262
|
|
3541
|
-
|
3542
|
-
|
3543
|
-
|
3544
|
-
str,
|
3545
|
-
"Hotkeys must be a comma-separated list of ss58s or hotkey names, e.g., "
|
3546
|
-
"`--include-hotkeys 5Grw....,5Grw....`.",
|
3547
|
-
)
|
3263
|
+
interactive_selection = False
|
3264
|
+
if origin_netuid is None and dest_netuid is None and not amount:
|
3265
|
+
interactive_selection = True
|
3548
3266
|
else:
|
3549
|
-
|
3267
|
+
if origin_netuid is None:
|
3268
|
+
origin_netuid = IntPrompt.ask(
|
3269
|
+
"Enter the [blue]origin subnet[/blue] (netuid)"
|
3270
|
+
)
|
3271
|
+
if not amount:
|
3272
|
+
amount = FloatPrompt.ask("Enter the [blue]amount[/blue] to transfer")
|
3550
3273
|
|
3551
|
-
|
3552
|
-
|
3553
|
-
|
3554
|
-
|
3555
|
-
|
3556
|
-
|
3274
|
+
if dest_netuid is None:
|
3275
|
+
dest_netuid = IntPrompt.ask(
|
3276
|
+
"Enter the [blue]destination subnet[/blue] (netuid)"
|
3277
|
+
)
|
3278
|
+
|
3279
|
+
return self._run_command(
|
3280
|
+
move.transfer_stake(
|
3281
|
+
wallet=wallet,
|
3282
|
+
subtensor=self.initialize_chain(network),
|
3283
|
+
origin_netuid=origin_netuid,
|
3284
|
+
dest_netuid=dest_netuid,
|
3285
|
+
dest_coldkey_ss58=dest_ss58,
|
3286
|
+
amount=amount,
|
3287
|
+
interactive_selection=interactive_selection,
|
3288
|
+
prompt=prompt,
|
3557
3289
|
)
|
3290
|
+
)
|
3291
|
+
|
3292
|
+
def stake_swap(
|
3293
|
+
self,
|
3294
|
+
network: Optional[list[str]] = Options.network,
|
3295
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
3296
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
3297
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3298
|
+
origin_netuid: Optional[int] = typer.Option(
|
3299
|
+
None,
|
3300
|
+
"--origin-netuid",
|
3301
|
+
"-o",
|
3302
|
+
"--origin",
|
3303
|
+
help="The netuid to swap stake from",
|
3304
|
+
),
|
3305
|
+
dest_netuid: Optional[int] = typer.Option(
|
3306
|
+
None,
|
3307
|
+
"--dest-netuid",
|
3308
|
+
"-d",
|
3309
|
+
"--dest",
|
3310
|
+
help="The netuid to swap stake to",
|
3311
|
+
),
|
3312
|
+
amount: float = typer.Option(
|
3313
|
+
None,
|
3314
|
+
"--amount",
|
3315
|
+
"-a",
|
3316
|
+
help="Amount of stake to swap",
|
3317
|
+
),
|
3318
|
+
swap_all: bool = typer.Option(
|
3319
|
+
False,
|
3320
|
+
"--swap-all",
|
3321
|
+
"--all",
|
3322
|
+
help="Swap all available stake",
|
3323
|
+
),
|
3324
|
+
prompt: bool = Options.prompt,
|
3325
|
+
wait_for_inclusion: bool = Options.wait_for_inclusion,
|
3326
|
+
wait_for_finalization: bool = Options.wait_for_finalization,
|
3327
|
+
quiet: bool = Options.quiet,
|
3328
|
+
verbose: bool = Options.verbose,
|
3329
|
+
):
|
3330
|
+
"""
|
3331
|
+
Swap stake between different subnets while keeping the same coldkey-hotkey pair ownership.
|
3332
|
+
|
3333
|
+
This command allows you to:
|
3334
|
+
- Move stake from one subnet to another subnet
|
3335
|
+
- Keep the same coldkey ownership
|
3336
|
+
- Keep the same hotkey ownership
|
3337
|
+
|
3338
|
+
You can specify:
|
3339
|
+
- The origin subnet (--origin-netuid)
|
3340
|
+
- The destination subnet (--dest-netuid)
|
3341
|
+
- The amount to swap (--amount)
|
3342
|
+
|
3343
|
+
If no arguments are provided, an interactive selection menu will be shown.
|
3344
|
+
|
3345
|
+
EXAMPLE
|
3346
|
+
|
3347
|
+
Swap 100 TAO from subnet 1 to subnet 2:
|
3348
|
+
[green]$[/green] btcli stake swap --wallet-name default --wallet-hotkey default --origin-netuid 1 --dest-netuid 2 --amount 100
|
3349
|
+
"""
|
3350
|
+
console.print(
|
3351
|
+
"[dim]This command moves stake from one subnet to another subnet while keeping the same coldkey-hotkey pair.[/dim]"
|
3352
|
+
)
|
3353
|
+
self.verbosity_handler(quiet, verbose)
|
3354
|
+
|
3355
|
+
wallet = self.wallet_ask(
|
3356
|
+
wallet_name,
|
3357
|
+
wallet_path,
|
3358
|
+
wallet_hotkey,
|
3359
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3360
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3361
|
+
)
|
3362
|
+
|
3363
|
+
interactive_selection = False
|
3364
|
+
if origin_netuid is None and dest_netuid is None and not amount:
|
3365
|
+
interactive_selection = True
|
3558
3366
|
else:
|
3559
|
-
|
3367
|
+
if origin_netuid is None:
|
3368
|
+
origin_netuid = IntPrompt.ask(
|
3369
|
+
"Enter the [blue]origin subnet[/blue] (netuid)"
|
3370
|
+
)
|
3371
|
+
if dest_netuid is None:
|
3372
|
+
dest_netuid = IntPrompt.ask(
|
3373
|
+
"Enter the [blue]destination subnet[/blue] (netuid)"
|
3374
|
+
)
|
3375
|
+
if not amount and not swap_all:
|
3376
|
+
amount = FloatPrompt.ask("Enter the [blue]amount[/blue] to swap")
|
3560
3377
|
|
3561
3378
|
return self._run_command(
|
3562
|
-
|
3563
|
-
wallet,
|
3564
|
-
self.initialize_chain(network),
|
3565
|
-
|
3566
|
-
|
3567
|
-
|
3568
|
-
|
3569
|
-
|
3570
|
-
|
3571
|
-
|
3572
|
-
|
3379
|
+
move.swap_stake(
|
3380
|
+
wallet=wallet,
|
3381
|
+
subtensor=self.initialize_chain(network),
|
3382
|
+
origin_netuid=origin_netuid,
|
3383
|
+
destination_netuid=dest_netuid,
|
3384
|
+
amount=amount,
|
3385
|
+
swap_all=swap_all,
|
3386
|
+
interactive_selection=interactive_selection,
|
3387
|
+
prompt=prompt,
|
3388
|
+
wait_for_inclusion=wait_for_inclusion,
|
3389
|
+
wait_for_finalization=wait_for_finalization,
|
3573
3390
|
)
|
3574
3391
|
)
|
3575
3392
|
|
@@ -3609,7 +3426,7 @@ class CLIManager:
|
|
3609
3426
|
wallet_name,
|
3610
3427
|
wallet_path,
|
3611
3428
|
wallet_hotkey,
|
3612
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3429
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3613
3430
|
validate=WV.WALLET_AND_HOTKEY,
|
3614
3431
|
)
|
3615
3432
|
|
@@ -3640,18 +3457,8 @@ class CLIManager:
|
|
3640
3457
|
wallet_hotkey: str = Options.wallet_hotkey,
|
3641
3458
|
wallet_path: str = Options.wallet_path,
|
3642
3459
|
network: Optional[list[str]] = Options.network,
|
3643
|
-
netuid: Optional[int] =
|
3644
|
-
|
3645
|
-
help="The netuid of the subnet, (e.g. 4)",
|
3646
|
-
prompt=False,
|
3647
|
-
),
|
3648
|
-
all_netuids: bool = typer.Option(
|
3649
|
-
False,
|
3650
|
-
"--all-netuids",
|
3651
|
-
"--all",
|
3652
|
-
"--allnetuids",
|
3653
|
-
help="When this flag is used it sets child hotkeys on all subnets.",
|
3654
|
-
),
|
3460
|
+
netuid: Optional[int] = Options.netuid_not_req,
|
3461
|
+
all_netuids: bool = Options.all_netuids,
|
3655
3462
|
proportions: list[float] = typer.Option(
|
3656
3463
|
[],
|
3657
3464
|
"--proportions",
|
@@ -3664,10 +3471,9 @@ class CLIManager:
|
|
3664
3471
|
wait_for_finalization: bool = Options.wait_for_finalization,
|
3665
3472
|
quiet: bool = Options.quiet,
|
3666
3473
|
verbose: bool = Options.verbose,
|
3667
|
-
prompt: bool = Options.prompt,
|
3668
3474
|
):
|
3669
3475
|
"""
|
3670
|
-
Set child hotkeys on
|
3476
|
+
Set child hotkeys on specified subnets.
|
3671
3477
|
|
3672
3478
|
Users can specify the 'proportion' to delegate to child hotkeys (ss58 address). The sum of proportions cannot be greater than 1.
|
3673
3479
|
|
@@ -3678,15 +3484,8 @@ class CLIManager:
|
|
3678
3484
|
[green]$[/green] btcli stake child set -c 5FCL3gmjtQV4xxxxuEPEFQVhyyyyqYgNwX7drFLw7MSdBnxP -c 5Hp5dxxxxtGg7pu8dN2btyyyyVA1vELmM9dy8KQv3LxV8PA7 --hotkey default --netuid 1 -p 0.3 -p 0.7
|
3679
3485
|
"""
|
3680
3486
|
self.verbosity_handler(quiet, verbose)
|
3681
|
-
|
3682
|
-
|
3683
|
-
raise typer.Exit()
|
3684
|
-
if all_netuids:
|
3685
|
-
netuid = None
|
3686
|
-
elif not netuid:
|
3687
|
-
netuid = IntPrompt.ask(
|
3688
|
-
"Enter a netuid (leave blank for all)", default=None, show_default=True
|
3689
|
-
)
|
3487
|
+
netuid = get_optional_netuid(netuid, all_netuids)
|
3488
|
+
|
3690
3489
|
children = list_prompt(
|
3691
3490
|
children,
|
3692
3491
|
str,
|
@@ -3711,7 +3510,7 @@ class CLIManager:
|
|
3711
3510
|
wallet_name,
|
3712
3511
|
wallet_path,
|
3713
3512
|
wallet_hotkey,
|
3714
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3513
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3715
3514
|
validate=WV.WALLET_AND_HOTKEY,
|
3716
3515
|
)
|
3717
3516
|
return self._run_command(
|
@@ -3723,7 +3522,6 @@ class CLIManager:
|
|
3723
3522
|
proportions=proportions,
|
3724
3523
|
wait_for_finalization=wait_for_finalization,
|
3725
3524
|
wait_for_inclusion=wait_for_inclusion,
|
3726
|
-
prompt=prompt,
|
3727
3525
|
)
|
3728
3526
|
)
|
3729
3527
|
|
@@ -3749,10 +3547,9 @@ class CLIManager:
|
|
3749
3547
|
wait_for_finalization: bool = Options.wait_for_finalization,
|
3750
3548
|
quiet: bool = Options.quiet,
|
3751
3549
|
verbose: bool = Options.verbose,
|
3752
|
-
prompt: bool = Options.prompt,
|
3753
3550
|
):
|
3754
3551
|
"""
|
3755
|
-
Remove all children hotkeys on a specified subnet
|
3552
|
+
Remove all children hotkeys on a specified subnet.
|
3756
3553
|
|
3757
3554
|
This command is used to remove delegated authority from all child hotkeys, removing their position and influence on the subnet.
|
3758
3555
|
|
@@ -3765,7 +3562,7 @@ class CLIManager:
|
|
3765
3562
|
wallet_name,
|
3766
3563
|
wallet_path,
|
3767
3564
|
wallet_hotkey,
|
3768
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3565
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3769
3566
|
validate=WV.WALLET_AND_HOTKEY,
|
3770
3567
|
)
|
3771
3568
|
if all_netuids and netuid:
|
@@ -3784,7 +3581,6 @@ class CLIManager:
|
|
3784
3581
|
netuid,
|
3785
3582
|
wait_for_inclusion,
|
3786
3583
|
wait_for_finalization,
|
3787
|
-
prompt=prompt,
|
3788
3584
|
)
|
3789
3585
|
)
|
3790
3586
|
|
@@ -3821,153 +3617,308 @@ class CLIManager:
|
|
3821
3617
|
verbose: bool = Options.verbose,
|
3822
3618
|
):
|
3823
3619
|
"""
|
3824
|
-
Get and set your child hotkey take on a specified subnet.
|
3620
|
+
Get and set your child hotkey take on a specified subnet.
|
3621
|
+
|
3622
|
+
The child hotkey take must be between 0 - 18%.
|
3623
|
+
|
3624
|
+
EXAMPLE
|
3625
|
+
|
3626
|
+
To get the current take value, do not use the '--take' option:
|
3627
|
+
|
3628
|
+
[green]$[/green] btcli stake child take --hotkey <child_hotkey> --netuid 1
|
3629
|
+
|
3630
|
+
To set a new take value, use the '--take' option:
|
3631
|
+
|
3632
|
+
[green]$[/green] btcli stake child take --hotkey <child_hotkey> --take 0.12 --netuid 1
|
3633
|
+
"""
|
3634
|
+
self.verbosity_handler(quiet, verbose)
|
3635
|
+
wallet = self.wallet_ask(
|
3636
|
+
wallet_name,
|
3637
|
+
wallet_path,
|
3638
|
+
wallet_hotkey,
|
3639
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3640
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3641
|
+
)
|
3642
|
+
if all_netuids and netuid:
|
3643
|
+
err_console.print("Specify either a netuid or '--all', not both.")
|
3644
|
+
raise typer.Exit()
|
3645
|
+
if all_netuids:
|
3646
|
+
netuid = None
|
3647
|
+
elif not netuid:
|
3648
|
+
netuid = IntPrompt.ask(
|
3649
|
+
"Enter netuid (leave blank for all)", default=None, show_default=True
|
3650
|
+
)
|
3651
|
+
return self._run_command(
|
3652
|
+
children_hotkeys.childkey_take(
|
3653
|
+
wallet=wallet,
|
3654
|
+
subtensor=self.initialize_chain(network),
|
3655
|
+
netuid=netuid,
|
3656
|
+
take=take,
|
3657
|
+
hotkey=hotkey,
|
3658
|
+
wait_for_inclusion=wait_for_inclusion,
|
3659
|
+
wait_for_finalization=wait_for_finalization,
|
3660
|
+
prompt=prompt,
|
3661
|
+
)
|
3662
|
+
)
|
3663
|
+
|
3664
|
+
def sudo_set(
|
3665
|
+
self,
|
3666
|
+
network: Optional[list[str]] = Options.network,
|
3667
|
+
wallet_name: str = Options.wallet_name,
|
3668
|
+
wallet_path: str = Options.wallet_path,
|
3669
|
+
wallet_hotkey: str = Options.wallet_hotkey,
|
3670
|
+
netuid: int = Options.netuid,
|
3671
|
+
param_name: str = typer.Option(
|
3672
|
+
"", "--param", "--parameter", help="The subnet hyperparameter to set"
|
3673
|
+
),
|
3674
|
+
param_value: str = typer.Option(
|
3675
|
+
"", "--value", help="Value to set the hyperparameter to."
|
3676
|
+
),
|
3677
|
+
quiet: bool = Options.quiet,
|
3678
|
+
verbose: bool = Options.verbose,
|
3679
|
+
):
|
3680
|
+
"""
|
3681
|
+
Used to set hyperparameters for a specific subnet.
|
3682
|
+
|
3683
|
+
This command allows subnet owners to modify hyperparameters such as its tempo, emission rates, and other hyperparameters.
|
3684
|
+
|
3685
|
+
EXAMPLE
|
3686
|
+
|
3687
|
+
[green]$[/green] btcli sudo set --netuid 1 --param tempo --value 400
|
3688
|
+
"""
|
3689
|
+
self.verbosity_handler(quiet, verbose)
|
3690
|
+
|
3691
|
+
hyperparams = self._run_command(
|
3692
|
+
sudo.get_hyperparameters(self.initialize_chain(network), netuid),
|
3693
|
+
exit_early=False,
|
3694
|
+
)
|
3695
|
+
|
3696
|
+
if not hyperparams:
|
3697
|
+
raise typer.Exit()
|
3698
|
+
|
3699
|
+
if not param_name:
|
3700
|
+
hyperparam_list = [field.name for field in fields(SubnetHyperparameters)]
|
3701
|
+
console.print("Available hyperparameters:\n")
|
3702
|
+
for idx, param in enumerate(hyperparam_list, start=1):
|
3703
|
+
console.print(f" {idx}. {param}")
|
3704
|
+
console.print()
|
3705
|
+
choice = IntPrompt.ask(
|
3706
|
+
"Enter the [bold]number[/bold] of the hyperparameter",
|
3707
|
+
choices=[str(i) for i in range(1, len(hyperparam_list) + 1)],
|
3708
|
+
show_choices=False,
|
3709
|
+
)
|
3710
|
+
param_name = hyperparam_list[choice - 1]
|
3711
|
+
|
3712
|
+
if not param_value:
|
3713
|
+
param_value = Prompt.ask(
|
3714
|
+
f"Enter the new value for [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{param_name}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] in the VALUE column format"
|
3715
|
+
)
|
3716
|
+
|
3717
|
+
wallet = self.wallet_ask(
|
3718
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3719
|
+
)
|
3720
|
+
return self._run_command(
|
3721
|
+
sudo.sudo_set_hyperparameter(
|
3722
|
+
wallet,
|
3723
|
+
self.initialize_chain(network),
|
3724
|
+
netuid,
|
3725
|
+
param_name,
|
3726
|
+
param_value,
|
3727
|
+
)
|
3728
|
+
)
|
3729
|
+
|
3730
|
+
def sudo_get(
|
3731
|
+
self,
|
3732
|
+
network: Optional[list[str]] = Options.network,
|
3733
|
+
netuid: int = Options.netuid,
|
3734
|
+
quiet: bool = Options.quiet,
|
3735
|
+
verbose: bool = Options.verbose,
|
3736
|
+
):
|
3737
|
+
"""
|
3738
|
+
Shows a list of the hyperparameters for the specified subnet.
|
3739
|
+
|
3740
|
+
The output of this command is the same as that of `btcli subnets hyperparameters`.
|
3741
|
+
|
3742
|
+
EXAMPLE
|
3743
|
+
|
3744
|
+
[green]$[/green] btcli sudo get --netuid 1
|
3745
|
+
"""
|
3746
|
+
self.verbosity_handler(quiet, verbose)
|
3747
|
+
return self._run_command(
|
3748
|
+
sudo.get_hyperparameters(self.initialize_chain(network), netuid)
|
3749
|
+
)
|
3750
|
+
|
3751
|
+
def sudo_senate(
|
3752
|
+
self,
|
3753
|
+
network: Optional[list[str]] = Options.network,
|
3754
|
+
quiet: bool = Options.quiet,
|
3755
|
+
verbose: bool = Options.verbose,
|
3756
|
+
):
|
3757
|
+
"""
|
3758
|
+
Shows the Senate members of the Bittensor's governance protocol.
|
3759
|
+
|
3760
|
+
This command lists the delegates involved in the decision-making process of the Bittensor network, showing their names and wallet addresses. This information is crucial for understanding who holds governance roles within the network.
|
3761
|
+
|
3762
|
+
EXAMPLE
|
3763
|
+
[green]$[/green] btcli sudo senate
|
3764
|
+
"""
|
3765
|
+
self.verbosity_handler(quiet, verbose)
|
3766
|
+
return self._run_command(sudo.get_senate(self.initialize_chain(network)))
|
3767
|
+
|
3768
|
+
def sudo_proposals(
|
3769
|
+
self,
|
3770
|
+
network: Optional[list[str]] = Options.network,
|
3771
|
+
quiet: bool = Options.quiet,
|
3772
|
+
verbose: bool = Options.verbose,
|
3773
|
+
):
|
3774
|
+
"""
|
3775
|
+
View active proposals for the senate in the Bittensor's governance protocol.
|
3825
3776
|
|
3826
|
-
|
3777
|
+
This command displays the details of ongoing proposals, including proposal hashes, votes, thresholds, and proposal data.
|
3827
3778
|
|
3828
3779
|
EXAMPLE
|
3780
|
+
[green]$[/green] btcli sudo proposals
|
3781
|
+
"""
|
3782
|
+
self.verbosity_handler(quiet, verbose)
|
3783
|
+
return self._run_command(sudo.proposals(self.initialize_chain(network)))
|
3829
3784
|
|
3830
|
-
|
3785
|
+
def sudo_senate_vote(
|
3786
|
+
self,
|
3787
|
+
network: Optional[list[str]] = Options.network,
|
3788
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
3789
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
3790
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3791
|
+
proposal: str = typer.Option(
|
3792
|
+
None,
|
3793
|
+
"--proposal",
|
3794
|
+
"--proposal-hash",
|
3795
|
+
prompt="Enter the proposal hash",
|
3796
|
+
help="The hash of the proposal to vote on.",
|
3797
|
+
),
|
3798
|
+
prompt: bool = Options.prompt,
|
3799
|
+
quiet: bool = Options.quiet,
|
3800
|
+
verbose: bool = Options.verbose,
|
3801
|
+
vote: bool = typer.Option(
|
3802
|
+
None,
|
3803
|
+
"--vote-aye/--vote-nay",
|
3804
|
+
prompt="Enter y to vote Aye, or enter n to vote Nay",
|
3805
|
+
help="The vote casted on the proposal",
|
3806
|
+
),
|
3807
|
+
):
|
3808
|
+
"""
|
3809
|
+
Cast a vote on an active proposal in Bittensor's governance protocol.
|
3831
3810
|
|
3832
|
-
|
3811
|
+
This command is used by Senate members to vote on various proposals that shape the network's future. Use `btcli sudo proposals` to see the active proposals and their hashes.
|
3833
3812
|
|
3834
|
-
|
3813
|
+
USAGE
|
3814
|
+
The user must specify the hash of the proposal they want to vote on. The command then allows the Senate member to cast a 'Yes' or 'No' vote, contributing to the decision-making process on the proposal. This command is crucial for Senate members to exercise their voting rights on key proposals. It plays a vital role in the governance and evolution of the Bittensor network.
|
3835
3815
|
|
3836
|
-
|
3816
|
+
EXAMPLE
|
3817
|
+
[green]$[/green] btcli sudo senate_vote --proposal <proposal_hash>
|
3837
3818
|
"""
|
3838
3819
|
self.verbosity_handler(quiet, verbose)
|
3839
3820
|
wallet = self.wallet_ask(
|
3840
3821
|
wallet_name,
|
3841
3822
|
wallet_path,
|
3842
3823
|
wallet_hotkey,
|
3843
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3824
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3844
3825
|
validate=WV.WALLET_AND_HOTKEY,
|
3845
3826
|
)
|
3846
|
-
if all_netuids and netuid:
|
3847
|
-
err_console.print("Specify either a netuid or '--all', not both.")
|
3848
|
-
raise typer.Exit()
|
3849
|
-
if all_netuids:
|
3850
|
-
netuid = None
|
3851
|
-
elif not netuid:
|
3852
|
-
netuid = IntPrompt.ask(
|
3853
|
-
"Enter netuid (leave blank for all)", default=None, show_default=True
|
3854
|
-
)
|
3855
3827
|
return self._run_command(
|
3856
|
-
|
3857
|
-
wallet
|
3858
|
-
subtensor=self.initialize_chain(network),
|
3859
|
-
netuid=netuid,
|
3860
|
-
take=take,
|
3861
|
-
hotkey=hotkey,
|
3862
|
-
wait_for_inclusion=wait_for_inclusion,
|
3863
|
-
wait_for_finalization=wait_for_finalization,
|
3864
|
-
prompt=prompt,
|
3828
|
+
sudo.senate_vote(
|
3829
|
+
wallet, self.initialize_chain(network), proposal, vote, prompt
|
3865
3830
|
)
|
3866
3831
|
)
|
3867
3832
|
|
3868
|
-
def
|
3833
|
+
def sudo_set_take(
|
3869
3834
|
self,
|
3870
3835
|
network: Optional[list[str]] = Options.network,
|
3871
|
-
wallet_name: str = Options.wallet_name,
|
3872
|
-
wallet_path: str = Options.wallet_path,
|
3873
|
-
wallet_hotkey: str = Options.wallet_hotkey,
|
3874
|
-
|
3875
|
-
param_name: str = typer.Option(
|
3876
|
-
"", "--param", "--parameter", help="The subnet hyperparameter to set"
|
3877
|
-
),
|
3878
|
-
param_value: str = typer.Option(
|
3879
|
-
"", "--value", help="Value to set the hyperparameter to."
|
3880
|
-
),
|
3836
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
3837
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
3838
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3839
|
+
take: float = typer.Option(None, help="The new take value."),
|
3881
3840
|
quiet: bool = Options.quiet,
|
3882
3841
|
verbose: bool = Options.verbose,
|
3883
3842
|
):
|
3884
3843
|
"""
|
3885
|
-
|
3844
|
+
Allows users to change their delegate take percentage.
|
3886
3845
|
|
3887
|
-
This command
|
3846
|
+
This command can be used to update the delegate takes. To run the command, the user must have a configured wallet with both hotkey and coldkey.
|
3847
|
+
The command makes sure the new take value is within 0-18% range.
|
3888
3848
|
|
3889
3849
|
EXAMPLE
|
3890
|
-
|
3891
|
-
[green]$[/green] btcli sudo set --netuid 1 --param tempo --value 400
|
3850
|
+
[green]$[/green] btcli sudo set-take --wallet-name my_wallet --wallet-hotkey my_hotkey
|
3892
3851
|
"""
|
3852
|
+
max_value = 0.18
|
3853
|
+
min_value = 0.00
|
3893
3854
|
self.verbosity_handler(quiet, verbose)
|
3894
3855
|
|
3895
|
-
|
3896
|
-
|
3897
|
-
|
3898
|
-
|
3899
|
-
|
3900
|
-
|
3856
|
+
wallet = self.wallet_ask(
|
3857
|
+
wallet_name,
|
3858
|
+
wallet_path,
|
3859
|
+
wallet_hotkey,
|
3860
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3861
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3862
|
+
)
|
3901
3863
|
|
3902
|
-
|
3903
|
-
|
3904
|
-
|
3905
|
-
|
3906
|
-
console.print(f" {idx}. {param}")
|
3907
|
-
console.print()
|
3908
|
-
choice = IntPrompt.ask(
|
3909
|
-
"Enter the [bold]number[/bold] of the hyperparameter",
|
3910
|
-
choices=[str(i) for i in range(1, len(hyperparam_list) + 1)],
|
3911
|
-
show_choices=False,
|
3912
|
-
)
|
3913
|
-
param_name = hyperparam_list[choice - 1]
|
3864
|
+
self._run_command(
|
3865
|
+
sudo.display_current_take(self.initialize_chain(network), wallet),
|
3866
|
+
exit_early=False,
|
3867
|
+
)
|
3914
3868
|
|
3915
|
-
if
|
3916
|
-
|
3917
|
-
|
3918
|
-
"Enter the new value for [dark_orange]alpha_low[/dark_orange]"
|
3919
|
-
)
|
3920
|
-
high_val = FloatPrompt.ask(
|
3921
|
-
"Enter the new value for [dark_orange]alpha_high[/dark_orange]"
|
3869
|
+
if not take:
|
3870
|
+
take = FloatPrompt.ask(
|
3871
|
+
f"Enter [blue]take value[/blue] (0.18 for 18%) [blue]Min: {min_value} Max: {max_value}"
|
3922
3872
|
)
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
param_value = Prompt.ask(
|
3927
|
-
f"Enter the new value for [dark_orange]{param_name}[/dark_orange] in the VALUE column format"
|
3873
|
+
if not (min_value <= take <= max_value):
|
3874
|
+
print_error(
|
3875
|
+
f"Take value must be between {min_value} and {max_value}. Provided value: {take}"
|
3928
3876
|
)
|
3877
|
+
raise typer.Exit()
|
3929
3878
|
|
3930
|
-
wallet = self.wallet_ask(
|
3931
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
3932
|
-
)
|
3933
3879
|
return self._run_command(
|
3934
|
-
sudo.
|
3935
|
-
wallet,
|
3936
|
-
self.initialize_chain(network),
|
3937
|
-
netuid,
|
3938
|
-
param_name,
|
3939
|
-
param_value,
|
3940
|
-
)
|
3880
|
+
sudo.set_take(wallet, self.initialize_chain(network), take)
|
3941
3881
|
)
|
3942
3882
|
|
3943
|
-
def
|
3883
|
+
def sudo_get_take(
|
3944
3884
|
self,
|
3945
3885
|
network: Optional[list[str]] = Options.network,
|
3946
|
-
|
3886
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
3887
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
3888
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3947
3889
|
quiet: bool = Options.quiet,
|
3948
3890
|
verbose: bool = Options.verbose,
|
3949
3891
|
):
|
3950
3892
|
"""
|
3951
|
-
|
3893
|
+
Allows users to check their delegate take percentage.
|
3952
3894
|
|
3953
|
-
|
3895
|
+
This command can be used to fetch the delegate take of your hotkey.
|
3954
3896
|
|
3955
3897
|
EXAMPLE
|
3956
|
-
|
3957
|
-
[green]$[/green] btcli sudo get --netuid 1
|
3898
|
+
[green]$[/green] btcli sudo get-take --wallet-name my_wallet --wallet-hotkey my_hotkey
|
3958
3899
|
"""
|
3959
3900
|
self.verbosity_handler(quiet, verbose)
|
3960
|
-
|
3961
|
-
|
3901
|
+
|
3902
|
+
wallet = self.wallet_ask(
|
3903
|
+
wallet_name,
|
3904
|
+
wallet_path,
|
3905
|
+
wallet_hotkey,
|
3906
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3907
|
+
validate=WV.WALLET_AND_HOTKEY,
|
3908
|
+
)
|
3909
|
+
|
3910
|
+
self._run_command(
|
3911
|
+
sudo.display_current_take(self.initialize_chain(network), wallet)
|
3962
3912
|
)
|
3963
3913
|
|
3964
3914
|
def subnets_list(
|
3965
3915
|
self,
|
3966
3916
|
network: Optional[list[str]] = Options.network,
|
3967
|
-
reuse_last: bool = Options.reuse_last,
|
3968
|
-
html_output: bool = Options.html_output,
|
3917
|
+
# reuse_last: bool = Options.reuse_last,
|
3918
|
+
# html_output: bool = Options.html_output,
|
3969
3919
|
quiet: bool = Options.quiet,
|
3970
3920
|
verbose: bool = Options.verbose,
|
3921
|
+
live_mode: bool = Options.live,
|
3971
3922
|
):
|
3972
3923
|
"""
|
3973
3924
|
List all subnets and their detailed information.
|
@@ -3988,48 +3939,189 @@ class CLIManager:
|
|
3988
3939
|
[green]$[/green] btcli subnets list
|
3989
3940
|
"""
|
3990
3941
|
self.verbosity_handler(quiet, verbose)
|
3991
|
-
if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
3992
|
-
|
3993
|
-
|
3994
|
-
|
3995
|
-
|
3996
|
-
|
3997
|
-
if reuse_last:
|
3998
|
-
|
3999
|
-
else:
|
4000
|
-
|
3942
|
+
# if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
3943
|
+
# err_console.print(
|
3944
|
+
# "Unable to use `--reuse-last` or `--html` when config 'no-cache' is set to 'True'. "
|
3945
|
+
# "Change the config to 'False' using `btcli config set`."
|
3946
|
+
# )
|
3947
|
+
# raise typer.Exit()
|
3948
|
+
# if reuse_last:
|
3949
|
+
# subtensor = None
|
3950
|
+
# else:
|
3951
|
+
subtensor = self.initialize_chain(network)
|
4001
3952
|
return self._run_command(
|
4002
3953
|
subnets.subnets_list(
|
4003
3954
|
subtensor,
|
4004
|
-
|
4005
|
-
|
3955
|
+
False, # reuse-last
|
3956
|
+
False, # html-output
|
4006
3957
|
not self.config.get("use_cache", True),
|
3958
|
+
verbose,
|
3959
|
+
live_mode,
|
3960
|
+
)
|
3961
|
+
)
|
3962
|
+
|
3963
|
+
def subnets_price(
|
3964
|
+
self,
|
3965
|
+
network: Optional[list[str]] = Options.network,
|
3966
|
+
netuids: str = typer.Option(
|
3967
|
+
None,
|
3968
|
+
"--netuids",
|
3969
|
+
"--netuid",
|
3970
|
+
"-n",
|
3971
|
+
help="Netuid(s) to show the price for.",
|
3972
|
+
),
|
3973
|
+
interval_hours: int = typer.Option(
|
3974
|
+
24,
|
3975
|
+
"--interval-hours",
|
3976
|
+
"--interval",
|
3977
|
+
help="The number of hours to show the historical price for.",
|
3978
|
+
),
|
3979
|
+
all_netuids: bool = typer.Option(
|
3980
|
+
False,
|
3981
|
+
"--all-netuids",
|
3982
|
+
"--all",
|
3983
|
+
help="Show the price for all subnets.",
|
3984
|
+
),
|
3985
|
+
log_scale: bool = typer.Option(
|
3986
|
+
False,
|
3987
|
+
"--log-scale",
|
3988
|
+
"--log",
|
3989
|
+
help="Show the price in log scale.",
|
3990
|
+
),
|
3991
|
+
html_output: bool = Options.html_output,
|
3992
|
+
):
|
3993
|
+
"""
|
3994
|
+
Shows the historical price of a subnet for the past 24 hours.
|
3995
|
+
|
3996
|
+
This command displays the historical price of a subnet for the past 24 hours.
|
3997
|
+
If the `--all` flag is used, the command will display the price for all subnets in html format.
|
3998
|
+
If the `--html` flag is used, the command will display the price in an HTML chart.
|
3999
|
+
If the `--log-scale` flag is used, the command will display the price in log scale.
|
4000
|
+
If no html flag is used, the command will display the price in the cli.
|
4001
|
+
|
4002
|
+
EXAMPLE
|
4003
|
+
|
4004
|
+
[green]$[/green] btcli subnets price --netuid 1
|
4005
|
+
[green]$[/green] btcli subnets price --netuid 1 --html --log
|
4006
|
+
[green]$[/green] btcli subnets price --all --html
|
4007
|
+
[green]$[/green] btcli subnets price --netuids 1,2,3,4 --html
|
4008
|
+
"""
|
4009
|
+
if netuids:
|
4010
|
+
netuids = parse_to_list(
|
4011
|
+
netuids,
|
4012
|
+
int,
|
4013
|
+
"Netuids must be a comma-separated list of ints, e.g., `--netuids 1,2,3,4`.",
|
4014
|
+
)
|
4015
|
+
if all_netuids and netuids:
|
4016
|
+
print_error("Cannot specify both --netuid and --all-netuids")
|
4017
|
+
raise typer.Exit()
|
4018
|
+
|
4019
|
+
if not netuids and not all_netuids:
|
4020
|
+
netuids = Prompt.ask(
|
4021
|
+
"Enter the [blue]netuid(s)[/blue] to view the price of in comma-separated format [dim](or Press Enter to view all subnets)[/dim]",
|
4022
|
+
)
|
4023
|
+
if not netuids:
|
4024
|
+
all_netuids = True
|
4025
|
+
html_output = True
|
4026
|
+
else:
|
4027
|
+
netuids = parse_to_list(
|
4028
|
+
netuids,
|
4029
|
+
int,
|
4030
|
+
"Netuids must be a comma-separated list of ints, e.g., `--netuids 1,2,3,4`.",
|
4031
|
+
)
|
4032
|
+
|
4033
|
+
if all_netuids:
|
4034
|
+
html_output = True
|
4035
|
+
|
4036
|
+
if html_output and is_linux():
|
4037
|
+
print_linux_dependency_message()
|
4038
|
+
|
4039
|
+
return self._run_command(
|
4040
|
+
price.price(
|
4041
|
+
self.initialize_chain(network),
|
4042
|
+
netuids,
|
4043
|
+
all_netuids,
|
4044
|
+
interval_hours,
|
4045
|
+
html_output,
|
4046
|
+
log_scale,
|
4047
|
+
)
|
4048
|
+
)
|
4049
|
+
|
4050
|
+
def subnets_show(
|
4051
|
+
self,
|
4052
|
+
network: Optional[list[str]] = Options.network,
|
4053
|
+
netuid: int = Options.netuid,
|
4054
|
+
quiet: bool = Options.quiet,
|
4055
|
+
verbose: bool = Options.verbose,
|
4056
|
+
prompt: bool = Options.prompt,
|
4057
|
+
):
|
4058
|
+
"""
|
4059
|
+
Displays detailed information about a subnet including participants and their state.
|
4060
|
+
|
4061
|
+
EXAMPLE
|
4062
|
+
|
4063
|
+
[green]$[/green] btcli subnets list
|
4064
|
+
"""
|
4065
|
+
self.verbosity_handler(quiet, verbose)
|
4066
|
+
subtensor = self.initialize_chain(network)
|
4067
|
+
return self._run_command(
|
4068
|
+
subnets.show(
|
4069
|
+
subtensor,
|
4070
|
+
netuid,
|
4071
|
+
verbose=verbose,
|
4072
|
+
prompt=prompt,
|
4007
4073
|
)
|
4008
4074
|
)
|
4009
4075
|
|
4010
|
-
def
|
4076
|
+
def subnets_burn_cost(
|
4011
4077
|
self,
|
4012
4078
|
network: Optional[list[str]] = Options.network,
|
4013
4079
|
quiet: bool = Options.quiet,
|
4014
4080
|
verbose: bool = Options.verbose,
|
4015
4081
|
):
|
4016
4082
|
"""
|
4017
|
-
Shows the required amount of TAO to be
|
4083
|
+
Shows the required amount of TAO to be recycled for creating a new subnet, i.e., cost of registering a new subnet.
|
4018
4084
|
|
4019
4085
|
The current implementation anneals the cost of creating a subnet over a period of two days. If the displayed cost is unappealing to you, check back in a day or two to see if it has decreased to a more affordable level.
|
4020
4086
|
|
4021
4087
|
EXAMPLE
|
4022
4088
|
|
4023
|
-
[green]$[/green] btcli subnets
|
4089
|
+
[green]$[/green] btcli subnets burn_cost
|
4024
4090
|
"""
|
4025
4091
|
self.verbosity_handler(quiet, verbose)
|
4026
|
-
return self._run_command(subnets.
|
4092
|
+
return self._run_command(subnets.burn_cost(self.initialize_chain(network)))
|
4027
4093
|
|
4028
4094
|
def subnets_create(
|
4029
4095
|
self,
|
4030
4096
|
wallet_name: str = Options.wallet_name,
|
4031
4097
|
wallet_path: str = Options.wallet_path,
|
4098
|
+
wallet_hotkey: str = Options.wallet_hotkey,
|
4032
4099
|
network: Optional[list[str]] = Options.network,
|
4100
|
+
subnet_name: Optional[str] = typer.Option(
|
4101
|
+
None, "--subnet-name", "--name", help="Name of the subnet"
|
4102
|
+
),
|
4103
|
+
github_repo: Optional[str] = typer.Option(
|
4104
|
+
None, "--github-repo", "--repo", help="GitHub repository URL"
|
4105
|
+
),
|
4106
|
+
subnet_contact: Optional[str] = typer.Option(
|
4107
|
+
None,
|
4108
|
+
"--subnet-contact",
|
4109
|
+
"--contact",
|
4110
|
+
"--email",
|
4111
|
+
help="Contact email for subnet",
|
4112
|
+
),
|
4113
|
+
subnet_url: Optional[str] = typer.Option(
|
4114
|
+
None, "--subnet-url", "--url", help="Subnet URL"
|
4115
|
+
),
|
4116
|
+
discord: Optional[str] = typer.Option(
|
4117
|
+
None, "--discord-handle", "--discord", help="Discord handle"
|
4118
|
+
),
|
4119
|
+
description: Optional[str] = typer.Option(
|
4120
|
+
None, "--description", help="Description"
|
4121
|
+
),
|
4122
|
+
additional_info: Optional[str] = typer.Option(
|
4123
|
+
None, "--additional-info", help="Additional information"
|
4124
|
+
),
|
4033
4125
|
prompt: bool = Options.prompt,
|
4034
4126
|
quiet: bool = Options.quiet,
|
4035
4127
|
verbose: bool = Options.verbose,
|
@@ -4045,13 +4137,44 @@ class CLIManager:
|
|
4045
4137
|
wallet = self.wallet_ask(
|
4046
4138
|
wallet_name,
|
4047
4139
|
wallet_path,
|
4048
|
-
|
4049
|
-
ask_for=[
|
4050
|
-
|
4140
|
+
wallet_hotkey,
|
4141
|
+
ask_for=[
|
4142
|
+
WO.NAME,
|
4143
|
+
WO.HOTKEY,
|
4144
|
+
WO.PATH,
|
4145
|
+
],
|
4146
|
+
validate=WV.WALLET_AND_HOTKEY,
|
4051
4147
|
)
|
4052
|
-
|
4053
|
-
|
4148
|
+
identity = prompt_for_subnet_identity(
|
4149
|
+
subnet_name=subnet_name,
|
4150
|
+
github_repo=github_repo,
|
4151
|
+
subnet_contact=subnet_contact,
|
4152
|
+
subnet_url=subnet_url,
|
4153
|
+
discord=discord,
|
4154
|
+
description=description,
|
4155
|
+
additional=additional_info,
|
4054
4156
|
)
|
4157
|
+
success = self._run_command(
|
4158
|
+
subnets.create(wallet, self.initialize_chain(network), identity, prompt),
|
4159
|
+
exit_early=False,
|
4160
|
+
)
|
4161
|
+
|
4162
|
+
if success and prompt:
|
4163
|
+
set_id = Confirm.ask(
|
4164
|
+
"[dark_sea_green3]Do you want to set/update your identity?",
|
4165
|
+
default=False,
|
4166
|
+
show_default=True,
|
4167
|
+
)
|
4168
|
+
if set_id:
|
4169
|
+
self.wallet_set_id(
|
4170
|
+
wallet_name=wallet.name,
|
4171
|
+
wallet_hotkey=wallet.hotkey,
|
4172
|
+
wallet_path=wallet.path,
|
4173
|
+
network=network,
|
4174
|
+
prompt=prompt,
|
4175
|
+
quiet=quiet,
|
4176
|
+
verbose=verbose,
|
4177
|
+
)
|
4055
4178
|
|
4056
4179
|
def subnets_pow_register(
|
4057
4180
|
self,
|
@@ -4100,7 +4223,6 @@ class CLIManager:
|
|
4100
4223
|
"-tbp",
|
4101
4224
|
help="Set the number of threads per block for CUDA.",
|
4102
4225
|
),
|
4103
|
-
prompt: bool = Options.prompt,
|
4104
4226
|
):
|
4105
4227
|
"""
|
4106
4228
|
Register a neuron (a subnet validator or a subnet miner) using Proof of Work (POW).
|
@@ -4126,7 +4248,7 @@ class CLIManager:
|
|
4126
4248
|
wallet_name,
|
4127
4249
|
wallet_path,
|
4128
4250
|
wallet_hotkey,
|
4129
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4251
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4130
4252
|
validate=WV.WALLET_AND_HOTKEY,
|
4131
4253
|
),
|
4132
4254
|
self.initialize_chain(network),
|
@@ -4138,7 +4260,6 @@ class CLIManager:
|
|
4138
4260
|
use_cuda,
|
4139
4261
|
dev_id,
|
4140
4262
|
threads_per_block,
|
4141
|
-
prompt=prompt,
|
4142
4263
|
)
|
4143
4264
|
)
|
4144
4265
|
|
@@ -4169,7 +4290,7 @@ class CLIManager:
|
|
4169
4290
|
wallet_name,
|
4170
4291
|
wallet_path,
|
4171
4292
|
wallet_hotkey,
|
4172
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4293
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4173
4294
|
validate=WV.WALLET_AND_HOTKEY,
|
4174
4295
|
)
|
4175
4296
|
return self._run_command(
|
@@ -4255,6 +4376,12 @@ class CLIManager:
|
|
4255
4376
|
)
|
4256
4377
|
raise typer.Exit()
|
4257
4378
|
|
4379
|
+
# For Rao games
|
4380
|
+
effective_network = get_effective_network(self.config, network)
|
4381
|
+
if is_rao_network(effective_network):
|
4382
|
+
print_error("This command is disabled on the 'rao' network.")
|
4383
|
+
raise typer.Exit()
|
4384
|
+
|
4258
4385
|
if reuse_last:
|
4259
4386
|
if netuid is not None:
|
4260
4387
|
console.print("Cannot specify netuid when using `--reuse-last`")
|
@@ -4298,7 +4425,6 @@ class CLIManager:
|
|
4298
4425
|
),
|
4299
4426
|
quiet: bool = Options.quiet,
|
4300
4427
|
verbose: bool = Options.verbose,
|
4301
|
-
prompt: bool = Options.prompt,
|
4302
4428
|
):
|
4303
4429
|
"""
|
4304
4430
|
Reveal weights for a specific subnet.
|
@@ -4357,7 +4483,7 @@ class CLIManager:
|
|
4357
4483
|
wallet_name,
|
4358
4484
|
wallet_path,
|
4359
4485
|
wallet_hotkey,
|
4360
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4486
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4361
4487
|
validate=WV.WALLET_AND_HOTKEY,
|
4362
4488
|
)
|
4363
4489
|
|
@@ -4370,7 +4496,6 @@ class CLIManager:
|
|
4370
4496
|
weights,
|
4371
4497
|
salt,
|
4372
4498
|
__version_as_int__,
|
4373
|
-
prompt=prompt,
|
4374
4499
|
)
|
4375
4500
|
)
|
4376
4501
|
|
@@ -4396,7 +4521,6 @@ class CLIManager:
|
|
4396
4521
|
),
|
4397
4522
|
quiet: bool = Options.quiet,
|
4398
4523
|
verbose: bool = Options.verbose,
|
4399
|
-
prompt: bool = Options.prompt,
|
4400
4524
|
):
|
4401
4525
|
"""
|
4402
4526
|
|
@@ -4455,7 +4579,7 @@ class CLIManager:
|
|
4455
4579
|
wallet_name,
|
4456
4580
|
wallet_path,
|
4457
4581
|
wallet_hotkey,
|
4458
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4582
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4459
4583
|
validate=WV.WALLET_AND_HOTKEY,
|
4460
4584
|
)
|
4461
4585
|
return self._run_command(
|
@@ -4467,7 +4591,6 @@ class CLIManager:
|
|
4467
4591
|
weights,
|
4468
4592
|
salt,
|
4469
4593
|
__version_as_int__,
|
4470
|
-
prompt=prompt,
|
4471
4594
|
)
|
4472
4595
|
)
|
4473
4596
|
|