bittensor-cli 8.2.0rc13__py3-none-any.whl → 8.2.0rc15__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 +1 -1
- bittensor_cli/cli.py +411 -28
- bittensor_cli/src/__init__.py +1 -0
- bittensor_cli/src/bittensor/balances.py +29 -1
- bittensor_cli/src/bittensor/chain_data.py +17 -2
- bittensor_cli/src/bittensor/subtensor_interface.py +94 -77
- bittensor_cli/src/bittensor/utils.py +25 -5
- bittensor_cli/src/commands/stake/move.py +992 -0
- bittensor_cli/src/commands/stake/stake.py +25 -1137
- bittensor_cli/src/commands/subnets/__init__.py +0 -0
- bittensor_cli/src/commands/subnets/price.py +867 -0
- bittensor_cli/src/commands/{subnets.py → subnets/subnets.py} +63 -202
- bittensor_cli/src/commands/sudo.py +1 -2
- bittensor_cli/src/commands/wallets.py +9 -59
- {bittensor_cli-8.2.0rc13.dist-info → bittensor_cli-8.2.0rc15.dist-info}/METADATA +3 -1
- bittensor_cli-8.2.0rc15.dist-info/RECORD +33 -0
- bittensor_cli-8.2.0rc13.dist-info/RECORD +0 -30
- {bittensor_cli-8.2.0rc13.dist-info → bittensor_cli-8.2.0rc15.dist-info}/WHEEL +0 -0
- {bittensor_cli-8.2.0rc13.dist-info → bittensor_cli-8.2.0rc15.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-8.2.0rc13.dist-info → bittensor_cli-8.2.0rc15.dist-info}/top_level.txt +0 -0
@@ -27,9 +27,10 @@ from bittensor_cli.src.bittensor.chain_data import (
|
|
27
27
|
decode_hex_identity,
|
28
28
|
DelegateInfoLite,
|
29
29
|
DynamicInfo,
|
30
|
+
SubnetState,
|
30
31
|
)
|
31
32
|
from bittensor_cli.src import DelegatesDetails
|
32
|
-
from bittensor_cli.src.bittensor.balances import Balance
|
33
|
+
from bittensor_cli.src.bittensor.balances import Balance, FixedPoint, fixed_to_float
|
33
34
|
from bittensor_cli.src import Constants, defaults, TYPE_REGISTRY
|
34
35
|
from bittensor_cli.src.bittensor.utils import (
|
35
36
|
ss58_to_vec_u8,
|
@@ -227,7 +228,7 @@ class SubtensorInterface:
|
|
227
228
|
else:
|
228
229
|
return []
|
229
230
|
|
230
|
-
async def
|
231
|
+
async def get_stake_for_coldkey(
|
231
232
|
self,
|
232
233
|
coldkey_ss58: str,
|
233
234
|
block_hash: Optional[str] = None,
|
@@ -264,25 +265,61 @@ class SubtensorInterface:
|
|
264
265
|
except ValueError:
|
265
266
|
bytes_result = bytes.fromhex(hex_bytes_result)
|
266
267
|
|
267
|
-
|
268
|
+
stakes = StakeInfo.list_from_vec_u8(bytes_result)
|
269
|
+
return [stake for stake in stakes if stake.stake > 0]
|
268
270
|
|
269
271
|
async def get_stake_for_coldkey_and_hotkey(
|
270
|
-
self,
|
272
|
+
self,
|
273
|
+
hotkey_ss58: str,
|
274
|
+
coldkey_ss58: str,
|
275
|
+
netuid: Optional[int] = None,
|
276
|
+
block_hash: Optional[str] = None,
|
271
277
|
) -> Balance:
|
272
278
|
"""
|
273
|
-
|
274
|
-
|
275
|
-
:
|
276
|
-
|
277
|
-
|
279
|
+
Returns the stake under a coldkey - hotkey pairing.
|
280
|
+
|
281
|
+
Args:
|
282
|
+
hotkey_ss58 (str): The SS58 address of the hotkey.
|
283
|
+
coldkey_ss58 (str): The SS58 address of the coldkey.
|
284
|
+
netuid (Optional[int]): The subnet ID to filter by. If provided, only returns stake for this specific subnet.
|
285
|
+
block_hash (Optional[str]): The block hash at which to query the stake information.
|
286
|
+
|
287
|
+
Returns:
|
288
|
+
Balance: The stake under the coldkey - hotkey pairing.
|
278
289
|
"""
|
279
|
-
|
290
|
+
alpha_shares = await self.substrate.query(
|
280
291
|
module="SubtensorModule",
|
281
|
-
storage_function="
|
282
|
-
params=[hotkey_ss58, coldkey_ss58],
|
292
|
+
storage_function="Alpha",
|
293
|
+
params=[hotkey_ss58, coldkey_ss58, netuid],
|
283
294
|
block_hash=block_hash,
|
284
295
|
)
|
285
|
-
|
296
|
+
|
297
|
+
hotkey_alpha = await self.substrate.query(
|
298
|
+
module="SubtensorModule",
|
299
|
+
storage_function="TotalHotkeyAlpha",
|
300
|
+
params=[hotkey_ss58, netuid],
|
301
|
+
block_hash=block_hash,
|
302
|
+
)
|
303
|
+
|
304
|
+
hotkey_shares = await self.substrate.query(
|
305
|
+
module="SubtensorModule",
|
306
|
+
storage_function="TotalHotkeyShares",
|
307
|
+
params=[hotkey_ss58, netuid],
|
308
|
+
block_hash=block_hash,
|
309
|
+
)
|
310
|
+
|
311
|
+
alpha_shares_as_float = fixed_to_float(alpha_shares or 0)
|
312
|
+
hotkey_shares_as_float = fixed_to_float(hotkey_shares or 0)
|
313
|
+
|
314
|
+
if hotkey_shares_as_float == 0:
|
315
|
+
return Balance.from_rao(0).set_unit(netuid=netuid)
|
316
|
+
|
317
|
+
stake = alpha_shares_as_float / hotkey_shares_as_float * (hotkey_alpha or 0)
|
318
|
+
|
319
|
+
return Balance.from_rao(int(stake)).set_unit(netuid=netuid)
|
320
|
+
|
321
|
+
# Alias
|
322
|
+
get_stake = get_stake_for_coldkey_and_hotkey
|
286
323
|
|
287
324
|
async def query_runtime_api(
|
288
325
|
self,
|
@@ -384,11 +421,11 @@ class SubtensorInterface:
|
|
384
421
|
|
385
422
|
:return: {address: Balance objects}
|
386
423
|
"""
|
387
|
-
sub_stakes = await self.
|
424
|
+
sub_stakes = await self.get_stake_for_coldkeys(
|
388
425
|
ss58_addresses, block_hash=block_hash
|
389
426
|
)
|
390
427
|
# Token pricing info
|
391
|
-
dynamic_info = await self.
|
428
|
+
dynamic_info = await self.all_subnets()
|
392
429
|
|
393
430
|
results = {}
|
394
431
|
for ss58, stake_info_list in sub_stakes.items():
|
@@ -552,6 +589,36 @@ class SubtensorInterface:
|
|
552
589
|
)
|
553
590
|
return result
|
554
591
|
|
592
|
+
async def get_subnet_state(
|
593
|
+
self, netuid: int, block_hash: Optional[str] = None
|
594
|
+
) -> Optional["SubnetState"]:
|
595
|
+
"""
|
596
|
+
Retrieves the state of a specific subnet within the Bittensor network.
|
597
|
+
|
598
|
+
Args:
|
599
|
+
netuid: The network UID of the subnet to query.
|
600
|
+
block_hash: The hash of the blockchain block number for the query.
|
601
|
+
|
602
|
+
Returns:
|
603
|
+
SubnetState object containing the subnet's state information, or None if the subnet doesn't exist.
|
604
|
+
"""
|
605
|
+
hex_bytes_result = await self.query_runtime_api(
|
606
|
+
runtime_api="SubnetInfoRuntimeApi",
|
607
|
+
method="get_subnet_state",
|
608
|
+
params=[netuid],
|
609
|
+
block_hash=block_hash,
|
610
|
+
)
|
611
|
+
|
612
|
+
if hex_bytes_result is None:
|
613
|
+
return None
|
614
|
+
|
615
|
+
try:
|
616
|
+
bytes_result = bytes.fromhex(hex_bytes_result[2:])
|
617
|
+
except ValueError:
|
618
|
+
bytes_result = bytes.fromhex(hex_bytes_result)
|
619
|
+
|
620
|
+
return SubnetState.from_vec_u8(bytes_result)
|
621
|
+
|
555
622
|
async def get_hyperparameter(
|
556
623
|
self,
|
557
624
|
param_name: str,
|
@@ -1256,27 +1323,6 @@ class SubtensorInterface:
|
|
1256
1323
|
|
1257
1324
|
return DelegateInfoLite.list_from_vec_u8(result) # TODO this won't work yet
|
1258
1325
|
|
1259
|
-
async def get_subnet_dynamic_info(
|
1260
|
-
self, netuid: int, block_hash: Optional[str] = None
|
1261
|
-
) -> "DynamicInfo":
|
1262
|
-
hex_bytes_result = await self.query_runtime_api(
|
1263
|
-
runtime_api="SubnetInfoRuntimeApi",
|
1264
|
-
method="get_dynamic_info",
|
1265
|
-
params=[netuid],
|
1266
|
-
block_hash=block_hash,
|
1267
|
-
)
|
1268
|
-
|
1269
|
-
if hex_bytes_result is None:
|
1270
|
-
return None
|
1271
|
-
|
1272
|
-
if hex_bytes_result.startswith("0x"):
|
1273
|
-
bytes_result = bytes.fromhex(hex_bytes_result[2:])
|
1274
|
-
else:
|
1275
|
-
bytes_result = bytes.fromhex(hex_bytes_result)
|
1276
|
-
|
1277
|
-
subnets = DynamicInfo.from_vec_u8(bytes_result)
|
1278
|
-
return subnets
|
1279
|
-
|
1280
1326
|
async def get_stake_for_coldkey_and_hotkey_on_netuid(
|
1281
1327
|
self,
|
1282
1328
|
hotkey_ss58: str,
|
@@ -1354,7 +1400,7 @@ class SubtensorInterface:
|
|
1354
1400
|
results[hotkey_ss58][netuid] = value
|
1355
1401
|
return results
|
1356
1402
|
|
1357
|
-
async def
|
1403
|
+
async def get_stake_for_coldkeys(
|
1358
1404
|
self, coldkey_ss58_list: list[str], block_hash: Optional[str] = None
|
1359
1405
|
) -> Optional[dict[str, list[StakeInfo]]]:
|
1360
1406
|
"""
|
@@ -1392,7 +1438,9 @@ class SubtensorInterface:
|
|
1392
1438
|
|
1393
1439
|
return StakeInfo.list_of_tuple_from_vec_u8(bytes_result) # type: ignore
|
1394
1440
|
|
1395
|
-
async def
|
1441
|
+
async def all_subnets(
|
1442
|
+
self, block_hash: Optional[str] = None
|
1443
|
+
) -> list["DynamicInfo"]:
|
1396
1444
|
query = await self.substrate.runtime_call(
|
1397
1445
|
"SubnetInfoRuntimeApi",
|
1398
1446
|
"get_all_dynamic_info",
|
@@ -1401,47 +1449,16 @@ class SubtensorInterface:
|
|
1401
1449
|
subnets = DynamicInfo.list_from_vec_u8(bytes.fromhex(query.decode()[2:]))
|
1402
1450
|
return subnets
|
1403
1451
|
|
1404
|
-
async def
|
1405
|
-
self,
|
1406
|
-
):
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
params=[netuid
|
1452
|
+
async def subnet(
|
1453
|
+
self, netuid: int, block_hash: Optional[str] = None
|
1454
|
+
) -> "DynamicInfo":
|
1455
|
+
query = await self.substrate.runtime_call(
|
1456
|
+
"SubnetInfoRuntimeApi",
|
1457
|
+
"get_dynamic_info",
|
1458
|
+
params=[netuid],
|
1411
1459
|
block_hash=block_hash,
|
1412
1460
|
)
|
1413
|
-
return
|
1414
|
-
netuid: u64_normalized_float(weight) for (netuid, weight) in result.items()
|
1415
|
-
}
|
1416
|
-
|
1417
|
-
async def get_subnet_tao(
|
1418
|
-
self, netuid: Optional[int] = None, block_hash: Optional[str] = None
|
1419
|
-
) -> dict[int, Balance]:
|
1420
|
-
"""
|
1421
|
-
Retrieves the total TAO for one or all subnets.
|
1422
|
-
|
1423
|
-
Args:
|
1424
|
-
netuid: Optional specific netuid to query. If None, returns data for all subnets.
|
1425
|
-
block_hash: Optional block hash to query at.
|
1426
|
-
|
1427
|
-
Returns:
|
1428
|
-
Dictionary mapping netuid to its total TAO balance
|
1429
|
-
"""
|
1430
|
-
if netuid is not None:
|
1431
|
-
result = await self.substrate.query(
|
1432
|
-
module="SubtensorModule",
|
1433
|
-
storage_function="SubnetTAO",
|
1434
|
-
params=[netuid],
|
1435
|
-
block_hash=block_hash,
|
1436
|
-
)
|
1437
|
-
return {netuid: Balance.from_rao(result or 0)}
|
1438
|
-
else:
|
1439
|
-
results = await self.substrate.query_map(
|
1440
|
-
module="SubtensorModule",
|
1441
|
-
storage_function="SubnetTAO",
|
1442
|
-
block_hash=block_hash,
|
1443
|
-
)
|
1444
|
-
return {netuid: Balance.from_rao(tao or 0) async for netuid, tao in results}
|
1461
|
+
return DynamicInfo.from_vec_u8(bytes.fromhex(query.decode()[2:]))
|
1445
1462
|
|
1446
1463
|
async def get_owned_hotkeys(
|
1447
1464
|
self,
|
@@ -2,6 +2,7 @@ import ast
|
|
2
2
|
import math
|
3
3
|
import os
|
4
4
|
import sqlite3
|
5
|
+
import platform
|
5
6
|
import webbrowser
|
6
7
|
import sys
|
7
8
|
from pathlib import Path
|
@@ -1202,17 +1203,36 @@ def is_valid_contact(contact: str) -> bool:
|
|
1202
1203
|
|
1203
1204
|
def get_subnet_name(subnet_info) -> str:
|
1204
1205
|
"""Get the subnet name, prioritizing subnet_identity.subnet_name over subnet.subnet_name.
|
1205
|
-
|
1206
|
+
|
1206
1207
|
Args:
|
1207
1208
|
subnet: The subnet dynamic info
|
1208
|
-
|
1209
|
+
|
1209
1210
|
Returns:
|
1210
1211
|
str: The subnet name or empty string if no name is found
|
1211
1212
|
"""
|
1212
1213
|
return (
|
1213
1214
|
subnet_info.subnet_identity.subnet_name
|
1214
|
-
if hasattr(subnet_info,
|
1215
|
-
and subnet_info.subnet_identity is not None
|
1215
|
+
if hasattr(subnet_info, "subnet_identity")
|
1216
|
+
and subnet_info.subnet_identity is not None
|
1216
1217
|
and subnet_info.subnet_identity.subnet_name is not None
|
1217
1218
|
else (subnet_info.subnet_name if subnet_info.subnet_name is not None else "")
|
1218
|
-
)
|
1219
|
+
)
|
1220
|
+
|
1221
|
+
|
1222
|
+
def print_linux_dependency_message():
|
1223
|
+
"""Prints the WebKit dependency message for Linux systems."""
|
1224
|
+
console.print("[red]This command requires WebKit dependencies on Linux.[/red]")
|
1225
|
+
console.print(
|
1226
|
+
"\nPlease install the required packages using one of the following commands based on your distribution:"
|
1227
|
+
)
|
1228
|
+
console.print("\nArch Linux / Manjaro:")
|
1229
|
+
console.print("[green]sudo pacman -S webkit2gtk[/green]")
|
1230
|
+
console.print("\nDebian / Ubuntu:")
|
1231
|
+
console.print("[green]sudo apt install libwebkit2gtk-4.0-dev[/green]")
|
1232
|
+
console.print("\nFedora / CentOS / AlmaLinux:")
|
1233
|
+
console.print("[green]sudo dnf install gtk3-devel webkit2gtk3-devel[/green]")
|
1234
|
+
|
1235
|
+
|
1236
|
+
def is_linux():
|
1237
|
+
"""Returns True if the operating system is Linux."""
|
1238
|
+
return platform.system().lower() == "linux"
|