bittensor-cli 8.2.0rc12__py3-none-any.whl → 8.2.0rc14__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.
@@ -29,7 +29,7 @@ from bittensor_cli.src.bittensor.chain_data import (
29
29
  DynamicInfo,
30
30
  )
31
31
  from bittensor_cli.src import DelegatesDetails
32
- from bittensor_cli.src.bittensor.balances import Balance
32
+ from bittensor_cli.src.bittensor.balances import Balance, FixedPoint, fixed_to_float
33
33
  from bittensor_cli.src import Constants, defaults, TYPE_REGISTRY
34
34
  from bittensor_cli.src.bittensor.utils import (
35
35
  ss58_to_vec_u8,
@@ -227,7 +227,7 @@ class SubtensorInterface:
227
227
  else:
228
228
  return []
229
229
 
230
- async def get_stake_info_for_coldkey(
230
+ async def get_stake_for_coldkey(
231
231
  self,
232
232
  coldkey_ss58: str,
233
233
  block_hash: Optional[str] = None,
@@ -264,25 +264,61 @@ class SubtensorInterface:
264
264
  except ValueError:
265
265
  bytes_result = bytes.fromhex(hex_bytes_result)
266
266
 
267
- return StakeInfo.list_from_vec_u8(bytes_result)
267
+ stakes = StakeInfo.list_from_vec_u8(bytes_result)
268
+ return [stake for stake in stakes if stake.stake > 0]
268
269
 
269
270
  async def get_stake_for_coldkey_and_hotkey(
270
- self, hotkey_ss58: str, coldkey_ss58: str, block_hash: Optional[str]
271
+ self,
272
+ hotkey_ss58: str,
273
+ coldkey_ss58: str,
274
+ netuid: Optional[int] = None,
275
+ block_hash: Optional[str] = None,
271
276
  ) -> Balance:
272
277
  """
273
- Retrieves stake information associated with a specific coldkey and hotkey.
274
- :param hotkey_ss58: the hotkey SS58 address to query
275
- :param coldkey_ss58: the coldkey SS58 address to query
276
- :param block_hash: the hash of the blockchain block number for the query.
277
- :return: Stake Balance for the given coldkey and hotkey
278
+ Returns the stake under a coldkey - hotkey pairing.
279
+
280
+ Args:
281
+ hotkey_ss58 (str): The SS58 address of the hotkey.
282
+ coldkey_ss58 (str): The SS58 address of the coldkey.
283
+ netuid (Optional[int]): The subnet ID to filter by. If provided, only returns stake for this specific subnet.
284
+ block_hash (Optional[str]): The block hash at which to query the stake information.
285
+
286
+ Returns:
287
+ Balance: The stake under the coldkey - hotkey pairing.
278
288
  """
279
- _result = await self.substrate.query(
289
+ alpha_shares = await self.substrate.query(
290
+ module="SubtensorModule",
291
+ storage_function="Alpha",
292
+ params=[hotkey_ss58, coldkey_ss58, netuid],
293
+ block_hash=block_hash,
294
+ )
295
+
296
+ hotkey_alpha = await self.substrate.query(
280
297
  module="SubtensorModule",
281
- storage_function="Stake",
282
- params=[hotkey_ss58, coldkey_ss58],
298
+ storage_function="TotalHotkeyAlpha",
299
+ params=[hotkey_ss58, netuid],
283
300
  block_hash=block_hash,
284
301
  )
285
- return Balance.from_rao(_result or 0)
302
+
303
+ hotkey_shares = await self.substrate.query(
304
+ module="SubtensorModule",
305
+ storage_function="TotalHotkeyShares",
306
+ params=[hotkey_ss58, netuid],
307
+ block_hash=block_hash,
308
+ )
309
+
310
+ alpha_shares_as_float = fixed_to_float(alpha_shares or 0)
311
+ hotkey_shares_as_float = fixed_to_float(hotkey_shares or 0)
312
+
313
+ if hotkey_shares_as_float == 0:
314
+ return Balance.from_rao(0).set_unit(netuid=netuid)
315
+
316
+ stake = alpha_shares_as_float / hotkey_shares_as_float * (hotkey_alpha or 0)
317
+
318
+ return Balance.from_rao(int(stake)).set_unit(netuid=netuid)
319
+
320
+ # Alias
321
+ get_stake = get_stake_for_coldkey_and_hotkey
286
322
 
287
323
  async def query_runtime_api(
288
324
  self,
@@ -384,11 +420,11 @@ class SubtensorInterface:
384
420
 
385
421
  :return: {address: Balance objects}
386
422
  """
387
- sub_stakes = await self.get_stake_info_for_coldkeys(
423
+ sub_stakes = await self.get_stake_for_coldkeys(
388
424
  ss58_addresses, block_hash=block_hash
389
425
  )
390
426
  # Token pricing info
391
- dynamic_info = await self.get_all_subnet_dynamic_info()
427
+ dynamic_info = await self.all_subnets()
392
428
 
393
429
  results = {}
394
430
  for ss58, stake_info_list in sub_stakes.items():
@@ -1256,27 +1292,6 @@ class SubtensorInterface:
1256
1292
 
1257
1293
  return DelegateInfoLite.list_from_vec_u8(result) # TODO this won't work yet
1258
1294
 
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
1295
  async def get_stake_for_coldkey_and_hotkey_on_netuid(
1281
1296
  self,
1282
1297
  hotkey_ss58: str,
@@ -1354,7 +1369,7 @@ class SubtensorInterface:
1354
1369
  results[hotkey_ss58][netuid] = value
1355
1370
  return results
1356
1371
 
1357
- async def get_stake_info_for_coldkeys(
1372
+ async def get_stake_for_coldkeys(
1358
1373
  self, coldkey_ss58_list: list[str], block_hash: Optional[str] = None
1359
1374
  ) -> Optional[dict[str, list[StakeInfo]]]:
1360
1375
  """
@@ -1392,7 +1407,9 @@ class SubtensorInterface:
1392
1407
 
1393
1408
  return StakeInfo.list_of_tuple_from_vec_u8(bytes_result) # type: ignore
1394
1409
 
1395
- async def get_all_subnet_dynamic_info(self, block_hash: Optional[str] = None) -> list["DynamicInfo"]:
1410
+ async def all_subnets(
1411
+ self, block_hash: Optional[str] = None
1412
+ ) -> list["DynamicInfo"]:
1396
1413
  query = await self.substrate.runtime_call(
1397
1414
  "SubnetInfoRuntimeApi",
1398
1415
  "get_all_dynamic_info",
@@ -1401,47 +1418,16 @@ class SubtensorInterface:
1401
1418
  subnets = DynamicInfo.list_from_vec_u8(bytes.fromhex(query.decode()[2:]))
1402
1419
  return subnets
1403
1420
 
1404
- async def get_global_weights(
1405
- self, netuids: list[int], block_hash: Optional[str] = None
1406
- ):
1407
- result = await self.substrate.query_multiple(
1408
- module="SubtensorModule",
1409
- storage_function="GlobalWeight",
1410
- params=[netuid for netuid in netuids],
1421
+ async def subnet(
1422
+ self, netuid: int, block_hash: Optional[str] = None
1423
+ ) -> "DynamicInfo":
1424
+ query = await self.substrate.runtime_call(
1425
+ "SubnetInfoRuntimeApi",
1426
+ "get_dynamic_info",
1427
+ params=[netuid],
1411
1428
  block_hash=block_hash,
1412
1429
  )
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}
1430
+ return DynamicInfo.from_vec_u8(bytes.fromhex(query.decode()[2:]))
1445
1431
 
1446
1432
  async def get_owned_hotkeys(
1447
1433
  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, 'subnet_identity')
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"