bittensor-cli 8.4.2__py3-none-any.whl → 9.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bittensor_cli/__init__.py +2 -2
- bittensor_cli/cli.py +1503 -1372
- bittensor_cli/src/__init__.py +625 -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 +123 -91
- 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 +2043 -0
- bittensor_cli/src/commands/sudo.py +529 -26
- bittensor_cli/src/commands/wallets.py +231 -535
- bittensor_cli/src/commands/weights.py +15 -11
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.dist-info}/METADATA +7 -4
- bittensor_cli-9.0.0rc1.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.2.dist-info/RECORD +0 -31
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.dist-info}/WHEEL +0 -0
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.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.0rc1"
|
62
69
|
|
63
70
|
|
64
71
|
_core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0)
|
@@ -127,6 +134,8 @@ 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(
|
@@ -162,6 +171,17 @@ class Options:
|
|
162
171
|
None,
|
163
172
|
help="The netuid of the subnet in the root network, (e.g. 1).",
|
164
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,
|
165
185
|
)
|
166
186
|
weights = typer.Option(
|
167
187
|
None,
|
@@ -207,6 +227,17 @@ class Options:
|
|
207
227
|
"--quiet",
|
208
228
|
help="Display only critical information on the console.",
|
209
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
|
+
)
|
210
241
|
|
211
242
|
|
212
243
|
def list_prompt(init_var: list, list_type: type, help_text: str) -> list:
|
@@ -249,7 +280,8 @@ def parse_to_list(
|
|
249
280
|
def verbosity_console_handler(verbosity_level: int = 1) -> None:
|
250
281
|
"""
|
251
282
|
Sets verbosity level of console output
|
252
|
-
: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)
|
253
285
|
"""
|
254
286
|
if verbosity_level not in range(3):
|
255
287
|
raise ValueError(
|
@@ -269,6 +301,32 @@ def verbosity_console_handler(verbosity_level: int = 1) -> None:
|
|
269
301
|
verbose_console.quiet = False
|
270
302
|
|
271
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
|
+
|
272
330
|
def get_n_words(n_words: Optional[int]) -> int:
|
273
331
|
"""
|
274
332
|
Prompts the user to select the number of words used in the mnemonic if not supplied or not within the
|
@@ -418,12 +476,21 @@ def version_callback(value: bool):
|
|
418
476
|
raise typer.Exit()
|
419
477
|
|
420
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
|
+
|
421
489
|
class CLIManager:
|
422
490
|
"""
|
423
491
|
:var app: the main CLI Typer app
|
424
492
|
:var config_app: the Typer app as it relates to config commands
|
425
493
|
:var wallet_app: the Typer app as it relates to wallet commands
|
426
|
-
:var root_app: the Typer app as it relates to root commands
|
427
494
|
:var stake_app: the Typer app as it relates to stake commands
|
428
495
|
:var sudo_app: the Typer app as it relates to sudo commands
|
429
496
|
:var subnets_app: the Typer app as it relates to subnets commands
|
@@ -434,7 +501,6 @@ class CLIManager:
|
|
434
501
|
app: typer.Typer
|
435
502
|
config_app: typer.Typer
|
436
503
|
wallet_app: typer.Typer
|
437
|
-
root_app: typer.Typer
|
438
504
|
subnets_app: typer.Typer
|
439
505
|
weights_app: typer.Typer
|
440
506
|
utils_app = typer.Typer(epilog=_epilog)
|
@@ -448,7 +514,9 @@ class CLIManager:
|
|
448
514
|
"use_cache": True,
|
449
515
|
"metagraph_cols": {
|
450
516
|
"UID": True,
|
451
|
-
"
|
517
|
+
"GLOBAL_STAKE": True,
|
518
|
+
"LOCAL_STAKE": True,
|
519
|
+
"STAKE_WEIGHT": True,
|
452
520
|
"RANK": True,
|
453
521
|
"TRUST": True,
|
454
522
|
"CONSENSUS": True,
|
@@ -476,7 +544,6 @@ class CLIManager:
|
|
476
544
|
)
|
477
545
|
self.config_app = typer.Typer(epilog=_epilog)
|
478
546
|
self.wallet_app = typer.Typer(epilog=_epilog)
|
479
|
-
self.root_app = typer.Typer(epilog=_epilog)
|
480
547
|
self.stake_app = typer.Typer(epilog=_epilog)
|
481
548
|
self.sudo_app = typer.Typer(epilog=_epilog)
|
482
549
|
self.subnets_app = typer.Typer(epilog=_epilog)
|
@@ -506,15 +573,6 @@ class CLIManager:
|
|
506
573
|
self.wallet_app, name="wallets", hidden=True, no_args_is_help=True
|
507
574
|
)
|
508
575
|
|
509
|
-
# root aliases
|
510
|
-
self.app.add_typer(
|
511
|
-
self.root_app,
|
512
|
-
name="root",
|
513
|
-
short_help="Root commands, alias: `r`",
|
514
|
-
no_args_is_help=True,
|
515
|
-
)
|
516
|
-
self.app.add_typer(self.root_app, name="r", hidden=True, no_args_is_help=True)
|
517
|
-
|
518
576
|
# stake aliases
|
519
577
|
self.app.add_typer(
|
520
578
|
self.stake_app,
|
@@ -563,7 +621,9 @@ class CLIManager:
|
|
563
621
|
)
|
564
622
|
|
565
623
|
# utils app
|
566
|
-
self.app.add_typer(
|
624
|
+
self.app.add_typer(
|
625
|
+
self.utils_app, name="utils", no_args_is_help=True, hidden=True
|
626
|
+
)
|
567
627
|
|
568
628
|
# config commands
|
569
629
|
self.config_app.command("set")(self.set_config)
|
@@ -600,16 +660,21 @@ class CLIManager:
|
|
600
660
|
"balance", rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"]
|
601
661
|
)(self.wallet_balance)
|
602
662
|
self.wallet_app.command(
|
603
|
-
"history",
|
663
|
+
"history",
|
664
|
+
rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
|
665
|
+
hidden=True,
|
604
666
|
)(self.wallet_history)
|
605
667
|
self.wallet_app.command(
|
606
|
-
"overview",
|
668
|
+
"overview",
|
669
|
+
rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
|
607
670
|
)(self.wallet_overview)
|
608
671
|
self.wallet_app.command(
|
609
672
|
"transfer", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
|
610
673
|
)(self.wallet_transfer)
|
611
674
|
self.wallet_app.command(
|
612
|
-
"inspect",
|
675
|
+
"inspect",
|
676
|
+
rich_help_panel=HELP_PANELS["WALLET"]["INFORMATION"],
|
677
|
+
hidden=True,
|
613
678
|
)(self.wallet_inspect)
|
614
679
|
self.wallet_app.command(
|
615
680
|
"faucet", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
|
@@ -624,59 +689,25 @@ class CLIManager:
|
|
624
689
|
"sign", rich_help_panel=HELP_PANELS["WALLET"]["OPERATIONS"]
|
625
690
|
)(self.wallet_sign)
|
626
691
|
|
627
|
-
# root commands
|
628
|
-
self.root_app.command("list")(self.root_list)
|
629
|
-
self.root_app.command(
|
630
|
-
"set-weights", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
631
|
-
)(self.root_set_weights)
|
632
|
-
self.root_app.command(
|
633
|
-
"get-weights", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
634
|
-
)(self.root_get_weights)
|
635
|
-
self.root_app.command(
|
636
|
-
"boost", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
637
|
-
)(self.root_boost)
|
638
|
-
self.root_app.command(
|
639
|
-
"slash", rich_help_panel=HELP_PANELS["ROOT"]["WEIGHT_MGMT"]
|
640
|
-
)(self.root_slash)
|
641
|
-
self.root_app.command(
|
642
|
-
"senate", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
643
|
-
)(self.root_senate)
|
644
|
-
self.root_app.command(
|
645
|
-
"senate-vote", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
646
|
-
)(self.root_senate_vote)
|
647
|
-
self.root_app.command("register")(self.root_register)
|
648
|
-
self.root_app.command(
|
649
|
-
"proposals", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
650
|
-
)(self.root_proposals)
|
651
|
-
self.root_app.command(
|
652
|
-
"set-take", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
653
|
-
)(self.root_set_take)
|
654
|
-
self.root_app.command(
|
655
|
-
"delegate-stake", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
656
|
-
)(self.root_delegate_stake)
|
657
|
-
self.root_app.command(
|
658
|
-
"undelegate-stake", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
659
|
-
)(self.root_undelegate_stake)
|
660
|
-
self.root_app.command(
|
661
|
-
"my-delegates", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
662
|
-
)(self.root_my_delegates)
|
663
|
-
self.root_app.command(
|
664
|
-
"list-delegates", rich_help_panel=HELP_PANELS["ROOT"]["DELEGATION"]
|
665
|
-
)(self.root_list_delegates)
|
666
|
-
self.root_app.command(
|
667
|
-
"nominate", rich_help_panel=HELP_PANELS["ROOT"]["GOVERNANCE"]
|
668
|
-
)(self.root_nominate)
|
669
|
-
|
670
692
|
# stake commands
|
671
|
-
self.stake_app.command(
|
672
|
-
"show", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
673
|
-
)(self.stake_show)
|
674
693
|
self.stake_app.command(
|
675
694
|
"add", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
676
695
|
)(self.stake_add)
|
677
696
|
self.stake_app.command(
|
678
697
|
"remove", rich_help_panel=HELP_PANELS["STAKE"]["STAKE_MGMT"]
|
679
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)
|
680
711
|
|
681
712
|
# stake-children commands
|
682
713
|
children_app = typer.Typer()
|
@@ -702,6 +733,21 @@ class CLIManager:
|
|
702
733
|
self.sudo_app.command("get", rich_help_panel=HELP_PANELS["SUDO"]["CONFIG"])(
|
703
734
|
self.sudo_get
|
704
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
|
+
)
|
705
751
|
|
706
752
|
# subnets commands
|
707
753
|
self.subnets_app.command(
|
@@ -711,8 +757,8 @@ class CLIManager:
|
|
711
757
|
"list", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
|
712
758
|
)(self.subnets_list)
|
713
759
|
self.subnets_app.command(
|
714
|
-
"
|
715
|
-
)(self.
|
760
|
+
"burn-cost", rich_help_panel=HELP_PANELS["SUBNETS"]["CREATION"]
|
761
|
+
)(self.subnets_burn_cost)
|
716
762
|
self.subnets_app.command(
|
717
763
|
"create", rich_help_panel=HELP_PANELS["SUBNETS"]["CREATION"]
|
718
764
|
)(self.subnets_create)
|
@@ -723,8 +769,14 @@ class CLIManager:
|
|
723
769
|
"register", rich_help_panel=HELP_PANELS["SUBNETS"]["REGISTER"]
|
724
770
|
)(self.subnets_register)
|
725
771
|
self.subnets_app.command(
|
726
|
-
"metagraph", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
|
727
|
-
)(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)
|
728
780
|
|
729
781
|
# weights commands
|
730
782
|
self.weights_app.command(
|
@@ -769,22 +821,49 @@ class CLIManager:
|
|
769
821
|
hidden=True,
|
770
822
|
)(self.wallet_get_id)
|
771
823
|
|
772
|
-
# Root
|
773
|
-
self.root_app.command("set_weights", hidden=True)(self.root_set_weights)
|
774
|
-
self.root_app.command("get_weights", hidden=True)(self.root_get_weights)
|
775
|
-
self.root_app.command("senate_vote", hidden=True)(self.root_senate_vote)
|
776
|
-
self.root_app.command("set_take", hidden=True)(self.root_set_take)
|
777
|
-
self.root_app.command("delegate_stake", hidden=True)(self.root_delegate_stake)
|
778
|
-
self.root_app.command("undelegate_stake", hidden=True)(
|
779
|
-
self.root_undelegate_stake
|
780
|
-
)
|
781
|
-
self.root_app.command("my_delegates", hidden=True)(self.root_my_delegates)
|
782
|
-
self.root_app.command("list_delegates", hidden=True)(self.root_list_delegates)
|
783
|
-
|
784
824
|
# Subnets
|
785
|
-
self.subnets_app.command("
|
825
|
+
self.subnets_app.command("burn_cost", hidden=True)(self.subnets_burn_cost)
|
786
826
|
self.subnets_app.command("pow_register", hidden=True)(self.subnets_pow_register)
|
787
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
|
+
|
788
867
|
def initialize_chain(
|
789
868
|
self,
|
790
869
|
network: Optional[list[str]] = None,
|
@@ -815,13 +894,13 @@ class CLIManager:
|
|
815
894
|
elif self.config["network"]:
|
816
895
|
self.subtensor = SubtensorInterface(self.config["network"])
|
817
896
|
console.print(
|
818
|
-
f"Using the specified network [
|
897
|
+
f"Using the specified network [{COLOR_PALETTE['GENERAL']['LINKS']}]{self.config['network']}[/{COLOR_PALETTE['GENERAL']['LINKS']}] from config"
|
819
898
|
)
|
820
899
|
else:
|
821
900
|
self.subtensor = SubtensorInterface(defaults.subtensor.network)
|
822
901
|
return self.subtensor
|
823
902
|
|
824
|
-
def _run_command(self, cmd: Coroutine):
|
903
|
+
def _run_command(self, cmd: Coroutine, exit_early: bool = True):
|
825
904
|
"""
|
826
905
|
Runs the supplied coroutine with `asyncio.run`
|
827
906
|
"""
|
@@ -837,7 +916,7 @@ class CLIManager:
|
|
837
916
|
initiated = True
|
838
917
|
result = await cmd
|
839
918
|
return result
|
840
|
-
except (ConnectionRefusedError, ssl.SSLError):
|
919
|
+
except (ConnectionRefusedError, ssl.SSLError, InvalidHandshake):
|
841
920
|
err_console.print(f"Unable to connect to the chain: {self.subtensor}")
|
842
921
|
verbose_console.print(traceback.format_exc())
|
843
922
|
except (
|
@@ -854,7 +933,12 @@ class CLIManager:
|
|
854
933
|
finally:
|
855
934
|
if initiated is False:
|
856
935
|
asyncio.create_task(cmd).cancel()
|
857
|
-
|
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):
|
941
|
+
err_console.print(f"An unknown error has occurred: {e}")
|
858
942
|
|
859
943
|
if sys.version_info < (3, 10):
|
860
944
|
# For Python 3.9 or lower
|
@@ -866,11 +950,21 @@ class CLIManager:
|
|
866
950
|
def main_callback(
|
867
951
|
self,
|
868
952
|
version: Annotated[
|
869
|
-
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
|
+
),
|
870
963
|
] = None,
|
871
964
|
):
|
872
965
|
"""
|
873
|
-
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.
|
874
968
|
"""
|
875
969
|
# Load or create the config file
|
876
970
|
if os.path.exists(self.config_path):
|
@@ -1178,39 +1272,16 @@ class CLIManager:
|
|
1178
1272
|
:return: created Wallet object
|
1179
1273
|
"""
|
1180
1274
|
# Prompt for missing attributes specified in ask_for
|
1181
|
-
|
1182
|
-
if wallet_path:
|
1183
|
-
if wallet_path == "default":
|
1184
|
-
wallet_path = defaults.wallet.path
|
1185
|
-
|
1186
|
-
elif self.config.get("wallet_path"):
|
1187
|
-
wallet_path = self.config.get("wallet_path")
|
1188
|
-
console.print(
|
1189
|
-
f"Using the wallet path from config:[bold magenta] {wallet_path}"
|
1190
|
-
)
|
1191
|
-
|
1192
|
-
if WO.PATH in ask_for and not wallet_path:
|
1193
|
-
wallet_path = Prompt.ask(
|
1194
|
-
"Enter the [blue]wallet path[/blue]"
|
1195
|
-
+ " [dark_sea_green3 italic](Hint: You can set this with `btcli config set --wallet-path`)[/dark_sea_green3 italic]",
|
1196
|
-
default=defaults.wallet.path,
|
1197
|
-
)
|
1198
|
-
if wallet_path:
|
1199
|
-
wallet_path = os.path.expanduser(wallet_path)
|
1200
|
-
else:
|
1201
|
-
wallet_path = os.path.expanduser(defaults.wallet.path)
|
1202
|
-
console.print(f"Using default wallet path: ({defaults.wallet.path})")
|
1203
|
-
|
1204
1275
|
if WO.NAME in ask_for and not wallet_name:
|
1205
1276
|
if self.config.get("wallet_name"):
|
1206
1277
|
wallet_name = self.config.get("wallet_name")
|
1207
1278
|
console.print(
|
1208
|
-
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}"
|
1209
1280
|
)
|
1210
1281
|
else:
|
1211
1282
|
wallet_name = Prompt.ask(
|
1212
1283
|
"Enter the [blue]wallet name[/blue]"
|
1213
|
-
+ " [
|
1284
|
+
+ f" [{COLOR_PALETTE['GENERAL']['HINT']} italic](Hint: You can set this with `btcli config set --wallet-name`)",
|
1214
1285
|
default=defaults.wallet.name,
|
1215
1286
|
)
|
1216
1287
|
|
@@ -1218,7 +1289,7 @@ class CLIManager:
|
|
1218
1289
|
if self.config.get("wallet_hotkey"):
|
1219
1290
|
wallet_hotkey = self.config.get("wallet_hotkey")
|
1220
1291
|
console.print(
|
1221
|
-
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}"
|
1222
1293
|
)
|
1223
1294
|
else:
|
1224
1295
|
wallet_hotkey = Prompt.ask(
|
@@ -1226,8 +1297,27 @@ class CLIManager:
|
|
1226
1297
|
+ " [dark_sea_green3 italic](Hint: You can set this with `btcli config set --wallet-hotkey`)[/dark_sea_green3 italic]",
|
1227
1298
|
default=defaults.wallet.hotkey,
|
1228
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
|
1229
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
|
+
)
|
1230
1318
|
# Create the Wallet object
|
1319
|
+
if wallet_path:
|
1320
|
+
wallet_path = os.path.expanduser(wallet_path)
|
1231
1321
|
wallet = Wallet(name=wallet_name, path=wallet_path, hotkey=wallet_hotkey)
|
1232
1322
|
|
1233
1323
|
# Validate the wallet if required
|
@@ -1383,7 +1473,7 @@ class CLIManager:
|
|
1383
1473
|
"Netuids must be a comma-separated list of ints, e.g., `--netuids 1,2,3,4`.",
|
1384
1474
|
)
|
1385
1475
|
|
1386
|
-
ask_for = [WO.NAME] if not all_wallets else []
|
1476
|
+
ask_for = [WO.NAME, WO.PATH] if not all_wallets else [WO.PATH]
|
1387
1477
|
validate = WV.WALLET if not all_wallets else WV.NONE
|
1388
1478
|
wallet = self.wallet_ask(
|
1389
1479
|
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
|
@@ -1413,6 +1503,7 @@ class CLIManager:
|
|
1413
1503
|
include_hotkeys,
|
1414
1504
|
exclude_hotkeys,
|
1415
1505
|
netuids_filter=netuids,
|
1506
|
+
verbose=verbose,
|
1416
1507
|
)
|
1417
1508
|
)
|
1418
1509
|
|
@@ -1430,12 +1521,9 @@ class CLIManager:
|
|
1430
1521
|
None,
|
1431
1522
|
"--amount",
|
1432
1523
|
"-a",
|
1433
|
-
prompt=
|
1524
|
+
prompt=True,
|
1434
1525
|
help="Amount (in TAO) to transfer.",
|
1435
1526
|
),
|
1436
|
-
transfer_all: bool = typer.Option(
|
1437
|
-
False, "--all", prompt=False, help="Transfer all available balance."
|
1438
|
-
),
|
1439
1527
|
wallet_name: str = Options.wallet_name,
|
1440
1528
|
wallet_path: str = Options.wallet_path,
|
1441
1529
|
wallet_hotkey: str = Options.wallet_hotkey,
|
@@ -1471,25 +1559,20 @@ class CLIManager:
|
|
1471
1559
|
wallet_name,
|
1472
1560
|
wallet_path,
|
1473
1561
|
wallet_hotkey,
|
1474
|
-
ask_for=[WO.NAME],
|
1562
|
+
ask_for=[WO.NAME, WO.PATH],
|
1475
1563
|
validate=WV.WALLET,
|
1476
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
|
+
|
1477
1572
|
subtensor = self.initialize_chain(network)
|
1478
|
-
if transfer_all and amount:
|
1479
|
-
print_error("Cannot specify an amount and '--all' flag.")
|
1480
|
-
raise typer.Exit()
|
1481
|
-
elif transfer_all:
|
1482
|
-
amount = 0
|
1483
|
-
elif not amount:
|
1484
|
-
amount = FloatPrompt.ask("Enter amount (in TAO) to transfer.")
|
1485
1573
|
return self._run_command(
|
1486
1574
|
wallets.transfer(
|
1487
|
-
wallet,
|
1488
|
-
subtensor,
|
1489
|
-
destination_ss58_address,
|
1490
|
-
amount,
|
1491
|
-
transfer_all,
|
1492
|
-
prompt,
|
1575
|
+
wallet, subtensor, destination_ss58_address, amount, prompt
|
1493
1576
|
)
|
1494
1577
|
)
|
1495
1578
|
|
@@ -1528,7 +1611,7 @@ class CLIManager:
|
|
1528
1611
|
wallet_name,
|
1529
1612
|
wallet_path,
|
1530
1613
|
wallet_hotkey,
|
1531
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
1614
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
1532
1615
|
validate=WV.WALLET_AND_HOTKEY,
|
1533
1616
|
)
|
1534
1617
|
if not destination_hotkey_name:
|
@@ -1540,7 +1623,7 @@ class CLIManager:
|
|
1540
1623
|
wallet_name,
|
1541
1624
|
wallet_path,
|
1542
1625
|
destination_hotkey_name,
|
1543
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
1626
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
1544
1627
|
validate=WV.WALLET_AND_HOTKEY,
|
1545
1628
|
)
|
1546
1629
|
self.initialize_chain(network)
|
@@ -1596,6 +1679,8 @@ class CLIManager:
|
|
1596
1679
|
|
1597
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.
|
1598
1681
|
"""
|
1682
|
+
print_error("This command is disabled on the 'rao' network.")
|
1683
|
+
raise typer.Exit()
|
1599
1684
|
self.verbosity_handler(quiet, verbose)
|
1600
1685
|
|
1601
1686
|
if netuids:
|
@@ -1606,11 +1691,12 @@ class CLIManager:
|
|
1606
1691
|
)
|
1607
1692
|
|
1608
1693
|
# if all-wallets is entered, ask for path
|
1609
|
-
ask_for = [WO.NAME] if not all_wallets else []
|
1694
|
+
ask_for = [WO.NAME, WO.PATH] if not all_wallets else [WO.PATH]
|
1610
1695
|
validate = WV.WALLET if not all_wallets else WV.NONE
|
1611
1696
|
wallet = self.wallet_ask(
|
1612
1697
|
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
|
1613
1698
|
)
|
1699
|
+
|
1614
1700
|
self.initialize_chain(network)
|
1615
1701
|
return self._run_command(
|
1616
1702
|
wallets.inspect(
|
@@ -1672,7 +1758,6 @@ class CLIManager:
|
|
1672
1758
|
"--max-successes",
|
1673
1759
|
help="Set the maximum number of times to successfully run the faucet for this command.",
|
1674
1760
|
),
|
1675
|
-
prompt: bool = Options.prompt,
|
1676
1761
|
):
|
1677
1762
|
"""
|
1678
1763
|
Obtain test TAO tokens by performing Proof of Work (PoW).
|
@@ -1696,7 +1781,7 @@ class CLIManager:
|
|
1696
1781
|
wallet_name,
|
1697
1782
|
wallet_path,
|
1698
1783
|
wallet_hotkey,
|
1699
|
-
ask_for=[WO.NAME],
|
1784
|
+
ask_for=[WO.NAME, WO.PATH],
|
1700
1785
|
validate=WV.WALLET,
|
1701
1786
|
)
|
1702
1787
|
return self._run_command(
|
@@ -1711,7 +1796,6 @@ class CLIManager:
|
|
1711
1796
|
output_in_place,
|
1712
1797
|
verbose,
|
1713
1798
|
max_successes,
|
1714
|
-
prompt,
|
1715
1799
|
)
|
1716
1800
|
)
|
1717
1801
|
|
@@ -1754,7 +1838,8 @@ class CLIManager:
|
|
1754
1838
|
|
1755
1839
|
if not wallet_name:
|
1756
1840
|
wallet_name = Prompt.ask(
|
1757
|
-
"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,
|
1758
1843
|
)
|
1759
1844
|
|
1760
1845
|
wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
|
@@ -1808,7 +1893,8 @@ class CLIManager:
|
|
1808
1893
|
|
1809
1894
|
if not wallet_name:
|
1810
1895
|
wallet_name = Prompt.ask(
|
1811
|
-
"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,
|
1812
1898
|
)
|
1813
1899
|
wallet = Wallet(wallet_name, wallet_hotkey, wallet_path)
|
1814
1900
|
|
@@ -1841,6 +1927,8 @@ class CLIManager:
|
|
1841
1927
|
use_password: bool = typer.Option(
|
1842
1928
|
False, # Overriden to False
|
1843
1929
|
help="Set to 'True' to protect the generated Bittensor key with a password.",
|
1930
|
+
is_flag=True,
|
1931
|
+
flag_value=True,
|
1844
1932
|
),
|
1845
1933
|
quiet: bool = Options.quiet,
|
1846
1934
|
verbose: bool = Options.verbose,
|
@@ -1897,7 +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
|
),
|
1991
|
+
uri: Optional[str] = Options.uri,
|
1901
1992
|
quiet: bool = Options.quiet,
|
1902
1993
|
verbose: bool = Options.verbose,
|
1903
1994
|
):
|
@@ -1919,12 +2010,14 @@ class CLIManager:
|
|
1919
2010
|
|
1920
2011
|
if not wallet_name:
|
1921
2012
|
wallet_name = Prompt.ask(
|
1922
|
-
"Enter the wallet name",
|
2013
|
+
f"Enter the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]wallet name",
|
2014
|
+
default=defaults.wallet.name,
|
1923
2015
|
)
|
1924
2016
|
|
1925
2017
|
if not wallet_hotkey:
|
1926
2018
|
wallet_hotkey = Prompt.ask(
|
1927
|
-
"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,
|
1928
2021
|
)
|
1929
2022
|
|
1930
2023
|
wallet = self.wallet_ask(
|
@@ -1934,8 +2027,9 @@ class CLIManager:
|
|
1934
2027
|
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
1935
2028
|
validate=WV.WALLET,
|
1936
2029
|
)
|
1937
|
-
|
1938
|
-
|
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))
|
1939
2033
|
|
1940
2034
|
def wallet_new_coldkey(
|
1941
2035
|
self,
|
@@ -1949,6 +2043,7 @@ class CLIManager:
|
|
1949
2043
|
help="The number of words used in the mnemonic. Options: [12, 15, 18, 21, 24]",
|
1950
2044
|
),
|
1951
2045
|
use_password: Optional[bool] = Options.use_password,
|
2046
|
+
uri: Optional[str] = Options.uri,
|
1952
2047
|
quiet: bool = Options.quiet,
|
1953
2048
|
verbose: bool = Options.verbose,
|
1954
2049
|
):
|
@@ -1974,7 +2069,8 @@ class CLIManager:
|
|
1974
2069
|
|
1975
2070
|
if not wallet_name:
|
1976
2071
|
wallet_name = Prompt.ask(
|
1977
|
-
"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,
|
1978
2074
|
)
|
1979
2075
|
|
1980
2076
|
wallet = self.wallet_ask(
|
@@ -1984,8 +2080,11 @@ class CLIManager:
|
|
1984
2080
|
ask_for=[WO.NAME, WO.PATH],
|
1985
2081
|
validate=WV.NONE,
|
1986
2082
|
)
|
1987
|
-
|
1988
|
-
|
2083
|
+
if not uri:
|
2084
|
+
n_words = get_n_words(n_words)
|
2085
|
+
return self._run_command(
|
2086
|
+
wallets.new_coldkey(wallet, n_words, use_password, uri)
|
2087
|
+
)
|
1989
2088
|
|
1990
2089
|
def wallet_check_ck_swap(
|
1991
2090
|
self,
|
@@ -2019,6 +2118,7 @@ class CLIManager:
|
|
2019
2118
|
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2020
2119
|
n_words: Optional[int] = None,
|
2021
2120
|
use_password: bool = Options.use_password,
|
2121
|
+
uri: Optional[str] = Options.uri,
|
2022
2122
|
quiet: bool = Options.quiet,
|
2023
2123
|
verbose: bool = Options.verbose,
|
2024
2124
|
):
|
@@ -2042,12 +2142,13 @@ class CLIManager:
|
|
2042
2142
|
|
2043
2143
|
if not wallet_name:
|
2044
2144
|
wallet_name = Prompt.ask(
|
2045
|
-
"Enter the name of the new wallet (coldkey)",
|
2145
|
+
f"Enter the name of the [{COLOR_PALETTE['GENERAL']['COLDKEY']}]new wallet (coldkey)",
|
2046
2146
|
default=defaults.wallet.name,
|
2047
2147
|
)
|
2048
2148
|
if not wallet_hotkey:
|
2049
2149
|
wallet_hotkey = Prompt.ask(
|
2050
|
-
"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,
|
2051
2152
|
)
|
2052
2153
|
|
2053
2154
|
self.verbosity_handler(quiet, verbose)
|
@@ -2058,12 +2159,14 @@ class CLIManager:
|
|
2058
2159
|
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
2059
2160
|
validate=WV.NONE,
|
2060
2161
|
)
|
2061
|
-
|
2162
|
+
if not uri:
|
2163
|
+
n_words = get_n_words(n_words)
|
2062
2164
|
return self._run_command(
|
2063
2165
|
wallets.wallet_create(
|
2064
2166
|
wallet,
|
2065
2167
|
n_words,
|
2066
2168
|
use_password,
|
2169
|
+
uri,
|
2067
2170
|
)
|
2068
2171
|
)
|
2069
2172
|
|
@@ -2108,8 +2211,18 @@ class CLIManager:
|
|
2108
2211
|
|
2109
2212
|
"""
|
2110
2213
|
self.verbosity_handler(quiet, verbose)
|
2111
|
-
|
2112
|
-
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:
|
2113
2226
|
valid_ss58s = [
|
2114
2227
|
ss58 for ss58 in set(ss58_addresses) if is_valid_ss58_address(ss58)
|
2115
2228
|
]
|
@@ -2119,20 +2232,45 @@ class CLIManager:
|
|
2119
2232
|
print_error(f"Incorrect ss58 address: {invalid_ss58}. Skipping.")
|
2120
2233
|
|
2121
2234
|
if valid_ss58s:
|
2122
|
-
wallet = None
|
2123
2235
|
ss58_addresses = valid_ss58s
|
2124
2236
|
else:
|
2125
2237
|
raise typer.Exit()
|
2126
2238
|
else:
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
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
|
+
)
|
2136
2274
|
subtensor = self.initialize_chain(network)
|
2137
2275
|
return self._run_command(
|
2138
2276
|
wallets.wallet_balance(wallet, subtensor, all_balances, ss58_addresses)
|
@@ -2158,19 +2296,23 @@ class CLIManager:
|
|
2158
2296
|
[green]$[/green] btcli wallet history
|
2159
2297
|
|
2160
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"
|
2161
2301
|
|
2162
|
-
|
2302
|
+
# if self.config.get("network"):
|
2303
|
+
# if self.config.get("network") != "finney":
|
2304
|
+
# console.print(no_use_config_str)
|
2163
2305
|
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2306
|
+
# For Rao games
|
2307
|
+
print_error("This command is disabled on the 'rao' network.")
|
2308
|
+
raise typer.Exit()
|
2167
2309
|
|
2168
2310
|
self.verbosity_handler(quiet, verbose)
|
2169
2311
|
wallet = self.wallet_ask(
|
2170
2312
|
wallet_name,
|
2171
2313
|
wallet_path,
|
2172
2314
|
wallet_hotkey,
|
2173
|
-
ask_for=[WO.NAME],
|
2315
|
+
ask_for=[WO.NAME, WO.PATH],
|
2174
2316
|
validate=WV.WALLET,
|
2175
2317
|
)
|
2176
2318
|
return self._run_command(wallets.wallet_history(wallet))
|
@@ -2181,69 +2323,42 @@ class CLIManager:
|
|
2181
2323
|
wallet_path: Optional[str] = Options.wallet_path,
|
2182
2324
|
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2183
2325
|
network: Optional[list[str]] = Options.network,
|
2184
|
-
|
2326
|
+
name: str = typer.Option(
|
2185
2327
|
"",
|
2186
|
-
"--
|
2187
|
-
"--display",
|
2328
|
+
"--name",
|
2188
2329
|
help="The display name for the identity.",
|
2189
2330
|
),
|
2190
|
-
legal_name: str = typer.Option(
|
2191
|
-
"",
|
2192
|
-
"--legal-name",
|
2193
|
-
"--legal",
|
2194
|
-
help="The legal name for the identity.",
|
2195
|
-
),
|
2196
2331
|
web_url: str = typer.Option(
|
2197
2332
|
"",
|
2198
2333
|
"--web-url",
|
2199
2334
|
"--web",
|
2200
2335
|
help="The web URL for the identity.",
|
2201
2336
|
),
|
2202
|
-
riot_handle: str = typer.Option(
|
2203
|
-
"",
|
2204
|
-
"--riot-handle",
|
2205
|
-
"--riot",
|
2206
|
-
help="The Riot handle for the identity.",
|
2207
|
-
),
|
2208
|
-
email: str = typer.Option(
|
2209
|
-
"",
|
2210
|
-
help="The email address for the identity.",
|
2211
|
-
),
|
2212
|
-
pgp_fingerprint: str = typer.Option(
|
2213
|
-
"",
|
2214
|
-
"--pgp-fingerprint",
|
2215
|
-
"--pgp",
|
2216
|
-
help="The PGP fingerprint for the identity.",
|
2217
|
-
),
|
2218
2337
|
image_url: str = typer.Option(
|
2219
2338
|
"",
|
2220
2339
|
"--image-url",
|
2221
2340
|
"--image",
|
2222
2341
|
help="The image URL for the identity.",
|
2223
2342
|
),
|
2224
|
-
|
2343
|
+
discord: str = typer.Option(
|
2225
2344
|
"",
|
2226
|
-
"--
|
2227
|
-
"
|
2228
|
-
help="The info for the identity.",
|
2345
|
+
"--discord",
|
2346
|
+
help="The Discord handle for the identity.",
|
2229
2347
|
),
|
2230
|
-
|
2348
|
+
description: str = typer.Option(
|
2231
2349
|
"",
|
2232
|
-
"
|
2233
|
-
"
|
2234
|
-
"--twitter-url",
|
2235
|
-
"--twitter",
|
2236
|
-
help="The 𝕏 (Twitter) URL for the identity.",
|
2350
|
+
"--description",
|
2351
|
+
help="The description for the identity.",
|
2237
2352
|
),
|
2238
|
-
|
2239
|
-
|
2240
|
-
"--
|
2241
|
-
help="
|
2353
|
+
additional: str = typer.Option(
|
2354
|
+
"",
|
2355
|
+
"--additional",
|
2356
|
+
help="Additional details for the identity.",
|
2242
2357
|
),
|
2243
|
-
|
2244
|
-
|
2245
|
-
"--
|
2246
|
-
help="
|
2358
|
+
github_repo: str = typer.Option(
|
2359
|
+
"",
|
2360
|
+
"--github",
|
2361
|
+
help="The GitHub repository for the identity.",
|
2247
2362
|
),
|
2248
2363
|
quiet: bool = Options.quiet,
|
2249
2364
|
verbose: bool = Options.verbose,
|
@@ -2271,94 +2386,67 @@ class CLIManager:
|
|
2271
2386
|
wallet_name,
|
2272
2387
|
wallet_path,
|
2273
2388
|
wallet_hotkey,
|
2274
|
-
ask_for=[WO.
|
2275
|
-
validate=WV.
|
2389
|
+
ask_for=[WO.NAME],
|
2390
|
+
validate=WV.WALLET,
|
2276
2391
|
)
|
2277
2392
|
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
image_url,
|
2287
|
-
info_,
|
2288
|
-
twitter_url,
|
2289
|
-
]
|
2290
|
-
):
|
2291
|
-
console.print(
|
2292
|
-
"[yellow]All fields are optional. Press Enter to skip a field.[/yellow]"
|
2293
|
-
)
|
2294
|
-
text_rejection = partial(
|
2295
|
-
retry_prompt,
|
2296
|
-
rejection=lambda x: sys.getsizeof(x) > 113,
|
2297
|
-
rejection_text="[red]Error:[/red] Identity field must be <= 64 raw bytes.",
|
2298
|
-
)
|
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
|
+
)
|
2299
2401
|
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
return True if len(pgp_fingerprint_encoded) != 20 else False
|
2308
|
-
|
2309
|
-
display_name = display_name or text_rejection("Display name")
|
2310
|
-
legal_name = legal_name or text_rejection("Legal name")
|
2311
|
-
web_url = web_url or text_rejection("Web URL")
|
2312
|
-
riot_handle = riot_handle or text_rejection("Riot handle")
|
2313
|
-
email = email or text_rejection("Email address")
|
2314
|
-
pgp_fingerprint = pgp_fingerprint or retry_prompt(
|
2315
|
-
"PGP fingerprint (Eg: A1B2 C3D4 E5F6 7890 1234 5678 9ABC DEF0 1234 5678)",
|
2316
|
-
lambda s: False if not s else pgp_check(s),
|
2317
|
-
"[red]Error:[/red] PGP Fingerprint must be exactly 20 bytes.",
|
2318
|
-
)
|
2319
|
-
image_url = image_url or text_rejection("Image URL")
|
2320
|
-
info_ = info_ or text_rejection("Enter info")
|
2321
|
-
twitter_url = twitter_url or text_rejection("𝕏 (Twitter) URL")
|
2322
|
-
|
2323
|
-
validator_id = validator_id or Confirm.ask(
|
2324
|
-
"Are you updating a [bold blue]validator hotkey[/bold blue] identity or a [bold blue]subnet "
|
2325
|
-
"owner[/bold blue] identity?\n"
|
2326
|
-
"Enter [bold green]Y[/bold green] for [bold]validator hotkey[/bold] or [bold red]N[/bold red] for "
|
2327
|
-
"[bold]subnet owner[/bold]",
|
2328
|
-
show_choices=True,
|
2329
|
-
)
|
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()
|
2330
2409
|
|
2331
|
-
|
2332
|
-
|
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
|
+
)
|
2333
2420
|
|
2334
2421
|
return self._run_command(
|
2335
2422
|
wallets.set_id(
|
2336
2423
|
wallet,
|
2337
2424
|
self.initialize_chain(network),
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
twitter_url,
|
2346
|
-
info_,
|
2347
|
-
validator_id,
|
2425
|
+
identity["name"],
|
2426
|
+
identity["url"],
|
2427
|
+
identity["image"],
|
2428
|
+
identity["discord"],
|
2429
|
+
identity["description"],
|
2430
|
+
identity["additional"],
|
2431
|
+
identity["github_repo"],
|
2348
2432
|
prompt,
|
2349
|
-
subnet_netuid,
|
2350
2433
|
)
|
2351
2434
|
)
|
2352
2435
|
|
2353
2436
|
def wallet_get_id(
|
2354
2437
|
self,
|
2355
|
-
|
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(
|
2356
2442
|
None,
|
2443
|
+
"--ss58",
|
2444
|
+
"--coldkey_ss58",
|
2445
|
+
"--coldkey.ss58_address",
|
2446
|
+
"--coldkey.ss58",
|
2357
2447
|
"--key",
|
2358
2448
|
"-k",
|
2359
|
-
"
|
2360
|
-
help="The coldkey or hotkey ss58 address to query.",
|
2361
|
-
prompt=True,
|
2449
|
+
help="Coldkey address of the wallet",
|
2362
2450
|
),
|
2363
2451
|
network: Optional[list[str]] = Options.network,
|
2364
2452
|
quiet: bool = Options.quiet,
|
@@ -2381,13 +2469,28 @@ class CLIManager:
|
|
2381
2469
|
|
2382
2470
|
[bold]Note[/bold]: This command is primarily used for informational purposes and has no side effects on the blockchain network state.
|
2383
2471
|
"""
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
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
|
2387
2490
|
|
2388
2491
|
self.verbosity_handler(quiet, verbose)
|
2389
2492
|
return self._run_command(
|
2390
|
-
wallets.get_id(self.initialize_chain(network),
|
2493
|
+
wallets.get_id(self.initialize_chain(network), coldkey_ss58)
|
2391
2494
|
)
|
2392
2495
|
|
2393
2496
|
def wallet_sign(
|
@@ -2421,882 +2524,127 @@ class CLIManager:
|
|
2421
2524
|
self.verbosity_handler(quiet, verbose)
|
2422
2525
|
if use_hotkey is None:
|
2423
2526
|
use_hotkey = Confirm.ask(
|
2424
|
-
"Would you like to sign the transaction using your [
|
2425
|
-
"\n[Type [
|
2426
|
-
"(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']}])",
|
2427
2530
|
default=False,
|
2428
2531
|
)
|
2429
2532
|
|
2430
|
-
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]
|
2431
2534
|
validate = WV.WALLET_AND_HOTKEY if use_hotkey else WV.WALLET
|
2432
2535
|
|
2433
2536
|
wallet = self.wallet_ask(
|
2434
2537
|
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
|
2435
2538
|
)
|
2436
2539
|
if not message:
|
2437
|
-
message =
|
2540
|
+
message = Prompt.ask("Enter the [blue]message[/blue] to encode and sign")
|
2438
2541
|
|
2439
2542
|
return self._run_command(wallets.sign(wallet, message, use_hotkey))
|
2440
2543
|
|
2441
|
-
def
|
2544
|
+
def stake_list(
|
2442
2545
|
self,
|
2443
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,
|
2444
2559
|
quiet: bool = Options.quiet,
|
2445
2560
|
verbose: bool = Options.verbose,
|
2561
|
+
no_prompt: bool = Options.prompt,
|
2562
|
+
# TODO add: all-wallets, reuse_last, html_output
|
2446
2563
|
):
|
2447
|
-
"""
|
2448
|
-
|
2449
|
-
|
2450
|
-
USAGE
|
2451
|
-
|
2452
|
-
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).
|
2453
|
-
|
2454
|
-
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)
|
2455
2566
|
|
2456
|
-
|
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
|
+
)
|
2457
2587
|
|
2458
|
-
[green]$[/green] btcli root list
|
2459
|
-
"""
|
2460
|
-
self.verbosity_handler(quiet, verbose)
|
2461
2588
|
return self._run_command(
|
2462
|
-
|
2589
|
+
stake.stake_list(
|
2590
|
+
wallet,
|
2591
|
+
coldkey_ss58,
|
2592
|
+
self.initialize_chain(network),
|
2593
|
+
live,
|
2594
|
+
verbose,
|
2595
|
+
no_prompt,
|
2596
|
+
)
|
2463
2597
|
)
|
2464
2598
|
|
2465
|
-
def
|
2599
|
+
def stake_add(
|
2466
2600
|
self,
|
2467
|
-
|
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,
|
2468
2638
|
wallet_name: str = Options.wallet_name,
|
2469
2639
|
wallet_path: str = Options.wallet_path,
|
2470
2640
|
wallet_hotkey: str = Options.wallet_hotkey,
|
2471
|
-
|
2472
|
-
None,
|
2473
|
-
"--netuids",
|
2474
|
-
"--netuid",
|
2475
|
-
"-n",
|
2476
|
-
help="Set the netuid(s) to set weights to. Separate multiple netuids with a comma, for example: `-n 0,1,2`.",
|
2477
|
-
),
|
2478
|
-
weights: str = Options.weights,
|
2641
|
+
network: Optional[list[str]] = Options.network,
|
2479
2642
|
prompt: bool = Options.prompt,
|
2480
2643
|
quiet: bool = Options.quiet,
|
2481
2644
|
verbose: bool = Options.verbose,
|
2482
2645
|
):
|
2483
2646
|
"""
|
2484
|
-
|
2485
|
-
|
2486
|
-
To use this command, you should specify the netuids and corresponding weights you wish to assign. This command is used by validators registered to the root subnet to influence the distribution of subnet rewards and responsibilities.
|
2487
|
-
|
2488
|
-
You must have a comprehensive understanding of the dynamics of the subnets to use this command. It is a powerful tool that directly impacts the subnet's operational mechanics and reward distribution.
|
2489
|
-
|
2490
|
-
EXAMPLE
|
2491
|
-
|
2492
|
-
With no spaces between the passed values:
|
2493
|
-
|
2494
|
-
[green]$[/green] btcli root set-weights --netuids 1,2 --weights 0.2,0.3
|
2495
|
-
|
2496
|
-
or
|
2497
|
-
|
2498
|
-
Include double quotes to include spaces between the passed values:
|
2499
|
-
|
2500
|
-
[green]$[/green] btcli root set-weights --netuids "1, 2" --weights "0.2, 0.3"
|
2501
|
-
"""
|
2502
|
-
self.verbosity_handler(quiet, verbose)
|
2503
|
-
|
2504
|
-
if netuids:
|
2505
|
-
netuids = parse_to_list(
|
2506
|
-
netuids,
|
2507
|
-
int,
|
2508
|
-
"Netuids must be a comma-separated list of ints, e.g., `--netuid 1,2,3,4`.",
|
2509
|
-
)
|
2510
|
-
else:
|
2511
|
-
netuids = list_prompt(netuids, int, "Enter netuids (e.g: 1, 4, 6)")
|
2512
|
-
|
2513
|
-
if weights:
|
2514
|
-
weights = parse_to_list(
|
2515
|
-
weights,
|
2516
|
-
float,
|
2517
|
-
"Weights must be a comma-separated list of floats, e.g., `--weights 0.3,0.4,0.3`.",
|
2518
|
-
)
|
2519
|
-
else:
|
2520
|
-
weights = list_prompt(
|
2521
|
-
weights, float, "Enter weights (e.g. 0.02, 0.03, 0.01)"
|
2522
|
-
)
|
2523
|
-
|
2524
|
-
if len(netuids) != len(weights):
|
2525
|
-
raise typer.BadParameter(
|
2526
|
-
"The number of netuids and weights must be the same."
|
2527
|
-
)
|
2528
|
-
|
2529
|
-
wallet = self.wallet_ask(
|
2530
|
-
wallet_name,
|
2531
|
-
wallet_path,
|
2532
|
-
wallet_hotkey,
|
2533
|
-
ask_for=[WO.HOTKEY, WO.NAME],
|
2534
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2535
|
-
)
|
2536
|
-
self._run_command(
|
2537
|
-
root.set_weights(
|
2538
|
-
wallet, self.initialize_chain(network), netuids, weights, prompt
|
2539
|
-
)
|
2540
|
-
)
|
2541
|
-
|
2542
|
-
def root_get_weights(
|
2543
|
-
self,
|
2544
|
-
network: Optional[list[str]] = Options.network,
|
2545
|
-
limit_min_col: Optional[int] = typer.Option(
|
2546
|
-
None,
|
2547
|
-
"--limit-min-col",
|
2548
|
-
"--min",
|
2549
|
-
help="Limit the left display of the table to this column.",
|
2550
|
-
),
|
2551
|
-
limit_max_col: Optional[int] = typer.Option(
|
2552
|
-
None,
|
2553
|
-
"--limit-max-col",
|
2554
|
-
"--max",
|
2555
|
-
help="Limit the right display of the table to this column.",
|
2556
|
-
),
|
2557
|
-
reuse_last: bool = Options.reuse_last,
|
2558
|
-
html_output: bool = Options.html_output,
|
2559
|
-
quiet: bool = Options.quiet,
|
2560
|
-
verbose: bool = Options.verbose,
|
2561
|
-
):
|
2562
|
-
"""
|
2563
|
-
Shows a table listing the weights assigned to each subnet in the root network.
|
2564
|
-
|
2565
|
-
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.
|
2566
|
-
|
2567
|
-
EXAMPLE
|
2568
|
-
|
2569
|
-
[green]$[/green] btcli root get_weights
|
2570
|
-
"""
|
2571
|
-
self.verbosity_handler(quiet, verbose)
|
2572
|
-
if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
2573
|
-
err_console.print(
|
2574
|
-
"Unable to use `--reuse-last` or `--html` when config 'no-cache' is set to 'True'."
|
2575
|
-
"Change it to 'False' using `btcli config set`."
|
2576
|
-
)
|
2577
|
-
raise typer.Exit()
|
2578
|
-
if not reuse_last:
|
2579
|
-
subtensor = self.initialize_chain(network)
|
2580
|
-
else:
|
2581
|
-
subtensor = None
|
2582
|
-
return self._run_command(
|
2583
|
-
root.get_weights(
|
2584
|
-
subtensor,
|
2585
|
-
limit_min_col,
|
2586
|
-
limit_max_col,
|
2587
|
-
reuse_last,
|
2588
|
-
html_output,
|
2589
|
-
not self.config.get("use_cache", True),
|
2590
|
-
)
|
2591
|
-
)
|
2592
|
-
|
2593
|
-
def root_boost(
|
2594
|
-
self,
|
2595
|
-
network: Optional[list[str]] = Options.network,
|
2596
|
-
wallet_name: str = Options.wallet_name,
|
2597
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2598
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2599
|
-
netuid: int = Options.netuid,
|
2600
|
-
amount: float = typer.Option(
|
2601
|
-
None,
|
2602
|
-
"--amount",
|
2603
|
-
"--increase",
|
2604
|
-
"-a",
|
2605
|
-
prompt="Enter the boost amount (added to existing weight)",
|
2606
|
-
help="Amount (float) to boost (added to the existing weight), (e.g. 0.01)",
|
2607
|
-
),
|
2608
|
-
prompt: bool = Options.prompt,
|
2609
|
-
quiet: bool = Options.quiet,
|
2610
|
-
verbose: bool = Options.verbose,
|
2611
|
-
):
|
2612
|
-
"""
|
2613
|
-
Increase (boost) the weights for a specific subnet in the root network. Any amount provided will be added to the subnet's existing weight.
|
2614
|
-
|
2615
|
-
EXAMPLE
|
2616
|
-
|
2617
|
-
[green]$[/green] btcli root boost --netuid 1 --increase 0.01
|
2618
|
-
"""
|
2619
|
-
self.verbosity_handler(quiet, verbose)
|
2620
|
-
wallet = self.wallet_ask(
|
2621
|
-
wallet_name,
|
2622
|
-
wallet_path,
|
2623
|
-
wallet_hotkey,
|
2624
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2625
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2626
|
-
)
|
2627
|
-
return self._run_command(
|
2628
|
-
root.set_boost(
|
2629
|
-
wallet, self.initialize_chain(network), netuid, amount, prompt
|
2630
|
-
)
|
2631
|
-
)
|
2632
|
-
|
2633
|
-
def root_slash(
|
2634
|
-
self,
|
2635
|
-
network: Optional[list[str]] = Options.network,
|
2636
|
-
wallet_name: str = Options.wallet_name,
|
2637
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2638
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2639
|
-
netuid: int = Options.netuid,
|
2640
|
-
amount: float = typer.Option(
|
2641
|
-
None,
|
2642
|
-
"--amount",
|
2643
|
-
"--decrease",
|
2644
|
-
"-a",
|
2645
|
-
prompt="Enter the slash amount (subtracted from the existing weight)",
|
2646
|
-
help="Amount (float) to slash (subtract from the existing weight), (e.g. 0.01)",
|
2647
|
-
),
|
2648
|
-
prompt: bool = Options.prompt,
|
2649
|
-
quiet: bool = Options.quiet,
|
2650
|
-
verbose: bool = Options.verbose,
|
2651
|
-
):
|
2652
|
-
"""
|
2653
|
-
Decrease (slash) the weights for a specific subnet in the root network. Any amount provided will be subtracted from the subnet's existing weight.
|
2654
|
-
|
2655
|
-
EXAMPLE
|
2656
|
-
|
2657
|
-
[green]$[/green] btcli root slash --netuid 1 --decrease 0.01
|
2658
|
-
|
2659
|
-
"""
|
2660
|
-
self.verbosity_handler(quiet, verbose)
|
2661
|
-
wallet = self.wallet_ask(
|
2662
|
-
wallet_name,
|
2663
|
-
wallet_path,
|
2664
|
-
wallet_hotkey,
|
2665
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2666
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2667
|
-
)
|
2668
|
-
return self._run_command(
|
2669
|
-
root.set_slash(
|
2670
|
-
wallet, self.initialize_chain(network), netuid, amount, prompt
|
2671
|
-
)
|
2672
|
-
)
|
2673
|
-
|
2674
|
-
def root_senate_vote(
|
2675
|
-
self,
|
2676
|
-
network: Optional[list[str]] = Options.network,
|
2677
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2678
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2679
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2680
|
-
proposal: str = typer.Option(
|
2681
|
-
None,
|
2682
|
-
"--proposal",
|
2683
|
-
"--proposal-hash",
|
2684
|
-
prompt="Enter the proposal hash",
|
2685
|
-
help="The hash of the proposal to vote on.",
|
2686
|
-
),
|
2687
|
-
prompt: bool = Options.prompt,
|
2688
|
-
quiet: bool = Options.quiet,
|
2689
|
-
verbose: bool = Options.verbose,
|
2690
|
-
vote: bool = typer.Option(
|
2691
|
-
None,
|
2692
|
-
"--vote-aye/--vote-nay",
|
2693
|
-
prompt="Enter y to vote Aye, or enter n to vote Nay",
|
2694
|
-
help="The vote casted on the proposal",
|
2695
|
-
),
|
2696
|
-
):
|
2697
|
-
"""
|
2698
|
-
Cast a vote on an active proposal in Bittensor's governance protocol.
|
2699
|
-
|
2700
|
-
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.
|
2701
|
-
|
2702
|
-
USAGE
|
2703
|
-
|
2704
|
-
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.
|
2705
|
-
|
2706
|
-
EXAMPLE
|
2707
|
-
|
2708
|
-
[green]$[/green] btcli root senate_vote --proposal <proposal_hash>
|
2709
|
-
"""
|
2710
|
-
self.verbosity_handler(quiet, verbose)
|
2711
|
-
wallet = self.wallet_ask(
|
2712
|
-
wallet_name,
|
2713
|
-
wallet_path,
|
2714
|
-
wallet_hotkey,
|
2715
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2716
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2717
|
-
)
|
2718
|
-
return self._run_command(
|
2719
|
-
root.senate_vote(
|
2720
|
-
wallet, self.initialize_chain(network), proposal, vote, prompt
|
2721
|
-
)
|
2722
|
-
)
|
2723
|
-
|
2724
|
-
def root_senate(
|
2725
|
-
self,
|
2726
|
-
network: Optional[list[str]] = Options.network,
|
2727
|
-
quiet: bool = Options.quiet,
|
2728
|
-
verbose: bool = Options.verbose,
|
2729
|
-
):
|
2730
|
-
"""
|
2731
|
-
Shows the Senate members of the Bittensor's governance protocol.
|
2732
|
-
|
2733
|
-
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.
|
2734
|
-
|
2735
|
-
EXAMPLE
|
2736
|
-
|
2737
|
-
[green]$[/green] btcli root senate
|
2738
|
-
"""
|
2739
|
-
self.verbosity_handler(quiet, verbose)
|
2740
|
-
return self._run_command(root.get_senate(self.initialize_chain(network)))
|
2741
|
-
|
2742
|
-
def root_register(
|
2743
|
-
self,
|
2744
|
-
network: Optional[list[str]] = Options.network,
|
2745
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2746
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2747
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2748
|
-
prompt: bool = Options.prompt,
|
2749
|
-
quiet: bool = Options.quiet,
|
2750
|
-
verbose: bool = Options.verbose,
|
2751
|
-
):
|
2752
|
-
"""
|
2753
|
-
Register a neuron to the root subnet by recycling some TAO to cover for the registration cost.
|
2754
|
-
|
2755
|
-
This command adds a new neuron as a validator on the root network. This will allow the neuron owner to set subnet weights.
|
2756
|
-
|
2757
|
-
# Usage:
|
2758
|
-
|
2759
|
-
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.
|
2760
|
-
|
2761
|
-
# Example usage:
|
2762
|
-
|
2763
|
-
[green]$[/green] btcli subnets register --netuid 1
|
2764
|
-
"""
|
2765
|
-
self.verbosity_handler(quiet, verbose)
|
2766
|
-
wallet = self.wallet_ask(
|
2767
|
-
wallet_name,
|
2768
|
-
wallet_path,
|
2769
|
-
wallet_hotkey,
|
2770
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2771
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2772
|
-
)
|
2773
|
-
return self._run_command(
|
2774
|
-
root.register(wallet, self.initialize_chain(network), prompt)
|
2775
|
-
)
|
2776
|
-
|
2777
|
-
def root_proposals(
|
2778
|
-
self,
|
2779
|
-
network: Optional[list[str]] = Options.network,
|
2780
|
-
quiet: bool = Options.quiet,
|
2781
|
-
verbose: bool = Options.verbose,
|
2782
|
-
):
|
2783
|
-
"""
|
2784
|
-
View active proposals for the senate in the Bittensor's governance protocol.
|
2785
|
-
|
2786
|
-
This command displays the details of ongoing proposals, including proposal hashes, votes, thresholds, and proposal data.
|
2787
|
-
|
2788
|
-
EXAMPLE
|
2789
|
-
|
2790
|
-
[green]$[/green] btcli root proposals
|
2791
|
-
"""
|
2792
|
-
self.verbosity_handler(quiet, verbose)
|
2793
|
-
return self._run_command(root.proposals(self.initialize_chain(network)))
|
2794
|
-
|
2795
|
-
def root_set_take(
|
2796
|
-
self,
|
2797
|
-
network: Optional[list[str]] = Options.network,
|
2798
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2799
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2800
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2801
|
-
take: float = typer.Option(None, help="The new take value."),
|
2802
|
-
quiet: bool = Options.quiet,
|
2803
|
-
verbose: bool = Options.verbose,
|
2804
|
-
):
|
2805
|
-
"""
|
2806
|
-
Allows users to change their delegate take percentage.
|
2807
|
-
|
2808
|
-
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:
|
2809
|
-
|
2810
|
-
1. The provided hotkey is already a delegate.
|
2811
|
-
2. The new take value is within 0-18% range.
|
2812
|
-
|
2813
|
-
EXAMPLE
|
2814
|
-
|
2815
|
-
[green]$[/green] btcli root set_take --wallet-name my_wallet --wallet-hotkey my_hotkey
|
2816
|
-
"""
|
2817
|
-
max_value = 0.18
|
2818
|
-
min_value = 0.00
|
2819
|
-
self.verbosity_handler(quiet, verbose)
|
2820
|
-
|
2821
|
-
if not take:
|
2822
|
-
max_value_style = typer.style(f"Max: {max_value}", fg="magenta")
|
2823
|
-
min_value_style = typer.style(f"Min: {min_value}", fg="magenta")
|
2824
|
-
prompt_text = typer.style(
|
2825
|
-
"Enter take value (0.18 for 18%)", fg="bright_cyan", bold=True
|
2826
|
-
)
|
2827
|
-
take = FloatPrompt.ask(f"{prompt_text} {min_value_style} {max_value_style}")
|
2828
|
-
|
2829
|
-
if not (min_value <= take <= max_value):
|
2830
|
-
print_error(
|
2831
|
-
f"Take value must be between {min_value} and {max_value}. Provided value: {take}"
|
2832
|
-
)
|
2833
|
-
raise typer.Exit()
|
2834
|
-
|
2835
|
-
wallet = self.wallet_ask(
|
2836
|
-
wallet_name,
|
2837
|
-
wallet_path,
|
2838
|
-
wallet_hotkey,
|
2839
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2840
|
-
validate=WV.WALLET_AND_HOTKEY,
|
2841
|
-
)
|
2842
|
-
|
2843
|
-
return self._run_command(
|
2844
|
-
root.set_take(wallet, self.initialize_chain(network), take)
|
2845
|
-
)
|
2846
|
-
|
2847
|
-
def root_delegate_stake(
|
2848
|
-
self,
|
2849
|
-
delegate_ss58key: str = typer.Option(
|
2850
|
-
None,
|
2851
|
-
help="The ss58 address of the delegate hotkey to stake TAO to.",
|
2852
|
-
prompt="Enter the hotkey ss58 address you want to delegate TAO to.",
|
2853
|
-
),
|
2854
|
-
amount: Optional[float] = typer.Option(
|
2855
|
-
None, help="The amount of TAO to stake. Do no specify if using `--all`"
|
2856
|
-
),
|
2857
|
-
stake_all: Optional[bool] = typer.Option(
|
2858
|
-
False,
|
2859
|
-
"--all",
|
2860
|
-
"-a",
|
2861
|
-
help="If specified, the command stakes all available TAO. Do not specify if using"
|
2862
|
-
" `--amount`",
|
2863
|
-
),
|
2864
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2865
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2866
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2867
|
-
network: Optional[list[str]] = Options.network,
|
2868
|
-
prompt: bool = Options.prompt,
|
2869
|
-
quiet: bool = Options.quiet,
|
2870
|
-
verbose: bool = Options.verbose,
|
2871
|
-
):
|
2872
|
-
"""
|
2873
|
-
Stakes TAO to a specified delegate hotkey.
|
2874
|
-
|
2875
|
-
This command allocates the user's TAO to the specified hotkey of a delegate, potentially earning staking rewards in return. If the
|
2876
|
-
`--all` flag is used, it delegates the entire TAO balance available in the user's wallet.
|
2877
|
-
|
2878
|
-
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.
|
2879
|
-
|
2880
|
-
EXAMPLE
|
2881
|
-
|
2882
|
-
[green]$[/green] btcli root delegate-stake --delegate_ss58key <SS58_ADDRESS> --amount <AMOUNT>
|
2883
|
-
|
2884
|
-
[green]$[/green] btcli root delegate-stake --delegate_ss58key <SS58_ADDRESS> --all
|
2885
|
-
|
2886
|
-
[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.
|
2887
|
-
"""
|
2888
|
-
self.verbosity_handler(quiet, verbose)
|
2889
|
-
if amount and stake_all:
|
2890
|
-
err_console.print(
|
2891
|
-
"Both `--amount` and `--all` are specified. Choose one or the other."
|
2892
|
-
)
|
2893
|
-
if not stake_all and not amount:
|
2894
|
-
while True:
|
2895
|
-
amount = FloatPrompt.ask(
|
2896
|
-
"Amount to [blue]stake (TAO τ)[/blue]", console=console
|
2897
|
-
)
|
2898
|
-
confirmation = FloatPrompt.ask(
|
2899
|
-
"Confirm the amount to stake [blue](TAO τ)[/blue]",
|
2900
|
-
console=console,
|
2901
|
-
)
|
2902
|
-
if amount == confirmation:
|
2903
|
-
break
|
2904
|
-
else:
|
2905
|
-
err_console.print(
|
2906
|
-
"[red]The amounts do not match. Please try again.[/red]"
|
2907
|
-
)
|
2908
|
-
|
2909
|
-
wallet = self.wallet_ask(
|
2910
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2911
|
-
)
|
2912
|
-
return self._run_command(
|
2913
|
-
root.delegate_stake(
|
2914
|
-
wallet,
|
2915
|
-
self.initialize_chain(network),
|
2916
|
-
amount,
|
2917
|
-
delegate_ss58key,
|
2918
|
-
prompt,
|
2919
|
-
)
|
2920
|
-
)
|
2921
|
-
|
2922
|
-
def root_undelegate_stake(
|
2923
|
-
self,
|
2924
|
-
delegate_ss58key: str = typer.Option(
|
2925
|
-
None,
|
2926
|
-
help="The ss58 address of the delegate to undelegate from.",
|
2927
|
-
prompt="Enter the hotkey ss58 address you want to undelegate from",
|
2928
|
-
),
|
2929
|
-
amount: Optional[float] = typer.Option(
|
2930
|
-
None, help="The amount of TAO to unstake. Do no specify if using `--all`"
|
2931
|
-
),
|
2932
|
-
unstake_all: Optional[bool] = typer.Option(
|
2933
|
-
False,
|
2934
|
-
"--all",
|
2935
|
-
"-a",
|
2936
|
-
help="If specified, the command undelegates all staked TAO from the delegate. Do not specify if using"
|
2937
|
-
" `--amount`",
|
2938
|
-
),
|
2939
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2940
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2941
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2942
|
-
network: Optional[list[str]] = Options.network,
|
2943
|
-
prompt: bool = Options.prompt,
|
2944
|
-
quiet: bool = Options.quiet,
|
2945
|
-
verbose: bool = Options.verbose,
|
2946
|
-
):
|
2947
|
-
"""
|
2948
|
-
Allows users to withdraw their staked TAO from a delegate.
|
2949
|
-
|
2950
|
-
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.
|
2951
|
-
|
2952
|
-
EXAMPLE
|
2953
|
-
|
2954
|
-
[green]$[/green] btcli undelegate --delegate_ss58key <SS58_ADDRESS> --amount <AMOUNT>
|
2955
|
-
|
2956
|
-
[green]$[/green] btcli undelegate --delegate_ss58key <SS58_ADDRESS> --all
|
2957
|
-
"""
|
2958
|
-
self.verbosity_handler(quiet, verbose)
|
2959
|
-
if amount and unstake_all:
|
2960
|
-
err_console.print(
|
2961
|
-
"Both `--amount` and `--all` are specified. Choose one or the other."
|
2962
|
-
)
|
2963
|
-
if not unstake_all and not amount:
|
2964
|
-
while True:
|
2965
|
-
amount = FloatPrompt.ask(
|
2966
|
-
"Amount to [blue]unstake (TAO τ)[/blue]", console=console
|
2967
|
-
)
|
2968
|
-
confirmation = FloatPrompt.ask(
|
2969
|
-
"Confirm the amount to unstake [blue](TAO τ)[/blue]",
|
2970
|
-
console=console,
|
2971
|
-
)
|
2972
|
-
if amount == confirmation:
|
2973
|
-
break
|
2974
|
-
else:
|
2975
|
-
err_console.print(
|
2976
|
-
"[red]The amounts do not match. Please try again.[/red]"
|
2977
|
-
)
|
2978
|
-
|
2979
|
-
wallet = self.wallet_ask(
|
2980
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2981
|
-
)
|
2982
|
-
self._run_command(
|
2983
|
-
root.delegate_unstake(
|
2984
|
-
wallet,
|
2985
|
-
self.initialize_chain(network),
|
2986
|
-
amount,
|
2987
|
-
delegate_ss58key,
|
2988
|
-
prompt,
|
2989
|
-
)
|
2990
|
-
)
|
2991
|
-
|
2992
|
-
def root_my_delegates(
|
2993
|
-
self,
|
2994
|
-
network: Optional[list[str]] = Options.network,
|
2995
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
2996
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
2997
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
2998
|
-
all_wallets: bool = typer.Option(
|
2999
|
-
False,
|
3000
|
-
"--all-wallets",
|
3001
|
-
"--all",
|
3002
|
-
"-a",
|
3003
|
-
help="If specified, the command aggregates information across all the wallets.",
|
3004
|
-
),
|
3005
|
-
quiet: bool = Options.quiet,
|
3006
|
-
verbose: bool = Options.verbose,
|
3007
|
-
):
|
3008
|
-
"""
|
3009
|
-
Shows a table with the details on the user's delegates.
|
3010
|
-
|
3011
|
-
The table output includes the following columns:
|
3012
|
-
|
3013
|
-
- Wallet: The name of the user's wallet (coldkey).
|
3014
|
-
|
3015
|
-
- OWNER: The name of the delegate who owns the hotkey.
|
3016
|
-
|
3017
|
-
- SS58: The truncated SS58 address of the delegate's hotkey.
|
3018
|
-
|
3019
|
-
- Delegation: The amount of TAO staked by the user to the delegate.
|
3020
|
-
|
3021
|
-
- τ/24h: The earnings from the delegate to the user over the past 24 hours.
|
3022
|
-
|
3023
|
-
- NOMS: The number of nominators for the delegate.
|
3024
|
-
|
3025
|
-
- OWNER STAKE(τ): The stake amount owned by the delegate.
|
3026
|
-
|
3027
|
-
- TOTAL STAKE(τ): The total stake amount held by the delegate.
|
3028
|
-
|
3029
|
-
- SUBNETS: The list of subnets the delegate is a part of.
|
3030
|
-
|
3031
|
-
- VPERMIT: Validator permits held by the delegate for various subnets.
|
3032
|
-
|
3033
|
-
- 24h/kτ: Earnings per 1000 TAO staked over the last 24 hours.
|
3034
|
-
|
3035
|
-
- Desc: A description of the delegate.
|
3036
|
-
|
3037
|
-
The command also sums and prints the total amount of TAO delegated across all wallets.
|
3038
|
-
|
3039
|
-
EXAMPLE
|
3040
|
-
|
3041
|
-
[green]$[/green] btcli root my-delegates
|
3042
|
-
[green]$[/green] btcli root my-delegates --all
|
3043
|
-
[green]$[/green] btcli root my-delegates --wallet-name my_wallet
|
3044
|
-
|
3045
|
-
[blue bold]Note[/blue bold]: This command is not intended to be used directly in user code.
|
3046
|
-
"""
|
3047
|
-
self.verbosity_handler(quiet, verbose)
|
3048
|
-
wallet = self.wallet_ask(
|
3049
|
-
wallet_name,
|
3050
|
-
wallet_path,
|
3051
|
-
wallet_hotkey,
|
3052
|
-
ask_for=([WO.NAME] if not all_wallets else []),
|
3053
|
-
validate=WV.WALLET if not all_wallets else WV.NONE,
|
3054
|
-
)
|
3055
|
-
self._run_command(
|
3056
|
-
root.my_delegates(wallet, self.initialize_chain(network), all_wallets)
|
3057
|
-
)
|
3058
|
-
|
3059
|
-
def root_list_delegates(
|
3060
|
-
self,
|
3061
|
-
network: Optional[list[str]] = Options.network,
|
3062
|
-
quiet: bool = Options.quiet,
|
3063
|
-
verbose: bool = Options.verbose,
|
3064
|
-
):
|
3065
|
-
"""
|
3066
|
-
Displays a table of Bittensor network-wide delegates, providing a comprehensive overview of delegate statistics and information.
|
3067
|
-
|
3068
|
-
This table helps users make informed decisions on which delegates to allocate their TAO stake.
|
3069
|
-
|
3070
|
-
The table columns include:
|
3071
|
-
|
3072
|
-
- INDEX: The delegate's index in the sorted list.
|
3073
|
-
|
3074
|
-
- DELEGATE: The name of the delegate.
|
3075
|
-
|
3076
|
-
- SS58: The delegate's unique ss58 address (truncated for display).
|
3077
|
-
|
3078
|
-
- NOMINATORS: The count of nominators backing the delegate.
|
3079
|
-
|
3080
|
-
- OWN STAKE(τ): The amount of delegate's own stake (not the TAO delegated from any nominators).
|
3081
|
-
|
3082
|
-
- TOTAL STAKE(τ): The delegate's total stake, i.e., the sum of delegate's own stake and nominators' stakes.
|
3083
|
-
|
3084
|
-
- CHANGE/(4h): The percentage change in the delegate's stake over the last four hours.
|
3085
|
-
|
3086
|
-
- SUBNETS: The subnets in which the delegate is registered.
|
3087
|
-
|
3088
|
-
- VPERMIT: Indicates the subnets in which the delegate has validator permits.
|
3089
|
-
|
3090
|
-
- NOMINATOR/(24h)/kτ: The earnings per 1000 τ staked by nominators in the last 24 hours.
|
3091
|
-
|
3092
|
-
- DELEGATE/(24h): The total earnings of the delegate in the last 24 hours.
|
3093
|
-
|
3094
|
-
- DESCRIPTION: A brief description of the delegate's purpose and operations.
|
3095
|
-
|
3096
|
-
[blue bold]NOTES:[/blue bold]
|
3097
|
-
|
3098
|
-
- Sorting is done based on the `TOTAL STAKE` column in descending order.
|
3099
|
-
- Changes in stake are shown as: increases in green and decreases in red.
|
3100
|
-
- Entries with no previous data are marked with `NA`.
|
3101
|
-
- Each delegate's name is a hyperlink to more information, if available.
|
3102
|
-
|
3103
|
-
EXAMPLE
|
3104
|
-
|
3105
|
-
[green]$[/green] btcli root list_delegates
|
3106
|
-
|
3107
|
-
[green]$[/green] btcli root list_delegates --subtensor.network finney # can also be `test` or `local`
|
3108
|
-
|
3109
|
-
[blue bold]NOTE[/blue bold]: This command is intended for use within a
|
3110
|
-
console application. It prints directly to the console and does not return any value.
|
3111
|
-
"""
|
3112
|
-
self.verbosity_handler(quiet, verbose)
|
3113
|
-
|
3114
|
-
if network:
|
3115
|
-
if "finney" in network:
|
3116
|
-
network = ["wss://archive.chain.opentensor.ai:443"]
|
3117
|
-
elif (conf_net := self.config.get("network")) == "finney":
|
3118
|
-
network = ["wss://archive.chain.opentensor.ai:443"]
|
3119
|
-
elif conf_net:
|
3120
|
-
network = [conf_net]
|
3121
|
-
else:
|
3122
|
-
network = ["wss://archive.chain.opentensor.ai:443"]
|
3123
|
-
|
3124
|
-
sub = self.initialize_chain(network)
|
3125
|
-
return self._run_command(root.list_delegates(sub))
|
3126
|
-
|
3127
|
-
# TODO: Confirm if we need a command for this - currently registering to root auto makes u delegate
|
3128
|
-
def root_nominate(
|
3129
|
-
self,
|
3130
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
3131
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
3132
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3133
|
-
network: Optional[list[str]] = Options.network,
|
3134
|
-
prompt: bool = Options.prompt,
|
3135
|
-
quiet: bool = Options.quiet,
|
3136
|
-
verbose: bool = Options.verbose,
|
3137
|
-
):
|
3138
|
-
"""
|
3139
|
-
Enables a wallet's hotkey to become a delegate.
|
3140
|
-
|
3141
|
-
This command handles the nomination process, including wallet unlocking and verification of the hotkey's current delegate status.
|
3142
|
-
|
3143
|
-
The command performs several checks:
|
3144
|
-
|
3145
|
-
- Verifies that the hotkey is not already a delegate to prevent redundant nominations.
|
3146
|
-
|
3147
|
-
- Tries to nominate the wallet and reports success or failure.
|
3148
|
-
|
3149
|
-
Upon success, the wallet's hotkey is registered as a delegate on the network.
|
3150
|
-
|
3151
|
-
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.
|
3152
|
-
|
3153
|
-
EXAMPLE
|
3154
|
-
|
3155
|
-
[green]$[/green] btcli root nominate
|
3156
|
-
|
3157
|
-
[green]$[/green] btcli root nominate --wallet-name my_wallet --wallet-hotkey my_hotkey
|
3158
|
-
|
3159
|
-
[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.
|
3160
|
-
"""
|
3161
|
-
self.verbosity_handler(quiet, verbose)
|
3162
|
-
wallet = self.wallet_ask(
|
3163
|
-
wallet_name,
|
3164
|
-
wallet_path,
|
3165
|
-
wallet_hotkey,
|
3166
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3167
|
-
validate=WV.WALLET_AND_HOTKEY,
|
3168
|
-
)
|
3169
|
-
return self._run_command(
|
3170
|
-
root.nominate(wallet, self.initialize_chain(network), prompt)
|
3171
|
-
)
|
3172
|
-
|
3173
|
-
def stake_show(
|
3174
|
-
self,
|
3175
|
-
all_wallets: bool = typer.Option(
|
3176
|
-
False,
|
3177
|
-
"--all",
|
3178
|
-
"--all-wallets",
|
3179
|
-
"-a",
|
3180
|
-
help="When set, the command checks all the coldkey wallets of the user instead of just the specified wallet.",
|
3181
|
-
),
|
3182
|
-
network: Optional[list[str]] = Options.network,
|
3183
|
-
wallet_name: Optional[str] = Options.wallet_name,
|
3184
|
-
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3185
|
-
wallet_path: Optional[str] = Options.wallet_path,
|
3186
|
-
reuse_last: bool = Options.reuse_last,
|
3187
|
-
html_output: bool = Options.html_output,
|
3188
|
-
quiet: bool = Options.quiet,
|
3189
|
-
verbose: bool = Options.verbose,
|
3190
|
-
):
|
3191
|
-
"""
|
3192
|
-
Lists all the stake accounts associated with a user's wallet.
|
3193
|
-
|
3194
|
-
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.
|
3195
|
-
|
3196
|
-
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.
|
3197
|
-
|
3198
|
-
The command shows a table with the below columns:
|
3199
|
-
|
3200
|
-
- Coldkey: The coldkey associated with the wallet.
|
3201
|
-
|
3202
|
-
- Balance: The balance of the coldkey.
|
3203
|
-
|
3204
|
-
- Hotkey: The names of the coldkey's own hotkeys and the delegate hotkeys to which this coldkey has staked.
|
3205
|
-
|
3206
|
-
- Stake: The amount of TAO staked to all the hotkeys.
|
3207
|
-
|
3208
|
-
- Rate: The rate of return on the stake, shown in TAO per day.
|
3209
|
-
|
3210
|
-
EXAMPLE
|
3211
|
-
|
3212
|
-
[green]$[/green] btcli stake show --all
|
3213
|
-
"""
|
3214
|
-
self.verbosity_handler(quiet, verbose)
|
3215
|
-
if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
3216
|
-
err_console.print(
|
3217
|
-
"Unable to use `--reuse-last` or `--html` when config 'no-cache' is set to 'True'. "
|
3218
|
-
"Please change the config to 'False' using `btcli config set`"
|
3219
|
-
)
|
3220
|
-
raise typer.Exit()
|
3221
|
-
if not reuse_last:
|
3222
|
-
subtensor = self.initialize_chain(network)
|
3223
|
-
else:
|
3224
|
-
subtensor = None
|
3225
|
-
|
3226
|
-
if all_wallets:
|
3227
|
-
wallet = self.wallet_ask(
|
3228
|
-
wallet_name,
|
3229
|
-
wallet_path,
|
3230
|
-
wallet_hotkey,
|
3231
|
-
ask_for=[],
|
3232
|
-
validate=WV.NONE,
|
3233
|
-
)
|
3234
|
-
else:
|
3235
|
-
wallet = self.wallet_ask(
|
3236
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
3237
|
-
)
|
3238
|
-
|
3239
|
-
return self._run_command(
|
3240
|
-
stake.show(
|
3241
|
-
wallet,
|
3242
|
-
subtensor,
|
3243
|
-
all_wallets,
|
3244
|
-
reuse_last,
|
3245
|
-
html_output,
|
3246
|
-
not self.config.get("use_cache", True),
|
3247
|
-
)
|
3248
|
-
)
|
3249
|
-
|
3250
|
-
def stake_add(
|
3251
|
-
self,
|
3252
|
-
stake_all: bool = typer.Option(
|
3253
|
-
False,
|
3254
|
-
"--all-tokens",
|
3255
|
-
"--all",
|
3256
|
-
"-a",
|
3257
|
-
help="When set, the command stakes all the available TAO from the coldkey.",
|
3258
|
-
),
|
3259
|
-
amount: float = typer.Option(
|
3260
|
-
0.0, "--amount", help="The amount of TAO to stake"
|
3261
|
-
),
|
3262
|
-
max_stake: float = typer.Option(
|
3263
|
-
0.0,
|
3264
|
-
"--max-stake",
|
3265
|
-
"-m",
|
3266
|
-
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.",
|
3267
|
-
),
|
3268
|
-
hotkey_ss58_address: str = typer.Option(
|
3269
|
-
"",
|
3270
|
-
help="The ss58 address of the hotkey to stake to.",
|
3271
|
-
),
|
3272
|
-
include_hotkeys: str = typer.Option(
|
3273
|
-
"",
|
3274
|
-
"--include-hotkeys",
|
3275
|
-
"-in",
|
3276
|
-
help="Specifies hotkeys by name or ss58 address to stake to. For example, `-in hk1,hk2`",
|
3277
|
-
),
|
3278
|
-
exclude_hotkeys: str = typer.Option(
|
3279
|
-
"",
|
3280
|
-
"--exclude-hotkeys",
|
3281
|
-
"-ex",
|
3282
|
-
help="Specifies hotkeys by name or ss58 address to not to stake to (use this option only with `--all-hotkeys`)"
|
3283
|
-
" i.e. `--all-hotkeys -ex hk3,hk4`",
|
3284
|
-
),
|
3285
|
-
all_hotkeys: bool = typer.Option(
|
3286
|
-
False,
|
3287
|
-
help="When set, this command stakes to all hotkeys associated with the wallet. Do not use if specifying "
|
3288
|
-
"hotkeys in `--include-hotkeys`.",
|
3289
|
-
),
|
3290
|
-
wallet_name: str = Options.wallet_name,
|
3291
|
-
wallet_path: str = Options.wallet_path,
|
3292
|
-
wallet_hotkey: str = Options.wallet_hotkey,
|
3293
|
-
network: Optional[list[str]] = Options.network,
|
3294
|
-
prompt: bool = Options.prompt,
|
3295
|
-
quiet: bool = Options.quiet,
|
3296
|
-
verbose: bool = Options.verbose,
|
3297
|
-
):
|
3298
|
-
"""
|
3299
|
-
Stake TAO to one or more hotkeys associated with the user's coldkey.
|
2647
|
+
Stake TAO to one or more hotkeys associated with the user's coldkey.
|
3300
2648
|
|
3301
2649
|
This command is used by a subnet validator to stake to their own hotkey. Compare this command with "btcli root delegate" that is typically run by a TAO holder to delegate their TAO to a delegate's hotkey.
|
3302
2650
|
|
@@ -3307,16 +2655,14 @@ class CLIManager:
|
|
3307
2655
|
[green]$[/green] btcli stake add --amount 100 --wallet-name <my_wallet> --wallet-hotkey <my_hotkey>
|
3308
2656
|
"""
|
3309
2657
|
self.verbosity_handler(quiet, verbose)
|
2658
|
+
netuid = get_optional_netuid(netuid, all_netuids)
|
3310
2659
|
|
3311
2660
|
if stake_all and amount:
|
3312
|
-
|
2661
|
+
err_console.print(
|
3313
2662
|
"Cannot specify an amount and 'stake-all'. Choose one or the other."
|
3314
2663
|
)
|
3315
2664
|
raise typer.Exit()
|
3316
2665
|
|
3317
|
-
if not stake_all and not amount and not max_stake:
|
3318
|
-
amount = FloatPrompt.ask("Amount to [blue]stake (TAO τ)[/blue]")
|
3319
|
-
|
3320
2666
|
if stake_all and not amount:
|
3321
2667
|
if not Confirm.ask("Stake all the available TAO tokens?", default=False):
|
3322
2668
|
raise typer.Exit()
|
@@ -3334,40 +2680,66 @@ class CLIManager:
|
|
3334
2680
|
)
|
3335
2681
|
raise typer.Exit()
|
3336
2682
|
|
3337
|
-
if
|
3338
|
-
not
|
3339
|
-
|
3340
|
-
|
3341
|
-
|
3342
|
-
|
3343
|
-
|
3344
|
-
|
3345
|
-
|
3346
|
-
|
3347
|
-
|
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 == "":
|
3348
2700
|
wallet = self.wallet_ask(
|
3349
|
-
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]
|
3350
2720
|
)
|
2721
|
+
include_hotkeys = hotkey_or_ss58
|
3351
2722
|
else:
|
3352
2723
|
wallet_hotkey = hotkey_or_ss58
|
3353
2724
|
wallet = self.wallet_ask(
|
3354
2725
|
wallet_name,
|
3355
2726
|
wallet_path,
|
3356
2727
|
wallet_hotkey,
|
3357
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2728
|
+
ask_for=[WO.NAME, WO.HOTKEY, WO.PATH],
|
3358
2729
|
validate=WV.WALLET_AND_HOTKEY,
|
3359
2730
|
)
|
2731
|
+
include_hotkeys = wallet.hotkey.ss58_address
|
3360
2732
|
|
3361
|
-
elif all_hotkeys or include_hotkeys or exclude_hotkeys
|
2733
|
+
elif all_hotkeys or include_hotkeys or exclude_hotkeys:
|
3362
2734
|
wallet = self.wallet_ask(
|
3363
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2735
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3364
2736
|
)
|
3365
2737
|
else:
|
3366
2738
|
wallet = self.wallet_ask(
|
3367
2739
|
wallet_name,
|
3368
2740
|
wallet_path,
|
3369
2741
|
wallet_hotkey,
|
3370
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2742
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3371
2743
|
validate=WV.WALLET_AND_HOTKEY,
|
3372
2744
|
)
|
3373
2745
|
|
@@ -3375,8 +2747,8 @@ class CLIManager:
|
|
3375
2747
|
included_hotkeys = parse_to_list(
|
3376
2748
|
include_hotkeys,
|
3377
2749
|
str,
|
3378
|
-
"Hotkeys must be a comma-separated list of ss58s
|
3379
|
-
|
2750
|
+
"Hotkeys must be a comma-separated list of ss58s, e.g., `--include-hotkeys 5Grw....,5Grw....`.",
|
2751
|
+
is_ss58=True,
|
3380
2752
|
)
|
3381
2753
|
else:
|
3382
2754
|
included_hotkeys = []
|
@@ -3385,24 +2757,54 @@ class CLIManager:
|
|
3385
2757
|
excluded_hotkeys = parse_to_list(
|
3386
2758
|
exclude_hotkeys,
|
3387
2759
|
str,
|
3388
|
-
"Hotkeys must be a comma-separated list of ss58s
|
3389
|
-
|
2760
|
+
"Hotkeys must be a comma-separated list of ss58s, e.g., `--exclude-hotkeys 5Grw....,5Grw....`.",
|
2761
|
+
is_ss58=True,
|
3390
2762
|
)
|
3391
2763
|
else:
|
3392
2764
|
excluded_hotkeys = []
|
3393
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
|
+
|
3394
2795
|
return self._run_command(
|
3395
2796
|
stake.stake_add(
|
3396
2797
|
wallet,
|
3397
2798
|
self.initialize_chain(network),
|
3398
|
-
|
2799
|
+
netuid,
|
3399
2800
|
stake_all,
|
2801
|
+
amount,
|
2802
|
+
False,
|
2803
|
+
prompt,
|
3400
2804
|
max_stake,
|
2805
|
+
all_hotkeys,
|
3401
2806
|
included_hotkeys,
|
3402
2807
|
excluded_hotkeys,
|
3403
|
-
all_hotkeys,
|
3404
|
-
prompt,
|
3405
|
-
hotkey_ss58_address,
|
3406
2808
|
)
|
3407
2809
|
)
|
3408
2810
|
|
@@ -3412,11 +2814,21 @@ class CLIManager:
|
|
3412
2814
|
wallet_name: str = Options.wallet_name,
|
3413
2815
|
wallet_path: str = Options.wallet_path,
|
3414
2816
|
wallet_hotkey: str = Options.wallet_hotkey,
|
2817
|
+
netuid: Optional[int] = Options.netuid_not_req,
|
2818
|
+
all_netuids: bool = Options.all_netuids,
|
3415
2819
|
unstake_all: bool = typer.Option(
|
3416
2820
|
False,
|
3417
2821
|
"--unstake-all",
|
3418
2822
|
"--all",
|
3419
|
-
|
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.",
|
3420
2832
|
),
|
3421
2833
|
amount: float = typer.Option(
|
3422
2834
|
0.0, "--amount", "-a", help="The amount of TAO to unstake."
|
@@ -3450,6 +2862,12 @@ class CLIManager:
|
|
3450
2862
|
"hotkeys in `--include-hotkeys`.",
|
3451
2863
|
),
|
3452
2864
|
prompt: bool = Options.prompt,
|
2865
|
+
interactive: bool = typer.Option(
|
2866
|
+
False,
|
2867
|
+
"--interactive",
|
2868
|
+
"-i",
|
2869
|
+
help="Enter interactive mode for unstaking.",
|
2870
|
+
),
|
3453
2871
|
quiet: bool = Options.quiet,
|
3454
2872
|
verbose: bool = Options.verbose,
|
3455
2873
|
):
|
@@ -3465,31 +2883,45 @@ class CLIManager:
|
|
3465
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.
|
3466
2884
|
"""
|
3467
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
|
3468
2889
|
|
3469
|
-
if
|
2890
|
+
if interactive and any(
|
2891
|
+
[hotkey_ss58_address, include_hotkeys, exclude_hotkeys, all_hotkeys]
|
2892
|
+
):
|
3470
2893
|
err_console.print(
|
3471
|
-
"
|
3472
|
-
"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."
|
3473
2895
|
)
|
3474
2896
|
raise typer.Exit()
|
3475
2897
|
|
3476
|
-
if
|
3477
|
-
err_console.print(
|
3478
|
-
"You have specified both including and excluding hotkeys options. Select one or the other."
|
3479
|
-
)
|
2898
|
+
if unstake_all and unstake_all_alpha:
|
2899
|
+
err_console.print("Cannot specify both unstake-all and unstake-all-alpha.")
|
3480
2900
|
raise typer.Exit()
|
3481
2901
|
|
3482
|
-
if unstake_all and
|
3483
|
-
|
3484
|
-
|
3485
|
-
|
3486
|
-
|
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()
|
3487
2916
|
|
3488
|
-
|
3489
|
-
|
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()
|
3490
2922
|
|
3491
|
-
|
3492
|
-
|
2923
|
+
if amount and amount <= 0:
|
2924
|
+
print_error(f"You entered an incorrect unstake amount: {amount}")
|
3493
2925
|
raise typer.Exit()
|
3494
2926
|
|
3495
2927
|
if (
|
@@ -3497,14 +2929,27 @@ class CLIManager:
|
|
3497
2929
|
and not hotkey_ss58_address
|
3498
2930
|
and not all_hotkeys
|
3499
2931
|
and not include_hotkeys
|
2932
|
+
and not interactive
|
2933
|
+
and not unstake_all
|
2934
|
+
and not unstake_all_alpha
|
3500
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
|
+
)
|
3501
2941
|
hotkey_or_ss58 = Prompt.ask(
|
3502
|
-
"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]",
|
3503
2943
|
)
|
3504
|
-
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):
|
3505
2950
|
hotkey_ss58_address = hotkey_or_ss58
|
3506
2951
|
wallet = self.wallet_ask(
|
3507
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
2952
|
+
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
|
3508
2953
|
)
|
3509
2954
|
else:
|
3510
2955
|
wallet_hotkey = hotkey_or_ss58
|
@@ -3512,56 +2957,436 @@ class CLIManager:
|
|
3512
2957
|
wallet_name,
|
3513
2958
|
wallet_path,
|
3514
2959
|
wallet_hotkey,
|
3515
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
2960
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3516
2961
|
validate=WV.WALLET_AND_HOTKEY,
|
3517
2962
|
)
|
3518
2963
|
|
3519
|
-
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:
|
3520
2977
|
wallet = self.wallet_ask(
|
3521
|
-
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]"
|
3522
3249
|
)
|
3523
3250
|
|
3251
|
+
if is_valid_ss58_address(dest_ss58):
|
3252
|
+
dest_ss58 = dest_ss58
|
3524
3253
|
else:
|
3525
|
-
|
3526
|
-
|
3254
|
+
dest_wallet = self.wallet_ask(
|
3255
|
+
dest_ss58,
|
3527
3256
|
wallet_path,
|
3528
|
-
|
3529
|
-
ask_for=[WO.NAME, WO.
|
3530
|
-
validate=WV.
|
3257
|
+
None,
|
3258
|
+
ask_for=[WO.NAME, WO.PATH],
|
3259
|
+
validate=WV.WALLET,
|
3531
3260
|
)
|
3261
|
+
dest_ss58 = dest_wallet.coldkeypub.ss58_address
|
3532
3262
|
|
3533
|
-
|
3534
|
-
|
3535
|
-
|
3536
|
-
str,
|
3537
|
-
"Hotkeys must be a comma-separated list of ss58s or hotkey names, e.g., "
|
3538
|
-
"`--include-hotkeys 5Grw....,5Grw....`.",
|
3539
|
-
)
|
3263
|
+
interactive_selection = False
|
3264
|
+
if origin_netuid is None and dest_netuid is None and not amount:
|
3265
|
+
interactive_selection = True
|
3540
3266
|
else:
|
3541
|
-
|
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")
|
3542
3273
|
|
3543
|
-
|
3544
|
-
|
3545
|
-
|
3546
|
-
|
3547
|
-
|
3548
|
-
|
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,
|
3549
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
|
3550
3366
|
else:
|
3551
|
-
|
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")
|
3552
3377
|
|
3553
3378
|
return self._run_command(
|
3554
|
-
|
3555
|
-
wallet,
|
3556
|
-
self.initialize_chain(network),
|
3557
|
-
|
3558
|
-
|
3559
|
-
|
3560
|
-
|
3561
|
-
|
3562
|
-
|
3563
|
-
|
3564
|
-
|
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,
|
3565
3390
|
)
|
3566
3391
|
)
|
3567
3392
|
|
@@ -3601,7 +3426,7 @@ class CLIManager:
|
|
3601
3426
|
wallet_name,
|
3602
3427
|
wallet_path,
|
3603
3428
|
wallet_hotkey,
|
3604
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3429
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3605
3430
|
validate=WV.WALLET_AND_HOTKEY,
|
3606
3431
|
)
|
3607
3432
|
|
@@ -3632,18 +3457,8 @@ class CLIManager:
|
|
3632
3457
|
wallet_hotkey: str = Options.wallet_hotkey,
|
3633
3458
|
wallet_path: str = Options.wallet_path,
|
3634
3459
|
network: Optional[list[str]] = Options.network,
|
3635
|
-
netuid: Optional[int] =
|
3636
|
-
|
3637
|
-
help="The netuid of the subnet, (e.g. 4)",
|
3638
|
-
prompt=False,
|
3639
|
-
),
|
3640
|
-
all_netuids: bool = typer.Option(
|
3641
|
-
False,
|
3642
|
-
"--all-netuids",
|
3643
|
-
"--all",
|
3644
|
-
"--allnetuids",
|
3645
|
-
help="When this flag is used it sets child hotkeys on all subnets.",
|
3646
|
-
),
|
3460
|
+
netuid: Optional[int] = Options.netuid_not_req,
|
3461
|
+
all_netuids: bool = Options.all_netuids,
|
3647
3462
|
proportions: list[float] = typer.Option(
|
3648
3463
|
[],
|
3649
3464
|
"--proportions",
|
@@ -3656,10 +3471,9 @@ class CLIManager:
|
|
3656
3471
|
wait_for_finalization: bool = Options.wait_for_finalization,
|
3657
3472
|
quiet: bool = Options.quiet,
|
3658
3473
|
verbose: bool = Options.verbose,
|
3659
|
-
prompt: bool = Options.prompt,
|
3660
3474
|
):
|
3661
3475
|
"""
|
3662
|
-
Set child hotkeys on
|
3476
|
+
Set child hotkeys on specified subnets.
|
3663
3477
|
|
3664
3478
|
Users can specify the 'proportion' to delegate to child hotkeys (ss58 address). The sum of proportions cannot be greater than 1.
|
3665
3479
|
|
@@ -3670,15 +3484,8 @@ class CLIManager:
|
|
3670
3484
|
[green]$[/green] btcli stake child set -c 5FCL3gmjtQV4xxxxuEPEFQVhyyyyqYgNwX7drFLw7MSdBnxP -c 5Hp5dxxxxtGg7pu8dN2btyyyyVA1vELmM9dy8KQv3LxV8PA7 --hotkey default --netuid 1 -p 0.3 -p 0.7
|
3671
3485
|
"""
|
3672
3486
|
self.verbosity_handler(quiet, verbose)
|
3673
|
-
|
3674
|
-
|
3675
|
-
raise typer.Exit()
|
3676
|
-
if all_netuids:
|
3677
|
-
netuid = None
|
3678
|
-
elif not netuid:
|
3679
|
-
netuid = IntPrompt.ask(
|
3680
|
-
"Enter a netuid (leave blank for all)", default=None, show_default=True
|
3681
|
-
)
|
3487
|
+
netuid = get_optional_netuid(netuid, all_netuids)
|
3488
|
+
|
3682
3489
|
children = list_prompt(
|
3683
3490
|
children,
|
3684
3491
|
str,
|
@@ -3703,7 +3510,7 @@ class CLIManager:
|
|
3703
3510
|
wallet_name,
|
3704
3511
|
wallet_path,
|
3705
3512
|
wallet_hotkey,
|
3706
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3513
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3707
3514
|
validate=WV.WALLET_AND_HOTKEY,
|
3708
3515
|
)
|
3709
3516
|
return self._run_command(
|
@@ -3715,7 +3522,6 @@ class CLIManager:
|
|
3715
3522
|
proportions=proportions,
|
3716
3523
|
wait_for_finalization=wait_for_finalization,
|
3717
3524
|
wait_for_inclusion=wait_for_inclusion,
|
3718
|
-
prompt=prompt,
|
3719
3525
|
)
|
3720
3526
|
)
|
3721
3527
|
|
@@ -3741,10 +3547,9 @@ class CLIManager:
|
|
3741
3547
|
wait_for_finalization: bool = Options.wait_for_finalization,
|
3742
3548
|
quiet: bool = Options.quiet,
|
3743
3549
|
verbose: bool = Options.verbose,
|
3744
|
-
prompt: bool = Options.prompt,
|
3745
3550
|
):
|
3746
3551
|
"""
|
3747
|
-
Remove all children hotkeys on a specified subnet
|
3552
|
+
Remove all children hotkeys on a specified subnet.
|
3748
3553
|
|
3749
3554
|
This command is used to remove delegated authority from all child hotkeys, removing their position and influence on the subnet.
|
3750
3555
|
|
@@ -3757,7 +3562,7 @@ class CLIManager:
|
|
3757
3562
|
wallet_name,
|
3758
3563
|
wallet_path,
|
3759
3564
|
wallet_hotkey,
|
3760
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3565
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3761
3566
|
validate=WV.WALLET_AND_HOTKEY,
|
3762
3567
|
)
|
3763
3568
|
if all_netuids and netuid:
|
@@ -3776,7 +3581,6 @@ class CLIManager:
|
|
3776
3581
|
netuid,
|
3777
3582
|
wait_for_inclusion,
|
3778
3583
|
wait_for_finalization,
|
3779
|
-
prompt=prompt,
|
3780
3584
|
)
|
3781
3585
|
)
|
3782
3586
|
|
@@ -3813,153 +3617,308 @@ class CLIManager:
|
|
3813
3617
|
verbose: bool = Options.verbose,
|
3814
3618
|
):
|
3815
3619
|
"""
|
3816
|
-
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.
|
3817
3776
|
|
3818
|
-
|
3777
|
+
This command displays the details of ongoing proposals, including proposal hashes, votes, thresholds, and proposal data.
|
3819
3778
|
|
3820
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)))
|
3821
3784
|
|
3822
|
-
|
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.
|
3823
3810
|
|
3824
|
-
|
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.
|
3825
3812
|
|
3826
|
-
|
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.
|
3827
3815
|
|
3828
|
-
|
3816
|
+
EXAMPLE
|
3817
|
+
[green]$[/green] btcli sudo senate_vote --proposal <proposal_hash>
|
3829
3818
|
"""
|
3830
3819
|
self.verbosity_handler(quiet, verbose)
|
3831
3820
|
wallet = self.wallet_ask(
|
3832
3821
|
wallet_name,
|
3833
3822
|
wallet_path,
|
3834
3823
|
wallet_hotkey,
|
3835
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
3824
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
3836
3825
|
validate=WV.WALLET_AND_HOTKEY,
|
3837
3826
|
)
|
3838
|
-
if all_netuids and netuid:
|
3839
|
-
err_console.print("Specify either a netuid or '--all', not both.")
|
3840
|
-
raise typer.Exit()
|
3841
|
-
if all_netuids:
|
3842
|
-
netuid = None
|
3843
|
-
elif not netuid:
|
3844
|
-
netuid = IntPrompt.ask(
|
3845
|
-
"Enter netuid (leave blank for all)", default=None, show_default=True
|
3846
|
-
)
|
3847
3827
|
return self._run_command(
|
3848
|
-
|
3849
|
-
wallet
|
3850
|
-
subtensor=self.initialize_chain(network),
|
3851
|
-
netuid=netuid,
|
3852
|
-
take=take,
|
3853
|
-
hotkey=hotkey,
|
3854
|
-
wait_for_inclusion=wait_for_inclusion,
|
3855
|
-
wait_for_finalization=wait_for_finalization,
|
3856
|
-
prompt=prompt,
|
3828
|
+
sudo.senate_vote(
|
3829
|
+
wallet, self.initialize_chain(network), proposal, vote, prompt
|
3857
3830
|
)
|
3858
3831
|
)
|
3859
3832
|
|
3860
|
-
def
|
3833
|
+
def sudo_set_take(
|
3861
3834
|
self,
|
3862
3835
|
network: Optional[list[str]] = Options.network,
|
3863
|
-
wallet_name: str = Options.wallet_name,
|
3864
|
-
wallet_path: str = Options.wallet_path,
|
3865
|
-
wallet_hotkey: str = Options.wallet_hotkey,
|
3866
|
-
|
3867
|
-
param_name: str = typer.Option(
|
3868
|
-
"", "--param", "--parameter", help="The subnet hyperparameter to set"
|
3869
|
-
),
|
3870
|
-
param_value: str = typer.Option(
|
3871
|
-
"", "--value", help="Value to set the hyperparameter to."
|
3872
|
-
),
|
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."),
|
3873
3840
|
quiet: bool = Options.quiet,
|
3874
3841
|
verbose: bool = Options.verbose,
|
3875
3842
|
):
|
3876
3843
|
"""
|
3877
|
-
|
3844
|
+
Allows users to change their delegate take percentage.
|
3878
3845
|
|
3879
|
-
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.
|
3880
3848
|
|
3881
3849
|
EXAMPLE
|
3882
|
-
|
3883
|
-
[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
|
3884
3851
|
"""
|
3852
|
+
max_value = 0.18
|
3853
|
+
min_value = 0.00
|
3885
3854
|
self.verbosity_handler(quiet, verbose)
|
3886
3855
|
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
3891
|
-
|
3892
|
-
|
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
|
+
)
|
3893
3863
|
|
3894
|
-
|
3895
|
-
|
3896
|
-
|
3897
|
-
|
3898
|
-
console.print(f" {idx}. {param}")
|
3899
|
-
console.print()
|
3900
|
-
choice = IntPrompt.ask(
|
3901
|
-
"Enter the [bold]number[/bold] of the hyperparameter",
|
3902
|
-
choices=[str(i) for i in range(1, len(hyperparam_list) + 1)],
|
3903
|
-
show_choices=False,
|
3904
|
-
)
|
3905
|
-
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
|
+
)
|
3906
3868
|
|
3907
|
-
if
|
3908
|
-
|
3909
|
-
|
3910
|
-
"Enter the new value for [dark_orange]alpha_low[/dark_orange]"
|
3911
|
-
)
|
3912
|
-
high_val = FloatPrompt.ask(
|
3913
|
-
"Enter the new value for [dark_orange]alpha_high[/dark_orange]"
|
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}"
|
3914
3872
|
)
|
3915
|
-
|
3916
|
-
|
3917
|
-
|
3918
|
-
param_value = Prompt.ask(
|
3919
|
-
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}"
|
3920
3876
|
)
|
3877
|
+
raise typer.Exit()
|
3921
3878
|
|
3922
|
-
wallet = self.wallet_ask(
|
3923
|
-
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME]
|
3924
|
-
)
|
3925
3879
|
return self._run_command(
|
3926
|
-
sudo.
|
3927
|
-
wallet,
|
3928
|
-
self.initialize_chain(network),
|
3929
|
-
netuid,
|
3930
|
-
param_name,
|
3931
|
-
param_value,
|
3932
|
-
)
|
3880
|
+
sudo.set_take(wallet, self.initialize_chain(network), take)
|
3933
3881
|
)
|
3934
3882
|
|
3935
|
-
def
|
3883
|
+
def sudo_get_take(
|
3936
3884
|
self,
|
3937
3885
|
network: Optional[list[str]] = Options.network,
|
3938
|
-
|
3886
|
+
wallet_name: Optional[str] = Options.wallet_name,
|
3887
|
+
wallet_path: Optional[str] = Options.wallet_path,
|
3888
|
+
wallet_hotkey: Optional[str] = Options.wallet_hotkey,
|
3939
3889
|
quiet: bool = Options.quiet,
|
3940
3890
|
verbose: bool = Options.verbose,
|
3941
3891
|
):
|
3942
3892
|
"""
|
3943
|
-
|
3893
|
+
Allows users to check their delegate take percentage.
|
3944
3894
|
|
3945
|
-
|
3895
|
+
This command can be used to fetch the delegate take of your hotkey.
|
3946
3896
|
|
3947
3897
|
EXAMPLE
|
3948
|
-
|
3949
|
-
[green]$[/green] btcli sudo get --netuid 1
|
3898
|
+
[green]$[/green] btcli sudo get-take --wallet-name my_wallet --wallet-hotkey my_hotkey
|
3950
3899
|
"""
|
3951
3900
|
self.verbosity_handler(quiet, verbose)
|
3952
|
-
|
3953
|
-
|
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)
|
3954
3912
|
)
|
3955
3913
|
|
3956
3914
|
def subnets_list(
|
3957
3915
|
self,
|
3958
3916
|
network: Optional[list[str]] = Options.network,
|
3959
|
-
reuse_last: bool = Options.reuse_last,
|
3960
|
-
html_output: bool = Options.html_output,
|
3917
|
+
# reuse_last: bool = Options.reuse_last,
|
3918
|
+
# html_output: bool = Options.html_output,
|
3961
3919
|
quiet: bool = Options.quiet,
|
3962
3920
|
verbose: bool = Options.verbose,
|
3921
|
+
live_mode: bool = Options.live,
|
3963
3922
|
):
|
3964
3923
|
"""
|
3965
3924
|
List all subnets and their detailed information.
|
@@ -3980,48 +3939,189 @@ class CLIManager:
|
|
3980
3939
|
[green]$[/green] btcli subnets list
|
3981
3940
|
"""
|
3982
3941
|
self.verbosity_handler(quiet, verbose)
|
3983
|
-
if (reuse_last or html_output) and self.config.get("use_cache") is False:
|
3984
|
-
|
3985
|
-
|
3986
|
-
|
3987
|
-
|
3988
|
-
|
3989
|
-
if reuse_last:
|
3990
|
-
|
3991
|
-
else:
|
3992
|
-
|
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)
|
3993
3952
|
return self._run_command(
|
3994
3953
|
subnets.subnets_list(
|
3995
3954
|
subtensor,
|
3996
|
-
|
3997
|
-
|
3955
|
+
False, # reuse-last
|
3956
|
+
False, # html-output
|
3998
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,
|
3999
4073
|
)
|
4000
4074
|
)
|
4001
4075
|
|
4002
|
-
def
|
4076
|
+
def subnets_burn_cost(
|
4003
4077
|
self,
|
4004
4078
|
network: Optional[list[str]] = Options.network,
|
4005
4079
|
quiet: bool = Options.quiet,
|
4006
4080
|
verbose: bool = Options.verbose,
|
4007
4081
|
):
|
4008
4082
|
"""
|
4009
|
-
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.
|
4010
4084
|
|
4011
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.
|
4012
4086
|
|
4013
4087
|
EXAMPLE
|
4014
4088
|
|
4015
|
-
[green]$[/green] btcli subnets
|
4089
|
+
[green]$[/green] btcli subnets burn_cost
|
4016
4090
|
"""
|
4017
4091
|
self.verbosity_handler(quiet, verbose)
|
4018
|
-
return self._run_command(subnets.
|
4092
|
+
return self._run_command(subnets.burn_cost(self.initialize_chain(network)))
|
4019
4093
|
|
4020
4094
|
def subnets_create(
|
4021
4095
|
self,
|
4022
4096
|
wallet_name: str = Options.wallet_name,
|
4023
4097
|
wallet_path: str = Options.wallet_path,
|
4098
|
+
wallet_hotkey: str = Options.wallet_hotkey,
|
4024
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
|
+
),
|
4025
4125
|
prompt: bool = Options.prompt,
|
4026
4126
|
quiet: bool = Options.quiet,
|
4027
4127
|
verbose: bool = Options.verbose,
|
@@ -4037,13 +4137,44 @@ class CLIManager:
|
|
4037
4137
|
wallet = self.wallet_ask(
|
4038
4138
|
wallet_name,
|
4039
4139
|
wallet_path,
|
4040
|
-
|
4041
|
-
ask_for=[
|
4042
|
-
|
4140
|
+
wallet_hotkey,
|
4141
|
+
ask_for=[
|
4142
|
+
WO.NAME,
|
4143
|
+
WO.HOTKEY,
|
4144
|
+
WO.PATH,
|
4145
|
+
],
|
4146
|
+
validate=WV.WALLET_AND_HOTKEY,
|
4043
4147
|
)
|
4044
|
-
|
4045
|
-
|
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,
|
4046
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
|
+
)
|
4047
4178
|
|
4048
4179
|
def subnets_pow_register(
|
4049
4180
|
self,
|
@@ -4092,7 +4223,6 @@ class CLIManager:
|
|
4092
4223
|
"-tbp",
|
4093
4224
|
help="Set the number of threads per block for CUDA.",
|
4094
4225
|
),
|
4095
|
-
prompt: bool = Options.prompt,
|
4096
4226
|
):
|
4097
4227
|
"""
|
4098
4228
|
Register a neuron (a subnet validator or a subnet miner) using Proof of Work (POW).
|
@@ -4118,7 +4248,7 @@ class CLIManager:
|
|
4118
4248
|
wallet_name,
|
4119
4249
|
wallet_path,
|
4120
4250
|
wallet_hotkey,
|
4121
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4251
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4122
4252
|
validate=WV.WALLET_AND_HOTKEY,
|
4123
4253
|
),
|
4124
4254
|
self.initialize_chain(network),
|
@@ -4130,7 +4260,6 @@ class CLIManager:
|
|
4130
4260
|
use_cuda,
|
4131
4261
|
dev_id,
|
4132
4262
|
threads_per_block,
|
4133
|
-
prompt=prompt,
|
4134
4263
|
)
|
4135
4264
|
)
|
4136
4265
|
|
@@ -4161,7 +4290,7 @@ class CLIManager:
|
|
4161
4290
|
wallet_name,
|
4162
4291
|
wallet_path,
|
4163
4292
|
wallet_hotkey,
|
4164
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4293
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4165
4294
|
validate=WV.WALLET_AND_HOTKEY,
|
4166
4295
|
)
|
4167
4296
|
return self._run_command(
|
@@ -4247,6 +4376,12 @@ class CLIManager:
|
|
4247
4376
|
)
|
4248
4377
|
raise typer.Exit()
|
4249
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
|
+
|
4250
4385
|
if reuse_last:
|
4251
4386
|
if netuid is not None:
|
4252
4387
|
console.print("Cannot specify netuid when using `--reuse-last`")
|
@@ -4290,7 +4425,6 @@ class CLIManager:
|
|
4290
4425
|
),
|
4291
4426
|
quiet: bool = Options.quiet,
|
4292
4427
|
verbose: bool = Options.verbose,
|
4293
|
-
prompt: bool = Options.prompt,
|
4294
4428
|
):
|
4295
4429
|
"""
|
4296
4430
|
Reveal weights for a specific subnet.
|
@@ -4349,7 +4483,7 @@ class CLIManager:
|
|
4349
4483
|
wallet_name,
|
4350
4484
|
wallet_path,
|
4351
4485
|
wallet_hotkey,
|
4352
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4486
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4353
4487
|
validate=WV.WALLET_AND_HOTKEY,
|
4354
4488
|
)
|
4355
4489
|
|
@@ -4362,7 +4496,6 @@ class CLIManager:
|
|
4362
4496
|
weights,
|
4363
4497
|
salt,
|
4364
4498
|
__version_as_int__,
|
4365
|
-
prompt=prompt,
|
4366
4499
|
)
|
4367
4500
|
)
|
4368
4501
|
|
@@ -4388,7 +4521,6 @@ class CLIManager:
|
|
4388
4521
|
),
|
4389
4522
|
quiet: bool = Options.quiet,
|
4390
4523
|
verbose: bool = Options.verbose,
|
4391
|
-
prompt: bool = Options.prompt,
|
4392
4524
|
):
|
4393
4525
|
"""
|
4394
4526
|
|
@@ -4447,7 +4579,7 @@ class CLIManager:
|
|
4447
4579
|
wallet_name,
|
4448
4580
|
wallet_path,
|
4449
4581
|
wallet_hotkey,
|
4450
|
-
ask_for=[WO.NAME, WO.HOTKEY],
|
4582
|
+
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
|
4451
4583
|
validate=WV.WALLET_AND_HOTKEY,
|
4452
4584
|
)
|
4453
4585
|
return self._run_command(
|
@@ -4459,7 +4591,6 @@ class CLIManager:
|
|
4459
4591
|
weights,
|
4460
4592
|
salt,
|
4461
4593
|
__version_as_int__,
|
4462
|
-
prompt=prompt,
|
4463
4594
|
)
|
4464
4595
|
)
|
4465
4596
|
|