Skip to content

Commit 075f52a

Browse files
committed
Porting.
1 parent c1d58aa commit 075f52a

File tree

3 files changed

+141
-36
lines changed

3 files changed

+141
-36
lines changed

bittensor/core/async_subtensor.py

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
decode_account_id,
2626
SubnetInfo,
2727
PrometheusInfo,
28+
ProposalVoteData,
2829
)
2930
from bittensor.core.extrinsics.asyncio.registration import register_extrinsic
3031
from bittensor.core.extrinsics.asyncio.root import (
@@ -76,26 +77,6 @@ class ParamWithTypes(TypedDict):
7677
type: str # ScaleType string of the parameter.
7778

7879

79-
class ProposalVoteData:
80-
index: int
81-
threshold: int
82-
ayes: list[str]
83-
nays: list[str]
84-
end: int
85-
86-
def __init__(self, proposal_dict: dict) -> None:
87-
self.index = proposal_dict["index"]
88-
self.threshold = proposal_dict["threshold"]
89-
self.ayes = self.decode_ss58_tuples(proposal_dict["ayes"])
90-
self.nays = self.decode_ss58_tuples(proposal_dict["nays"])
91-
self.end = proposal_dict["end"]
92-
93-
@staticmethod
94-
def decode_ss58_tuples(line: tuple):
95-
"""Decodes a tuple of ss58 addresses formatted as bytes tuples."""
96-
return [decode_account_id(line[x][0]) for x in range(len(line))]
97-
98-
9980
def _decode_hex_identity_dict(info_dictionary: dict[str, Any]) -> dict[str, Any]:
10081
"""Decodes a dictionary of hexadecimal identities."""
10182
for k, v in info_dictionary.items():
@@ -1405,6 +1386,7 @@ async def sign_and_send_extrinsic(
14051386
wallet: "Wallet",
14061387
wait_for_inclusion: bool = True,
14071388
wait_for_finalization: bool = False,
1389+
sign_with: str = "coldkey",
14081390
) -> tuple[bool, str]:
14091391
"""
14101392
Helper method to sign and submit an extrinsic call to chain.
@@ -1414,13 +1396,19 @@ async def sign_and_send_extrinsic(
14141396
wallet (bittensor_wallet.Wallet): the wallet whose coldkey will be used to sign the extrinsic
14151397
wait_for_inclusion (bool): whether to wait until the extrinsic call is included on the chain
14161398
wait_for_finalization (bool): whether to wait until the extrinsic call is finalized on the chain
1399+
sign_with: the wallet attr to sign the extrinsic call [coldkey (default), hotkey, or coldkeypub]
14171400
14181401
Returns:
14191402
(success, error message)
14201403
"""
1404+
if sign_with not in ("coldkey", "hotkey", "coldkeypub"):
1405+
raise AttributeError(
1406+
f"'sign_with' must be either 'coldkey', 'hotkey' or 'coldkeypub', not '{sign_with}'"
1407+
)
1408+
14211409
extrinsic = await self.substrate.create_signed_extrinsic(
1422-
call=call, keypair=wallet.coldkey
1423-
) # sign with coldkey
1410+
call=call, keypair=getattr(wallet, sign_with)
1411+
)
14241412
try:
14251413
response = await self.substrate.submit_extrinsic(
14261414
extrinsic,
@@ -1437,24 +1425,38 @@ async def sign_and_send_extrinsic(
14371425
except SubstrateRequestException as e:
14381426
return False, format_error_message(e)
14391427

1440-
async def get_children(self, hotkey: str, netuid: int) -> tuple[bool, list, str]:
1428+
async def get_children(
1429+
self,
1430+
hotkey: str,
1431+
netuid: int,
1432+
block: Optional[int] = None,
1433+
block_hash: Optional[str] = None,
1434+
reuse_block: bool = False,
1435+
) -> tuple[bool, list, str]:
14411436
"""
14421437
This method retrieves the children of a given hotkey and netuid. It queries the SubtensorModule's ChildKeys
14431438
storage function to get the children and formats them before returning as a tuple.
14441439
14451440
Args:
14461441
hotkey: The hotkey value.
14471442
netuid: The netuid value.
1443+
block: The block number to query. Do not specify if using block_hash or reuse_block.
1444+
block_hash: The hash of the blockchain block number for the query. Do not specify if using bloc or
1445+
reuse_block.
1446+
reuse_block: Whether to reuse the last-used blockchain hash. Do not set if using block_hash or reuse_block.
14481447
14491448
Returns:
14501449
A tuple containing a boolean indicating success or failure, a list of formatted children, and an error
14511450
message (if applicable)
14521451
"""
1452+
block_hash = await self._determine_block_hash(block, block_hash, reuse_block)
14531453
try:
14541454
children = await self.substrate.query(
14551455
module="SubtensorModule",
14561456
storage_function="ChildKeys",
14571457
params=[hotkey, netuid],
1458+
block_hash=block_hash,
1459+
reuse_block_hash=reuse_block,
14581460
)
14591461
if children:
14601462
formatted_children = []
@@ -2702,3 +2704,36 @@ async def unstake(
27022704
wait_for_inclusion=wait_for_inclusion,
27032705
wait_for_finalization=wait_for_finalization,
27042706
)
2707+
2708+
async def state_call(
2709+
self,
2710+
method: str,
2711+
data: str,
2712+
block: Optional[int] = None,
2713+
block_hash: Optional[str] = None,
2714+
reuse_block: bool = False,
2715+
) -> dict[Any, Any]:
2716+
"""
2717+
Makes a state call to the Bittensor blockchain, allowing for direct queries of the blockchain's state. This
2718+
function is typically used for advanced queries that require specific method calls and data inputs.
2719+
2720+
Args:
2721+
method: The method name for the state call.
2722+
data: The data to be passed to the method.
2723+
block: The blockchain block number at which to perform the state call.
2724+
block_hash: The hash of the block to retrieve the parameter from. Do not specify if using block or
2725+
reuse_block
2726+
reuse_block: Whether to use the last-used block. Do not set if using block_hash or block.
2727+
2728+
Returns:
2729+
result (dict[Any, Any]): The result of the rpc call.
2730+
2731+
The state call function provides a more direct and flexible way of querying blockchain data, useful for specific
2732+
use cases where standard queries are insufficient.
2733+
"""
2734+
block_hash = await self._determine_block_hash(block, block_hash, reuse_block)
2735+
return self.substrate.rpc_request(
2736+
method="state_call",
2737+
params=[method, data, block_hash] if block_hash else [method, data],
2738+
reuse_block_hash=reuse_block,
2739+
)
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
from typing import TypedDict
1+
from bittensor.core.chain_data.utils import decode_account_id
22

33

44
# Senate / Proposal data
5-
class ProposalVoteData(TypedDict):
6-
"""
7-
This TypedDict represents the data structure for a proposal vote in the Senate.
8-
9-
Attributes:
10-
index (int): The index of the proposal.
11-
threshold (int): The threshold required for the proposal to pass.
12-
ayes (List[str]): List of senators who voted 'aye'.
13-
nays (List[str]): List of senators who voted 'nay'.
14-
end (int): The ending timestamp of the voting period.
15-
"""
16-
5+
class ProposalVoteData:
176
index: int
187
threshold: int
198
ayes: list[str]
209
nays: list[str]
2110
end: int
11+
12+
def __init__(self, proposal_dict: dict) -> None:
13+
self.index = proposal_dict["index"]
14+
self.threshold = proposal_dict["threshold"]
15+
self.ayes = self.decode_ss58_tuples(proposal_dict["ayes"])
16+
self.nays = self.decode_ss58_tuples(proposal_dict["nays"])
17+
self.end = proposal_dict["end"]
18+
19+
@staticmethod
20+
def decode_ss58_tuples(line: tuple):
21+
"""Decodes a tuple of ss58 addresses formatted as bytes tuples."""
22+
return [decode_account_id(line[x][0]) for x in range(len(line))]

bittensor/core/subtensor.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
SubnetHyperparameters,
3333
SubnetInfo,
3434
StakeInfo,
35+
ProposalVoteData,
36+
decode_account_id,
3537
)
3638
from bittensor.core.config import Config
3739
from bittensor.core.errors import SubstrateRequestException
@@ -2376,3 +2378,70 @@ def get_delegated(
23762378
return []
23772379

23782380
return DelegateInfo.delegated_list_from_vec_u8(bytes(result))
2381+
2382+
def get_vote_data(
2383+
self,
2384+
proposal_hash: str,
2385+
block: Optional[int] = None,
2386+
) -> Optional[ProposalVoteData]:
2387+
"""
2388+
Retrieves the voting data for a specific proposal on the Bittensor blockchain. This data includes information
2389+
about how senate members have voted on the proposal.
2390+
2391+
Args:
2392+
proposal_hash: The hash of the proposal for which voting data is requested.
2393+
block: The block number to query. Do not specify if using block_hash or reuse_block.
2394+
2395+
Returns:
2396+
An object containing the proposal's voting data, or `None` if not found.
2397+
2398+
This function is important for tracking and understanding the decision-making processes within the Bittensor
2399+
network, particularly how proposals are received and acted upon by the governing body.
2400+
"""
2401+
vote_data = self.substrate.query(
2402+
module="Triumvirate",
2403+
storage_function="Voting",
2404+
params=[proposal_hash],
2405+
block_hash=None if block is None else self.get_block_hash(block),
2406+
)
2407+
if vote_data is None:
2408+
return None
2409+
else:
2410+
return ProposalVoteData(vote_data)
2411+
2412+
def get_children(
2413+
self, hotkey: str, netuid: int, block: Optional[int] = None
2414+
) -> tuple[bool, list, str]:
2415+
"""
2416+
This method retrieves the children of a given hotkey and netuid. It queries the SubtensorModule's ChildKeys
2417+
storage function to get the children and formats them before returning as a tuple.
2418+
2419+
Args:
2420+
hotkey: The hotkey value.
2421+
netuid: The netuid value.
2422+
block: the blockchain block number for the query
2423+
2424+
Returns:
2425+
A tuple containing a boolean indicating success or failure, a list of formatted children, and an error
2426+
message (if applicable)
2427+
"""
2428+
block_hash = None if block is None else self.get_block_hash(block)
2429+
try:
2430+
children = self.substrate.query(
2431+
module="SubtensorModule",
2432+
storage_function="ChildKeys",
2433+
params=[hotkey, netuid],
2434+
block_hash=block_hash,
2435+
)
2436+
if children:
2437+
formatted_children = []
2438+
for proportion, child in children:
2439+
# Convert U64 to int
2440+
formatted_child = decode_account_id(child[0])
2441+
int_proportion = int(proportion)
2442+
formatted_children.append((int_proportion, formatted_child))
2443+
return True, formatted_children, ""
2444+
else:
2445+
return True, [], ""
2446+
except SubstrateRequestException as e:
2447+
return False, [], format_error_message(e)

0 commit comments

Comments
 (0)