Skip to content

Commit f519384

Browse files
authored
Merge pull request #2614 from opentensor/async/thewhaleking/pre-merge-rao-cleanup
Cleanups, fixes, improvements for rao
2 parents ab673a3 + b4c7249 commit f519384

File tree

12 files changed

+377
-280
lines changed

12 files changed

+377
-280
lines changed

bittensor/core/async_subtensor.py

Lines changed: 108 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@
6565
)
6666
from bittensor.core.metagraph import AsyncMetagraph
6767
from bittensor.core.settings import version_as_int, TYPE_REGISTRY, DELEGATES_DETAILS_URL
68-
from bittensor.core.types import ParamWithTypes
69-
from bittensor.core.types import SubtensorMixin
68+
from bittensor.core.types import ParamWithTypes, SubtensorMixin
7069
from bittensor.utils import (
7170
decode_hex_identity_dict,
7271
format_error_message,
@@ -563,12 +562,16 @@ async def all_subnets(
563562
block_number: Optional[int] = None,
564563
block_hash: Optional[str] = None,
565564
reuse_block: bool = False,
566-
) -> Optional[list["DynamicInfo"]]:
565+
) -> Optional[list[DynamicInfo]]:
567566
"""
568567
Retrieves the subnet information for all subnets in the network.
569568
570569
Args:
571-
block_number (Optional[int]): The block number to query the subnet information from.
570+
block_number (Optional[int]): The block number to query the subnet information from. Do not specify if using
571+
block_hash or reuse_block
572+
block_hash: The hash of the blockchain block number for the query. Do not specify if using reuse_block or
573+
block.
574+
reuse_block: Whether to reuse the last-used blockchain block hash. Do not set if using block_hash or block.
572575
573576
Returns:
574577
Optional[DynamicInfo]: A list of DynamicInfo objects, each containing detailed information about a subnet.
@@ -577,6 +580,8 @@ async def all_subnets(
577580
block_hash = await self.determine_block_hash(
578581
block_number, block_hash, reuse_block
579582
)
583+
if not block_hash and reuse_block:
584+
block_hash = self.substrate.last_block_hash
580585
query = await self.substrate.runtime_call(
581586
"SubnetInfoRuntimeApi",
582587
"get_all_dynamic_info",
@@ -799,7 +804,7 @@ async def get_balance(
799804
block: Optional[int] = None,
800805
block_hash: Optional[str] = None,
801806
reuse_block: bool = False,
802-
) -> "Balance":
807+
) -> Balance:
803808
"""
804809
Retrieves the balance for given coldkey.
805810
@@ -1321,9 +1326,29 @@ async def get_minimum_required_stake(self):
13211326
return Balance.from_rao(getattr(result, "value", 0))
13221327

13231328
async def get_metagraph_info(
1324-
self, netuid: int, block: Optional[int] = None
1325-
) -> Optional[MetagraphInfo]:
1326-
block_hash = await self.get_block_hash(block)
1329+
self,
1330+
netuid: int,
1331+
block: Optional[int] = None,
1332+
block_hash: Optional[str] = None,
1333+
reuse_block: bool = False,
1334+
) -> MetagraphInfo:
1335+
"""
1336+
Retrieves the MetagraphInfo dataclass from the node for a single subnet (netuid)
1337+
1338+
Arguments:
1339+
netuid: The NetUID of the subnet.
1340+
block: the block number at which to retrieve the hyperparameter. Do not specify if using block_hash or
1341+
reuse_block
1342+
block_hash: The hash of blockchain block number for the query. Do not specify if using
1343+
block or reuse_block
1344+
reuse_block: Whether to reuse the last-used block hash. Do not set if using block_hash or block.
1345+
1346+
Returns:
1347+
MetagraphInfo dataclass
1348+
"""
1349+
block_hash = await self.determine_block_hash(block, block_hash, reuse_block)
1350+
if not block_hash and reuse_block:
1351+
block_hash = self.substrate.last_block_hash
13271352

13281353
query = await self.substrate.runtime_call(
13291354
"SubnetInfoRuntimeApi",
@@ -1335,10 +1360,27 @@ async def get_metagraph_info(
13351360
return MetagraphInfo.from_vec_u8(metagraph_bytes)
13361361

13371362
async def get_all_metagraphs_info(
1338-
self, block: Optional[int] = None
1363+
self,
1364+
block: Optional[int] = None,
1365+
block_hash: Optional[str] = None,
1366+
reuse_block: bool = False,
13391367
) -> list[MetagraphInfo]:
1340-
block_hash = await self.get_block_hash(block)
1368+
"""
1369+
Retrieves a list of MetagraphInfo objects for all subnets
1370+
1371+
Arguments:
1372+
block: the block number at which to retrieve the hyperparameter. Do not specify if using block_hash or
1373+
reuse_block
1374+
block_hash (Optional[str]): The hash of blockchain block number for the query. Do not specify if using
1375+
block or reuse_block
1376+
reuse_block (bool): Whether to reuse the last-used block hash. Do not set if using block_hash or block.
13411377
1378+
Returns:
1379+
MetagraphInfo dataclass
1380+
"""
1381+
block_hash = await self.determine_block_hash(block, block_hash.reuse_block)
1382+
if not block_hash and reuse_block:
1383+
block_hash = self.substrate.last_block_hash
13421384
query = await self.substrate.runtime_call(
13431385
"SubnetInfoRuntimeApi",
13441386
"get_all_metagraphs",
@@ -1492,9 +1534,11 @@ async def get_stake(
14921534
Args:
14931535
hotkey_ss58 (str): The SS58 address of the hotkey.
14941536
coldkey_ss58 (str): The SS58 address of the coldkey.
1495-
netuid (Optional[int]): The subnet ID to filter by. If provided, only returns stake for this specific subnet.
1537+
netuid (Optional[int]): The subnet ID to filter by. If provided, only returns stake for this specific
1538+
subnet.
14961539
block (Optional[int]): The block number at which to query the stake information.
1497-
block_hash (Optional[str]): The hash of the block to retrieve the stake from. Do not specify if using block or reuse_block
1540+
block_hash (Optional[str]): The hash of the block to retrieve the stake from. Do not specify if using block
1541+
or reuse_block
14981542
reuse_block (bool): Whether to use the last-used block. Do not set if using block_hash or block.
14991543
15001544
Returns:
@@ -1569,18 +1613,15 @@ async def get_stake_for_coldkey(
15691613
hex_bytes_result = await self.query_runtime_api(
15701614
runtime_api="StakeInfoRuntimeApi",
15711615
method="get_stake_info_for_coldkey",
1572-
params=[encoded_coldkey], # type: ignore
1616+
params=[encoded_coldkey],
15731617
block_hash=block_hash,
1618+
reuse_block=reuse_block,
15741619
)
15751620

15761621
if hex_bytes_result is None:
15771622
return []
1578-
try:
1579-
bytes_result = bytes.fromhex(hex_bytes_result[2:])
1580-
except ValueError:
1581-
bytes_result = bytes.fromhex(hex_bytes_result)
15821623

1583-
stakes = StakeInfo.list_from_vec_u8(bytes_result) # type: ignore
1624+
stakes = StakeInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) # type: ignore
15841625
return [stake for stake in stakes if stake.stake > 0]
15851626

15861627
async def get_stake_info_for_coldkey(
@@ -1898,8 +1939,8 @@ async def get_total_subnets(
18981939
return getattr(result, "value", None)
18991940

19001941
async def get_transfer_fee(
1901-
self, wallet: "Wallet", dest: str, value: Union["Balance", float, int]
1902-
) -> "Balance":
1942+
self, wallet: "Wallet", dest: str, value: Union[Balance, float, int]
1943+
) -> Balance:
19031944
"""
19041945
Calculates the transaction fee for transferring tokens from a wallet to a specified destination address. This
19051946
function simulates the transfer to estimate the associated cost, taking into account the current network
@@ -2501,7 +2542,7 @@ async def recycle(
25012542
block: Optional[int] = None,
25022543
block_hash: Optional[str] = None,
25032544
reuse_block: bool = False,
2504-
) -> Optional["Balance"]:
2545+
) -> Optional[Balance]:
25052546
"""
25062547
Retrieves the 'Burn' hyperparameter for a specified subnet. The 'Burn' parameter represents the amount of Tao
25072548
that is effectively recycled within the Bittensor network.
@@ -2530,7 +2571,7 @@ async def recycle(
25302571
async def subnet(
25312572
self,
25322573
netuid: int,
2533-
block_number: int = None,
2574+
block: int = None,
25342575
block_hash: Optional[str] = None,
25352576
reuse_block: bool = False,
25362577
) -> Optional[DynamicInfo]:
@@ -2539,21 +2580,16 @@ async def subnet(
25392580
25402581
Args:
25412582
netuid (int): The unique identifier of the subnet.
2542-
block_number (Optional[int]): The block number to get the subnets at.
2583+
block (Optional[int]): The block number to get the subnets at.
2584+
block_hash (str): The hash of the blockchain block number for the query.
2585+
reuse_block (bool): Whether to reuse the last-used blockchain block hash.
25432586
25442587
Returns:
25452588
Optional[DynamicInfo]: A DynamicInfo object, containing detailed information about a subnet.
2546-
2547-
This function can be called in two ways:
2548-
1. As a context manager:
2549-
async with sub:
2550-
subnet = await sub.subnet(1)
2551-
2. Directly:
2552-
subnet = await sub.subnet(1)
25532589
"""
2554-
block_hash = await self.determine_block_hash(
2555-
block_number, block_hash, reuse_block
2556-
)
2590+
block_hash = await self.determine_block_hash(block, block_hash, reuse_block)
2591+
if not block_hash and reuse_block:
2592+
block_hash = self.substrate.last_block_hash
25572593
query = await self.substrate.runtime_call(
25582594
"SubnetInfoRuntimeApi",
25592595
"get_dynamic_info",
@@ -2681,6 +2717,41 @@ async def tx_rate_limit(
26812717
)
26822718
return getattr(result, "value", None)
26832719

2720+
async def wait_for_block(self, block: Optional[int] = None):
2721+
"""
2722+
Waits until a specific block is reached on the chain. If no block is specified,
2723+
waits for the next block.
2724+
2725+
Args:
2726+
block (Optional[int]): The block number to wait for. If None, waits for next block.
2727+
2728+
Returns:
2729+
bool: True if the target block was reached, False if timeout occurred.
2730+
2731+
Example:
2732+
>>> await subtensor.wait_for_block() # Waits for next block
2733+
>>> await subtensor.wait_for_block(block=1234) # Waits for specific block
2734+
"""
2735+
2736+
async def handler(block_data: dict):
2737+
logging.debug(
2738+
f'reached block {block_data["header"]["number"]}. Waiting for block {target_block}'
2739+
)
2740+
if block_data["header"]["number"] >= target_block:
2741+
return True
2742+
2743+
current_block = await self.substrate.get_block()
2744+
current_block_hash = current_block.get("header", {}).get("hash")
2745+
if block is not None:
2746+
target_block = block
2747+
else:
2748+
target_block = current_block["header"]["number"] + 1
2749+
2750+
await self.substrate._get_block_handler(
2751+
current_block_hash, header_only=True, subscription_handler=handler
2752+
)
2753+
return True
2754+
26842755
async def weights(
26852756
self,
26862757
netuid: int,
@@ -2817,6 +2888,7 @@ async def add_stake(
28172888
Args:
28182889
wallet (bittensor_wallet.Wallet): The wallet to be used for staking.
28192890
hotkey_ss58 (Optional[str]): The ``SS58`` address of the hotkey associated with the neuron.
2891+
netuid: subnet UID
28202892
amount (Balance): The amount of TAO to stake.
28212893
wait_for_inclusion (bool): Waits for the transaction to be included in a block.
28222894
wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain.
@@ -2853,6 +2925,7 @@ async def add_stake_multiple(
28532925
Args:
28542926
wallet (bittensor_wallet.Wallet): The wallet used for staking.
28552927
hotkey_ss58s (list[str]): List of ``SS58`` addresses of hotkeys to stake to.
2928+
netuids: list of subnet UIDs
28562929
amounts (list[Balance]): Corresponding amounts of TAO to stake for each hotkey.
28572930
wait_for_inclusion (bool): Waits for the transaction to be included in a block.
28582931
wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain.
@@ -3387,7 +3460,7 @@ async def swap_stake(
33873460
hotkey_ss58: str,
33883461
origin_netuid: int,
33893462
destination_netuid: int,
3390-
amount: Union["Balance", float],
3463+
amount: Balance,
33913464
wait_for_inclusion: bool = True,
33923465
wait_for_finalization: bool = False,
33933466
) -> bool:
@@ -3465,7 +3538,7 @@ async def transfer(
34653538
self,
34663539
wallet: "Wallet",
34673540
dest: str,
3468-
amount: "Balance",
3541+
amount: Balance,
34693542
transfer_all: bool = False,
34703543
wait_for_inclusion: bool = True,
34713544
wait_for_finalization: bool = False,

0 commit comments

Comments
 (0)