bittensor-cli 9.0.0rc4__py3-none-any.whl → 9.0.2__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 -3
- bittensor_cli/cli.py +254 -99
- bittensor_cli/src/__init__.py +50 -25
- bittensor_cli/src/bittensor/balances.py +1 -1
- bittensor_cli/src/bittensor/chain_data.py +20 -8
- bittensor_cli/src/bittensor/extrinsics/registration.py +26 -34
- bittensor_cli/src/bittensor/extrinsics/root.py +5 -11
- bittensor_cli/src/bittensor/extrinsics/transfer.py +15 -13
- bittensor_cli/src/bittensor/subtensor_interface.py +20 -20
- bittensor_cli/src/bittensor/utils.py +129 -19
- bittensor_cli/src/commands/stake/add.py +4 -8
- bittensor_cli/src/commands/stake/children_hotkeys.py +13 -19
- bittensor_cli/src/commands/stake/list.py +44 -77
- bittensor_cli/src/commands/stake/move.py +3 -3
- bittensor_cli/src/commands/stake/remove.py +216 -101
- bittensor_cli/src/commands/subnets/subnets.py +147 -5
- bittensor_cli/src/commands/sudo.py +192 -70
- bittensor_cli/src/commands/wallets.py +102 -52
- bittensor_cli/src/commands/weights.py +9 -13
- bittensor_cli/version.py +18 -0
- {bittensor_cli-9.0.0rc4.dist-info → bittensor_cli-9.0.2.dist-info}/METADATA +3 -3
- bittensor_cli-9.0.2.dist-info/RECORD +35 -0
- bittensor_cli-9.0.0rc4.dist-info/RECORD +0 -34
- {bittensor_cli-9.0.0rc4.dist-info → bittensor_cli-9.0.2.dist-info}/WHEEL +0 -0
- {bittensor_cli-9.0.0rc4.dist-info → bittensor_cli-9.0.2.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.0.0rc4.dist-info → bittensor_cli-9.0.2.dist-info}/top_level.txt +0 -0
bittensor_cli/src/__init__.py
CHANGED
@@ -4,12 +4,23 @@ from typing import Any, Optional
|
|
4
4
|
|
5
5
|
|
6
6
|
class Constants:
|
7
|
-
networks = [
|
7
|
+
networks = [
|
8
|
+
"local",
|
9
|
+
"finney",
|
10
|
+
"test",
|
11
|
+
"archive",
|
12
|
+
"subvortex",
|
13
|
+
"rao",
|
14
|
+
"dev",
|
15
|
+
"latent-lite",
|
16
|
+
]
|
8
17
|
finney_entrypoint = "wss://entrypoint-finney.opentensor.ai:443"
|
9
18
|
finney_test_entrypoint = "wss://test.finney.opentensor.ai:443"
|
10
19
|
archive_entrypoint = "wss://archive.chain.opentensor.ai:443"
|
20
|
+
subvortex_entrypoint = "ws://subvortex.info:9944"
|
21
|
+
local_entrypoint = "ws://127.0.0.1:9944"
|
11
22
|
rao_entrypoint = "wss://rao.chain.opentensor.ai:443"
|
12
|
-
dev_entrypoint = "wss://dev.chain.opentensor.ai:443
|
23
|
+
dev_entrypoint = "wss://dev.chain.opentensor.ai:443"
|
13
24
|
local_entrypoint = "ws://127.0.0.1:9944"
|
14
25
|
latent_lite_entrypoint = "wss://lite.sub.latent.to:443"
|
15
26
|
network_map = {
|
@@ -20,6 +31,7 @@ class Constants:
|
|
20
31
|
"dev": dev_entrypoint,
|
21
32
|
"rao": rao_entrypoint,
|
22
33
|
"latent-lite": latent_lite_entrypoint,
|
34
|
+
"subvortex": subvortex_entrypoint,
|
23
35
|
}
|
24
36
|
delegates_detail_url = "https://raw.githubusercontent.com/opentensor/bittensor-delegates/main/public/delegates.json"
|
25
37
|
|
@@ -100,7 +112,7 @@ class Defaults:
|
|
100
112
|
}
|
101
113
|
|
102
114
|
class subtensor:
|
103
|
-
network = "
|
115
|
+
network = "finney"
|
104
116
|
chain_endpoint = None
|
105
117
|
_mock = False
|
106
118
|
|
@@ -631,28 +643,40 @@ NETWORK_EXPLORER_MAP = {
|
|
631
643
|
|
632
644
|
|
633
645
|
HYPERPARAMS = {
|
634
|
-
|
635
|
-
"
|
636
|
-
"
|
637
|
-
"
|
638
|
-
"
|
639
|
-
"max_weights_limit": "sudo_set_max_weight_limit",
|
640
|
-
"
|
641
|
-
"
|
642
|
-
"
|
643
|
-
"
|
644
|
-
"
|
645
|
-
"
|
646
|
-
"
|
647
|
-
"
|
648
|
-
"
|
649
|
-
"
|
650
|
-
"
|
651
|
-
"
|
652
|
-
"
|
653
|
-
"
|
654
|
-
"
|
655
|
-
"
|
646
|
+
# btcli name: (subtensor method, root-only bool)
|
647
|
+
"rho": ("sudo_set_rho", False),
|
648
|
+
"kappa": ("sudo_set_kappa", False),
|
649
|
+
"immunity_period": ("sudo_set_immunity_period", False),
|
650
|
+
"min_allowed_weights": ("sudo_set_min_allowed_weights", False),
|
651
|
+
"max_weights_limit": ("sudo_set_max_weight_limit", False),
|
652
|
+
"tempo": ("sudo_set_tempo", True),
|
653
|
+
"min_difficulty": ("sudo_set_min_difficulty", False),
|
654
|
+
"max_difficulty": ("sudo_set_max_difficulty", False),
|
655
|
+
"weights_version": ("sudo_set_weights_version_key", False),
|
656
|
+
"weights_rate_limit": ("sudo_set_weights_set_rate_limit", False),
|
657
|
+
"adjustment_interval": ("sudo_set_adjustment_interval", True),
|
658
|
+
"activity_cutoff": ("sudo_set_activity_cutoff", False),
|
659
|
+
"target_regs_per_interval": ("sudo_set_target_registrations_per_interval", True),
|
660
|
+
"min_burn": ("sudo_set_min_burn", True),
|
661
|
+
"max_burn": ("sudo_set_max_burn", False),
|
662
|
+
"bonds_moving_avg": ("sudo_set_bonds_moving_average", False),
|
663
|
+
"max_regs_per_block": ("sudo_set_max_registrations_per_block", True),
|
664
|
+
"serving_rate_limit": ("sudo_set_serving_rate_limit", False),
|
665
|
+
"max_validators": ("sudo_set_max_allowed_validators", True),
|
666
|
+
"adjustment_alpha": ("sudo_set_adjustment_alpha", False),
|
667
|
+
"difficulty": ("sudo_set_difficulty", False),
|
668
|
+
"commit_reveal_period": (
|
669
|
+
"sudo_set_commit_reveal_weights_interval",
|
670
|
+
False,
|
671
|
+
),
|
672
|
+
"commit_reveal_weights_enabled": ("sudo_set_commit_reveal_weights_enabled", False),
|
673
|
+
"alpha_values": ("sudo_set_alpha_values", False),
|
674
|
+
"liquid_alpha_enabled": ("sudo_set_liquid_alpha_enabled", False),
|
675
|
+
"registration_allowed": ("sudo_set_network_registration_allowed", False),
|
676
|
+
"network_pow_registration_allowed": (
|
677
|
+
"sudo_set_network_pow_registration_allowed",
|
678
|
+
False,
|
679
|
+
),
|
656
680
|
}
|
657
681
|
|
658
682
|
# Help Panels for cli help
|
@@ -686,6 +710,7 @@ HELP_PANELS = {
|
|
686
710
|
"INFO": "Subnet Information",
|
687
711
|
"CREATION": "Subnet Creation & Management",
|
688
712
|
"REGISTER": "Neuron Registration",
|
713
|
+
"IDENTITY": "Subnet Identity Management",
|
689
714
|
},
|
690
715
|
"WEIGHTS": {"COMMIT_REVEAL": "Commit / Reveal"},
|
691
716
|
}
|
@@ -76,7 +76,7 @@ class Balance:
|
|
76
76
|
if self.unit == UNITS[0]:
|
77
77
|
return f"{self.unit} {float(self.tao):,.4f}"
|
78
78
|
else:
|
79
|
-
return f"{float(self.tao):,.4f} {self.unit}\u200e"
|
79
|
+
return f"\u200e{float(self.tao):,.4f} {self.unit}\u200e"
|
80
80
|
|
81
81
|
def __rich__(self):
|
82
82
|
return "[green]{}[/green][green]{}[/green][green].[/green][dim green]{}[/dim green]".format(
|
@@ -156,7 +156,7 @@ class SubnetHyperparameters(InfoBase):
|
|
156
156
|
def _fix_decoded(
|
157
157
|
cls, decoded: Union[dict, "SubnetHyperparameters"]
|
158
158
|
) -> "SubnetHyperparameters":
|
159
|
-
return
|
159
|
+
return cls(
|
160
160
|
rho=decoded.get("rho"),
|
161
161
|
kappa=decoded.get("kappa"),
|
162
162
|
immunity_period=decoded.get("immunity_period"),
|
@@ -197,6 +197,7 @@ class StakeInfo(InfoBase):
|
|
197
197
|
stake: Balance # Stake for the hotkey-coldkey pair
|
198
198
|
locked: Balance # Stake which is locked.
|
199
199
|
emission: Balance # Emission for the hotkey-coldkey pair
|
200
|
+
tao_emission: Balance # TAO emission for the hotkey-coldkey pair
|
200
201
|
drain: int
|
201
202
|
is_registered: bool
|
202
203
|
|
@@ -208,11 +209,20 @@ class StakeInfo(InfoBase):
|
|
208
209
|
stake = Balance.from_rao(decoded.get("stake")).set_unit(netuid)
|
209
210
|
locked = Balance.from_rao(decoded.get("locked")).set_unit(netuid)
|
210
211
|
emission = Balance.from_rao(decoded.get("emission")).set_unit(netuid)
|
212
|
+
tao_emission = Balance.from_rao(decoded.get("tao_emission"))
|
211
213
|
drain = int(decoded.get("drain"))
|
212
214
|
is_registered = bool(decoded.get("is_registered"))
|
213
215
|
|
214
|
-
return
|
215
|
-
hotkey,
|
216
|
+
return cls(
|
217
|
+
hotkey,
|
218
|
+
coldkey,
|
219
|
+
netuid,
|
220
|
+
stake,
|
221
|
+
locked,
|
222
|
+
emission,
|
223
|
+
tao_emission,
|
224
|
+
drain,
|
225
|
+
is_registered,
|
216
226
|
)
|
217
227
|
|
218
228
|
|
@@ -293,7 +303,7 @@ class NeuronInfo(InfoBase):
|
|
293
303
|
axon_info = decoded.get("axon_info", {})
|
294
304
|
coldkey = decode_account_id(decoded.get("coldkey"))
|
295
305
|
hotkey = decode_account_id(decoded.get("hotkey"))
|
296
|
-
return
|
306
|
+
return cls(
|
297
307
|
hotkey=hotkey,
|
298
308
|
coldkey=coldkey,
|
299
309
|
uid=decoded.get("uid"),
|
@@ -555,7 +565,7 @@ class SubnetInfo(InfoBase):
|
|
555
565
|
|
556
566
|
@classmethod
|
557
567
|
def _fix_decoded(cls, decoded: "SubnetInfo") -> "SubnetInfo":
|
558
|
-
return
|
568
|
+
return cls(
|
559
569
|
netuid=decoded.get("netuid"),
|
560
570
|
rho=decoded.get("rho"),
|
561
571
|
kappa=decoded.get("kappa"),
|
@@ -594,7 +604,7 @@ class SubnetIdentity(InfoBase):
|
|
594
604
|
|
595
605
|
@classmethod
|
596
606
|
def _fix_decoded(cls, decoded: dict) -> "SubnetIdentity":
|
597
|
-
return
|
607
|
+
return cls(
|
598
608
|
subnet_name=bytes(decoded["subnet_name"]).decode(),
|
599
609
|
github_repo=bytes(decoded["github_repo"]).decode(),
|
600
610
|
subnet_contact=bytes(decoded["subnet_contact"]).decode(),
|
@@ -750,7 +760,9 @@ class DynamicInfo(InfoBase):
|
|
750
760
|
)
|
751
761
|
return alpha_returned, slippage, slippage_pct_float
|
752
762
|
|
753
|
-
def alpha_to_tao_with_slippage(
|
763
|
+
def alpha_to_tao_with_slippage(
|
764
|
+
self, alpha: Balance
|
765
|
+
) -> tuple[Balance, Balance, float]:
|
754
766
|
"""
|
755
767
|
Returns an estimate of how much TAO would a staker receive if they unstake their alpha using the current pool state.
|
756
768
|
Args:
|
@@ -826,7 +838,7 @@ class SubnetState(InfoBase):
|
|
826
838
|
@classmethod
|
827
839
|
def _fix_decoded(cls, decoded: Any) -> "SubnetState":
|
828
840
|
netuid = decoded.get("netuid")
|
829
|
-
return
|
841
|
+
return cls(
|
830
842
|
netuid=netuid,
|
831
843
|
hotkeys=[decode_account_id(val) for val in decoded.get("hotkeys")],
|
832
844
|
coldkeys=[decode_account_id(val) for val in decoded.get("coldkeys")],
|
@@ -18,9 +18,7 @@ import typing
|
|
18
18
|
from typing import Optional
|
19
19
|
import subprocess
|
20
20
|
|
21
|
-
import backoff
|
22
21
|
from bittensor_wallet import Wallet
|
23
|
-
from bittensor_wallet.errors import KeyFileError
|
24
22
|
from Crypto.Hash import keccak
|
25
23
|
import numpy as np
|
26
24
|
from rich.prompt import Confirm
|
@@ -39,6 +37,8 @@ from bittensor_cli.src.bittensor.utils import (
|
|
39
37
|
get_human_readable,
|
40
38
|
print_verbose,
|
41
39
|
print_error,
|
40
|
+
unlock_key,
|
41
|
+
hex_to_bytes,
|
42
42
|
)
|
43
43
|
|
44
44
|
if typing.TYPE_CHECKING:
|
@@ -616,10 +616,7 @@ async def register_extrinsic(
|
|
616
616
|
if not success:
|
617
617
|
success, err_msg = (
|
618
618
|
False,
|
619
|
-
format_error_message(
|
620
|
-
await response.error_message,
|
621
|
-
substrate=subtensor.substrate,
|
622
|
-
),
|
619
|
+
format_error_message(await response.error_message),
|
623
620
|
)
|
624
621
|
# Look error here
|
625
622
|
# https://github.com/opentensor/subtensor/blob/development/pallets/subtensor/src/errors.rs
|
@@ -697,11 +694,8 @@ async def burned_register_extrinsic(
|
|
697
694
|
finalization/inclusion, the response is `True`.
|
698
695
|
"""
|
699
696
|
|
700
|
-
|
701
|
-
|
702
|
-
except KeyFileError:
|
703
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
704
|
-
return False
|
697
|
+
if not (unlock_status := unlock_key(wallet, print_out=False)).success:
|
698
|
+
return False, unlock_status.message
|
705
699
|
|
706
700
|
with console.status(
|
707
701
|
f":satellite: Checking Account on [bold]subnet:{netuid}[/bold]...",
|
@@ -796,7 +790,7 @@ async def run_faucet_extrinsic(
|
|
796
790
|
tpb: int = 256,
|
797
791
|
num_processes: Optional[int] = None,
|
798
792
|
update_interval: Optional[int] = None,
|
799
|
-
log_verbose: bool =
|
793
|
+
log_verbose: bool = True,
|
800
794
|
max_successes: int = 3,
|
801
795
|
) -> tuple[bool, str]:
|
802
796
|
r"""Runs a continual POW to get a faucet of TAO on the test net.
|
@@ -835,10 +829,8 @@ async def run_faucet_extrinsic(
|
|
835
829
|
return False, "Requires torch"
|
836
830
|
|
837
831
|
# Unlock coldkey
|
838
|
-
|
839
|
-
|
840
|
-
except KeyFileError:
|
841
|
-
return False, "There was an error unlocking your coldkey"
|
832
|
+
if not (unlock_status := unlock_key(wallet, print_out=False)).success:
|
833
|
+
return False, unlock_status.message
|
842
834
|
|
843
835
|
# Get previous balance.
|
844
836
|
old_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
|
@@ -846,8 +838,12 @@ async def run_faucet_extrinsic(
|
|
846
838
|
# Attempt rolling registration.
|
847
839
|
attempts = 1
|
848
840
|
successes = 1
|
841
|
+
pow_result: Optional[POWSolution]
|
849
842
|
while True:
|
850
843
|
try:
|
844
|
+
account_nonce = await subtensor.substrate.get_account_nonce(
|
845
|
+
wallet.coldkey.ss58_address
|
846
|
+
)
|
851
847
|
pow_result = None
|
852
848
|
while pow_result is None or await pow_result.is_stale(subtensor=subtensor):
|
853
849
|
# Solve latest POW.
|
@@ -856,7 +852,7 @@ async def run_faucet_extrinsic(
|
|
856
852
|
if prompt:
|
857
853
|
err_console.print("CUDA is not available.")
|
858
854
|
return False, "CUDA is not available."
|
859
|
-
pow_result
|
855
|
+
pow_result = await create_pow(
|
860
856
|
subtensor,
|
861
857
|
wallet,
|
862
858
|
-1,
|
@@ -869,7 +865,7 @@ async def run_faucet_extrinsic(
|
|
869
865
|
log_verbose=log_verbose,
|
870
866
|
)
|
871
867
|
else:
|
872
|
-
pow_result
|
868
|
+
pow_result = await create_pow(
|
873
869
|
subtensor,
|
874
870
|
wallet,
|
875
871
|
-1,
|
@@ -889,7 +885,7 @@ async def run_faucet_extrinsic(
|
|
889
885
|
},
|
890
886
|
)
|
891
887
|
extrinsic = await subtensor.substrate.create_signed_extrinsic(
|
892
|
-
call=call, keypair=wallet.coldkey
|
888
|
+
call=call, keypair=wallet.coldkey, nonce=account_nonce
|
893
889
|
)
|
894
890
|
response = await subtensor.substrate.submit_extrinsic(
|
895
891
|
extrinsic,
|
@@ -902,7 +898,7 @@ async def run_faucet_extrinsic(
|
|
902
898
|
if not await response.is_success:
|
903
899
|
err_console.print(
|
904
900
|
f":cross_mark: [red]Failed[/red]: "
|
905
|
-
f"{format_error_message(await response.error_message
|
901
|
+
f"{format_error_message(await response.error_message)}"
|
906
902
|
)
|
907
903
|
if attempts == max_allowed_attempts:
|
908
904
|
raise MaxAttemptsException
|
@@ -974,7 +970,7 @@ async def _check_for_newest_block_and_update(
|
|
974
970
|
block_number, difficulty, block_hash = await _get_block_with_retry(
|
975
971
|
subtensor=subtensor, netuid=netuid
|
976
972
|
)
|
977
|
-
block_bytes =
|
973
|
+
block_bytes = hex_to_bytes(block_hash)
|
978
974
|
|
979
975
|
update_curr_block(
|
980
976
|
curr_diff,
|
@@ -1027,6 +1023,9 @@ async def _block_solver(
|
|
1027
1023
|
stop_event.clear()
|
1028
1024
|
|
1029
1025
|
solution_queue = Queue()
|
1026
|
+
if cuda:
|
1027
|
+
num_processes = len(dev_id)
|
1028
|
+
|
1030
1029
|
finished_queues = [Queue() for _ in range(num_processes)]
|
1031
1030
|
check_block = Lock()
|
1032
1031
|
|
@@ -1036,7 +1035,6 @@ async def _block_solver(
|
|
1036
1035
|
|
1037
1036
|
if cuda:
|
1038
1037
|
# Create a worker per CUDA device
|
1039
|
-
num_processes = len(dev_id)
|
1040
1038
|
solvers = [
|
1041
1039
|
_CUDASolver(
|
1042
1040
|
i,
|
@@ -1079,7 +1077,7 @@ async def _block_solver(
|
|
1079
1077
|
subtensor=subtensor, netuid=netuid
|
1080
1078
|
)
|
1081
1079
|
|
1082
|
-
block_bytes =
|
1080
|
+
block_bytes = hex_to_bytes(block_hash)
|
1083
1081
|
old_block_number = block_number
|
1084
1082
|
# Set to current block
|
1085
1083
|
_update_curr_block(
|
@@ -1354,11 +1352,9 @@ def _terminate_workers_and_wait_for_exit(
|
|
1354
1352
|
worker.terminate()
|
1355
1353
|
|
1356
1354
|
|
1357
|
-
# TODO verify this works with async
|
1358
|
-
@backoff.on_exception(backoff.constant, Exception, interval=1, max_tries=3)
|
1359
1355
|
async def _get_block_with_retry(
|
1360
1356
|
subtensor: "SubtensorInterface", netuid: int
|
1361
|
-
) -> tuple[int, int,
|
1357
|
+
) -> tuple[int, int, str]:
|
1362
1358
|
"""
|
1363
1359
|
Gets the current block number, difficulty, and block hash from the substrate node.
|
1364
1360
|
|
@@ -1370,10 +1366,9 @@ async def _get_block_with_retry(
|
|
1370
1366
|
:raises Exception: If the block hash is None.
|
1371
1367
|
:raises ValueError: If the difficulty is None.
|
1372
1368
|
"""
|
1373
|
-
|
1374
|
-
block_hash =
|
1375
|
-
|
1376
|
-
) # TODO check if I need to do all this
|
1369
|
+
block = await subtensor.substrate.get_block()
|
1370
|
+
block_hash = block["header"]["hash"]
|
1371
|
+
block_number = block["header"]["number"]
|
1377
1372
|
try:
|
1378
1373
|
difficulty = (
|
1379
1374
|
1_000_000
|
@@ -1746,10 +1741,7 @@ async def swap_hotkey_extrinsic(
|
|
1746
1741
|
)
|
1747
1742
|
return False
|
1748
1743
|
|
1749
|
-
|
1750
|
-
wallet.unlock_coldkey()
|
1751
|
-
except KeyFileError:
|
1752
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
1744
|
+
if not unlock_key(wallet).success:
|
1753
1745
|
return False
|
1754
1746
|
|
1755
1747
|
if prompt:
|
@@ -21,7 +21,6 @@ import time
|
|
21
21
|
from typing import Union, List, TYPE_CHECKING
|
22
22
|
|
23
23
|
from bittensor_wallet import Wallet, Keypair
|
24
|
-
from bittensor_wallet.errors import KeyFileError
|
25
24
|
import numpy as np
|
26
25
|
from numpy.typing import NDArray
|
27
26
|
from rich.prompt import Confirm
|
@@ -37,6 +36,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
37
36
|
u16_normalized_float,
|
38
37
|
print_verbose,
|
39
38
|
format_error_message,
|
39
|
+
unlock_key,
|
40
40
|
)
|
41
41
|
|
42
42
|
if TYPE_CHECKING:
|
@@ -306,10 +306,7 @@ async def root_register_extrinsic(
|
|
306
306
|
the response is `True`.
|
307
307
|
"""
|
308
308
|
|
309
|
-
|
310
|
-
wallet.unlock_coldkey()
|
311
|
-
except KeyFileError:
|
312
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
309
|
+
if not unlock_key(wallet).success:
|
313
310
|
return False
|
314
311
|
|
315
312
|
print_verbose(f"Checking if hotkey ({wallet.hotkey_str}) is registered on root")
|
@@ -427,10 +424,7 @@ async def set_root_weights_extrinsic(
|
|
427
424
|
err_console.print("Your hotkey is not registered to the root network")
|
428
425
|
return False
|
429
426
|
|
430
|
-
|
431
|
-
wallet.unlock_coldkey()
|
432
|
-
except KeyFileError:
|
433
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
427
|
+
if not unlock_key(wallet).success:
|
434
428
|
return False
|
435
429
|
|
436
430
|
# First convert types.
|
@@ -492,11 +486,11 @@ async def set_root_weights_extrinsic(
|
|
492
486
|
console.print(":white_heavy_check_mark: [green]Finalized[/green]")
|
493
487
|
return True
|
494
488
|
else:
|
495
|
-
fmt_err = format_error_message(error_message
|
489
|
+
fmt_err = format_error_message(error_message)
|
496
490
|
err_console.print(f":cross_mark: [red]Failed[/red]: {fmt_err}")
|
497
491
|
return False
|
498
492
|
|
499
493
|
except SubstrateRequestException as e:
|
500
|
-
fmt_err = format_error_message(e
|
494
|
+
fmt_err = format_error_message(e)
|
501
495
|
err_console.print(":cross_mark: [red]Failed[/red]: error:{}".format(fmt_err))
|
502
496
|
return False
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import asyncio
|
2
2
|
|
3
3
|
from bittensor_wallet import Wallet
|
4
|
-
from bittensor_wallet.errors import KeyFileError
|
5
4
|
from rich.prompt import Confirm
|
6
5
|
from async_substrate_interface.errors import SubstrateRequestException
|
7
6
|
|
@@ -15,6 +14,8 @@ from bittensor_cli.src.bittensor.utils import (
|
|
15
14
|
format_error_message,
|
16
15
|
get_explorer_url_for_network,
|
17
16
|
is_valid_bittensor_address_or_public_key,
|
17
|
+
print_error,
|
18
|
+
unlock_key,
|
18
19
|
)
|
19
20
|
|
20
21
|
|
@@ -23,6 +24,7 @@ async def transfer_extrinsic(
|
|
23
24
|
wallet: Wallet,
|
24
25
|
destination: str,
|
25
26
|
amount: Balance,
|
27
|
+
transfer_all: bool = False,
|
26
28
|
wait_for_inclusion: bool = True,
|
27
29
|
wait_for_finalization: bool = False,
|
28
30
|
keep_alive: bool = True,
|
@@ -34,6 +36,7 @@ async def transfer_extrinsic(
|
|
34
36
|
:param wallet: Bittensor wallet object to make transfer from.
|
35
37
|
:param destination: Destination public key address (ss58_address or ed25519) of recipient.
|
36
38
|
:param amount: Amount to stake as Bittensor balance.
|
39
|
+
:param transfer_all: Whether to transfer all funds from this wallet to the destination address.
|
37
40
|
:param wait_for_inclusion: If set, waits for the extrinsic to enter a block before returning `True`,
|
38
41
|
or returns `False` if the extrinsic fails to enter the block within the timeout.
|
39
42
|
:param wait_for_finalization: If set, waits for the extrinsic to be finalized on the chain before returning
|
@@ -63,9 +66,9 @@ async def transfer_extrinsic(
|
|
63
66
|
except SubstrateRequestException as e:
|
64
67
|
payment_info = {"partial_fee": int(2e7)} # assume 0.02 Tao
|
65
68
|
err_console.print(
|
66
|
-
f":cross_mark: [red]Failed to get payment info[/red]
|
67
|
-
f"
|
68
|
-
f" Defaulting to default transfer fee: {payment_info['
|
69
|
+
f":cross_mark: [red]Failed to get payment info[/red]:[bold white]\n"
|
70
|
+
f" {format_error_message(e)}[/bold white]\n"
|
71
|
+
f" Defaulting to default transfer fee: {payment_info['partialFee']}"
|
69
72
|
)
|
70
73
|
|
71
74
|
return Balance.from_rao(payment_info["partial_fee"])
|
@@ -98,11 +101,7 @@ async def transfer_extrinsic(
|
|
98
101
|
block_hash_ = response.block_hash
|
99
102
|
return True, block_hash_, ""
|
100
103
|
else:
|
101
|
-
return (
|
102
|
-
False,
|
103
|
-
"",
|
104
|
-
format_error_message(await response.error_message, subtensor.substrate),
|
105
|
-
)
|
104
|
+
return False, "", format_error_message(await response.error_message)
|
106
105
|
|
107
106
|
# Validate destination address.
|
108
107
|
if not is_valid_bittensor_address_or_public_key(destination):
|
@@ -112,10 +111,7 @@ async def transfer_extrinsic(
|
|
112
111
|
return False
|
113
112
|
console.print(f"[dark_orange]Initiating transfer on network: {subtensor.network}")
|
114
113
|
# Unlock wallet coldkey.
|
115
|
-
|
116
|
-
wallet.unlock_coldkey()
|
117
|
-
except KeyFileError:
|
118
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
114
|
+
if not unlock_key(wallet).success:
|
119
115
|
return False
|
120
116
|
|
121
117
|
# Check balance.
|
@@ -139,6 +135,12 @@ async def transfer_extrinsic(
|
|
139
135
|
existential_deposit = Balance(0)
|
140
136
|
|
141
137
|
# Check if we have enough balance.
|
138
|
+
if transfer_all is True:
|
139
|
+
amount = account_balance - fee - existential_deposit
|
140
|
+
if amount < Balance(0):
|
141
|
+
print_error("Not enough balance to transfer")
|
142
|
+
return False
|
143
|
+
|
142
144
|
if account_balance < (amount + fee + existential_deposit):
|
143
145
|
err_console.print(
|
144
146
|
":cross_mark: [bold red]Not enough balance[/bold red]:\n\n"
|
@@ -112,8 +112,8 @@ class SubtensorInterface:
|
|
112
112
|
f"[yellow]Connecting to Substrate:[/yellow][bold white] {self}..."
|
113
113
|
):
|
114
114
|
try:
|
115
|
-
|
116
|
-
|
115
|
+
await self.substrate.initialize()
|
116
|
+
return self
|
117
117
|
except TimeoutError: # TODO verify
|
118
118
|
err_console.print(
|
119
119
|
"\n[red]Error[/red]: Timeout occurred connecting to substrate. "
|
@@ -352,7 +352,7 @@ class SubtensorInterface:
|
|
352
352
|
*ss58_addresses,
|
353
353
|
block_hash: Optional[str] = None,
|
354
354
|
reuse_block: bool = False,
|
355
|
-
) -> dict[str, Balance]:
|
355
|
+
) -> dict[str, tuple[Balance, Balance]]:
|
356
356
|
"""
|
357
357
|
Returns the total stake held on a coldkey.
|
358
358
|
|
@@ -370,7 +370,8 @@ class SubtensorInterface:
|
|
370
370
|
|
371
371
|
results = {}
|
372
372
|
for ss58, stake_info_list in sub_stakes.items():
|
373
|
-
|
373
|
+
total_tao_value = Balance(0)
|
374
|
+
total_swapped_tao_value = Balance(0)
|
374
375
|
for sub_stake in stake_info_list:
|
375
376
|
if sub_stake.stake.rao == 0:
|
376
377
|
continue
|
@@ -381,19 +382,20 @@ class SubtensorInterface:
|
|
381
382
|
netuid
|
382
383
|
)
|
383
384
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
tao_ownership = Balance(0)
|
385
|
+
# Without slippage
|
386
|
+
tao_value = pool.alpha_to_tao(alpha_value)
|
387
|
+
total_tao_value += tao_value
|
388
388
|
|
389
|
-
|
390
|
-
|
391
|
-
|
389
|
+
# With slippage
|
390
|
+
if netuid == 0:
|
391
|
+
swapped_tao_value = tao_value
|
392
|
+
else:
|
393
|
+
swapped_tao_value, _, _ = pool.alpha_to_tao_with_slippage(
|
394
|
+
sub_stake.stake
|
392
395
|
)
|
396
|
+
total_swapped_tao_value += swapped_tao_value
|
393
397
|
|
394
|
-
|
395
|
-
|
396
|
-
results[ss58] = Balance.from_rao(all_staked_tao)
|
398
|
+
results[ss58] = (total_tao_value, total_swapped_tao_value)
|
397
399
|
return results
|
398
400
|
|
399
401
|
async def get_total_stake_for_hotkey(
|
@@ -402,7 +404,7 @@ class SubtensorInterface:
|
|
402
404
|
netuids: Optional[list[int]] = None,
|
403
405
|
block_hash: Optional[str] = None,
|
404
406
|
reuse_block: bool = False,
|
405
|
-
) -> dict[str, dict[int,
|
407
|
+
) -> dict[str, dict[int, Balance]]:
|
406
408
|
"""
|
407
409
|
Returns the total stake held on a hotkey.
|
408
410
|
|
@@ -1064,11 +1066,9 @@ class SubtensorInterface:
|
|
1064
1066
|
if await response.is_success:
|
1065
1067
|
return True, ""
|
1066
1068
|
else:
|
1067
|
-
return False, format_error_message(
|
1068
|
-
await response.error_message, substrate=self.substrate
|
1069
|
-
)
|
1069
|
+
return False, format_error_message(await response.error_message)
|
1070
1070
|
except SubstrateRequestException as e:
|
1071
|
-
return False, format_error_message(e
|
1071
|
+
return False, format_error_message(e)
|
1072
1072
|
|
1073
1073
|
async def get_children(self, hotkey, netuid) -> tuple[bool, list, str]:
|
1074
1074
|
"""
|
@@ -1098,7 +1098,7 @@ class SubtensorInterface:
|
|
1098
1098
|
else:
|
1099
1099
|
return True, [], ""
|
1100
1100
|
except SubstrateRequestException as e:
|
1101
|
-
return False, [], format_error_message(e
|
1101
|
+
return False, [], format_error_message(e)
|
1102
1102
|
|
1103
1103
|
async def get_subnet_hyperparameters(
|
1104
1104
|
self, netuid: int, block_hash: Optional[str] = None
|