bittensor-cli 9.0.2__py3-none-any.whl → 9.1.0__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/cli.py +84 -18
- bittensor_cli/src/__init__.py +3 -0
- bittensor_cli/src/bittensor/balances.py +5 -6
- bittensor_cli/src/bittensor/chain_data.py +287 -25
- bittensor_cli/src/bittensor/subtensor_interface.py +54 -12
- bittensor_cli/src/bittensor/utils.py +13 -2
- bittensor_cli/src/commands/stake/add.py +2 -4
- bittensor_cli/src/commands/stake/children_hotkeys.py +2 -0
- bittensor_cli/src/commands/stake/move.py +17 -24
- bittensor_cli/src/commands/stake/remove.py +3 -8
- bittensor_cli/src/commands/subnets/subnets.py +6 -7
- bittensor_cli/src/commands/sudo.py +5 -0
- bittensor_cli/src/commands/view.py +2876 -0
- bittensor_cli/version.py +2 -1
- {bittensor_cli-9.0.2.dist-info → bittensor_cli-9.1.0.dist-info}/METADATA +1 -1
- {bittensor_cli-9.0.2.dist-info → bittensor_cli-9.1.0.dist-info}/RECORD +19 -18
- {bittensor_cli-9.0.2.dist-info → bittensor_cli-9.1.0.dist-info}/WHEEL +0 -0
- {bittensor_cli-9.0.2.dist-info → bittensor_cli-9.1.0.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.0.2.dist-info → bittensor_cli-9.1.0.dist-info}/top_level.txt +0 -0
@@ -20,6 +20,7 @@ from bittensor_cli.src.bittensor.chain_data import (
|
|
20
20
|
decode_hex_identity,
|
21
21
|
DynamicInfo,
|
22
22
|
SubnetState,
|
23
|
+
MetagraphInfo,
|
23
24
|
)
|
24
25
|
from bittensor_cli.src import DelegatesDetails
|
25
26
|
from bittensor_cli.src.bittensor.balances import Balance, fixed_to_float
|
@@ -1252,6 +1253,38 @@ class SubtensorInterface:
|
|
1252
1253
|
else:
|
1253
1254
|
return Balance.from_rao(_result).set_unit(int(netuid))
|
1254
1255
|
|
1256
|
+
async def get_metagraph_info(
|
1257
|
+
self, netuid: int, block_hash: Optional[str] = None
|
1258
|
+
) -> Optional[MetagraphInfo]:
|
1259
|
+
hex_bytes_result = await self.query_runtime_api(
|
1260
|
+
runtime_api="SubnetInfoRuntimeApi",
|
1261
|
+
method="get_metagraph",
|
1262
|
+
params=[netuid],
|
1263
|
+
block_hash=block_hash,
|
1264
|
+
)
|
1265
|
+
|
1266
|
+
if hex_bytes_result is None:
|
1267
|
+
return None
|
1268
|
+
|
1269
|
+
try:
|
1270
|
+
bytes_result = bytes.fromhex(hex_bytes_result[2:])
|
1271
|
+
except ValueError:
|
1272
|
+
bytes_result = bytes.fromhex(hex_bytes_result)
|
1273
|
+
|
1274
|
+
return MetagraphInfo.from_any(bytes_result)
|
1275
|
+
|
1276
|
+
async def get_all_metagraphs_info(
|
1277
|
+
self, block_hash: Optional[str] = None
|
1278
|
+
) -> list[MetagraphInfo]:
|
1279
|
+
hex_bytes_result = await self.query_runtime_api(
|
1280
|
+
runtime_api="SubnetInfoRuntimeApi",
|
1281
|
+
method="get_all_metagraphs",
|
1282
|
+
params=[],
|
1283
|
+
block_hash=block_hash,
|
1284
|
+
)
|
1285
|
+
|
1286
|
+
return MetagraphInfo.list_from_any(hex_bytes_result)
|
1287
|
+
|
1255
1288
|
async def multi_get_stake_for_coldkey_and_hotkey_on_netuid(
|
1256
1289
|
self,
|
1257
1290
|
hotkey_ss58s: list[str],
|
@@ -1327,20 +1360,29 @@ class SubtensorInterface:
|
|
1327
1360
|
This function is useful for analyzing the stake distribution and delegation patterns of multiple
|
1328
1361
|
accounts simultaneously, offering a broader perspective on network participation and investment strategies.
|
1329
1362
|
"""
|
1330
|
-
|
1331
|
-
runtime_api="StakeInfoRuntimeApi",
|
1332
|
-
method="get_stake_info_for_coldkeys",
|
1333
|
-
params=[coldkey_ss58_list],
|
1334
|
-
block_hash=block_hash,
|
1335
|
-
)
|
1336
|
-
if result is None:
|
1337
|
-
return None
|
1363
|
+
BATCH_SIZE = 60
|
1338
1364
|
|
1365
|
+
tasks = []
|
1366
|
+
for i in range(0, len(coldkey_ss58_list), BATCH_SIZE):
|
1367
|
+
ss58_chunk = coldkey_ss58_list[i : i + BATCH_SIZE]
|
1368
|
+
tasks.append(
|
1369
|
+
self.query_runtime_api(
|
1370
|
+
runtime_api="StakeInfoRuntimeApi",
|
1371
|
+
method="get_stake_info_for_coldkeys",
|
1372
|
+
params=[ss58_chunk],
|
1373
|
+
block_hash=block_hash,
|
1374
|
+
)
|
1375
|
+
)
|
1376
|
+
results = await asyncio.gather(*tasks)
|
1339
1377
|
stake_info_map = {}
|
1340
|
-
for
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1378
|
+
for result in results:
|
1379
|
+
if result is None:
|
1380
|
+
continue
|
1381
|
+
for coldkey_bytes, stake_info_list in result:
|
1382
|
+
coldkey_ss58 = decode_account_id(coldkey_bytes)
|
1383
|
+
stake_info_map[coldkey_ss58] = StakeInfo.list_from_any(stake_info_list)
|
1384
|
+
|
1385
|
+
return stake_info_map if stake_info_map else None
|
1344
1386
|
|
1345
1387
|
async def all_subnets(self, block_hash: Optional[str] = None) -> list[DynamicInfo]:
|
1346
1388
|
result = await self.query_runtime_api(
|
@@ -1279,14 +1279,25 @@ def print_linux_dependency_message():
|
|
1279
1279
|
"""Prints the WebKit dependency message for Linux systems."""
|
1280
1280
|
console.print("[red]This command requires WebKit dependencies on Linux.[/red]")
|
1281
1281
|
console.print(
|
1282
|
-
"\nPlease
|
1282
|
+
"\nPlease make sure these packages are installed on your system for PyWry to work:"
|
1283
1283
|
)
|
1284
1284
|
console.print("\nArch Linux / Manjaro:")
|
1285
1285
|
console.print("[green]sudo pacman -S webkit2gtk[/green]")
|
1286
1286
|
console.print("\nDebian / Ubuntu:")
|
1287
1287
|
console.print("[green]sudo apt install libwebkit2gtk-4.0-dev[/green]")
|
1288
|
+
console.print("\nNote for Ubuntu 24.04+ & Debian 13+:")
|
1289
|
+
console.print("You may need these additional steps to install libwebkit2gtk:")
|
1290
|
+
console.print(
|
1291
|
+
"\tCreate a new source file with: [green]sudo vim /etc/apt/sources.list.d/jammy-temp.list[/green]"
|
1292
|
+
)
|
1293
|
+
console.print(
|
1294
|
+
"\tAdd this into the file and save: [green]deb http://archive.ubuntu.com/ubuntu jammy main universe[/green]"
|
1295
|
+
)
|
1296
|
+
console.print(
|
1297
|
+
"\tUpdate the repository and install the webkit dependency: [green]sudo apt update && sudo apt install libwebkit2gtk-4.0-dev[/green]"
|
1298
|
+
)
|
1288
1299
|
console.print("\nFedora / CentOS / AlmaLinux:")
|
1289
|
-
console.print("[green]sudo dnf install gtk3-devel webkit2gtk3-devel[/green]")
|
1300
|
+
console.print("[green]sudo dnf install gtk3-devel webkit2gtk3-devel[/green]\n\n")
|
1290
1301
|
|
1291
1302
|
|
1292
1303
|
def is_linux():
|
@@ -17,6 +17,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
17
17
|
is_valid_ss58_address,
|
18
18
|
print_error,
|
19
19
|
print_verbose,
|
20
|
+
unlock_key,
|
20
21
|
)
|
21
22
|
from bittensor_wallet import Wallet
|
22
23
|
from bittensor_wallet.errors import KeyFileError
|
@@ -338,10 +339,7 @@ async def stake_add(
|
|
338
339
|
if prompt:
|
339
340
|
if not Confirm.ask("Would you like to continue?"):
|
340
341
|
raise typer.Exit()
|
341
|
-
|
342
|
-
wallet.unlock_coldkey()
|
343
|
-
except KeyFileError:
|
344
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
342
|
+
if not unlock_key(wallet).success:
|
345
343
|
return False
|
346
344
|
|
347
345
|
if safe_staking:
|
@@ -671,6 +671,8 @@ async def childkey_take(
|
|
671
671
|
chk_take = await get_childkey_take(
|
672
672
|
subtensor=subtensor, netuid=netuid, hotkey=ss58
|
673
673
|
)
|
674
|
+
if chk_take is None:
|
675
|
+
chk_take = 0
|
674
676
|
chk_take = u16_to_float(chk_take)
|
675
677
|
console.print(
|
676
678
|
f"Child take for {ss58} is: {chk_take * 100:.2f}% on netuid {netuid}."
|
@@ -17,6 +17,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
17
17
|
format_error_message,
|
18
18
|
group_subnets,
|
19
19
|
get_subnet_name,
|
20
|
+
unlock_key,
|
20
21
|
)
|
21
22
|
|
22
23
|
if TYPE_CHECKING:
|
@@ -334,8 +335,7 @@ async def stake_move_selection(
|
|
334
335
|
|
335
336
|
|
336
337
|
async def stake_transfer_selection(
|
337
|
-
wallet: Wallet,
|
338
|
-
subtensor: "SubtensorInterface",
|
338
|
+
wallet: Wallet, subtensor: "SubtensorInterface", origin_hotkey: str
|
339
339
|
):
|
340
340
|
"""Selection interface for transferring stakes."""
|
341
341
|
(
|
@@ -352,7 +352,7 @@ async def stake_transfer_selection(
|
|
352
352
|
|
353
353
|
available_stakes = {}
|
354
354
|
for stake in stakes:
|
355
|
-
if stake.stake.tao > 0 and stake.hotkey_ss58 ==
|
355
|
+
if stake.stake.tao > 0 and stake.hotkey_ss58 == origin_hotkey:
|
356
356
|
available_stakes[stake.netuid] = {
|
357
357
|
"hotkey_ss58": stake.hotkey_ss58,
|
358
358
|
"stake": stake.stake,
|
@@ -621,10 +621,7 @@ async def move_stake(
|
|
621
621
|
raise typer.Exit()
|
622
622
|
|
623
623
|
# Perform moving operation.
|
624
|
-
|
625
|
-
wallet.unlock_coldkey()
|
626
|
-
except KeyFileError:
|
627
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
624
|
+
if not unlock_key(wallet).success:
|
628
625
|
return False
|
629
626
|
with console.status(
|
630
627
|
f"\n:satellite: Moving [blue]{amount_to_move_as_balance}[/blue] from [blue]{origin_hotkey}[/blue] on netuid: [blue]{origin_netuid}[/blue] \nto "
|
@@ -697,6 +694,7 @@ async def transfer_stake(
|
|
697
694
|
wallet: Wallet,
|
698
695
|
subtensor: "SubtensorInterface",
|
699
696
|
amount: float,
|
697
|
+
origin_hotkey: str,
|
700
698
|
origin_netuid: int,
|
701
699
|
dest_netuid: int,
|
702
700
|
dest_coldkey_ss58: str,
|
@@ -709,6 +707,7 @@ async def transfer_stake(
|
|
709
707
|
wallet (Wallet): Bittensor wallet object.
|
710
708
|
subtensor (SubtensorInterface): Subtensor interface instance.
|
711
709
|
amount (float): Amount to transfer.
|
710
|
+
origin_hotkey (str): The hotkey SS58 to transfer the stake from.
|
712
711
|
origin_netuid (int): The netuid to transfer stake from.
|
713
712
|
dest_netuid (int): The netuid to transfer stake to.
|
714
713
|
dest_coldkey_ss58 (str): The destination coldkey to transfer stake to.
|
@@ -718,8 +717,9 @@ async def transfer_stake(
|
|
718
717
|
Returns:
|
719
718
|
bool: True if transfer was successful, False otherwise.
|
720
719
|
"""
|
720
|
+
origin_hotkey = origin_hotkey or wallet.hotkey.ss58_address
|
721
721
|
if interactive_selection:
|
722
|
-
selection = await stake_transfer_selection(wallet, subtensor)
|
722
|
+
selection = await stake_transfer_selection(wallet, subtensor, origin_hotkey)
|
723
723
|
origin_netuid = selection["origin_netuid"]
|
724
724
|
amount = selection["amount"]
|
725
725
|
dest_netuid = selection["destination_netuid"]
|
@@ -739,16 +739,15 @@ async def transfer_stake(
|
|
739
739
|
return False
|
740
740
|
|
741
741
|
# Get current stake balances
|
742
|
-
hotkey_ss58 = wallet.hotkey.ss58_address
|
743
742
|
with console.status(f"Retrieving stake data from {subtensor.network}..."):
|
744
743
|
current_stake = await subtensor.get_stake(
|
745
744
|
coldkey_ss58=wallet.coldkeypub.ss58_address,
|
746
|
-
hotkey_ss58=
|
745
|
+
hotkey_ss58=origin_hotkey,
|
747
746
|
netuid=origin_netuid,
|
748
747
|
)
|
749
748
|
current_dest_stake = await subtensor.get_stake(
|
750
749
|
coldkey_ss58=dest_coldkey_ss58,
|
751
|
-
hotkey_ss58=
|
750
|
+
hotkey_ss58=origin_hotkey,
|
752
751
|
netuid=dest_netuid,
|
753
752
|
)
|
754
753
|
amount_to_transfer = Balance.from_tao(amount).set_unit(origin_netuid)
|
@@ -768,8 +767,8 @@ async def transfer_stake(
|
|
768
767
|
subtensor=subtensor,
|
769
768
|
origin_netuid=origin_netuid,
|
770
769
|
destination_netuid=dest_netuid,
|
771
|
-
origin_hotkey=
|
772
|
-
destination_hotkey=
|
770
|
+
origin_hotkey=origin_hotkey,
|
771
|
+
destination_hotkey=origin_hotkey,
|
773
772
|
amount_to_move=amount_to_transfer,
|
774
773
|
)
|
775
774
|
|
@@ -777,10 +776,7 @@ async def transfer_stake(
|
|
777
776
|
raise typer.Exit()
|
778
777
|
|
779
778
|
# Perform transfer operation
|
780
|
-
|
781
|
-
wallet.unlock_coldkey()
|
782
|
-
except KeyFileError:
|
783
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
779
|
+
if not unlock_key(wallet).success:
|
784
780
|
return False
|
785
781
|
|
786
782
|
with console.status("\n:satellite: Transferring stake ..."):
|
@@ -789,7 +785,7 @@ async def transfer_stake(
|
|
789
785
|
call_function="transfer_stake",
|
790
786
|
call_params={
|
791
787
|
"destination_coldkey": dest_coldkey_ss58,
|
792
|
-
"hotkey":
|
788
|
+
"hotkey": origin_hotkey,
|
793
789
|
"origin_netuid": origin_netuid,
|
794
790
|
"destination_netuid": dest_netuid,
|
795
791
|
"alpha_amount": amount_to_transfer.rao,
|
@@ -820,12 +816,12 @@ async def transfer_stake(
|
|
820
816
|
new_stake, new_dest_stake = await asyncio.gather(
|
821
817
|
subtensor.get_stake(
|
822
818
|
coldkey_ss58=wallet.coldkeypub.ss58_address,
|
823
|
-
hotkey_ss58=
|
819
|
+
hotkey_ss58=origin_hotkey,
|
824
820
|
netuid=origin_netuid,
|
825
821
|
),
|
826
822
|
subtensor.get_stake(
|
827
823
|
coldkey_ss58=dest_coldkey_ss58,
|
828
|
-
hotkey_ss58=
|
824
|
+
hotkey_ss58=origin_hotkey,
|
829
825
|
netuid=dest_netuid,
|
830
826
|
),
|
831
827
|
)
|
@@ -933,10 +929,7 @@ async def swap_stake(
|
|
933
929
|
raise typer.Exit()
|
934
930
|
|
935
931
|
# Perform swap operation
|
936
|
-
|
937
|
-
wallet.unlock_coldkey()
|
938
|
-
except KeyFileError:
|
939
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
932
|
+
if not unlock_key(wallet).success:
|
940
933
|
return False
|
941
934
|
|
942
935
|
with console.status(
|
@@ -21,6 +21,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
21
21
|
is_valid_ss58_address,
|
22
22
|
format_error_message,
|
23
23
|
group_subnets,
|
24
|
+
unlock_key,
|
24
25
|
)
|
25
26
|
|
26
27
|
if TYPE_CHECKING:
|
@@ -268,10 +269,7 @@ async def unstake(
|
|
268
269
|
raise typer.Exit()
|
269
270
|
|
270
271
|
# Execute extrinsics
|
271
|
-
|
272
|
-
wallet.unlock_coldkey()
|
273
|
-
except KeyFileError:
|
274
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
272
|
+
if not unlock_key(wallet).success:
|
275
273
|
return False
|
276
274
|
|
277
275
|
with console.status("\n:satellite: Performing unstaking operations...") as status:
|
@@ -465,10 +463,7 @@ async def unstake_all(
|
|
465
463
|
):
|
466
464
|
return False
|
467
465
|
|
468
|
-
|
469
|
-
wallet.unlock_coldkey()
|
470
|
-
except KeyFileError:
|
471
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
466
|
+
if not unlock_key(wallet).success:
|
472
467
|
return False
|
473
468
|
|
474
469
|
with console.status("Unstaking all stakes...") as status:
|
@@ -97,8 +97,10 @@ async def register_subnetwork_extrinsic(
|
|
97
97
|
sn_burn_cost = await burn_cost(subtensor)
|
98
98
|
if sn_burn_cost > your_balance:
|
99
99
|
err_console.print(
|
100
|
-
f"Your balance of: [{COLOR_PALETTE['POOLS']['TAO']}]{your_balance}[{COLOR_PALETTE['POOLS']['TAO']}]
|
101
|
-
f"
|
100
|
+
f"Your balance of: [{COLOR_PALETTE['POOLS']['TAO']}]{your_balance}[{COLOR_PALETTE['POOLS']['TAO']}]"
|
101
|
+
f" is not enough to burn "
|
102
|
+
f"[{COLOR_PALETTE['POOLS']['TAO']}]{sn_burn_cost}[{COLOR_PALETTE['POOLS']['TAO']}] "
|
103
|
+
f"to register a subnet."
|
102
104
|
)
|
103
105
|
return False
|
104
106
|
|
@@ -107,7 +109,7 @@ async def register_subnetwork_extrinsic(
|
|
107
109
|
f"Your balance is: [{COLOR_PALETTE['POOLS']['TAO']}]{your_balance}"
|
108
110
|
)
|
109
111
|
if not Confirm.ask(
|
110
|
-
f"Do you want to
|
112
|
+
f"Do you want to burn [{COLOR_PALETTE['POOLS']['TAO']}]{sn_burn_cost} to register a subnet?"
|
111
113
|
):
|
112
114
|
return False
|
113
115
|
|
@@ -145,10 +147,7 @@ async def register_subnetwork_extrinsic(
|
|
145
147
|
)
|
146
148
|
return False
|
147
149
|
|
148
|
-
|
149
|
-
wallet.unlock_coldkey()
|
150
|
-
except KeyFileError:
|
151
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
150
|
+
if not unlock_key(wallet).success:
|
152
151
|
return False
|
153
152
|
|
154
153
|
with console.status(":satellite: Registering subnet...", spinner="earth"):
|
@@ -189,6 +189,11 @@ async def set_hyperparameter_extrinsic(
|
|
189
189
|
":cross_mark: [red]Invalid hyperparameter specified.[/red]"
|
190
190
|
)
|
191
191
|
return False
|
192
|
+
if sudo_:
|
193
|
+
if not Confirm.ask(
|
194
|
+
"This hyperparam is only settable by root sudo users. If you are not, this will fail. Please confirm"
|
195
|
+
):
|
196
|
+
return False
|
192
197
|
|
193
198
|
substrate = subtensor.substrate
|
194
199
|
msg_value = value if not arbitrary_extrinsic else call_params
|