diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 9e1519c290..2a02b2e9e5 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -11,13 +11,10 @@ from bittensor_wallet.utils import SS58_FORMAT from numpy.typing import NDArray from scalecodec import GenericCall -from scalecodec.base import RuntimeConfiguration -from scalecodec.type_registry import load_type_registry_preset from substrateinterface.exceptions import SubstrateRequestException from bittensor.core.chain_data import ( DelegateInfo, - custom_rpc_type_registry, StakeInfo, NeuronInfoLite, NeuronInfo, @@ -50,7 +47,6 @@ from bittensor.core.settings import version_as_int from bittensor.utils import ( torch, - ss58_to_vec_u8, format_error_message, decode_hex_identity_dict, validate_chain_endpoint, @@ -498,17 +494,15 @@ async def get_delegates( List of DelegateInfo objects, or an empty list if there are no delegates. """ block_hash = await self._determine_block_hash(block, block_hash, reuse_block) - hex_bytes_result = await self.query_runtime_api( + result = await self.query_runtime_api( runtime_api="DelegateInfoRuntimeApi", method="get_delegates", params=[], block_hash=block_hash, reuse_block=reuse_block, ) - if hex_bytes_result is not None: - return DelegateInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) - else: - return [] + + return DelegateInfo.list_from_any(result) if result is not None else [] async def get_stake_info_for_coldkey( self, @@ -534,20 +528,19 @@ async def get_stake_info_for_coldkey( Stake information is vital for account holders to assess their investment and participation in the network's delegation and consensus processes. """ - encoded_coldkey = ss58_to_vec_u8(coldkey_ss58) block_hash = await self._determine_block_hash(block, block_hash, reuse_block) - hex_bytes_result = await self.query_runtime_api( + result = await self.query_runtime_api( runtime_api="StakeInfoRuntimeApi", method="get_stake_info_for_coldkey", - params=[encoded_coldkey], + params=[coldkey_ss58], block_hash=block_hash, reuse_block=reuse_block, ) - if hex_bytes_result is None: + if result is None: return [] - return StakeInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) + return StakeInfo.list_from_any(result) async def get_stake_for_coldkey_and_hotkey( self, @@ -585,11 +578,11 @@ async def query_runtime_api( self, runtime_api: str, method: str, - params: Optional[Union[list[list[int]], dict[str, int], list[int]]], + params: Optional[Union[list[Any], dict[str, Any]]], block: Optional[int] = None, block_hash: Optional[str] = None, reuse_block: bool = False, - ) -> Optional[str]: + ) -> Optional[Any]: """ Queries the runtime API of the Bittensor blockchain, providing a way to interact with the underlying runtime and retrieve data encoded in Scale Bytes format. This function is essential for advanced users who need to @@ -605,46 +598,17 @@ async def query_runtime_api( reuse_block: Whether to reuse the last-used block hash. Do not set if using block_hash or block Returns: - The Scale Bytes encoded result from the runtime API call, or `None` if the call fails. + The decoded result from the runtime API call, or `None` if the call fails. This function enables access to the deeper layers of the Bittensor blockchain, allowing for detailed and specific interactions with the network's runtime environment. """ block_hash = await self._determine_block_hash(block, block_hash, reuse_block) - - call_definition = TYPE_REGISTRY["runtime_api"][runtime_api]["methods"][method] - - data = ( - "0x" - if params is None - else await self.encode_params( - call_definition=call_definition, params=params - ) - ) - api_method = f"{runtime_api}_{method}" - - json_result = await self.substrate.rpc_request( - method="state_call", - params=[api_method, data, block_hash] if block_hash else [api_method, data], - reuse_block_hash=reuse_block, + result = await self.substrate.runtime_call( + runtime_api, method, params, block_hash ) - if json_result is None: - return None - - return_type = call_definition["type"] - - as_scale_bytes = scalecodec.ScaleBytes(json_result["result"]) # type: ignore - - rpc_runtime_config = RuntimeConfiguration() - rpc_runtime_config.update_type_registry(load_type_registry_preset("legacy")) - rpc_runtime_config.update_type_registry(custom_rpc_type_registry) - - obj = rpc_runtime_config.create_scale_object(return_type, as_scale_bytes) - if obj.data.to_hex() == "0x0400": # RPC returned None result - return None - - return obj.decode() + return result async def get_balance( self, @@ -1002,7 +966,7 @@ async def neurons( decentralized structure and the dynamics of its consensus and governance processes. """ block_hash = await self._determine_block_hash(block, block_hash, reuse_block) - hex_bytes_result = await self.query_runtime_api( + result = await self.query_runtime_api( runtime_api="NeuronInfoRuntimeApi", method="get_neurons", params=[netuid], @@ -1010,10 +974,10 @@ async def neurons( reuse_block=reuse_block, ) - if hex_bytes_result is None: + if result is None: return [] - return NeuronInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) + return NeuronInfo.list_from_any(result) async def neurons_lite( self, @@ -1041,7 +1005,7 @@ async def neurons_lite( of the network's decentralized structure and neuron dynamics. """ block_hash = await self._determine_block_hash(block, block_hash, reuse_block) - hex_bytes_result = await self.query_runtime_api( + result = await self.query_runtime_api( runtime_api="NeuronInfoRuntimeApi", method="get_neurons_lite", params=[netuid], @@ -1049,10 +1013,10 @@ async def neurons_lite( reuse_block=reuse_block, ) - if hex_bytes_result is None: + if result is None: return [] - return NeuronInfoLite.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) + return NeuronInfoLite.list_from_any(result) async def get_neuron_for_pubkey_and_subnet( self, @@ -1092,16 +1056,20 @@ async def get_neuron_for_pubkey_and_subnet( if uid is None: return NeuronInfo.get_null_neuron() - params = [netuid, uid] - json_body = await self.substrate.rpc_request( - method="neuronInfo_getNeuron", - params=params, + result = await self.query_runtime_api( + runtime_api="NeuronInfoRuntimeApi", + method="get_neuron", + params=[ + netuid, + uid, + ], # TODO check to see if this can accept more than one at a time + block_hash=block_hash, ) - if not (result := json_body.get("result", None)): + if not result: return NeuronInfo.get_null_neuron() - return NeuronInfo.from_vec_u8(bytes(result)) + return NeuronInfo.from_any(result) async def neuron_for_uid( self, @@ -1137,16 +1105,20 @@ async def neuron_for_uid( if reuse_block: block_hash = self.substrate.last_block_hash - params = [netuid, uid, block_hash] if block_hash else [netuid, uid] - json_body = await self.substrate.rpc_request( - method="neuronInfo_getNeuron", - params=params, # custom rpc method + result = await self.query_runtime_api( + runtime_api="NeuronInfoRuntimeApi", + method="get_neuron", + params=[ + netuid, + uid, + ], + block_hash=block_hash, ) - if not (result := json_body.get("result", None)): + + if not result: return NeuronInfo.get_null_neuron() - bytes_result = bytes(result) - return NeuronInfo.from_vec_u8(bytes_result) + return NeuronInfo.from_any(result) async def get_delegated( self, @@ -1177,16 +1149,18 @@ async def get_delegated( if (bh := await self._determine_block_hash(block, block_hash, reuse_block)) else (self.substrate.last_block_hash if reuse_block else None) ) - encoded_coldkey = ss58_to_vec_u8(coldkey_ss58) - json_body = await self.substrate.rpc_request( - method="delegateInfo_getDelegated", - params=([block_hash, encoded_coldkey] if block_hash else [encoded_coldkey]), + + result = await self.query_runtime_api( + runtime_api="DelegateInfoRuntimeApi", + method="get_delegated", + params=[coldkey_ss58], + block_hash=block_hash, ) - if not (result := json_body.get("result")): + if not result: return [] - return DelegateInfo.delegated_list_from_vec_u8(bytes(result)) + return DelegateInfo.delegated_list_from_any(result) async def query_identity( self, @@ -1496,7 +1470,7 @@ async def get_subnet_hyperparameters( they interact with the network's consensus and incentive mechanisms. """ block_hash = await self._determine_block_hash(block, block_hash, reuse_block) - hex_bytes_result = await self.query_runtime_api( + result = await self.query_runtime_api( runtime_api="SubnetInfoRuntimeApi", method="get_subnet_hyperparams", params=[netuid], @@ -1504,10 +1478,10 @@ async def get_subnet_hyperparameters( reuse_block=reuse_block, ) - if hex_bytes_result is None: + if result is None: return [] - return SubnetHyperparameters.from_vec_u8(hex_to_bytes(hex_bytes_result)) + return SubnetHyperparameters.from_any(result) async def get_vote_data( self, diff --git a/bittensor/core/chain_data/__init__.py b/bittensor/core/chain_data/__init__.py index 760eaa3354..9393ac86bc 100644 --- a/bittensor/core/chain_data/__init__.py +++ b/bittensor/core/chain_data/__init__.py @@ -18,6 +18,6 @@ from .stake_info import StakeInfo from .subnet_hyperparameters import SubnetHyperparameters from .subnet_info import SubnetInfo -from .utils import custom_rpc_type_registry, decode_account_id, process_stake_data +from .utils import decode_account_id, process_stake_data ProposalCallData = GenericCall diff --git a/bittensor/core/chain_data/delegate_info.py b/bittensor/core/chain_data/delegate_info.py index a840d1bb15..459489d591 100644 --- a/bittensor/core/chain_data/delegate_info.py +++ b/bittensor/core/chain_data/delegate_info.py @@ -1,15 +1,17 @@ -import bt_decode - from dataclasses import dataclass -from typing import Optional +from typing import Any, Optional + +import bt_decode +import munch +from bittensor.core.chain_data.info_base import InfoBase from bittensor.core.chain_data.utils import decode_account_id from bittensor.utils import u16_normalized_float from bittensor.utils.balance import Balance @dataclass -class DelegateInfo: +class DelegateInfo(InfoBase): """ Dataclass for delegate information. For a lighter version of this class, see ``DelegateInfoLite``. @@ -40,8 +42,7 @@ class DelegateInfo: total_daily_return: Balance # Total daily return of the delegate @classmethod - def from_vec_u8(cls, vec_u8: bytes) -> Optional["DelegateInfo"]: - decoded = bt_decode.DelegateInfo.decode(vec_u8) + def _fix_decoded(cls, decoded: "DelegateInfo") -> Optional["DelegateInfo"]: hotkey = decode_account_id(decoded.delegate_ss58) owner = decode_account_id(decoded.owner_ss58) nominators = [ @@ -63,36 +64,14 @@ def from_vec_u8(cls, vec_u8: bytes) -> Optional["DelegateInfo"]: @classmethod def list_from_vec_u8(cls, vec_u8: bytes) -> list["DelegateInfo"]: decoded = bt_decode.DelegateInfo.decode_vec(vec_u8) - results = [] - for d in decoded: - hotkey = decode_account_id(d.delegate_ss58) - owner = decode_account_id(d.owner_ss58) - nominators = [ - (decode_account_id(x), Balance.from_rao(y)) for x, y in d.nominators - ] - total_stake = sum((x[1] for x in nominators)) if nominators else Balance(0) - results.append( - DelegateInfo( - hotkey_ss58=hotkey, - total_stake=total_stake, - nominators=nominators, - owner_ss58=owner, - take=u16_normalized_float(d.take), - validator_permits=d.validator_permits, - registrations=d.registrations, - return_per_1000=Balance.from_rao(d.return_per_1000), - total_daily_return=Balance.from_rao(d.total_daily_return), - ) - ) - return results + return [cls._fix_decoded(d) for d in decoded] @classmethod - def delegated_list_from_vec_u8( - cls, vec_u8: bytes + def fix_delegated_list( + cls, delegated_list: list[tuple["DelegateInfo", Balance]] ) -> list[tuple["DelegateInfo", Balance]]: - decoded = bt_decode.DelegateInfo.decode_delegated(vec_u8) results = [] - for d, b in decoded: + for d, b in delegated_list: nominators = [ (decode_account_id(x), Balance.from_rao(y)) for x, y in d.nominators ] @@ -110,3 +89,17 @@ def delegated_list_from_vec_u8( ) results.append((delegate, Balance.from_rao(b))) return results + + @classmethod + def delegated_list_from_vec_u8( + cls, vec_u8: bytes + ) -> list[tuple["DelegateInfo", Balance]]: + decoded = bt_decode.DelegateInfo.decode_delegated(vec_u8) + return cls.fix_delegated_list(decoded) + + @classmethod + def delegated_list_from_any( + cls, any_list: list[Any] + ) -> list[tuple["DelegateInfo", Balance]]: + any_list = [munch.munchify(any_) for any_ in any_list] + return cls.fix_delegated_list(any_list) diff --git a/bittensor/core/chain_data/info_base.py b/bittensor/core/chain_data/info_base.py new file mode 100644 index 0000000000..acd4e7c0e5 --- /dev/null +++ b/bittensor/core/chain_data/info_base.py @@ -0,0 +1,27 @@ +from abc import abstractmethod +from dataclasses import dataclass +from typing import Any, TypeVar + +import munch + +T = TypeVar("T", bound="InfoBase") + + +@dataclass +class InfoBase: + """Base dataclass for info objects.""" + + @abstractmethod + def _fix_decoded(self, decoded: Any) -> T: + raise NotImplementedError( + "This is an abstract method and must be implemented in a subclass." + ) + + @classmethod + def from_any(cls, any_: Any) -> T: + any_ = munch.munchify(any_) + return cls._fix_decoded(any_) + + @classmethod + def list_from_any(cls, any_list: list[Any]) -> list[T]: + return [cls.from_any(any_) for any_ in any_list] diff --git a/bittensor/core/chain_data/neuron_info.py b/bittensor/core/chain_data/neuron_info.py index ecc1b2488c..bf7be918fe 100644 --- a/bittensor/core/chain_data/neuron_info.py +++ b/bittensor/core/chain_data/neuron_info.py @@ -1,10 +1,11 @@ from dataclasses import dataclass -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, Optional import bt_decode import netaddr from bittensor.core.chain_data.axon_info import AxonInfo +from bittensor.core.chain_data.info_base import InfoBase from bittensor.core.chain_data.prometheus_info import PrometheusInfo from bittensor.core.chain_data.utils import decode_account_id, process_stake_data from bittensor.utils import u16_normalized_float @@ -16,7 +17,7 @@ @dataclass -class NeuronInfo: +class NeuronInfo(InfoBase): """Represents the metadata of a neuron including keys, UID, stake, rankings, and other attributes. Attributes: @@ -125,41 +126,40 @@ def get_null_neuron() -> "NeuronInfo": return neuron @classmethod - def from_vec_u8(cls, vec_u8: bytes) -> "NeuronInfo": + def _fix_decoded(cls, decoded: Any) -> "NeuronInfo": """Instantiates NeuronInfo from a byte vector.""" - n = bt_decode.NeuronInfo.decode(bytes(vec_u8)) - stake_dict = process_stake_data(n.stake) + stake_dict = process_stake_data(decoded.stake) total_stake = sum(stake_dict.values()) if stake_dict else Balance(0) - axon_info = n.axon_info - coldkey = decode_account_id(n.coldkey) - hotkey = decode_account_id(n.hotkey) + axon_info = decoded.axon_info + coldkey = decode_account_id(decoded.coldkey) + hotkey = decode_account_id(decoded.hotkey) return NeuronInfo( hotkey=hotkey, coldkey=coldkey, - uid=n.uid, - netuid=n.netuid, - active=n.active, + uid=decoded.uid, + netuid=decoded.netuid, + active=decoded.active, stake=total_stake, stake_dict=stake_dict, total_stake=total_stake, - rank=u16_normalized_float(n.rank), - emission=n.emission / 1e9, - incentive=u16_normalized_float(n.incentive), - consensus=u16_normalized_float(n.consensus), - trust=u16_normalized_float(n.trust), - validator_trust=u16_normalized_float(n.validator_trust), - dividends=u16_normalized_float(n.dividends), - last_update=n.last_update, - validator_permit=n.validator_permit, - weights=[[e[0], e[1]] for e in n.weights], - bonds=[[e[0], e[1]] for e in n.bonds], - pruning_score=n.pruning_score, + rank=u16_normalized_float(decoded.rank), + emission=decoded.emission / 1e9, + incentive=u16_normalized_float(decoded.incentive), + consensus=u16_normalized_float(decoded.consensus), + trust=u16_normalized_float(decoded.trust), + validator_trust=u16_normalized_float(decoded.validator_trust), + dividends=u16_normalized_float(decoded.dividends), + last_update=decoded.last_update, + validator_permit=decoded.validator_permit, + weights=[[e[0], e[1]] for e in decoded.weights], + bonds=[[e[0], e[1]] for e in decoded.bonds], + pruning_score=decoded.pruning_score, prometheus_info=PrometheusInfo( - block=n.prometheus_info.block, - version=n.prometheus_info.version, - ip=str(netaddr.IPAddress(n.prometheus_info.ip)), - port=n.prometheus_info.port, - ip_type=n.prometheus_info.ip_type, + block=decoded.prometheus_info.block, + version=decoded.prometheus_info.version, + ip=str(netaddr.IPAddress(decoded.prometheus_info.ip)), + port=decoded.prometheus_info.port, + ip_type=decoded.prometheus_info.ip_type, ), axon_info=AxonInfo( version=axon_info.version, @@ -179,52 +179,9 @@ def from_vec_u8(cls, vec_u8: bytes) -> "NeuronInfo": def list_from_vec_u8(cls, vec_u8: bytes) -> list["NeuronInfo"]: nn = bt_decode.NeuronInfo.decode_vec(bytes(vec_u8)) - def fix(n): - stake_dict = process_stake_data(n.stake) - total_stake = sum(stake_dict.values()) if stake_dict else Balance(0) - axon_info = n.axon_info - coldkey = decode_account_id(n.coldkey) - hotkey = decode_account_id(n.hotkey) - return NeuronInfo( - hotkey=hotkey, - coldkey=coldkey, - uid=n.uid, - netuid=n.netuid, - active=n.active, - stake=total_stake, - stake_dict=stake_dict, - total_stake=total_stake, - rank=u16_normalized_float(n.rank), - emission=n.emission / 1e9, - incentive=u16_normalized_float(n.incentive), - consensus=u16_normalized_float(n.consensus), - trust=u16_normalized_float(n.trust), - validator_trust=u16_normalized_float(n.validator_trust), - dividends=u16_normalized_float(n.dividends), - last_update=n.last_update, - validator_permit=n.validator_permit, - weights=[[e[0], e[1]] for e in n.weights], - bonds=[[e[0], e[1]] for e in n.bonds], - pruning_score=n.pruning_score, - prometheus_info=PrometheusInfo( - block=n.prometheus_info.block, - version=n.prometheus_info.version, - ip=str(netaddr.IPAddress(n.prometheus_info.ip)), - port=n.prometheus_info.port, - ip_type=n.prometheus_info.ip_type, - ), - axon_info=AxonInfo( - version=axon_info.version, - ip=str(netaddr.IPAddress(axon_info.ip)), - port=axon_info.port, - ip_type=axon_info.ip_type, - placeholder1=axon_info.placeholder1, - placeholder2=axon_info.placeholder2, - protocol=axon_info.protocol, - hotkey=hotkey, - coldkey=coldkey, - ), - is_null=False, - ) - - return [fix(n) for n in nn] + return [cls._fix_decoded(n) for n in nn] + + @classmethod + def from_vec_u8(cls, vec_u8: bytes) -> "NeuronInfo": + n = bt_decode.NeuronInfo.decode(vec_u8) + return cls._fix_decoded(n) diff --git a/bittensor/core/chain_data/neuron_info_lite.py b/bittensor/core/chain_data/neuron_info_lite.py index 48d9ed4ca1..6ef1da1f9e 100644 --- a/bittensor/core/chain_data/neuron_info_lite.py +++ b/bittensor/core/chain_data/neuron_info_lite.py @@ -1,10 +1,11 @@ from dataclasses import dataclass -from typing import Optional +from typing import Any, Optional import bt_decode import netaddr from bittensor.core.chain_data.axon_info import AxonInfo +from bittensor.core.chain_data.info_base import InfoBase from bittensor.core.chain_data.prometheus_info import PrometheusInfo from bittensor.core.chain_data.utils import decode_account_id, process_stake_data from bittensor.utils import u16_normalized_float @@ -12,7 +13,7 @@ @dataclass -class NeuronInfoLite: +class NeuronInfoLite(InfoBase): """ NeuronInfoLite is a dataclass representing neuron metadata without weights and bonds. @@ -95,6 +96,67 @@ def get_null_neuron() -> "NeuronInfoLite": ) return neuron + @classmethod + def _fix_decoded(cls, decoded: Any) -> "NeuronInfoLite": + active = decoded.active + axon_info = decoded.axon_info + coldkey = decode_account_id(decoded.coldkey) + consensus = decoded.consensus + dividends = decoded.dividends + emission = decoded.emission + hotkey = decode_account_id(decoded.hotkey) + incentive = decoded.incentive + last_update = decoded.last_update + netuid = decoded.netuid + prometheus_info = decoded.prometheus_info + pruning_score = decoded.pruning_score + rank = decoded.rank + stake_dict = process_stake_data(decoded.stake) + stake = sum(stake_dict.values()) if stake_dict else Balance(0) + trust = decoded.trust + uid = decoded.uid + validator_permit = decoded.validator_permit + validator_trust = decoded.validator_trust + + return NeuronInfoLite( + active=active, + axon_info=AxonInfo( + version=axon_info.version, + ip=str(netaddr.IPAddress(axon_info.ip)), + port=axon_info.port, + ip_type=axon_info.ip_type, + placeholder1=axon_info.placeholder1, + placeholder2=axon_info.placeholder2, + protocol=axon_info.protocol, + hotkey=hotkey, + coldkey=coldkey, + ), + coldkey=coldkey, + consensus=u16_normalized_float(consensus), + dividends=u16_normalized_float(dividends), + emission=emission / 1e9, + hotkey=hotkey, + incentive=u16_normalized_float(incentive), + last_update=last_update, + netuid=netuid, + prometheus_info=PrometheusInfo( + version=prometheus_info.version, + ip=str(netaddr.IPAddress(prometheus_info.ip)), + port=prometheus_info.port, + ip_type=prometheus_info.ip_type, + block=prometheus_info.block, + ), + pruning_score=pruning_score, + rank=u16_normalized_float(rank), + stake_dict=stake_dict, + stake=stake, + total_stake=stake, + trust=u16_normalized_float(trust), + uid=uid, + validator_permit=validator_permit, + validator_trust=u16_normalized_float(validator_trust), + ) + @classmethod def list_from_vec_u8(cls, vec_u8: bytes) -> list["NeuronInfoLite"]: """ @@ -107,65 +169,4 @@ def list_from_vec_u8(cls, vec_u8: bytes) -> list["NeuronInfoLite"]: list[NeuronInfoLite]: A list of NeuronInfoLite instances decoded from the provided bytes object. """ decoded = bt_decode.NeuronInfoLite.decode_vec(vec_u8) - results = [] - for item in decoded: - active = item.active - axon_info = item.axon_info - coldkey = decode_account_id(item.coldkey) - consensus = item.consensus - dividends = item.dividends - emission = item.emission - hotkey = decode_account_id(item.hotkey) - incentive = item.incentive - last_update = item.last_update - netuid = item.netuid - prometheus_info = item.prometheus_info - pruning_score = item.pruning_score - rank = item.rank - stake_dict = process_stake_data(item.stake) - stake = sum(stake_dict.values()) if stake_dict else Balance(0) - trust = item.trust - uid = item.uid - validator_permit = item.validator_permit - validator_trust = item.validator_trust - results.append( - NeuronInfoLite( - active=active, - axon_info=AxonInfo( - version=axon_info.version, - ip=str(netaddr.IPAddress(axon_info.ip)), - port=axon_info.port, - ip_type=axon_info.ip_type, - placeholder1=axon_info.placeholder1, - placeholder2=axon_info.placeholder2, - protocol=axon_info.protocol, - hotkey=hotkey, - coldkey=coldkey, - ), - coldkey=coldkey, - consensus=u16_normalized_float(consensus), - dividends=u16_normalized_float(dividends), - emission=emission / 1e9, - hotkey=hotkey, - incentive=u16_normalized_float(incentive), - last_update=last_update, - netuid=netuid, - prometheus_info=PrometheusInfo( - version=prometheus_info.version, - ip=str(netaddr.IPAddress(prometheus_info.ip)), - port=prometheus_info.port, - ip_type=prometheus_info.ip_type, - block=prometheus_info.block, - ), - pruning_score=pruning_score, - rank=u16_normalized_float(rank), - stake_dict=stake_dict, - stake=stake, - total_stake=stake, - trust=u16_normalized_float(trust), - uid=uid, - validator_permit=validator_permit, - validator_trust=u16_normalized_float(validator_trust), - ) - ) - return results + return [cls._fix_decoded(d) for d in decoded] diff --git a/bittensor/core/chain_data/stake_info.py b/bittensor/core/chain_data/stake_info.py index 8d3b5020fb..085298ccc2 100644 --- a/bittensor/core/chain_data/stake_info.py +++ b/bittensor/core/chain_data/stake_info.py @@ -1,19 +1,20 @@ from dataclasses import dataclass -from typing import Optional, Any +from typing import Any, Optional +import bt_decode from scalecodec.utils.ss58 import ss58_encode +from bittensor.core.chain_data.info_base import InfoBase from bittensor.core.chain_data.utils import ( - from_scale_encoding, + decode_account_id, from_scale_encoding_using_type_string, - ChainDataType, ) from bittensor.core.settings import SS58_FORMAT from bittensor.utils.balance import Balance @dataclass -class StakeInfo: +class StakeInfo(InfoBase): """ Dataclass for representing stake information linked to hotkey and coldkey pairs. @@ -36,13 +37,21 @@ def fix_decoded_values(cls, decoded: Any) -> "StakeInfo": stake=Balance.from_rao(decoded["stake"]), ) + @classmethod + def _fix_decoded(cls, decoded: Any) -> "StakeInfo": + hotkey = decode_account_id(decoded.hotkey) + coldkey = decode_account_id(decoded.coldkey) + stake = Balance.from_rao(decoded.stake) + + return StakeInfo(hotkey, coldkey, stake) + @classmethod def from_vec_u8(cls, vec_u8: list[int]) -> Optional["StakeInfo"]: """Returns a StakeInfo object from a ``vec_u8``.""" if len(vec_u8) == 0: return None - decoded = from_scale_encoding(vec_u8, ChainDataType.StakeInfo) + decoded = bt_decode.StakeInfo.decode(vec_u8) if decoded is None: return None @@ -70,9 +79,9 @@ def list_of_tuple_from_vec_u8( } @classmethod - def list_from_vec_u8(cls, vec_u8: list[int]) -> list["StakeInfo"]: + def list_from_vec_u8(cls, vec_u8: bytes) -> list["StakeInfo"]: """Returns a list of StakeInfo objects from a ``vec_u8``.""" - decoded = from_scale_encoding(vec_u8, ChainDataType.StakeInfo, is_vec=True) + decoded = bt_decode.StakeInfo.decode_vec(vec_u8) if decoded is None: return [] diff --git a/bittensor/core/chain_data/subnet_hyperparameters.py b/bittensor/core/chain_data/subnet_hyperparameters.py index c28f802cfc..b233a6f393 100644 --- a/bittensor/core/chain_data/subnet_hyperparameters.py +++ b/bittensor/core/chain_data/subnet_hyperparameters.py @@ -1,11 +1,13 @@ from dataclasses import dataclass -from typing import Optional +from typing import Any, Optional import bt_decode +from bittensor.core.chain_data.info_base import InfoBase + @dataclass -class SubnetHyperparameters: +class SubnetHyperparameters(InfoBase): """ This class represents the hyperparameters for a subnet. @@ -68,7 +70,7 @@ class SubnetHyperparameters: liquid_alpha_enabled: bool @classmethod - def from_vec_u8(cls, vec_u8: bytes) -> Optional["SubnetHyperparameters"]: + def _fix_decoded(cls, decoded: Any) -> "SubnetHyperparameters": """ Create a `SubnetHyperparameters` instance from a vector of bytes. @@ -80,7 +82,6 @@ def from_vec_u8(cls, vec_u8: bytes) -> Optional["SubnetHyperparameters"]: Returns: Optional[SubnetHyperparameters]: An instance of `SubnetHyperparameters` if decoding is successful, None otherwise. """ - decoded = bt_decode.SubnetHyperparameters.decode(vec_u8) return SubnetHyperparameters( rho=decoded.rho, kappa=decoded.kappa, @@ -110,3 +111,8 @@ def from_vec_u8(cls, vec_u8: bytes) -> Optional["SubnetHyperparameters"]: alpha_low=decoded.alpha_low, liquid_alpha_enabled=decoded.liquid_alpha_enabled, ) + + @classmethod + def from_vec_u8(cls, vec_u8: bytes) -> Optional["SubnetHyperparameters"]: + decoded = bt_decode.SubnetHyperparameters.decode(vec_u8) + return cls._fix_decoded(decoded) diff --git a/bittensor/core/chain_data/subnet_info.py b/bittensor/core/chain_data/subnet_info.py index 4169746a08..4e37716a5d 100644 --- a/bittensor/core/chain_data/subnet_info.py +++ b/bittensor/core/chain_data/subnet_info.py @@ -1,14 +1,16 @@ from dataclasses import dataclass +from typing import Any import bt_decode +from bittensor.core.chain_data.info_base import InfoBase from bittensor.core.chain_data.utils import decode_account_id from bittensor.utils import u16_normalized_float from bittensor.utils.balance import Balance @dataclass -class SubnetInfo: +class SubnetInfo(InfoBase): """Dataclass for subnet info.""" netuid: int @@ -30,34 +32,33 @@ class SubnetInfo: burn: Balance owner_ss58: str + @classmethod + def _fix_decoded(cls, decoded: Any) -> "SubnetInfo": + return SubnetInfo( + netuid=decoded.netuid, + rho=decoded.rho, + kappa=decoded.kappa, + difficulty=decoded.difficulty, + immunity_period=decoded.immunity_period, + max_allowed_validators=decoded.max_allowed_validators, + min_allowed_weights=decoded.min_allowed_weights, + max_weight_limit=decoded.max_weights_limit, + scaling_law_power=decoded.scaling_law_power, + subnetwork_n=decoded.subnetwork_n, + max_n=decoded.max_allowed_uids, + blocks_since_epoch=decoded.blocks_since_last_step, + tempo=decoded.tempo, + modality=decoded.network_modality, + connection_requirements={ + str(int(netuid)): u16_normalized_float(int(req)) + for (netuid, req) in decoded.network_connect + }, + emission_value=decoded.emission_values, + burn=Balance.from_rao(decoded.burn), + owner_ss58=decode_account_id(decoded.owner), + ) + @classmethod def list_from_vec_u8(cls, vec_u8: bytes) -> list["SubnetInfo"]: decoded = bt_decode.SubnetInfo.decode_vec_option(vec_u8) - result = [] - for d in decoded: - result.append( - SubnetInfo( - netuid=d.netuid, - rho=d.rho, - kappa=d.kappa, - difficulty=d.difficulty, - immunity_period=d.immunity_period, - max_allowed_validators=d.max_allowed_validators, - min_allowed_weights=d.min_allowed_weights, - max_weight_limit=d.max_weights_limit, - scaling_law_power=d.scaling_law_power, - subnetwork_n=d.subnetwork_n, - max_n=d.max_allowed_uids, - blocks_since_epoch=d.blocks_since_last_step, - tempo=d.tempo, - modality=d.network_modality, - connection_requirements={ - str(int(netuid)): u16_normalized_float(int(req)) - for (netuid, req) in d.network_connect - }, - emission_value=d.emission_values, - burn=Balance.from_rao(d.burn), - owner_ss58=decode_account_id(d.owner), - ) - ) - return result + return [cls._fix_decoded(d) for d in decoded] diff --git a/bittensor/core/chain_data/utils.py b/bittensor/core/chain_data/utils.py index 1218b9ea56..28b8bb4d43 100644 --- a/bittensor/core/chain_data/utils.py +++ b/bittensor/core/chain_data/utils.py @@ -95,90 +95,6 @@ def from_scale_encoding_using_type_string( custom_rpc_type_registry = { "types": { - "SubnetInfo": { - "type": "struct", - "type_mapping": [ - ["netuid", "Compact"], - ["rho", "Compact"], - ["kappa", "Compact"], - ["difficulty", "Compact"], - ["immunity_period", "Compact"], - ["max_allowed_validators", "Compact"], - ["min_allowed_weights", "Compact"], - ["max_weights_limit", "Compact"], - ["scaling_law_power", "Compact"], - ["subnetwork_n", "Compact"], - ["max_allowed_uids", "Compact"], - ["blocks_since_last_step", "Compact"], - ["tempo", "Compact"], - ["network_modality", "Compact"], - ["network_connect", "Vec<[u16; 2]>"], - ["emission_values", "Compact"], - ["burn", "Compact"], - ["owner", "AccountId"], - ], - }, - "DelegateInfo": { - "type": "struct", - "type_mapping": [ - ["delegate_ss58", "AccountId"], - ["take", "Compact"], - ["nominators", "Vec<(AccountId, Compact)>"], - ["owner_ss58", "AccountId"], - ["registrations", "Vec>"], - ["validator_permits", "Vec>"], - ["return_per_1000", "Compact"], - ["total_daily_return", "Compact"], - ], - }, - "NeuronInfo": { - "type": "struct", - "type_mapping": [ - ["hotkey", "AccountId"], - ["coldkey", "AccountId"], - ["uid", "Compact"], - ["netuid", "Compact"], - ["active", "bool"], - ["axon_info", "axon_info"], - ["prometheus_info", "PrometheusInfo"], - ["stake", "Vec<(AccountId, Compact)>"], - ["rank", "Compact"], - ["emission", "Compact"], - ["incentive", "Compact"], - ["consensus", "Compact"], - ["trust", "Compact"], - ["validator_trust", "Compact"], - ["dividends", "Compact"], - ["last_update", "Compact"], - ["validator_permit", "bool"], - ["weights", "Vec<(Compact, Compact)>"], - ["bonds", "Vec<(Compact, Compact)>"], - ["pruning_score", "Compact"], - ], - }, - "NeuronInfoLite": { - "type": "struct", - "type_mapping": [ - ["hotkey", "AccountId"], - ["coldkey", "AccountId"], - ["uid", "Compact"], - ["netuid", "Compact"], - ["active", "bool"], - ["axon_info", "axon_info"], - ["prometheus_info", "PrometheusInfo"], - ["stake", "Vec<(AccountId, Compact)>"], - ["rank", "Compact"], - ["emission", "Compact"], - ["incentive", "Compact"], - ["consensus", "Compact"], - ["trust", "Compact"], - ["validator_trust", "Compact"], - ["dividends", "Compact"], - ["last_update", "Compact"], - ["validator_permit", "bool"], - ["pruning_score", "Compact"], - ], - }, "NeuronCertificate": { "type": "struct", "type_mapping": [ @@ -223,38 +139,6 @@ def from_scale_encoding_using_type_string( ["stake", "Compact"], ], }, - "SubnetHyperparameters": { - "type": "struct", - "type_mapping": [ - ["rho", "Compact"], - ["kappa", "Compact"], - ["immunity_period", "Compact"], - ["min_allowed_weights", "Compact"], - ["max_weights_limit", "Compact"], - ["tempo", "Compact"], - ["min_difficulty", "Compact"], - ["max_difficulty", "Compact"], - ["weights_version", "Compact"], - ["weights_rate_limit", "Compact"], - ["adjustment_interval", "Compact"], - ["activity_cutoff", "Compact"], - ["registration_allowed", "bool"], - ["target_regs_per_interval", "Compact"], - ["min_burn", "Compact"], - ["max_burn", "Compact"], - ["bonds_moving_avg", "Compact"], - ["max_regs_per_block", "Compact"], - ["serving_rate_limit", "Compact"], - ["max_validators", "Compact"], - ["adjustment_alpha", "Compact"], - ["difficulty", "Compact"], - ["commit_reveal_weights_interval", "Compact"], - ["commit_reveal_weights_enabled", "bool"], - ["alpha_high", "Compact"], - ["alpha_low", "Compact"], - ["liquid_alpha_enabled", "bool"], - ], - }, "ScheduledColdkeySwapInfo": { "type": "struct", "type_mapping": [ @@ -277,6 +161,9 @@ def decode_account_id(account_id_bytes: Union[bytes, str]) -> str: Returns: str: The decoded AccountId as a Base64 string. """ + if isinstance(account_id_bytes, tuple) and isinstance(account_id_bytes[0], tuple): + account_id_bytes = account_id_bytes[0] + # Convert the AccountId bytes to a Base64 string return ss58_encode(bytes(account_id_bytes).hex(), SS58_FORMAT) diff --git a/bittensor/core/settings.py b/bittensor/core/settings.py index 2da8ecb5a1..22bf343305 100644 --- a/bittensor/core/settings.py +++ b/bittensor/core/settings.py @@ -103,168 +103,6 @@ "types": { "Balance": "u64", # Need to override default u128 }, - "runtime_api": { - "DelegateInfoRuntimeApi": { - "methods": { - "get_delegated": { - "params": [ - { - "name": "coldkey", - "type": "Vec", - }, - ], - "type": "Vec", - }, - "get_delegates": { - "params": [], - "type": "Vec", - }, - } - }, - "NeuronInfoRuntimeApi": { - "methods": { - "get_neuron_lite": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - { - "name": "uid", - "type": "u16", - }, - ], - "type": "Vec", - }, - "get_neurons_lite": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - ], - "type": "Vec", - }, - "get_neuron": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - { - "name": "uid", - "type": "u16", - }, - ], - "type": "Vec", - }, - "get_neurons": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - ], - "type": "Vec", - }, - } - }, - "StakeInfoRuntimeApi": { - "methods": { - "get_stake_info_for_coldkey": { - "params": [ - { - "name": "coldkey_account_vec", - "type": "Vec", - }, - ], - "type": "Vec", - }, - "get_stake_info_for_coldkeys": { - "params": [ - { - "name": "coldkey_account_vecs", - "type": "Vec>", - }, - ], - "type": "Vec", - }, - }, - }, - "ValidatorIPRuntimeApi": { - "methods": { - "get_associated_validator_ip_info_for_subnet": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - ], - "type": "Vec", - }, - }, - }, - "SubnetInfoRuntimeApi": { - "methods": { - "get_subnet_hyperparams": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - ], - "type": "Vec", - }, - "get_subnet_info": { - "params": [ - { - "name": "netuid", - "type": "u16", - }, - ], - "type": "Vec", - }, - "get_subnets_info": { - "params": [], - "type": "Vec", - }, - } - }, - "SubnetRegistrationRuntimeApi": { - "methods": {"get_network_registration_cost": {"params": [], "type": "u64"}} - }, - "ColdkeySwapRuntimeApi": { - "methods": { - "get_scheduled_coldkey_swap": { - "params": [ - { - "name": "coldkey_account_vec", - "type": "Vec", - }, - ], - "type": "Vec", - }, - "get_remaining_arbitration_period": { - "params": [ - { - "name": "coldkey_account_vec", - "type": "Vec", - }, - ], - "type": "Vec", - }, - "get_coldkey_swap_destinations": { - "params": [ - { - "name": "coldkey_account_vec", - "type": "Vec", - }, - ], - "type": "Vec", - }, - } - }, - }, } diff --git a/bittensor/utils/substrate_interface.py b/bittensor/utils/substrate_interface.py index 75e2c27ffa..2f043d3ad2 100644 --- a/bittensor/utils/substrate_interface.py +++ b/bittensor/utils/substrate_interface.py @@ -14,10 +14,17 @@ from dataclasses import dataclass from datetime import datetime from hashlib import blake2b +from itertools import chain +from types import SimpleNamespace from typing import Optional, Any, Union, Callable, Awaitable, cast, TYPE_CHECKING from bittensor_wallet import Keypair -from bt_decode import PortableRegistry, decode as decode_by_type_string, MetadataV15 +from bt_decode import ( + PortableRegistry, + decode as decode_by_type_string, + encode as encode_by_type_string, + MetadataV15, +) from scalecodec import GenericExtrinsic, ss58_encode, ss58_decode, is_valid_ss58_address from scalecodec.base import ScaleBytes, ScaleType, RuntimeConfigurationObject from scalecodec.type_registry import load_type_registry_preset @@ -31,7 +38,10 @@ ExtrinsicNotFound, BlockNotFound, ) -from bittensor.utils import hex_to_bytes +from bittensor.utils import ( + hex_to_bytes, + ss58_address_to_bytes, +) from bittensor.utils.btlogging import logging if TYPE_CHECKING: @@ -376,6 +386,33 @@ def get(self, name): return self[name] +class DictWithValue(dict): + value: Any + + def __init__(self, value: Any = None): + super().__init__() + self.value = value + + def __getitem__(self, key: Union[str, int]): + result = super().get(key) + if not result and isinstance(key, int): + # if the key is not found, return the key at the given index + return list(chain.from_iterable(self.items()))[key] + return result + + @classmethod + def from_dict(cls, dict_: dict): + inst = cls() + # recursively convert all values to DictWithValue + for key, value in dict_.items(): + if isinstance(value, dict): + value = cls.from_dict(value) + inst[key] = value + inst.value = dict_ + + return inst + + class ExtrinsicReceipt: """ A wrapper around AsyncExtrinsicReceipt that allows for using all the calls from it in a synchronous context @@ -880,6 +917,7 @@ async def retrieve(self, item_id: int) -> Optional[dict]: class AsyncSubstrateInterface: registry: Optional[PortableRegistry] = None + metadata_v15: Optional[MetadataV15] = None runtime_version = None type_registry_preset = None transaction_version = None @@ -949,6 +987,7 @@ def __init__( ) self.__metadata_cache = {} self.metadata_version_hex = "0x0f000000" # v15 + self.metadata_v15 = None self.event_loop = asyncio.get_event_loop() self.sync_calls = sync_calls self.extrinsic_receipt_cls = ( @@ -975,6 +1014,64 @@ async def initialize(self): async def __aexit__(self, exc_type, exc_val, exc_tb): pass + @staticmethod + def _type_registry_to_scale_info_types( + registry_types: list[dict[str, Any]], + ) -> list[dict[str, Any]]: + scale_info_types = [] + for type_entry in registry_types: + new_type_entry = DictWithValue(value=type_entry) + if ( + "variant" in type_entry["type"]["def"] + and len(type_entry["type"]["def"]["variant"]) == 0 + ): + type_entry["type"]["def"]["variant"] = { + "variants": [] + } # add empty variants field to variant type if empty + + for key, value in type_entry.items(): + if isinstance(value, dict): + entry = DictWithValue.from_dict(value) + else: + entry = SimpleNamespace(value=value) + new_type_entry[key] = entry + + scale_info_types.append(new_type_entry) + + return scale_info_types + + @staticmethod + def _type_id_to_name(ty_id: int) -> str: + type_string = f"scale_info::{ty_id}" + + return type_string + + def _type_registry_apis_to_runtime_api( + self, apis: list[dict[str, Any]] + ) -> dict[str, Any]: + runtime_api = {} + for api in apis: + api_name = api["name"] + methods = api["methods"] + + runtime_api[api_name] = { + "methods": { + method["name"]: { + "description": "\n".join(method["docs"]), + "params": [ + { + "name": input["name"], + "type": self._type_id_to_name(input["ty"]), + } + for input in method["inputs"] + ], + "type": self._type_id_to_name(method["output"]), + } + for method in methods + } + } + return runtime_api + @property def chain(self): """ @@ -1080,6 +1177,7 @@ async def load_registry(self): metadata_option_bytes = bytes.fromhex(metadata_option_hex_str[2:]) metadata_v15 = MetadataV15.decode_from_metadata_option(metadata_option_bytes) self.registry = PortableRegistry.from_metadata_v15(metadata_v15) + self.metadata_v15 = metadata_v15 async def decode_scale( self, type_string: str, scale_bytes: bytes, _attempt=1, _retries=3 @@ -1122,25 +1220,27 @@ async def _wait_for_registry(): raise ValueError("Registry was never loaded.") return obj - async def encode_scale(self, type_string, value, block_hash=None) -> ScaleBytes: + async def encode_scale(self, type_string, value) -> bytes: """ Helper function to encode arbitrary data into SCALE-bytes for given RUST type_string Args: type_string: the type string of the SCALE object for decoding value: value to encode - block_hash: the hash of the blockchain block whose metadata to use for encoding Returns: - ScaleBytes encoded value + Encoded SCALE bytes """ - if not self.__metadata or block_hash: - await self.init_runtime(block_hash=block_hash) + if value is None: + result = b"\x00" + else: + if type_string == "scale_info::0": # Is an AccountId + # encode string into AccountId + ## AccountId is a composite type with one, unnamed field + return ss58_address_to_bytes(value) - obj = self.runtime_config.create_scale_object( - type_string=type_string, metadata=self.__metadata - ) - return obj.encode(value) + result = bytes(encode_by_type_string(type_string, self.registry, value)) + return result def ss58_encode( self, public_key: Union[str, bytes], ss58_format: int = None @@ -3081,13 +3181,13 @@ async def get_chain_finalised_head(self): return response.get("result") - async def runtime_call( + async def runtime_call_wait_to_decode( self, api: str, method: str, params: Optional[Union[list, dict]] = None, block_hash: Optional[str] = None, - ) -> ScaleType: + ) -> tuple[str, bytes]: """ Calls a runtime API method @@ -3098,7 +3198,7 @@ async def runtime_call( block_hash: Hash of the block at which to make the runtime API call Returns: - ScaleType from the runtime call + Tuple of the runtime call type and the result bytes """ if not self.__metadata or block_hash: await self.init_runtime(block_hash=block_hash) @@ -3107,57 +3207,66 @@ async def runtime_call( params = {} try: - runtime_call_def = self.runtime_config.type_registry["runtime_api"][api][ - "methods" - ][method] - runtime_api_types = self.runtime_config.type_registry["runtime_api"][ - api - ].get("types", {}) + metadata_v15 = self.metadata_v15.value() + apis = {entry["name"]: entry for entry in metadata_v15["apis"]} + api_entry = apis[api] + methods = {entry["name"]: entry for entry in api_entry["methods"]} + runtime_call_def = methods[method] except KeyError: raise ValueError(f"Runtime API Call '{api}.{method}' not found in registry") - if isinstance(params, list) and len(params) != len(runtime_call_def["params"]): + if isinstance(params, list) and len(params) != len(runtime_call_def["inputs"]): raise ValueError( f"Number of parameter provided ({len(params)}) does not " - f"match definition {len(runtime_call_def['params'])}" + f"match definition {len(runtime_call_def['inputs'])}" ) - # Add runtime API types to registry - self.runtime_config.update_type_registry_types(runtime_api_types) - runtime = Runtime( - self.chain, - self.runtime_config, - self.__metadata, - self.type_registry, - ) - # Encode params - param_data = ScaleBytes(bytes()) - for idx, param in enumerate(runtime_call_def["params"]): - scale_obj = runtime.runtime_config.create_scale_object(param["type"]) + param_data = b"" + for idx, param in enumerate(runtime_call_def["inputs"]): + param_type_string = f'scale_info::{param["ty"]}' if isinstance(params, list): - param_data += scale_obj.encode(params[idx]) + param_data += await self.encode_scale(param_type_string, params[idx]) else: if param["name"] not in params: raise ValueError(f"Runtime Call param '{param['name']}' is missing") - param_data += scale_obj.encode(params[param["name"]]) + param_data += await self.encode_scale( + param_type_string, params[param["name"]] + ) # RPC request result_data = await self.rpc_request( - "state_call", [f"{api}_{method}", str(param_data), block_hash] + "state_call", [f"{api}_{method}", param_data.hex(), block_hash] ) - # Decode result - # TODO update this to use bt-decode - result_obj = runtime.runtime_config.create_scale_object( - runtime_call_def["type"] - ) - result_obj.decode( - ScaleBytes(result_data["result"]), - check_remaining=self.config.get("strict_scale_decode"), + output_type_string = f'scale_info::{runtime_call_def["output"]}' + + return output_type_string, hex_to_bytes(result_data["result"]) + + async def runtime_call( + self, + api: str, + method: str, + params: Optional[Union[list, dict]] = None, + block_hash: Optional[str] = None, + ) -> ScaleType: + """ + Calls a runtime API method + :param api: Name of the runtime API e.g. 'TransactionPaymentApi' + :param method: Name of the method e.g. 'query_fee_details' + :param params: List of parameters needed to call the runtime API + :param block_hash: Hash of the block at which to make the runtime API call + :return: ScaleType from the runtime call + """ + # Get the runtime call type and result bytes + runtime_call_type, result_bytes = await self.runtime_call_wait_to_decode( + api, method, params, block_hash ) + # Decode the result bytes + result_obj = await self.decode_scale(runtime_call_type, result_bytes) + return result_obj async def get_account_nonce(self, account_address: str) -> int: diff --git a/tests/helpers/integration_websocket_data.py b/tests/helpers/integration_websocket_data.py index 6bd2e926e5..1b8618a55c 100644 --- a/tests/helpers/integration_websocket_data.py +++ b/tests/helpers/integration_websocket_data.py @@ -43,191 +43,6 @@ }, }, }, - "rpc_methods": { - "[]": { - "jsonrpc": "2.0", - "result": { - "methods": [ - "account_nextIndex", - "archive_unstable_body", - "archive_unstable_call", - "archive_unstable_finalizedHeight", - "archive_unstable_genesisHash", - "archive_unstable_hashByHeight", - "archive_unstable_header", - "archive_unstable_storage", - "author_hasKey", - "author_hasSessionKeys", - "author_insertKey", - "author_pendingExtrinsics", - "author_removeExtrinsic", - "author_rotateKeys", - "author_submitAndWatchExtrinsic", - "author_submitExtrinsic", - "author_unwatchExtrinsic", - "chainHead_v1_body", - "chainHead_v1_call", - "chainHead_v1_continue", - "chainHead_v1_follow", - "chainHead_v1_header", - "chainHead_v1_stopOperation", - "chainHead_v1_storage", - "chainHead_v1_unfollow", - "chainHead_v1_unpin", - "chainSpec_v1_chainName", - "chainSpec_v1_genesisHash", - "chainSpec_v1_properties", - "chain_getBlock", - "chain_getBlockHash", - "chain_getFinalisedHead", - "chain_getFinalizedHead", - "chain_getHead", - "chain_getHeader", - "chain_getRuntimeVersion", - "chain_subscribeAllHeads", - "chain_subscribeFinalisedHeads", - "chain_subscribeFinalizedHeads", - "chain_subscribeNewHead", - "chain_subscribeNewHeads", - "chain_subscribeRuntimeVersion", - "chain_unsubscribeAllHeads", - "chain_unsubscribeFinalisedHeads", - "chain_unsubscribeFinalizedHeads", - "chain_unsubscribeNewHead", - "chain_unsubscribeNewHeads", - "chain_unsubscribeRuntimeVersion", - "childstate_getKeys", - "childstate_getKeysPaged", - "childstate_getKeysPagedAt", - "childstate_getStorage", - "childstate_getStorageEntries", - "childstate_getStorageHash", - "childstate_getStorageSize", - "debug_getBadBlocks", - "debug_getRawBlock", - "debug_getRawHeader", - "debug_getRawReceipts", - "debug_getRawTransaction", - "delegateInfo_getDelegate", - "delegateInfo_getDelegated", - "delegateInfo_getDelegates", - "eth_accounts", - "eth_blockNumber", - "eth_call", - "eth_chainId", - "eth_coinbase", - "eth_estimateGas", - "eth_feeHistory", - "eth_gasPrice", - "eth_getBalance", - "eth_getBlockByHash", - "eth_getBlockByNumber", - "eth_getBlockReceipts", - "eth_getBlockTransactionCountByHash", - "eth_getBlockTransactionCountByNumber", - "eth_getCode", - "eth_getFilterChanges", - "eth_getFilterLogs", - "eth_getLogs", - "eth_getStorageAt", - "eth_getTransactionByBlockHashAndIndex", - "eth_getTransactionByBlockNumberAndIndex", - "eth_getTransactionByHash", - "eth_getTransactionCount", - "eth_getTransactionReceipt", - "eth_getUncleByBlockHashAndIndex", - "eth_getUncleByBlockNumberAndIndex", - "eth_getUncleCountByBlockHash", - "eth_getUncleCountByBlockNumber", - "eth_getWork", - "eth_hashrate", - "eth_maxPriorityFeePerGas", - "eth_mining", - "eth_newBlockFilter", - "eth_newFilter", - "eth_newPendingTransactionFilter", - "eth_protocolVersion", - "eth_sendRawTransaction", - "eth_sendTransaction", - "eth_submitHashrate", - "eth_submitWork", - "eth_subscribe", - "eth_syncing", - "eth_uninstallFilter", - "eth_unsubscribe", - "net_listening", - "net_peerCount", - "net_version", - "neuronInfo_getNeuron", - "neuronInfo_getNeuronLite", - "neuronInfo_getNeurons", - "neuronInfo_getNeuronsLite", - "offchain_localStorageGet", - "offchain_localStorageSet", - "payment_queryFeeDetails", - "payment_queryInfo", - "rpc_methods", - "state_call", - "state_callAt", - "state_getChildReadProof", - "state_getKeys", - "state_getKeysPaged", - "state_getKeysPagedAt", - "state_getMetadata", - "state_getPairs", - "state_getReadProof", - "state_getRuntimeVersion", - "state_getStorage", - "state_getStorageAt", - "state_getStorageHash", - "state_getStorageHashAt", - "state_getStorageSize", - "state_getStorageSizeAt", - "state_queryStorage", - "state_queryStorageAt", - "state_subscribeRuntimeVersion", - "state_subscribeStorage", - "state_traceBlock", - "state_unsubscribeRuntimeVersion", - "state_unsubscribeStorage", - "subnetInfo_getLockCost", - "subnetInfo_getSubnetHyperparams", - "subnetInfo_getSubnetInfo", - "subnetInfo_getSubnetInfo_v2", - "subnetInfo_getSubnetsInf_v2", - "subnetInfo_getSubnetsInfo", - "subscribe_newHead", - "system_accountNextIndex", - "system_addLogFilter", - "system_addReservedPeer", - "system_chain", - "system_chainType", - "system_dryRun", - "system_dryRunAt", - "system_health", - "system_localListenAddresses", - "system_localPeerId", - "system_name", - "system_nodeRoles", - "system_peers", - "system_properties", - "system_removeReservedPeer", - "system_reservedPeers", - "system_resetLogFilter", - "system_syncState", - "system_unstable_networkState", - "system_version", - "transactionWatch_v1_submitAndWatch", - "transactionWatch_v1_unwatch", - "transaction_v1_broadcast", - "transaction_v1_stop", - "unsubscribe_newHead", - "web3_clientVersion", - "web3_sha3", - ] - }, - } - }, "state_getRuntimeVersion": { '["0x119e135f8ae6eac1f3fc47fc14838afcfdbee13e8dba14657ae150f4d56f6df2"]': { "jsonrpc": "2.0", @@ -264,16 +79,15 @@ } }, "state_getStorageAt": { - '["0x658faa385070e074c85bf6b568cf05550e30450fc4d507a846032a7fa65d9a431700", null]': { + '["0x658faa385070e074c85bf6b568cf05550e30450fc4d507a846032a7fa65d9a430100", null]': { "jsonrpc": "2.0", "result": "0x01", }, - '["0x658faa385070e074c85bf6b568cf0555696e262a16e52255a69d8acd793541461700", null]': { + '["0x658faa385070e074c85bf6b568cf0555696e262a16e52255a69d8acd793541460100", null]': { "jsonrpc": "2.0", - "result": "0x4ce0d61400000000000eeb150000000000c89016000000000051b6190000000000d6e71b00000000001b111e0000000000525d1e0000000000083a2200000000000e3a220000000000bb702200000000009ecc310000000000cb41240000000000dc41240000000000eb4124000000000051222500000000005563280000000000f4552b000000000052562b0000000000fb372d0000000000", + "result": "0x04a800000000000000", }, }, - "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, }, "bonds": { "chain_getHead": { @@ -898,62 +712,136 @@ "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, }, "get_all_subnets_info": { - "state_call": { - '["SubnetInfoRuntimeApi_get_subnets_info", "0x"]': { - "jsonrpc": "2.0", - "result": "0x760d0100dd03010028feff0100025a62020140010200feff0300c80102010200040000310202286bee0000000000000000000000000000000000000000000000000000000000000000010428feff01000000010204feff0300c87901010404500000893902286beed43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d010828feff0100025a62020001020110a10fc87c0104090ea10f00000e93104702286beed43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d010c28feff010013ffffffffffffffff214e010104feff0300c8010401049905a10500005d1e04aa29477c7ad9689f38bdcf6e0a52b67346e09d3a132677fd654c58f4fb569143011028feff0100025a6202817001020110a10fc86c0104110ea10f00000002286beed2b77364d1c3b445cd69bd59f1a87dcb26c9ce3f46437d55b88b43f1c177e776011428feff0100025a62020001020110a10fc8500104150ea10f00000002286bee545734b760233cff9db36ae17ec01cd00639209af337d818eb5ff60995347b1b011828feff0100025a62020001020110a10fc8340104190ea10f00000002286bee545734b760233cff9db36ae17ec01cd00639209af337d818eb5ff60995347b1b011c28feff0100025a62020001020110a10fc81c01041d0ea10f00000002286bee545734b760233cff9db36ae17ec01cd00639209af337d818eb5ff60995347b1b012028feff0100025a6202214e010204feff0300c859020104b891010000a9a804f88542cc87224bf8cd4aabf49dd06f89c6032f6a6b15c86b5c3293d492bcc276012428feff0100025a6202214e01020101fd07c8340104250ea10f00004c0460101454e0638a1e1aaae8859324b47b86e70d137eae8a2ffb29dbc7efc58b57012828feff0100025a6202214e010104feff0300c8480104290ea10f00000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd34012c28feff010013ffffffffffffffff214e0c04feff0300c86c010414a105000000049eded74323104f9ce9cb6b07d4ad1095fca84700a910637effd43060dba23a6e013028feff010013ffffffffffffffff214e010104feff0300c86d01010418a105000000044cafab2196e7acade8ded4c4ffa483a6fbc83b1f211e2a555f05e74c782d7f41013428feff010013ffffffffffffffff214e010104feff0300c8b801041ca10500000004784d6f92a188c629a89e1f9dff61988361b5ae4455fea456f32dbc7f2c2c4814013828feff010013ffffffffffffffff214e010104feff0300c848010420a105000000049c15f9024e0f7d6e0fd1797c1ab35b3a619f0dbffd45c27e8fe332168c7a0b76013c28feff010013ffffffffffffffff214e010104feff0300c80104010424a1050000a675010004ce461b7b509fe67688b9e217849c8dbb6a45c00bcf3b77698f90288a34dab25a014028feff010013ffffffffffffffff214e010104feff0300c820010428a10500000004aa72a3f3be29d530b858b98bf207763bf60cccecd18f343e3428dacb8d848a1e014428feff010013ffffffffffffffff214e010104feff0300c81801042ca10500000004aa72a3f3be29d530b858b98bf207763bf60cccecd18f343e3428dacb8d848a1e014828feff010013ffffffffffffffff214e010104feff0300c8e4010430a1050000ae55010004fa19f3c1916abb9c8fe3b15ce5d36e9941f40b00c2b2e5aee38463e8e8444c51014c28feff010013ffffffffffffffff214e010104feff0300c868010434a105000000042c1f081c25cfab215fe7f6d785208a70f5d5de9b78441cd6837ce0fa5af48403015028feff010013ffffffffffffffff214e010104feff0300c860010438a1050000000460165e8d9e5dbc5784efb3996b4decd66adb05f1c295113f30077925b6e16e7e015428feff010013ffffffffffffffff214e0c04feff0300c85801043ca105000000042e09742a7fcdec892fe7e484ade70ce31a2362103bf683c69f6755c8cd890c61015828feff0100419c8170010104feff0300c801040104590ea10f00005a63100002093d00cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd34015c28feff0100025a6202214e010104feff0300c84c01045d0ea10f00000004f6146686eaae2f2fe1b2802f86666265785305aaee08f10a26e2018020bf6902016028feff0100025a6202214e010104feff0300c8c5010104610ea10f000015010400e258276eebf75010a79b2d97b47ff77ce9d5eed1e45d27a165b3f85f604b00016428feff010013ffffffffffffffff214e010104feff0300c8610201044ca10500000c0452baa947bcfd423ba837a805ccc0f6f846933fb0e9aa30bb317adfae43dee00b016828feff010013ffffffffffffffff214e010104feff0300c820010450a10500000004f6146686eaae2f2fe1b2802f86666265785305aaee08f10a26e2018020bf6902016c28feff010013ffffffffffffffff214e010104feff0300c8ac010454a1050000000452baa947bcfd423ba837a805ccc0f6f846933fb0e9aa30bb317adfae43dee00b017028feff010013ffffffffffffffff214e010104feff0300c8d0010458a10500000004f283651894ca4ae7ef252a850cdff364636c90db22c4df2a8e52d5ec0d8b4305017428feff010013ffffffffffffffff214e010104feff0300c82401045ca10500000004f2e6a87d26c36ed8b52703410891c9bdda5659918e115e9701339df6744b1047017828feff010013ffffffffffffffff214e010104feff0300c82c010460a10500000004c47fa889cc99165e57e1311d8631281a9c7d25c969d81597436ea9b79d15cc02017c28feff010013ffffffffffffffff214e010104feff0300c84101010464a10500000004c47fa889cc99165e57e1311d8631281a9c7d25c969d81597436ea9b79d15cc02018028feff010013ffffffffffffffff214e010104feff0300c8f901010468a105000056b1ad0d043c3093ce8800882069e5dd77d99ed634731f84498bba383757ecf30cb794ca5a018428feff010013ffffffffffffffff214e010104feff0300c83401046ca10500000004ae52013cb556e37df85553e8cd090c5c0ee25d05e1f22fde2899993d13332d33018828feff010013ffffffffffffffff214e010104feff0300c8dc010470a105000000044e0b2aaafc29f2393261b9aecb4e934658d871c0cd0e03b2a9bb8b510478613a018c28feff010013ffffffffffffffff214e010104feff0300c814010474a10500000004e44900413c6497d9fd0935d39789a74c693d8132f7c30c4df47eb1bedffa5c48019028feff010013ffffffffffffffff214e010104feff0300c818010478a1050000650304bc736a93c0cc60ba45e4aa656309e86ba7db12ff9d17fb0fb959e0edc677af1a019428feff010013ffffffffffffffff214e010104feff0300c84c01047ca10500000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd34019828feff010013ffffffffffffffff214e010104feff0300c83502010480a105000041130400cf02147e8f297c3379cc2891cf2bec1d771050a99244d7f4a08b9b34ec112a019c28feff010013ffffffffffffffff214e010104feff0300c864010484a1050000000432ef3983ef112af1081ad1ed96c4e9ba1d8d0e09664ae0d43e337b5ed89dc46301a028feff010013ffffffffffffffff214e010104feff0300c890010488a1050000000462981343120d52859357e1ce44559c70dfc80af594e4b5cabfb877029c67fe5501a428feff010013ffffffffffffffff214e010104feff0300c8a801048ca10500000004382b0c4b1b74314d201b6236f4d8c5a0974eae7940b3365a262ff95d207e421f01a828feff010013ffffffffffffffff214e010104feff0300c854010490a10500000004f8d6d28d7987616966fd863f97facac92c5f15398cfe11e09718960faebf073701ac28feff010013ffffffffffffffff214e010104feff0300c81c010494a105000000044650f668dacc57530a916dcffd6e48f6bfb3455bca892011cb4ead9e28496b4d01b028feff010013ffffffffffffffff214e010104feff0300c824010498a105000000049cd9caf4886a26f3c4d6e090ef7c637f80a42a88fee38a9d356cfa53020da53b01b428feff010013ffffffffffffffff214e010104feff0300c81001049ca1050000000472c37bdba84a4d5addec7974683b1aede7e6132af5031b1b7a5c560663e4216601b828feff010013ffffffffffffffff214e010104feff0300c8080104a0a105000000049867c7af9c5242c73b06e306ec6c22474ec5fa20f3b3d8b23652b3edcf48e35e01bc28feff010013ffffffffffffffff214e010104feff0300c87c0104a4a10500000004f62982f69cd326757775461ea8999554d3b784798ed09a73657d9a1c7685c70e01c028feff010013ffffffffffffffff214e010104feff0300c8080104a8a10500000004066029174005cab99602769451ef7b3b522981953a5f92b1c173bec13049997001c428feff010013ffffffffffffffff214e010104feff0300c8440104aca105000000043255130e936c142bf173137a8842c953c0c2d7746dc2c83fb573663c130d5e5201c828feff010013ffffffffffffffff214e010104feff0300c8140104b0a105000000045481d9339236b9f5ec8cbaff62faaafbc0cdf18d083b90959112f7f1b660553901cc28feff010013ffffffffffffffff214e010104feff0300c8e9010104b4a1050000367e3100046ef967c23cac38431dd1ff76ffad3d357924b0b4c52d86149f2981db1d5cf25b01d028feff010013ffffffffffffffff214e010104feff0300c84c0104b8a105000000046c3503742199e5978ef1c2690bfba4f281f59ed4b6b0f3ae8250e87bbb658d5801d428feff010013ffffffffffffffff214e010104feff0300c8340104bca105000000046428c1017d5e553f421598a26daf5a77844dca3a2f8f80cad8b51f16f632f35701d828feff010013ffffffffffffffff214e010104feff0300c8040104c0a105000000045a6c8783f6328eb976ec60c4f7fe075b817ede4a42b32a3bf18a6cf438c3ba2a01dc28feff010013ffffffffffffffff214e010104feff0300c81c0104c4a10500000004243cef52f666203a62f360d8b5474e3eddd4803aebb95f18ef0e8089d969194501e028feff010013ffffffffffffffff214e010104feff0300c8100104c8a1050000b10104287b5425fc2a87f8c3acf8a962798286db3d20719fe48fe9b8f664a1ddaafb6301e428feff010013ffffffffffffffff214e010104feff0300c8140104cca10500000004f8d6d28d7987616966fd863f97facac92c5f15398cfe11e09718960faebf073701e828feff010013ffffffffffffffff214e010104feff0300c8080104d0a10500000004ba43bd94ebbbb95eda10b7f82a3fabb3946f8f2f89a4ae3645dca8f5619ecc6f01ec28feff010013ffffffffffffffff214e010104feff0300c8140104d4a10500000004704f85febf2a6a1a71ed8e8d1e33af23796c802c6477c07751dcb35a09cf9d6001f028feff010013ffffffffffffffff214e010104feff0300c8140104d8a1050000000414908cb9fe96a7858ddc9f5af7fe6b2474dd1eeaa21c25d1f727056d7e2b142e01f428feff010013ffffffffffffffff214e010104feff0300c801040104dca10500005a3aee0404ae8354c4c102911a1b58875e439213a3d625b3896c3435967dddaa1d486ed70e01f828feff010013ffffffffffffffff214e010104feff0300c8300104e0a10500000004385922bb4363e72f17b4b0076ac167d19002f14c1b416c62e6286160067db73e01fc28feff010013ffffffffffffffff214e010104feff0300c8280104e4a10500000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd3401010128feff0100025a6202014001020110a10fc80901010404910100000000000000000000000000000000000000000000000000000000000000000000000001050128feff010013ffffffffffffffff214e010104feff0300c85d020104eca10500000004dcac67c6e135c1fb0234ebe2e2ccda083be6f91ebf18bccb8e922014d5080a1301090128feff010013ffffffffffffffff214e01010110a10fc8040104f0a105000096f2b13f042e1cf99a40a714e7df90a96f5c45168df1568893335a51cee93c543f1c39d106010d0128feff010013ffffffffffffffff214e010104feff0300c82c0104f4a105000000044069cd29a83311187c0f2930bc85695dfdf9e6f4646af9f6e2eafd2b7cef2b4101110128feff010013ffffffffffffffff214e010104feff0300c8040104f8a10500000004d2b77364d1c3b445cd69bd59f1a87dcb26c9ce3f46437d55b88b43f1c177e77601150128feff010013ffffffffffffffff214e010104feff0300c81c0104fca10500000004562d2afdb196526fe60bdc57c99f61c326cf7bf64377ebb269f9ffe5d4fe660701190128feff010013ffffffffffffffff214e010104feff0300c82001040101a105000000042ca75380b47a9a7465bac949527ef9f5a11856a7168797d4b78e1d457e47e947011d0128feff010013ffffffffffffffff214e010104feff0300c81801040501a10500000004b6c908350e87d29190aae491ac5f05d6c3262658125d5184da8446459829555901210128feff010013ffffffffffffffff214e010104feff0300c84801040901a105000091010458b93695d1b7cbaa6694e16b923c0ea1270bc3a11da44ccbdcc073ea3b09986401250128feff010013ffffffffffffffff214e010104feff0300c85401040d01a1050000000002599642053134e8f9699342e55fa074d8114df91e48bcf534740ba200be3e2d01290128feff010013ffffffffffffffff214e010104feff0300c86801041101a10500000004a22ce27c67f902395783b074b05a5372102c50cced56a792309fb10381b4d35c012d0128feff010013ffffffffffffffff214e010104feff0300c82801041501a105000098046c18068fdb7d1adb1bb5fbfed9578b3bdef882bbd79fd1c8709aa9087dcb3b4501310128feff010013ffffffffffffffff214e010104feff0300c8a90201041901a10500000004d849c3d25149fc5b8f00d2e4b3a9cf6a355af3c8aea5c1415f894e8f5e68522b01350128feff010013ffffffffffffffff214e010104feff0300c8190101041d01a10500000000141f1d5c5b356fa67490c9281c432e776b7706840801a652ac2a86152515683e01390128feff010013ffffffffffffffff214e010104feff0300c8590101042101a105000000047c5e19496686cf8a2f632709ac337d1b1c94210624f715910e3c89a8607ba34c013d0128feff010013ffffffffffffffff214e010104feff0300c89001042501a105000000045cf7811df39b6057753cff0822157f19351d292e5ea660710bc783ec44fe1b1201410128feff010013ffffffffffffffff214e010104feff0300c8b001042901a10500005910044e0b2aaafc29f2393261b9aecb4e934658d871c0cd0e03b2a9bb8b510478613a01450128feff010013ffffffffffffffff214e010104feff0300c81c01042d01a10500000004cce86023da931c965f5730beb54df83bdcd356edae149326622a07eb9d6f023101490128feff010013ffffffffffffffff214e010104feff0300c83801043101a105000000047081208ce88f99da3e45677997c82da7217cce89f1ed7e7482b1ac0543d75775014d0128feff010013ffffffffffffffff214e010104feff0300c81801043501a1050000deb00100049c4a7a07880883c14fd19b8e011bcb958d14656e73e7b572e7c50d1456b0e60e01510128feff010013ffffffffffffffff214e010104feff0300c81801043901a10500000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd3401550128feff010013ffffffffffffffff214e010104feff0300c81001043d01a105000000041c0857f7a760f66378e3962fa49ec6fc4905bd8728943556fc14ef7223cc1d0f01590128feff010013ffffffffffffffff214e010104feff0300c81401044101a105000000049a9baa94fa4e9bcb51740b491513d28333eafc9667e302db0b9a042b08de2d34015d0128feff010013ffffffffffffffff214e010104feff0300c8ad0201044501a105000008040c7fe2932483a11b56515d3bd501ab2efe19cda3428488bbbbacf2aeba628b1d01610128feff010013ffffffffffffffff214e010104feff0300c8110201044901a1050000080402cc620c7885c1c6007c9d88d3f4276e197bb8620c02c28d9c638a877733592001650128feff010013ffffffffffffffff214e010104feff0300c87d0101044d01a10500009d0a04bc736a93c0cc60ba45e4aa656309e86ba7db12ff9d17fb0fb959e0edc677af1a01690128feff010013ffffffffffffffff214e010104feff0300c81401045101a105000000042c077963acf22bb9ceb35cceeb60ddd92900e4dcca6530dc25732e9bae7e240d016d0128feff010013ffffffffffffffff214e010104feff0300c81401045501a10500000004bc0f52cb129e482919639de704710bc352ad0875a17b857f63fd2c345c57880901710128feff010013ffffffffffffffffc15d010104feff0300c8bd0201045901a10500002e5081010498189717e30483c50257ee0b32e016b8d51b3b5e069f0f8bc29324f8723c017f01750128feff010013ffffffffffffffff214e010104feff0300c8ad0201045d01a10500000004467438014a82998e9b0796d3b5b6c948a87c02c5a67dc604d8fb05c429e1b41501790128feff010013ffffffffffffffff214e010104feff0300c81001046101a10500000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd34017d0128feff010013ffffffffffffffff214e010104feff0300c81c01046501a1050000000418ad7c0e9f700b034f5c7ef2bc80cd9d4fa4d8c39f636bb631fef7647105137501810128feff010013ffffffffffffffff214e010104feff0300c8f901010400040000220c2f5204d868f60727d5cfaa22309f04df53c475b0169c7a4372c82485dd828e745de81c01850128feff010013ffffffffffffffff31750404feff0300c8a401046d01a105000086ca0300049c78ec2b3154e3f9ec61ba535e2194ef4c168dff9fdc57801f92229021ec146f01890128feff010013ffffffffffffffff214e010104feff0300c8090101047101a10500000004c21295ef014e2b6b24b401c4189627b7bc10d855376a762b8f5ac7652c04144d018d0128feff010013ffffffffffffffff214e010104feff0300c84c01047501a10500000004b8b090d259b562a21a1aaccd4cf325d1acee257b58d53f2681dd05a9d96d112301910128feff010013ffffffffffffffff214e010104feff0300c8350101047901a1050000a63d0900040aff7c60342e1090c9249fe503297824ebe84ecb7a4bf2a48ed1ca97132b564601950128feff010013ffffffffffffffff214e010104feff0300c80c01047d01a1050000000410958b33fc945ef3a7e2f986d9de174a75b277590d66d984500098d32e51f90601990128feff010013ffffffffffffffff214e010104feff0300c88401048101a1050000290e04ae8354c4c102911a1b58875e439213a3d625b3896c3435967dddaa1d486ed70e019d0128feff010013ffffffffffffffff214e010104feff0300c80401048501a10500000004da507701de58f8ba575d4a257cac9a521351bcab4eb79f53cd80a8ad911a755601a10128feff010013ffffffffffffffff214e010104feff0300c8cd0201048901a10500000004bc61b83982c8bcf5cc27e0331b20b2dd3e3ce465a2247b38db806f7790c6cb1701a50128feff010013ffffffffffffffff214e010104feff0300c80401048d01a10500000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd3401a90128feff010013ffffffffffffffff214e010104feff0300c80801049101a10500000004da507701de58f8ba575d4a257cac9a521351bcab4eb79f53cd80a8ad911a755601ad0128feff010013ffffffffffffffff214e010104feff0300c80401049501a10500000004a0b74e1ef41081197f29e8cbc456b21e793773f11d4edc711b26784aff59217b01b10128feff010013ffffffffffffffff214e010104feff0300c80c01049901a10500000004bc61b83982c8bcf5cc27e0331b20b2dd3e3ce465a2247b38db806f7790c6cb1701b50128feff010013ffffffffffffffff214e010104feff0300c80401049d01a105000000040aff7c60342e1090c9249fe503297824ebe84ecb7a4bf2a48ed1ca97132b564601b90128feff010013ffffffffffffffff214e010104feff0300c8080104a101a105000000044064631b31d92d852e137bc24310ec8bd86baf98ae2b03f1f4ba5d63d543897401bd0128feff010013ffffffffffffffff214e010104feff0300c8080104a501a105000000044064631b31d92d852e137bc24310ec8bd86baf98ae2b03f1f4ba5d63d543897401c10128feff010013ffffffffffffffff214e010104feff0300c8180104a901a1050000000700e40b5402f88542cc87224bf8cd4aabf49dd06f89c6032f6a6b15c86b5c3293d492bcc27601c50128feff010013ffffffffffffffff214e010104feff0300c8280104ad01a105000000046ec0eae062cede94212a0e73245db91cc13e257e6d673234a4b6d2791d9e340a01c90128feff010013ffffffffffffffff214e010104feff0300c8380104b101a105000000046ec0eae062cede94212a0e73245db91cc13e257e6d673234a4b6d2791d9e340a01cd0128feff010013ffffffffffffffff214e010104feff0300c83c0104b501a10500001e08070004788f2b1ac959b16dfd4d9c89f5b18ebc74d09871cda393a38d0856fb2a3fb54701d10128feff010013ffffffffffffffff214e010104feff0300c80d030104b901a10500000004aea85b4974fa81ea2d7d4f32c48812f2ccd1bc4d33993ef561c619b514d20f1e01d50128feff010013ffffffffffffffff214e010104feff0300c8100104bd01a10500000004b4d81a55e74730810604042874a2f49c6b086265f93f0dddfd39c82df2580c2801d90128feff010013ffffffffffffffff214e010104feff0300c865030104c101a10500000004a2ff6a9c3f5e50653c47819edcf4ab2eb94b48676f6eaee096c03b27708bd40101dd0128feff010013ffffffffffffffff214e010104feff0300c85d010104c501a1050000080494e9915614debc1df7e6467b62bd072ad5271c0e9c52da18c5c41c2c96ed3b6701e10128feff010013ffffffffffffffff214e010104feff0300c84c0104c901a105000000045a6c8783f6328eb976ec60c4f7fe075b817ede4a42b32a3bf18a6cf438c3ba2a01e50128feff010013ffffffffffffffff214e010104feff0300c8040104cd01a10500000004b67e7cc8c21432c5313c160396d647acdadd258af4806e20cf7a9e98ae49452001e90128feff010013ffffffffffffffff214e010104feff0300c8040104d101a10500000004b67e7cc8c21432c5313c160396d647acdadd258af4806e20cf7a9e98ae49452001ed0128feff010013ffffffffffffffff214e010104feff0300c8980104d501a1050000150104029c392906a0a017628ea03318c728d06294196390f13310c4cc47767d15073201f10128feff010013ffffffffffffffff214e010104feff0300c8040104d901a10500000004f219738d34359f9bae71932e806cc820a13e804bd9a30e884e232a71fb831b1301f50128feff010013ffffffffffffffff214e010104feff0300c8040104dd01a10500000004b67e7cc8c21432c5313c160396d647acdadd258af4806e20cf7a9e98ae49452001f90128feff010013ffffffffffffffff214e010104feff0300c8040104e101a1050000000498124a43481bc08ab174cf5214c8bd5f5d655da79105e26453dafa7c39bc2f7401fd0128feff010013ffffffffffffffff214e010104feff0300c8400104e501a10500000004cabf3601a75fdb45d95cfdeec3ee4779eb37e9ec982aa7632dfbddd4a607fd3401010228feff010013ffffffffffffffff214e010104feff0300c80c0104e901a10500000000e4185238bc9a20d310aaba4e6d0829812421c212f12e5154d1d55f079053a07801050228feff010013ffffffffffffffff214e010104feff0300c8080104ed01a10500000004ca32d7e056d12c126ffb3473211f5433038578d9ad5ee6025cafaf388d61445901090228feff010013ffffffffffffffff214e010104feff0300c80c0104f101a105000090042e10a36666eeceb1c4fedec194b9dad328fb394b557108ef3157cd00e1f67d63010d0228feff010013ffffffffffffffff214e010104feff0300c8140104f501a105000000049ca45ad90467d0cd912ea33d34e46e3a53c81eca841a466e63410234c439441f01110228feff010013ffffffffffffffff214e010104feff0300c8080104f901a105000000042684f1e6edd65d1d5126fdcc9b938ef888c636ef865154590f3b836167fba95f01150228feff010013ffffffffffffffff214e010104feff0300c8840104fd01a10500000004720952a3a738425806538be8514951f1f28ea41313cf6d1195e28ded76defd6a01190228feff010013ffffffffffffffff214e010114feff0300c87801040102a1050000710104161efad0a0ee3457f73b773db22eb6c3322f49a8cbf14b46233ca5eaed4fda25011d0228feff010013ffffffffffffffff214e010104feff0300c82001040502a105000000042ad643a435e0a78ffc03c351a705a68ef0645c805ca08780f0948c51dcd9952201210228feff010013ffffffffffffffff214e010104feff0300c81801040902a10500000004da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f01250228feff010013ffffffffffffffff214e010104feff0300c80401040d02a1050000000438fb2438348d1d376ec3adab05380da91d4fbea5693aaf6724a8846523a9095101290228feff010013ffffffffffffffff214e010104feff0300c8010201041102a1050000667e310004d4d3dce26a8ba3fbd49d1a8f3da83fddaa3766d4344885b4e6034e948647954a012d0228feff010013ffffffffffffffff214e010104feff0300c80801041502a10500000004c85fe6ebfecf63bfb863b8ab2428625a89f408f71d1bd1762bbb5beb1aaa784501310228feff010013ffffffffffffffff214e010104feff0300c81c01041902a10500000004921e3a08d1df8f952d7a726ce9814d3f704016184ee5c0bef9cd02d7ccf2941001350228feff010013ffffffffffffffff214e010104feff0300c80d0201041d02a105000000044e893a6773cfcbca6d0d341f447a1f09f476183ebd2aa552d81a2bcfd3a09d1d01390228feff010013ffffffffffffffff214e010104feff0300c81c01042102a1050000cd0a046e3def08c71e9c9ae953bfd0db7562a93b7e4256471a04ce87650a2e18a8c34f013d0228feff010013ffffffffffffffff214e010104feff0300c81801042502a1050000000410958b33fc945ef3a7e2f986d9de174a75b277590d66d984500098d32e51f90601410228feff010013ffffffffffffffff214e010104feff0300c80401042902a10500000004a2546ee63c4aabf1ba1df58eedc03608ebb0c6c1fc6a7db13d9fc357be93b61a01450228feff010013ffffffffffffffff214e010104feff0300c80401042d02a1050000000416300bc028c9dc5ec552055e2f1459c00e123510f1cf2b2910c2ed8af7fdda1a01490228feff010013ffffffffffffffff214e010104feff0300c82801043102a10500000004f2c1602920841065e9c51576fd9933cb3b2bf68141444ffcc0534352c5603310014d0228feff010013ffffffffffffffff214e010104feff0300c80c01043502a10500000004b8c763135cef8b29f90190e886b8fd5851313732904323e2021a8ccc732efb6c01510228feff010013ffffffffffffffff214e010104feff0300c80401043902a10500000004785b8b6a7ddacad7ac6df5a55319f1b68d6dd90f1b1fb81a73538877fd4d367401550228feff010013ffffffffffffffff214e010104feff0300c80c01043d02a1050000000416300bc028c9dc5ec552055e2f1459c00e123510f1cf2b2910c2ed8af7fdda1a01590228feff010013ffffffffffffffff214e010104feff0300c80801044102a10500000004c26cde1b916da78e6d466be0ec85df92d0e41952e2932059506f957c5df4f61d015d0228feff010013ffffffffffffffff214e010104feff0300c80401044502a10500000004e04f3a2b9c39597f59981eae01595bdb0a6b32e0017bd995805061b9d7bafd6d01610228feff010013ffffffffffffffff214e010104feff0300c80401044902a10500000004c26cde1b916da78e6d466be0ec85df92d0e41952e2932059506f957c5df4f61d01650228feff010013ffffffffffffffff214e010104feff0300c80401044d02a10500000004c26cde1b916da78e6d466be0ec85df92d0e41952e2932059506f957c5df4f61d01690228feff010013ffffffffffffffff214e010104feff0300c80401045102a1050000000410958b33fc945ef3a7e2f986d9de174a75b277590d66d984500098d32e51f906016d0228feff010013ffffffffffffffff214e010104feff0300c84d0101045502a105000000044e0432b09d21c191b4b25ac7616cf43d75c2ed092e3ed23ebfa390d07680a83401710228feff010013ffffffffffffffff214e010104feff0300c80401045902a105000000042239b60c1eb3cd7ddea7a2934e290e713cdea006129e2960dba3c1a9281d042001750228feff010013ffffffffffffffff214e010104feff0300c83801045d02a10500000004d868f60727d5cfaa22309f04df53c475b0169c7a4372c82485dd828e745de81c01790228feff010013ffffffffffffffff214e010104feff0300c80401046102a105000000048e7fe1bf8ab18fd50b136895ee607b568a790243517f27d76c7ddb0f6ac6dd20017d0228feff010013ffffffffffffffff214e010104feff0300c82001046502a105000000040e429d885b61386d3f639166534f4d7882627d9fb540ec96619a9ef91c4af35601810228feff010013ffffffffffffffff214e010104feff0300c80801046902a105000000041257de87a71abb164403f7cb9ea65d0721f8bb89d8bd85754deceedd91e8605301850228feff010013ffffffffffffffff214e010104feff0300c80c01046d02a1050000000426fcf3c21137f92dac2f4039a3c9885b7696a20347177eeb60d20ea68ff5cd5b01890228feff010013ffffffffffffffff214e010104feff0300c81001047102a10500000004e833288b965a5325d27efa376c571179a7ce6cc5908470dd86275d9eef83562c018d0228feff010013ffffffffffffffff214e010104feff0300c86c01047502a105000000044c344d80452b90c876b99369151b26156409b5875a22c07c1693a82e2b35986801910228feff010013ffffffffffffffff01e1010104feff0300c82001047902a105000000025a620264d07d502ad2cdcf29b27682d70763421d27ca814ae2bfefbddcaab871ff0b2301950228feff010013ffffffffffffffff214e010104feff0300c8d401047d02a10500001501042001e6ca766ae6def412109f344e2fbbefab098147fea271333ce3701e88355f01990228feff010013ffffffffffffffff214e010104feff0300c85c01048102a10500000004ce28b1b257a89f311ac782667e3f7af340117daef84ca049a72c9c5f6421f33a019d0228feff010013ffffffffffffffff214e010104feff0300c81801048502a105000000046830702062b0d0924d337807c18bd102676e299776149bb2d4f5e49b0194e73701a10228feff010013ffffffffffffffff214e010104feff0300c8bd0301048902a1050000000426299eb393ac0cb8f3122bdccf96e0951f81564deccfb01388abe8083c14a96f01a50228feff010013ffffffffffffffff214e010104feff0300c8d90301048d02a1050000000426299eb393ac0cb8f3122bdccf96e0951f81564deccfb01388abe8083c14a96f01a90228feff010013ffffffffffffffff214e010104feff0300c80c01049102a10500000004bc677a5d3da894932b49479192497d919a73444771028e8891ce14a14958520301ad0228feff010013ffffffffffffffff214e010104feff0300c8e401049502a10500000004ae23f59c62637058a98ac980bb8d9910f479509d9b3d482837d3210ac29a0f5901b10228feff010013ffffffffffffffff214e010104feff0300c80d0201049902a1050000000498d3aab78ce2f0c9f3bc7c075fd2a5509e81bec998e67ef95604e589a10b9f7201b50228feff010013ffffffffffffffff214e010104feff0300c82801049d02a105000000042cc129858d576c3b2ff3686c9df3a6969dee293ff87a7e455e727b0fcae6d22301b90228feff010000214e010104feff0300c84d010104a102a105000000002c706a060e1dd966aba8300f48a6be49ec5ef5ef7f56ac0bca33e32abf47753b01bd0228feff010013ffffffffffffffff214e010104feff0300c80c0104a502a10500000004f81ac18c34e8f647b7cc260ce62b3cb8e4a0576fd22ab4c005f0f820decd596a01c10228feff010013ffffffffffffffff214e010104feff0300c829010104a902a1050000000460ebd421a5b19fe326b93643588fb91c3b3ed8f882e89326ed281e94cab4ff0e01c50228feff010013ffffffffffffffff214e010104feff0300c8080104ad02a10500000004f81ac18c34e8f647b7cc260ce62b3cb8e4a0576fd22ab4c005f0f820decd596a01c90228feff010013ffffffffffffffff214e010104feff0300c8280104b102a105000000044e0b2aaafc29f2393261b9aecb4e934658d871c0cd0e03b2a9bb8b510478613a01cd0228feff010013ffffffffffffffff214e010104feff0300c8140104b502a105000000046c3503742199e5978ef1c2690bfba4f281f59ed4b6b0f3ae8250e87bbb658d5801d10228feff010013ffffffffffffffff214e010104feff0300c8e00104b902a1050000a40492afe6f8c459227b6b1a8c781a38e6ea1d57be68e6eec9d284fefb822fc4143e01d50228feff010013ffffffffffffffff214e010104feff0300c879010104bd02a105000000005cddfb0337a71d2ef6312b6f6750e55f53404967673542bd917e4cfe4310200301d90228feff010013ffffffffffffffff214e010104feff0300c8380104c102a1050000000474a935fec56f3862eeaf3e2d70d9742dbba0fb79c18c109d31c01610f758e17e01dd0228feff010013ffffffffffffffff214e010104feff0300c8700104c502a1050000a18e04b0bf6a8083d5c2914689c2d0a761baf8655a7f1558ca1b221eaf8cb7d942bc4001e10228feff010013ffffffffffffffff214e010104feff0300c8080104c902a105000000042096d288ed0ef4fc6c5b510bb038184bb8c3999ab0a2e824a0670f0a2b691a6601e50228feff010013ffffffffffffffff214e010104feff0300c8040104cd02a10500000004c61585185e3e38e41b1ffaf3415e0e44535efc260d4a283135d6290995c2bf4901e90228feff010013ffffffffffffffff214e010104feff0300c8040104d102a10500000004bc736a93c0cc60ba45e4aa656309e86ba7db12ff9d17fb0fb959e0edc677af1a01ed0228feff010013ffffffffffffffff214e010104feff0300c8000104d502a10500000004cb891e3e509b3d088b18c0bdac4c57bbf7af9a7f48be88593c8464a805c7589901f10228feff010013ffffffffffffffff214e010104feff0300c8100104d902a105000000049eac515ad2fa5d8dbb6f9789ff1e983e93f131b518d59e3bd55066e19d12ac7c01f50228feff010013ffffffffffffffff214e010104feff0300c8040104dd02a105000000047884f886831b3df75de913cb4e87d703c13b0256673a2000d33f0863eae2205f01f90228feff010013ffffffffffffffff214e010104feff0300c8040104e102a105000000047884f886831b3df75de913cb4e87d703c13b0256673a2000d33f0863eae2205f01fd0228feff010013ffffffffffffffff214e010104feff0300c8040104e502a10500000004d61582800a31f20815eaf12df6b08e53e736a316941cab42fa319cb34f79854701010328feff010013ffffffffffffffff214e010104feff0300c8640104e902a105000000042e226f8afd0950c55e65f6e8620f3c2a1cab5f9a0b45ae16023e9d254610fc2601050328feff010013ffffffffffffffff214e010104feff0300c80c0104ed02a105000000042a89d979b0fa36843dcdfd380fd9ed9d84b79fd4f6b6f51481cdd241a598327601090328feff010013ffffffffffffffff214e010104feff0300c8040104f102a105000000042a89d979b0fa36843dcdfd380fd9ed9d84b79fd4f6b6f51481cdd241a5983276010d0328feff010013ffffffffffffffff214e010104feff0300c80c0104f502a10500000004a22cca87f973c39b20bb2fe043c8d08395913ead78749678a10971284c2a1f4401110328feff010013ffffffffffffffff214e010104feff0300c8180104f902a105000000045c87e6890ba3e666b0021a8251a36100ac52650195ff51aa00efc5c3fc04b25101150328feff010013ffffffffffffffff214e010104feff0300c8580104fd02a1050000210104965fcb3292491234fa2467fca6e6c9ceebf16d196625b6d664edba9a0807ca0401190328feff010013ffffffffffffffff214e010104feff0300c80401040103a10500000004c6e3016e3c689109fe815e2450deea12bc7cc156cf594b5b04a8978af8b9ae52011d0328feff0100025a6202214e010104feff0300c82c01040503a1050000000284d7170ebd5759c939fe54296f138d7b28745751005cb8c22c27d8d96e7fc5de4c787501210328feff010013ffffffffffffffff214e010104feff0300c81001040903a10500000002286bee7417b92f59afc9e516059444b66db8e69745db91f422739ecf88e53962095a7c01250328feff010013ffffffffffffffff214e010104feff0300c80c01040d03a10500000004f6aa2e51b4f78061a2eed5f18b5cf0b8a6a513e0f01dd9551fb35d5c625ebb5101290328feff010013ffffffffffffffff214e010104feff0300c8bc01041103a105000000048270981d68c8a4bbb7d62f12bea32322f798332034e569ea7aea8a6759df4b42012d0328feff010013ffffffffffffffff214e010104feff0300c83001041503a105000044048ec05cbec265c3b3e839ded71b722602d1421646b96ad819df763cc8e0d48f2a01310328feff010013ffffffffffffffff214e010104feff0300c82c01041903a1050000e912046820887e492454131cf89922a0369adcdb38c48b6981a0791948b1e91dd7ee1f01350328feff010013ffffffffffffffff214e010104feff0300c81c01041d03a105000000046231b9b8f2534ce782af830fcc1743dd61bef59e41d7120daf3f5f7625b7b31d01390328feff010013ffffffffffffffff214e010104feff0300c80801042103a105000000044c5d28f0187dbdb7fe2be86a2de475dc13bb757462e0ab9ecbaa093528c87a15013d0328feff010013ffffffffffffffff214e010104feff0300c81001042503a10500000004600b40c88f29657d76509e2a97acb5ed847079dc6e88f4031c34fd4c46e35e5401410328feff010013ffffffffffffffff214e010104feff0300c86c01042903a10500000004e275a22dab76aa1bf9db37cbf76e90f290a5e20652e2869b59f0b0711ca4f20d01450328feff010013ffffffffffffffff214e010104feff0300c80c01042d03a10500000004167291393eb7bf3873eaf587f80172234c8159d0213dd03989905af9a371173e01490328feff010013ffffffffffffffff214e010104feff0300c80401043103a105000000048eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48014d0328feff010013ffffffffffffffff214e010104feff0300c80c01043503a10500000004a28e86072a4b7215dd3c7c6aedfc8679549549ee4077ae81baad5e7f4c4e053c01510328feff010013ffffffffffffffff214e010104feff0300c8500104000400000004cce86023da931c965f5730beb54df83bdcd356edae149326622a07eb9d6f023101550328feff010013ffffffffffffffff214e010104feff0300c81801043d03a1050000590504ae278c523c5d5e0278d296a40089e9c2d2e83df934ced5dd283f7ca931a6744801590328feff010013ffffffffffffffff214e010104feff0300c81801044103a10500000004bee8212193998958977b4609b91747a2b9879f512a3c6981c9c6c8b05cbb476d015d0328feff010013ffffffffffffffff214e010104feff0300c80801044503a105000000042096d288ed0ef4fc6c5b510bb038184bb8c3999ab0a2e824a0670f0a2b691a6601610328feff010013ffffffffffffffff214e010104feff0300c80401044903a105000000042096d288ed0ef4fc6c5b510bb038184bb8c3999ab0a2e824a0670f0a2b691a6601650328feff010013ffffffffffffffff214e010104feff0300c89001044d03a1050000094404c6aed2621eae09d0edce51309061697c26edb9994a5341315c6a5329560f973e01690328feff010013ffffffffffffffff214e010104feff0300c81001045103a105000000041846172c481ff3ec2a644bbff46b08566798d799ff568b832b5a6d73263e2e1a016d0328feff010013ffffffffffffffff214e010104feff0300c80401045503a105000000881e56e8937de6f995c94957d587a71f305e806604a185438361e393896aa03b6101710328feff010004214e010104feff0300c8590101045903a105000000dc1846172c481ff3ec2a644bbff46b08566798d799ff568b832b5a6d73263e2e1a01750328feff010013ffffffffffffffff214e010104feff0300c80401045d03a1050000003d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01790328feff010013ffffffffffffffff214e010104feff0300c82801046103a1050000001502101f5e7ec4042b882a1b9e4bb3d0071686fb4277f7a8a7e2b7a04965a777751f017d0328feff0100a10f214e010104feff0300c89001046503a10500000091025e9fbe002b8938fe32272911e028eb12b8c5dacf940b42aa9f06969b2f18190301810328feff010013ffffffffffffffff214e010104feff0300c80401046903a1050000007105dce5f748cbc0587ade043bb45bc4a204b513446ceff7d8f40fc04a203879bf0801850328feff010013ffffffffffffffff214e010104feff0300c81401046d03a10500000029082ab01699210c939cbeef200d87138d001801ffa29d70d939f022d5cdf0fa9a1401890328feff010013ffffffffffffffff214e010104feff0300c80c01047103a1050000884d154013122bab03e02e19d00211efc50b92402c1fbf38d48e68c02020be6ce34b76018d0328feff010013ffffffffffffffff214e010104feff0300c80401047503a105000000352b73e54b664571974c351a3ec31b77457a5c7e407e02c7bba869418f03aa3c4bc401910328feff010013ffffffffffffffff214e010104feff0300c80c01047903a10500000059325eea96f4e0299103455a1adcb8b151671eebd0f9dba78fb797f1f9b56460d03801950328feff010013ffffffffffffffff214e010104feff0300c80801047d03a1050000006558002326240a609c72641c6a3fcad3ad2ee33f2db95f6c16e181f7c62fa063834b01990328feff010013ffffffffffffffff214e010104feff0300c82001048103a1050000bae4cd00bdbc9e51e2ae2ef754202057c705d83bd3dec7ccac3d65962a0bfc87dd68acbe1362019d0328feff010013ffffffffffffffff214e010104feff0300c80c01048503a1050000000ad602004e69579598dacfaf868fd3da108240dcac14399ba37284caea9f9fb4a536e22d01a10328feff010013ffffffffffffffff214e010104feff0300c89c01048903a1050000094404c6aed2621eae09d0edce51309061697c26edb9994a5341315c6a5329560f973e01a50328feff010013ffffffffffffffff214e010104feff0300c81001048d03a1050000001e7704000e429d885b61386d3f639166534f4d7882627d9fb540ec96619a9ef91c4af35601a90328feff010013ffffffffffffffff214e010104feff0300c80c01049103a105000000fe4505008a68f5033ee2b421019fb11e349f645be407004d32ea32bd0690e07c634c6b2401ad0328feff010013ffffffffffffffff214e010104feff0300c80401049503a10500000056631000a4fd4fcc0ebfdadd67ddc28e54c5d5c5f81432f309e09c0aa006e250c345677401b10328feff010013ffffffffffffffff214e010104feff0300c83001049903a1050000a404b4acf171326fd530b4f50fe68260a1d7ac8ee918469400e81604420379cb524401b50328feff010013ffffffffffffffff214e010104feff0300c81001049d03a1050000000078291b047688e8e91f99a0eaaaa0a9bda2d3e286767417df7c434fdf55b0e64501b90328feff010013ffffffffffffffff214e010104feff0300c8080104a103a1050000004ac42b002c5a12354279d049a1d8f29e42e7476c42aecc832a333c5f5823e572f47d657501bd03280200020013ffffffffffffffff214e010104feff0300c8080104a503a1050000000b00a0724e180934a2e742e406a2de9b308e2aba1cf911638daf8665db7ae0673861bdf0e4064c01c10328feff010013ffffffffffffffff214e010104feff0300c8080104a903a1050000005a8f83034269c309fd10916776c24e6afc6a2876037f2a7cc53e547de1fa5d03b262907401c50328feff010013ffffffffffffffff214e010104feff0300c8400104ad03a1050000003ed23205062ed2cbd984cda1964f6c63382840b248ece865dd8562460c0f0f8a77bfdb7301c90328feff010013ffffffffffffffff214e010104feff0300c8080104b103a1050000007e88f904de5251d30f454cdeaa942e3979a22ac2a3b824458ba03f3afc592cb78a905d2901cd0328feff010013ffffffffffffffff214e010104feff0300c8040104b503a105000000bef498075c239ed29d89fcf63035c36cba4d21ac077485beae41c1f7ca03ceb7c7fa5f7f01d10328feff010013ffffffffffffffff214e010104feff0300c80c0104b903a1050000004e3cd2090edbd5fb628bb9ba85a5d8351ee2b9146840c0c7eeba4a38ac000e147c14933c01d50328feff010013ffffffffffffffff214e010104feff0300c81c0104bd03a105000000aa66150b24b6f83352f4d04fb7ecee93f39ff5fbb752eca4289a870072961981010d973d01d90328feff010013ffffffffffffffff214e010104feff0300c8080104c103a10500000052410cd09e51e2ae2ef754202057c705d83bd3dec7ccac3d65962a0bfc87dd68acbe1362", - } - }, - "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, - }, - "get_balance": { "chain_getHead": { "[]": { "jsonrpc": "2.0", - "result": "0x1b3f85dc8c83cada6d1782c955973a509a37c62af3d6ba29f5fd816aee37eb3b", + "result": "0xe9729c54c0e59c611198b560a7a93e52154100187d04dfc09d1dc1a6572d4006", } }, "chain_getHeader": { - '["0x1b3f85dc8c83cada6d1782c955973a509a37c62af3d6ba29f5fd816aee37eb3b"]': { + '["0xe9729c54c0e59c611198b560a7a93e52154100187d04dfc09d1dc1a6572d4006"]': { "jsonrpc": "2.0", "result": { "digest": { "logs": [ - "0x066175726120ab489a0800000000", - "0x0466726f6e88015b559367fb27665be180a32109a44b153dd14cafb22eb908ac9e79a308916c9a00", - "0x056175726101012030b4a878800704102801d12f2dfe4b3f66bd8c3fbe236e4881ed1b9bdbaf6c8eb6200f9db52945187c3c1f46d8b4c08c1b50e2002d94594e0c751069ca7d8d", + "0x0661757261209b489a0800000000", + "0x0466726f6e8801fa9bcb7befe1394a353134de30ad705326185473f91cd6be31397c06759e007800", + "0x0561757261010128b382541b4a78e5c9ff3cee4ae48fe3c5337add9f1baad15b72939990218773794b348babefd9fa28312c5b5097b52b034d90a331a747dcfcd03fa37a7fb482", ] }, - "extrinsicsRoot": "0xf7eaa2bb07e7650b27ee819ee07c987207ad40220f250e4eebb1178e19734242", - "number": "0x31ce9e", - "parentHash": "0xd867f39bb9e2a626945183af01065b61d0695d435a765bfd0ce5f821fbed8f82", - "stateRoot": "0x3096ed3b5859801b59e2fb348ef560e87f473a799dea9be12982b969fdd1dfaf", + "extrinsicsRoot": "0xfabdc25842a79c97f6029f17f0f7521ec5f9b41815932f1dcc2cb0752fa0ca9a", + "number": "0x31ce8e", + "parentHash": "0xae0ef35761d050ada6d4f09efec39ca430d4f4c50b927741b32fd487d382ead8", + "stateRoot": "0x7da2cf163b71981ea914cc9f8ddecf662faee1f6f04acf5e814a16f086ddbe78", + }, + }, + "[null]": { + "jsonrpc": "2.0", + "result": { + "digest": { + "logs": [ + "0x0661757261209c489a0800000000", + "0x0466726f6e8801b81937c0aed82aace40c1860c8f8be871ed90466eb702dcd50fef49a70ca8dcf00", + "0x056175726101016a8bbee0a2b31058eff0df90b3b194cc7824e735e09b957136291639ff36c2047102e48742ac2ac14fe1634b652bba055b00383b06cea6482c56755b74c3c88b", + ] + }, + "extrinsicsRoot": "0x42acc4ffcaba39f003a14f13e2dc69e5b93198724a019515f31e22baf0b240f7", + "number": "0x31ce8f", + "parentHash": "0xe9729c54c0e59c611198b560a7a93e52154100187d04dfc09d1dc1a6572d4006", + "stateRoot": "0x319de5cb67bbf31e93a7db2e75b9bca48ce8d0b91d5156ce2c738eb178700d98", }, + }, + }, + "state_call": { + '["SubnetInfoRuntimeApi_get_subnets_info", "", null]': { + "jsonrpc": "2.0", + "result": "0x0c010028feff0100025a62020140010100feff0300c800010180910100000002286bee000000000000000000000000000000000000000000000000000000000000000000010428feff0100025a6202214e010104feff0300c80401049903a10500000002286beed43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d00010c28feff0100025a6202014001020110a10fc8000140988d0100000002286bee000000000000000000000000000000000000000000000000000000000000000000", } }, - "rpc_methods": { - "[]": { + "state_getRuntimeVersion": { + '["0xae0ef35761d050ada6d4f09efec39ca430d4f4c50b927741b32fd487d382ead8"]': { "jsonrpc": "2.0", "result": { - "methods": [ - "account_nextIndex", - "archive_unstable_body", - "archive_unstable_call", - "archive_unstable_finalizedHeight", - "archive_unstable_genesisHash", - "archive_unstable_hashByHeight", - "archive_unstable_header", - "archive_unstable_storage", - "author_hasKey", - "author_hasSessionKeys", - "author_insertKey", - "author_pendingExtrinsics", - "author_removeExtrinsic", - "author_rotateKeys", - "author_submitAndWatchExtrinsic", - "author_submitExtrinsic", - "author_unwatchExtrinsic", - "chainHead_v1_body", + "apis": [ + ["0xdf6acb689907609b", 5], + ["0x37e397fc7c91f5e4", 2], + ["0x40fe3ad401f8959a", 6], + ["0xfbc577b9d747efd6", 1], + ["0xd2bc9897eed08f15", 3], + ["0xf78b278be53f454c", 2], + ["0xdd718d5cc53262d4", 1], + ["0xab3c0572291feb8b", 1], + ["0xed99c5acb25eedf5", 3], + ["0xbc9d89904f5b923f", 1], + ["0x37c8bb1350a9a2a8", 4], + ["0xf3ff14d5ab527059", 3], + ["0x582211f65bb14b89", 5], + ["0xe65b00e46cedd0aa", 2], + ["0x42e62be4a39e5b60", 1], + ["0x806df4ccaa9ed485", 1], + ["0x8375104b299b74c5", 1], + ["0x5d1fbfbe852f2807", 1], + ["0xc6886e2f8e598b0a", 1], + ], + "authoringVersion": 1, + "implName": "node-subtensor", + "implVersion": 1, + "specName": "node-subtensor", + "specVersion": 208, + "stateVersion": 1, + "transactionVersion": 1, + }, + } + }, + }, + "get_balance": { + "chain_getHead": { + "[]": { + "jsonrpc": "2.0", + "result": "0x1b3f85dc8c83cada6d1782c955973a509a37c62af3d6ba29f5fd816aee37eb3b", + } + }, + "chain_getHeader": { + '["0x1b3f85dc8c83cada6d1782c955973a509a37c62af3d6ba29f5fd816aee37eb3b"]': { + "jsonrpc": "2.0", + "result": { + "digest": { + "logs": [ + "0x066175726120ab489a0800000000", + "0x0466726f6e88015b559367fb27665be180a32109a44b153dd14cafb22eb908ac9e79a308916c9a00", + "0x056175726101012030b4a878800704102801d12f2dfe4b3f66bd8c3fbe236e4881ed1b9bdbaf6c8eb6200f9db52945187c3c1f46d8b4c08c1b50e2002d94594e0c751069ca7d8d", + ] + }, + "extrinsicsRoot": "0xf7eaa2bb07e7650b27ee819ee07c987207ad40220f250e4eebb1178e19734242", + "number": "0x31ce9e", + "parentHash": "0xd867f39bb9e2a626945183af01065b61d0695d435a765bfd0ce5f821fbed8f82", + "stateRoot": "0x3096ed3b5859801b59e2fb348ef560e87f473a799dea9be12982b969fdd1dfaf", + }, + } + }, + "rpc_methods": { + "[]": { + "jsonrpc": "2.0", + "result": { + "methods": [ + "account_nextIndex", + "archive_unstable_body", + "archive_unstable_call", + "archive_unstable_finalizedHeight", + "archive_unstable_genesisHash", + "archive_unstable_hashByHeight", + "archive_unstable_header", + "archive_unstable_storage", + "author_hasKey", + "author_hasSessionKeys", + "author_insertKey", + "author_pendingExtrinsics", + "author_removeExtrinsic", + "author_rotateKeys", + "author_submitAndWatchExtrinsic", + "author_submitExtrinsic", + "author_unwatchExtrinsic", + "chainHead_v1_body", "chainHead_v1_call", "chainHead_v1_continue", "chainHead_v1_follow", @@ -2318,449 +2206,78 @@ ["0xd2bc9897eed08f15", 3], ["0xf78b278be53f454c", 2], ["0xdd718d5cc53262d4", 1], - ["0xab3c0572291feb8b", 1], - ["0xed99c5acb25eedf5", 3], - ["0xbc9d89904f5b923f", 1], - ["0x37c8bb1350a9a2a8", 4], - ["0xf3ff14d5ab527059", 3], - ["0x582211f65bb14b89", 5], - ["0xe65b00e46cedd0aa", 2], - ["0x42e62be4a39e5b60", 1], - ["0x806df4ccaa9ed485", 1], - ["0x8375104b299b74c5", 1], - ["0x5d1fbfbe852f2807", 1], - ["0xc6886e2f8e598b0a", 1], - ], - "authoringVersion": 1, - "implName": "node-subtensor", - "implVersion": 1, - "specName": "node-subtensor", - "specVersion": 208, - "stateVersion": 1, - "transactionVersion": 1, - }, - } - }, - "state_queryStorageAt": { - '[["0x658faa385070e074c85bf6b568cf0555ea6aa4e81a33d2c120ef55203e0eb5603e9947bb89c47cd7ad643c5d30c0e6954af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f6894461700"], null]': { - "jsonrpc": "2.0", - "result": [ - { - "block": "0x1e326794f8c851e3b5675e603bf726120b074348a6c0d3e8ea354f6880a49f7b", - "changes": [ - [ - "0x658faa385070e074c85bf6b568cf0555ea6aa4e81a33d2c120ef55203e0eb5603e9947bb89c47cd7ad643c5d30c0e6954af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f6894461700", - "0x01", - ] - ], - } - ], - } - }, - "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, - }, - "get_neuron_for_pubkey_and_subnet": { - "chain_getHead": { - "[]": { - "jsonrpc": "2.0", - "result": "0x9d58a80049c3eaabf68f6bc83b1dd3f36bc3dcc7d75be17ee53dfc678e4ee111", - } - }, - "chain_getHeader": { - '["0x9d58a80049c3eaabf68f6bc83b1dd3f36bc3dcc7d75be17ee53dfc678e4ee111"]': { - "jsonrpc": "2.0", - "result": { - "digest": { - "logs": [ - "0x066175726120a0489a0800000000", - "0x0466726f6e8801b2557a32e7b78d386e67769c083405a148fe57d80528d9aca8eb9ddbbfac288800", - "0x05617572610101b8a3e510b65d00ebc479d3102632250e7354a619d7719757df6b0666c1eaa0039debd861b6ae79fcbc4f82b87d5efbc5ca089e318918e5274d0380782c91188b", - ] - }, - "extrinsicsRoot": "0x226f5c8e7d52bebaa5fb56a9a9f8344667533c2f9edac2eed9c91c64a9cc653c", - "number": "0x31ce93", - "parentHash": "0x9259b771b0f59b1ed8f38f604ab4f4a3e63dc0988754e664be2d40d58970958c", - "stateRoot": "0x8d8552df3fa7fb8569216cc69516dd3067af8d5bad60cf363c1337719bd31a12", - }, - } - }, - "neuronInfo_getNeuron": { - "[23, 5]": { - "jsonrpc": "2.0", - "result": [ - 74, - 247, - 89, - 137, - 82, - 248, - 118, - 131, - 32, - 74, - 42, - 12, - 34, - 102, - 249, - 65, - 167, - 72, - 153, - 189, - 105, - 176, - 206, - 86, - 228, - 42, - 130, - 130, - 15, - 104, - 148, - 70, - 18, - 87, - 222, - 135, - 167, - 26, - 187, - 22, - 68, - 3, - 247, - 203, - 158, - 166, - 93, - 7, - 33, - 248, - 187, - 137, - 216, - 189, - 133, - 117, - 77, - 236, - 238, - 221, - 145, - 232, - 96, - 83, - 20, - 92, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4, - 18, - 87, - 222, - 135, - 167, - 26, - 187, - 22, - 68, - 3, - 247, - 203, - 158, - 166, - 93, - 7, - 33, - 248, - 187, - 137, - 216, - 189, - 133, - 117, - 77, - 236, - 238, - 221, - 145, - 232, - 96, - 83, - 3, - 176, - 236, - 104, - 179, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 110, - 68, - 120, - 0, - 1, - 0, - 0, - 0, - ], - } - }, - "rpc_methods": { - "[]": { - "jsonrpc": "2.0", - "result": { - "methods": [ - "account_nextIndex", - "archive_unstable_body", - "archive_unstable_call", - "archive_unstable_finalizedHeight", - "archive_unstable_genesisHash", - "archive_unstable_hashByHeight", - "archive_unstable_header", - "archive_unstable_storage", - "author_hasKey", - "author_hasSessionKeys", - "author_insertKey", - "author_pendingExtrinsics", - "author_removeExtrinsic", - "author_rotateKeys", - "author_submitAndWatchExtrinsic", - "author_submitExtrinsic", - "author_unwatchExtrinsic", - "chainHead_v1_body", - "chainHead_v1_call", - "chainHead_v1_continue", - "chainHead_v1_follow", - "chainHead_v1_header", - "chainHead_v1_stopOperation", - "chainHead_v1_storage", - "chainHead_v1_unfollow", - "chainHead_v1_unpin", - "chainSpec_v1_chainName", - "chainSpec_v1_genesisHash", - "chainSpec_v1_properties", - "chain_getBlock", - "chain_getBlockHash", - "chain_getFinalisedHead", - "chain_getFinalizedHead", - "chain_getHead", - "chain_getHeader", - "chain_getRuntimeVersion", - "chain_subscribeAllHeads", - "chain_subscribeFinalisedHeads", - "chain_subscribeFinalizedHeads", - "chain_subscribeNewHead", - "chain_subscribeNewHeads", - "chain_subscribeRuntimeVersion", - "chain_unsubscribeAllHeads", - "chain_unsubscribeFinalisedHeads", - "chain_unsubscribeFinalizedHeads", - "chain_unsubscribeNewHead", - "chain_unsubscribeNewHeads", - "chain_unsubscribeRuntimeVersion", - "childstate_getKeys", - "childstate_getKeysPaged", - "childstate_getKeysPagedAt", - "childstate_getStorage", - "childstate_getStorageEntries", - "childstate_getStorageHash", - "childstate_getStorageSize", - "debug_getBadBlocks", - "debug_getRawBlock", - "debug_getRawHeader", - "debug_getRawReceipts", - "debug_getRawTransaction", - "delegateInfo_getDelegate", - "delegateInfo_getDelegated", - "delegateInfo_getDelegates", - "eth_accounts", - "eth_blockNumber", - "eth_call", - "eth_chainId", - "eth_coinbase", - "eth_estimateGas", - "eth_feeHistory", - "eth_gasPrice", - "eth_getBalance", - "eth_getBlockByHash", - "eth_getBlockByNumber", - "eth_getBlockReceipts", - "eth_getBlockTransactionCountByHash", - "eth_getBlockTransactionCountByNumber", - "eth_getCode", - "eth_getFilterChanges", - "eth_getFilterLogs", - "eth_getLogs", - "eth_getStorageAt", - "eth_getTransactionByBlockHashAndIndex", - "eth_getTransactionByBlockNumberAndIndex", - "eth_getTransactionByHash", - "eth_getTransactionCount", - "eth_getTransactionReceipt", - "eth_getUncleByBlockHashAndIndex", - "eth_getUncleByBlockNumberAndIndex", - "eth_getUncleCountByBlockHash", - "eth_getUncleCountByBlockNumber", - "eth_getWork", - "eth_hashrate", - "eth_maxPriorityFeePerGas", - "eth_mining", - "eth_newBlockFilter", - "eth_newFilter", - "eth_newPendingTransactionFilter", - "eth_protocolVersion", - "eth_sendRawTransaction", - "eth_sendTransaction", - "eth_submitHashrate", - "eth_submitWork", - "eth_subscribe", - "eth_syncing", - "eth_uninstallFilter", - "eth_unsubscribe", - "net_listening", - "net_peerCount", - "net_version", - "neuronInfo_getNeuron", - "neuronInfo_getNeuronLite", - "neuronInfo_getNeurons", - "neuronInfo_getNeuronsLite", - "offchain_localStorageGet", - "offchain_localStorageSet", - "payment_queryFeeDetails", - "payment_queryInfo", - "rpc_methods", - "state_call", - "state_callAt", - "state_getChildReadProof", - "state_getKeys", - "state_getKeysPaged", - "state_getKeysPagedAt", - "state_getMetadata", - "state_getPairs", - "state_getReadProof", - "state_getRuntimeVersion", - "state_getStorage", - "state_getStorageAt", - "state_getStorageHash", - "state_getStorageHashAt", - "state_getStorageSize", - "state_getStorageSizeAt", - "state_queryStorage", - "state_queryStorageAt", - "state_subscribeRuntimeVersion", - "state_subscribeStorage", - "state_traceBlock", - "state_unsubscribeRuntimeVersion", - "state_unsubscribeStorage", - "subnetInfo_getLockCost", - "subnetInfo_getSubnetHyperparams", - "subnetInfo_getSubnetInfo", - "subnetInfo_getSubnetInfo_v2", - "subnetInfo_getSubnetsInf_v2", - "subnetInfo_getSubnetsInfo", - "subscribe_newHead", - "system_accountNextIndex", - "system_addLogFilter", - "system_addReservedPeer", - "system_chain", - "system_chainType", - "system_dryRun", - "system_dryRunAt", - "system_health", - "system_localListenAddresses", - "system_localPeerId", - "system_name", - "system_nodeRoles", - "system_peers", - "system_properties", - "system_removeReservedPeer", - "system_reservedPeers", - "system_resetLogFilter", - "system_syncState", - "system_unstable_networkState", - "system_version", - "transactionWatch_v1_submitAndWatch", - "transactionWatch_v1_unwatch", - "transaction_v1_broadcast", - "transaction_v1_stop", - "unsubscribe_newHead", - "web3_clientVersion", - "web3_sha3", - ] + ["0xab3c0572291feb8b", 1], + ["0xed99c5acb25eedf5", 3], + ["0xbc9d89904f5b923f", 1], + ["0x37c8bb1350a9a2a8", 4], + ["0xf3ff14d5ab527059", 3], + ["0x582211f65bb14b89", 5], + ["0xe65b00e46cedd0aa", 2], + ["0x42e62be4a39e5b60", 1], + ["0x806df4ccaa9ed485", 1], + ["0x8375104b299b74c5", 1], + ["0x5d1fbfbe852f2807", 1], + ["0xc6886e2f8e598b0a", 1], + ], + "authoringVersion": 1, + "implName": "node-subtensor", + "implVersion": 1, + "specName": "node-subtensor", + "specVersion": 208, + "stateVersion": 1, + "transactionVersion": 1, + }, + } + }, + "state_queryStorageAt": { + '[["0x658faa385070e074c85bf6b568cf0555ea6aa4e81a33d2c120ef55203e0eb5603e9947bb89c47cd7ad643c5d30c0e6954af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f6894461700"], null]': { + "jsonrpc": "2.0", + "result": [ + { + "block": "0x1e326794f8c851e3b5675e603bf726120b074348a6c0d3e8ea354f6880a49f7b", + "changes": [ + [ + "0x658faa385070e074c85bf6b568cf0555ea6aa4e81a33d2c120ef55203e0eb5603e9947bb89c47cd7ad643c5d30c0e6954af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f6894461700", + "0x01", + ] + ], + } + ], + } + }, + "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, + }, + "get_neuron_for_pubkey_and_subnet": { + "chain_getHead": { + "[]": { + "jsonrpc": "2.0", + "result": "0x9d58a80049c3eaabf68f6bc83b1dd3f36bc3dcc7d75be17ee53dfc678e4ee111", + } + }, + "chain_getHeader": { + '["0x9d58a80049c3eaabf68f6bc83b1dd3f36bc3dcc7d75be17ee53dfc678e4ee111"]': { + "jsonrpc": "2.0", + "result": { + "digest": { + "logs": [ + "0x066175726120a0489a0800000000", + "0x0466726f6e8801b2557a32e7b78d386e67769c083405a148fe57d80528d9aca8eb9ddbbfac288800", + "0x05617572610101b8a3e510b65d00ebc479d3102632250e7354a619d7719757df6b0666c1eaa0039debd861b6ae79fcbc4f82b87d5efbc5ca089e318918e5274d0380782c91188b", + ] + }, + "extrinsicsRoot": "0x226f5c8e7d52bebaa5fb56a9a9f8344667533c2f9edac2eed9c91c64a9cc653c", + "number": "0x31ce93", + "parentHash": "0x9259b771b0f59b1ed8f38f604ab4f4a3e63dc0988754e664be2d40d58970958c", + "stateRoot": "0x8d8552df3fa7fb8569216cc69516dd3067af8d5bad60cf363c1337719bd31a12", }, } }, + "state_call": { + '["NeuronInfoRuntimeApi_get_neuron", "01000500", null]': { + "jsonrpc": "2.0", + "result": "0x016a4368adc8781240b59c45ccacbf5a7ee0ca3a7adc7e893c27b4956e172c0220d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d0000000000000000a10201000000", + }, + }, "state_getRuntimeVersion": { '["0x9259b771b0f59b1ed8f38f604ab4f4a3e63dc0988754e664be2d40d58970958c"]': { "jsonrpc": "2.0", @@ -2797,12 +2314,11 @@ } }, "state_getStorageAt": { - '["0x658faa385070e074c85bf6b568cf0555aab1b4e78e1ea8305462ee53b3686dc817003e9947bb89c47cd7ad643c5d30c0e6954af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f689446", null]': { + '["0x658faa385070e074c85bf6b568cf0555aab1b4e78e1ea8305462ee53b3686dc801000107dcdbd6d7a9d789ac7a30a57647f66a4368adc8781240b59c45ccacbf5a7ee0ca3a7adc7e893c27b4956e172c0220", null]': { "jsonrpc": "2.0", "result": "0x0500", } }, - "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, }, "get_prometheus_info": { "chain_getHead": { @@ -6196,195 +5712,11 @@ }, }, }, - "rpc_methods": { - "[]": { - "jsonrpc": "2.0", - "result": { - "methods": [ - "account_nextIndex", - "archive_unstable_body", - "archive_unstable_call", - "archive_unstable_finalizedHeight", - "archive_unstable_genesisHash", - "archive_unstable_hashByHeight", - "archive_unstable_header", - "archive_unstable_storage", - "author_hasKey", - "author_hasSessionKeys", - "author_insertKey", - "author_pendingExtrinsics", - "author_removeExtrinsic", - "author_rotateKeys", - "author_submitAndWatchExtrinsic", - "author_submitExtrinsic", - "author_unwatchExtrinsic", - "chainHead_v1_body", - "chainHead_v1_call", - "chainHead_v1_continue", - "chainHead_v1_follow", - "chainHead_v1_header", - "chainHead_v1_stopOperation", - "chainHead_v1_storage", - "chainHead_v1_unfollow", - "chainHead_v1_unpin", - "chainSpec_v1_chainName", - "chainSpec_v1_genesisHash", - "chainSpec_v1_properties", - "chain_getBlock", - "chain_getBlockHash", - "chain_getFinalisedHead", - "chain_getFinalizedHead", - "chain_getHead", - "chain_getHeader", - "chain_getRuntimeVersion", - "chain_subscribeAllHeads", - "chain_subscribeFinalisedHeads", - "chain_subscribeFinalizedHeads", - "chain_subscribeNewHead", - "chain_subscribeNewHeads", - "chain_subscribeRuntimeVersion", - "chain_unsubscribeAllHeads", - "chain_unsubscribeFinalisedHeads", - "chain_unsubscribeFinalizedHeads", - "chain_unsubscribeNewHead", - "chain_unsubscribeNewHeads", - "chain_unsubscribeRuntimeVersion", - "childstate_getKeys", - "childstate_getKeysPaged", - "childstate_getKeysPagedAt", - "childstate_getStorage", - "childstate_getStorageEntries", - "childstate_getStorageHash", - "childstate_getStorageSize", - "debug_getBadBlocks", - "debug_getRawBlock", - "debug_getRawHeader", - "debug_getRawReceipts", - "debug_getRawTransaction", - "delegateInfo_getDelegate", - "delegateInfo_getDelegated", - "delegateInfo_getDelegates", - "eth_accounts", - "eth_blockNumber", - "eth_call", - "eth_chainId", - "eth_coinbase", - "eth_estimateGas", - "eth_feeHistory", - "eth_gasPrice", - "eth_getBalance", - "eth_getBlockByHash", - "eth_getBlockByNumber", - "eth_getBlockReceipts", - "eth_getBlockTransactionCountByHash", - "eth_getBlockTransactionCountByNumber", - "eth_getCode", - "eth_getFilterChanges", - "eth_getFilterLogs", - "eth_getLogs", - "eth_getStorageAt", - "eth_getTransactionByBlockHashAndIndex", - "eth_getTransactionByBlockNumberAndIndex", - "eth_getTransactionByHash", - "eth_getTransactionCount", - "eth_getTransactionReceipt", - "eth_getUncleByBlockHashAndIndex", - "eth_getUncleByBlockNumberAndIndex", - "eth_getUncleCountByBlockHash", - "eth_getUncleCountByBlockNumber", - "eth_getWork", - "eth_hashrate", - "eth_maxPriorityFeePerGas", - "eth_mining", - "eth_newBlockFilter", - "eth_newFilter", - "eth_newPendingTransactionFilter", - "eth_protocolVersion", - "eth_sendRawTransaction", - "eth_sendTransaction", - "eth_submitHashrate", - "eth_submitWork", - "eth_subscribe", - "eth_syncing", - "eth_uninstallFilter", - "eth_unsubscribe", - "net_listening", - "net_peerCount", - "net_version", - "neuronInfo_getNeuron", - "neuronInfo_getNeuronLite", - "neuronInfo_getNeurons", - "neuronInfo_getNeuronsLite", - "offchain_localStorageGet", - "offchain_localStorageSet", - "payment_queryFeeDetails", - "payment_queryInfo", - "rpc_methods", - "state_call", - "state_callAt", - "state_getChildReadProof", - "state_getKeys", - "state_getKeysPaged", - "state_getKeysPagedAt", - "state_getMetadata", - "state_getPairs", - "state_getReadProof", - "state_getRuntimeVersion", - "state_getStorage", - "state_getStorageAt", - "state_getStorageHash", - "state_getStorageHashAt", - "state_getStorageSize", - "state_getStorageSizeAt", - "state_queryStorage", - "state_queryStorageAt", - "state_subscribeRuntimeVersion", - "state_subscribeStorage", - "state_traceBlock", - "state_unsubscribeRuntimeVersion", - "state_unsubscribeStorage", - "subnetInfo_getLockCost", - "subnetInfo_getSubnetHyperparams", - "subnetInfo_getSubnetInfo", - "subnetInfo_getSubnetInfo_v2", - "subnetInfo_getSubnetsInf_v2", - "subnetInfo_getSubnetsInfo", - "subscribe_newHead", - "system_accountNextIndex", - "system_addLogFilter", - "system_addReservedPeer", - "system_chain", - "system_chainType", - "system_dryRun", - "system_dryRunAt", - "system_health", - "system_localListenAddresses", - "system_localPeerId", - "system_name", - "system_nodeRoles", - "system_peers", - "system_properties", - "system_removeReservedPeer", - "system_reservedPeers", - "system_resetLogFilter", - "system_syncState", - "system_unstable_networkState", - "system_version", - "transactionWatch_v1_submitAndWatch", - "transactionWatch_v1_unwatch", - "transaction_v1_broadcast", - "transaction_v1_stop", - "unsubscribe_newHead", - "web3_clientVersion", - "web3_sha3", - ] - }, - } - }, "state_call": { - '["NeuronInfoRuntimeApi_get_neurons_lite", "0x1700"]': { + '["NeuronInfoRuntimeApi_get_neurons_lite", "0100", null]': { "jsonrpc": "2.0", - "result": "0x35364cb26667d9765b6aaa76c1b7f0f2786c03257a090081bb483b1e6862e409f64e3f6aa1c0384f95f3ec8f764309523a653a5bd814632fe2eff931d35c606a5e0c65005c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046aa1c0384f95f3ec8f764309523a653a5bd814632fe2eff931d35c606a5e0c65620bb70000000000000000825b53000100c0dcbc2b619e07312e6fa2e1b9c91eb6826c77ab732fa1670bfa175c3cc06b01d89c740d9dfede764de5284c89dcedac74aa23b2d303a668e251620b78d79949045c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d89c740d9dfede764de5284c89dcedac74aa23b2d303a668e251620b78d7994907f1a79e0402000000000000003aac57000100e6e23c10ab6ed114577d8fa56f976d350aabea07e0382c6ab0313f1fd5b4ed7c9aa545ce482f48c3160fa706bbafe923bb8248403141729d95c96699b615f04d085c00e390160000000000b40200001329d44300000000000000000000000049080404000000000000000000000000000000000000000000000000000000000000000000049aa545ce482f48c3160fa706bbafe923bb8248403141729d95c96699b615f04d000000000000000022435a000100866eda07c029ea2856de08c183ddff461cb6ce83f8ec49150ef5647eee8f4c6b40469c545b3d0396a76ca1c41a6c090266e2e532adc9fde080d9e90d2e7b093d0c5c00dfb8190000000000b5020000026fb5d50000000000000000000000009aac04040000000000000000000000000000000000000000000000000000000000000000000440469c545b3d0396a76ca1c41a6c090266e2e532adc9fde080d9e90d2e7b093dea2b0e000000000000000046d9660001000cc6dd507099d72736a92d6f889e4024e3431ac57eb9eb1fe0ca3302c6d4c867509b91e2cf336358ec2f3fe6e0598e2909c29a57597765240dfa8db41e7dd46a105c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004509b91e2cf336358ec2f3fe6e0598e2909c29a57597765240dfa8db41e7dd46a00000000000000005a9f6f0001004af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f6894461257de87a71abb164403f7cb9ea65d0721f8bb89d8bd85754deceedd91e86053145c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041257de87a71abb164403f7cb9ea65d0721f8bb89d8bd85754deceedd91e8605303b0ec68b3000000000000006e4478000100ba7c215ab878d9231d11bdaa5e4717b90d3b85df986abc669de607b1da6a020c74d879f5f872947565597d2f0c310fa0658d168ecd68a2ad3d5ec63438561643185c00265e1e0000000000b5020000583937a2000000000000000000000000d54f04040000000000000000000000000000000000000000000000000000000000000000000474d879f5f872947565597d2f0c310fa0658d168ecd68a2ad3d5ec6343856164307ed6f74c302000000000000004a7579000100084667e9ab96aca6c12c3094d740142cc4d36e423ede27b752978ffc70841b4dda618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f1c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f07bfb78a48170000000000000022e888000100f4b1b7c1237c118a43504f0b1f312c027fb7517cb46911d9a9ab1c432be0b039da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f205c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f0753238a4817000000000000003ae888000100446ad8dfc37a54c8c1030e70eedd53b7b410cec1376a0aae42fd376b9749272f002326240a609c72641c6a3fcad3ad2ee33f2db95f6c16e181f7c62fa063834b245c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004002326240a609c72641c6a3fcad3ad2ee33f2db95f6c16e181f7c62fa063834b07fcbacd2e0200000000000000eec2890001008a90be061598f4b592afbd546bcb6beadb3c02f5c129df2e11b698f9543dbd412aa58acc7df6cea78de0928a5c6c2e79f3d24e5893d6a5971738cfbc03ca8f33285c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042aa58acc7df6cea78de0928a5c6c2e79f3d24e5893d6a5971738cfbc03ca8f330f65f486c4ba2401000000000000007a32c70001feff03000efdb10e8dfe2e73b6f29ce09aaad2c374dc22e2a64fcad4a77ed547e9175a08de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed4632c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed46300000000000000002e0791000100984a52dfdfbba392625d238ff859ec78d79b04f8ad456c9ab8d8426a085d4e73de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed463305c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed46307b7ec18d01f00000000000000720791000100c260f03b11e0e67574deb81febf89f6afb697d6c36d165f4ecb65522ea433805de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed463345c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed4630000000000000000ae079100010024126de9392aa70486873b23182a00ee1b9e2f394a46d409230871113a76be56b88597476f139767a85863d096b7668620bcf7cb531a950006f18b26d4b30600385c00792d2b0000000000b60200004a024d940000000000000000000000009756040400000000000000000000000000000000000000000000000000000000000000000004b88597476f139767a85863d096b7668620bcf7cb531a950006f18b26d4b306000771d8c05f520000000000000046899400010062380cd8c9bbe606cfda6572b6da580ec035ec57b18dc3d64acbcef53c3efc71143906b4ea1ab0986976c98468b8371bd54cba3330c0e895a1762d8e96c12c023c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004143906b4ea1ab0986976c98468b8371bd54cba3330c0e895a1762d8e96c12c024a930c0000000000000000568da100010006c112ee93775bb184b6bf00f22adee24091efe725c249db3ba01b15274b2a2f9ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d405c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d07e68ca9693100000000000000d257ad000100e45433ff9820f9d62b98feff2a95281d14ff6028a9b3c78063a11bbd0fc7bd549ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d445c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d5a9c11a7000000000000004a59ad000100fa01f3e6d839007cc8179e6cb40fb87d4b87502315568340cc51255d4b526d59b24a20c37c76fe89b0ab49ef5ef0e5ceeb33964ef89a496944e9b31cb4915d1b485c004bc72d0000000000b60200008cbc4c94000000000000000000000000464a040400000000000000000000000000000000000000000000000000000000000000000004b24a20c37c76fe89b0ab49ef5ef0e5ceeb33964ef89a496944e9b31cb4915d1bd51500000000000000eedfb4000100", + # "result": "0x35364cb26667d9765b6aaa76c1b7f0f2786c03257a090081bb483b1e6862e409f64e3f6aa1c0384f95f3ec8f764309523a653a5bd814632fe2eff931d35c606a5e0c65005c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046aa1c0384f95f3ec8f764309523a653a5bd814632fe2eff931d35c606a5e0c65620bb70000000000000000825b53000100c0dcbc2b619e07312e6fa2e1b9c91eb6826c77ab732fa1670bfa175c3cc06b01d89c740d9dfede764de5284c89dcedac74aa23b2d303a668e251620b78d79949045c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d89c740d9dfede764de5284c89dcedac74aa23b2d303a668e251620b78d7994907f1a79e0402000000000000003aac57000100e6e23c10ab6ed114577d8fa56f976d350aabea07e0382c6ab0313f1fd5b4ed7c9aa545ce482f48c3160fa706bbafe923bb8248403141729d95c96699b615f04d085c00e390160000000000b40200001329d44300000000000000000000000049080404000000000000000000000000000000000000000000000000000000000000000000049aa545ce482f48c3160fa706bbafe923bb8248403141729d95c96699b615f04d000000000000000022435a000100866eda07c029ea2856de08c183ddff461cb6ce83f8ec49150ef5647eee8f4c6b40469c545b3d0396a76ca1c41a6c090266e2e532adc9fde080d9e90d2e7b093d0c5c00dfb8190000000000b5020000026fb5d50000000000000000000000009aac04040000000000000000000000000000000000000000000000000000000000000000000440469c545b3d0396a76ca1c41a6c090266e2e532adc9fde080d9e90d2e7b093dea2b0e000000000000000046d9660001000cc6dd507099d72736a92d6f889e4024e3431ac57eb9eb1fe0ca3302c6d4c867509b91e2cf336358ec2f3fe6e0598e2909c29a57597765240dfa8db41e7dd46a105c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004509b91e2cf336358ec2f3fe6e0598e2909c29a57597765240dfa8db41e7dd46a00000000000000005a9f6f0001004af7598952f87683204a2a0c2266f941a74899bd69b0ce56e42a82820f6894461257de87a71abb164403f7cb9ea65d0721f8bb89d8bd85754deceedd91e86053145c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041257de87a71abb164403f7cb9ea65d0721f8bb89d8bd85754deceedd91e8605303b0ec68b3000000000000006e4478000100ba7c215ab878d9231d11bdaa5e4717b90d3b85df986abc669de607b1da6a020c74d879f5f872947565597d2f0c310fa0658d168ecd68a2ad3d5ec63438561643185c00265e1e0000000000b5020000583937a2000000000000000000000000d54f04040000000000000000000000000000000000000000000000000000000000000000000474d879f5f872947565597d2f0c310fa0658d168ecd68a2ad3d5ec6343856164307ed6f74c302000000000000004a7579000100084667e9ab96aca6c12c3094d740142cc4d36e423ede27b752978ffc70841b4dda618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f1c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f07bfb78a48170000000000000022e888000100f4b1b7c1237c118a43504f0b1f312c027fb7517cb46911d9a9ab1c432be0b039da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f205c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004da618f84f833dc38b54f31cca63c408134bcce60f38c16c2f64fd4cf37068b0f0753238a4817000000000000003ae888000100446ad8dfc37a54c8c1030e70eedd53b7b410cec1376a0aae42fd376b9749272f002326240a609c72641c6a3fcad3ad2ee33f2db95f6c16e181f7c62fa063834b245c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004002326240a609c72641c6a3fcad3ad2ee33f2db95f6c16e181f7c62fa063834b07fcbacd2e0200000000000000eec2890001008a90be061598f4b592afbd546bcb6beadb3c02f5c129df2e11b698f9543dbd412aa58acc7df6cea78de0928a5c6c2e79f3d24e5893d6a5971738cfbc03ca8f33285c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042aa58acc7df6cea78de0928a5c6c2e79f3d24e5893d6a5971738cfbc03ca8f330f65f486c4ba2401000000000000007a32c70001feff03000efdb10e8dfe2e73b6f29ce09aaad2c374dc22e2a64fcad4a77ed547e9175a08de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed4632c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed46300000000000000002e0791000100984a52dfdfbba392625d238ff859ec78d79b04f8ad456c9ab8d8426a085d4e73de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed463305c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed46307b7ec18d01f00000000000000720791000100c260f03b11e0e67574deb81febf89f6afb697d6c36d165f4ecb65522ea433805de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed463345c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004de74e52b42323230d99ec6f46fc1bf01b03f54f11f02fddb9d9668535e8ed4630000000000000000ae079100010024126de9392aa70486873b23182a00ee1b9e2f394a46d409230871113a76be56b88597476f139767a85863d096b7668620bcf7cb531a950006f18b26d4b30600385c00792d2b0000000000b60200004a024d940000000000000000000000009756040400000000000000000000000000000000000000000000000000000000000000000004b88597476f139767a85863d096b7668620bcf7cb531a950006f18b26d4b306000771d8c05f520000000000000046899400010062380cd8c9bbe606cfda6572b6da580ec035ec57b18dc3d64acbcef53c3efc71143906b4ea1ab0986976c98468b8371bd54cba3330c0e895a1762d8e96c12c023c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004143906b4ea1ab0986976c98468b8371bd54cba3330c0e895a1762d8e96c12c024a930c0000000000000000568da100010006c112ee93775bb184b6bf00f22adee24091efe725c249db3ba01b15274b2a2f9ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d405c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d07e68ca9693100000000000000d257ad000100e45433ff9820f9d62b98feff2a95281d14ff6028a9b3c78063a11bbd0fc7bd549ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d445c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049ef89253596e8764aecef9a452db36da8188153e0f707f1a0a37011583b5e82d5a9c11a7000000000000004a59ad000100fa01f3e6d839007cc8179e6cb40fb87d4b87502315568340cc51255d4b526d59b24a20c37c76fe89b0ab49ef5ef0e5ceeb33964ef89a496944e9b31cb4915d1b485c004bc72d0000000000b60200008cbc4c94000000000000000000000000464a040400000000000000000000000000000000000000000000000000000000000000000004b24a20c37c76fe89b0ab49ef5ef0e5ceeb33964ef89a496944e9b31cb4915d1bd51500000000000000eedfb4000100", + "result": "0x046a4368adc8781240b59c45ccacbf5a7ee0ca3a7adc7e893c27b4956e172c0220d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d000401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d000000000000000071530100", } }, "state_getRuntimeVersion": { @@ -6422,7 +5754,6 @@ }, } }, - "system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}}, }, "min_allowed_weights": { "chain_getHead": { diff --git a/tests/helpers/registry b/tests/helpers/registry index a19c2d2b28..cfce236fdb 100644 Binary files a/tests/helpers/registry and b/tests/helpers/registry differ diff --git a/tests/integration_tests/test_subtensor_integration.py b/tests/integration_tests/test_subtensor_integration.py index dcf149e62e..74e22837e2 100644 --- a/tests/integration_tests/test_subtensor_integration.py +++ b/tests/integration_tests/test_subtensor_integration.py @@ -28,13 +28,15 @@ async def prepare_test(mocker, seed): with open( os.path.join(os.path.dirname(__file__), "..", "helpers", "registry"), "rb" ) as f: - registry = PortableRegistry.from_metadata_v15( - MetadataV15.decode_from_metadata_option(f.read()) - ) + metadata_v15 = MetadataV15.decode_from_metadata_option(f.read()) + registry = PortableRegistry.from_metadata_v15(metadata_v15) subtensor = Subtensor("unknown", _mock=True) mocker.patch.object(subtensor.substrate.ws, "ws", FakeWebsocket(seed=seed)) mocker.patch.object(subtensor.substrate.ws, "_initialized", True) mocker.patch.object(subtensor.substrate._async_instance, "registry", registry) + mocker.patch.object( + subtensor.substrate._async_instance, "metadata_v15", metadata_v15 + ) subtensor.substrate.ws._receiving_task = asyncio.create_task( subtensor.substrate.ws._start_receiving() ) @@ -49,15 +51,15 @@ async def test_get_all_subnets_info(mocker): assert result[0].owner_ss58 == "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM" assert result[1].kappa == 32767 assert result[1].max_weight_limit == 65535 - assert result[1].blocks_since_epoch == 1 + assert result[1].blocks_since_epoch == 230 @pytest.mark.asyncio async def test_metagraph(mocker): subtensor = await prepare_test(mocker, "metagraph") - result = subtensor.metagraph(23) - assert result.n == 19 - assert result.netuid == 23 + result = subtensor.metagraph(1) + assert result.n == 1 + assert result.netuid == 1 assert result.block == 3264143 @@ -107,8 +109,8 @@ async def test_is_hotkey_registered(mocker): @pytest.mark.asyncio async def test_blocks_since_last_update(mocker): subtensor = await prepare_test(mocker, "blocks_since_last_update") - result = subtensor.blocks_since_last_update(23, 5) - assert result == 1293687 + result = subtensor.blocks_since_last_update(1, 0) + assert result == 3221134 @pytest.mark.asyncio @@ -128,11 +130,13 @@ async def test_subnetwork_n(mocker): @pytest.mark.asyncio -async def test_get_neuron_for_pubkey_and_subnet(hotkey, netuid, mocker): +async def test_get_neuron_for_pubkey_and_subnet(mocker): subtensor = await prepare_test(mocker, "get_neuron_for_pubkey_and_subnet") - result = subtensor.get_neuron_for_pubkey_and_subnet(hotkey, netuid) + result = subtensor.get_neuron_for_pubkey_and_subnet( + "5EU2xVWC7qffsUNGtvakp5WCj7WGJMPkwG1dsm3qnU2Kqvee", 1 + ) assert isinstance(result, NeuronInfo) - assert result.hotkey == hotkey + assert result.hotkey == "5EU2xVWC7qffsUNGtvakp5WCj7WGJMPkwG1dsm3qnU2Kqvee" assert isinstance(result.total_stake, Balance) assert isinstance(result.axon_info, AxonInfo) assert result.is_null is False diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index 6132e9736f..0bf5f13a01 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -1,3 +1,5 @@ +import unittest.mock as mock + import pytest from bittensor import AsyncSubtensor @@ -392,30 +394,26 @@ async def test_is_hotkey_delegate(subtensor, mocker, hotkey_ss58_in_result): @pytest.mark.parametrize( - "fake_hex_bytes_result, response", [(None, []), ("0xaabbccdd", b"\xaa\xbb\xcc\xdd")] + "fake_result, response", [(None, []), ([mock.Mock()], [mock.Mock()])] ) @pytest.mark.asyncio -async def test_get_delegates(subtensor, mocker, fake_hex_bytes_result, response): +async def test_get_delegates(subtensor, mocker, fake_result, response): """Tests get_delegates method.""" # Preps mocked_query_runtime_api = mocker.AsyncMock( - autospec=subtensor.query_runtime_api, return_value=fake_hex_bytes_result + autospec=subtensor.query_runtime_api, return_value=fake_result ) subtensor.query_runtime_api = mocked_query_runtime_api - mocked_delegate_info_list_from_vec_u8 = mocker.Mock() - async_subtensor.DelegateInfo.list_from_vec_u8 = ( - mocked_delegate_info_list_from_vec_u8 - ) + mocked_delegate_info_list_from_any = mocker.Mock() + async_subtensor.DelegateInfo.list_from_any = mocked_delegate_info_list_from_any # Call result = await subtensor.get_delegates(block_hash=None, reuse_block=True) # Asserts - if fake_hex_bytes_result: - assert result == mocked_delegate_info_list_from_vec_u8.return_value - mocked_delegate_info_list_from_vec_u8.assert_called_once_with( - bytes.fromhex(fake_hex_bytes_result[2:]) - ) + if fake_result: + assert result == mocked_delegate_info_list_from_any.return_value + mocked_delegate_info_list_from_any.assert_called_once_with(fake_result) else: assert result == response @@ -429,26 +427,21 @@ async def test_get_delegates(subtensor, mocker, fake_hex_bytes_result, response) @pytest.mark.parametrize( - "fake_hex_bytes_result, response", [(None, []), ("0x001122", b"\xaa\xbb\xcc\xdd")] + "fake_result, response", [(None, []), ([mock.Mock()], [mock.Mock()])] ) @pytest.mark.asyncio -async def test_get_stake_info_for_coldkey( - subtensor, mocker, fake_hex_bytes_result, response -): +async def test_get_stake_info_for_coldkey(subtensor, mocker, fake_result, response): """Tests get_stake_info_for_coldkey method.""" # Preps fake_coldkey_ss58 = "fake_coldkey_58" - mocked_ss58_to_vec_u8 = mocker.Mock() - async_subtensor.ss58_to_vec_u8 = mocked_ss58_to_vec_u8 - mocked_query_runtime_api = mocker.AsyncMock( - autospec=subtensor.query_runtime_api, return_value=fake_hex_bytes_result + autospec=subtensor.query_runtime_api, return_value=fake_result ) subtensor.query_runtime_api = mocked_query_runtime_api - mocked_stake_info_list_from_vec_u8 = mocker.Mock() - async_subtensor.StakeInfo.list_from_vec_u8 = mocked_stake_info_list_from_vec_u8 + mocked_stake_info_list_from_any = mocker.Mock() + async_subtensor.StakeInfo.list_from_any = mocked_stake_info_list_from_any # Call result = await subtensor.get_stake_info_for_coldkey( @@ -456,19 +449,16 @@ async def test_get_stake_info_for_coldkey( ) # Asserts - if fake_hex_bytes_result: - assert result == mocked_stake_info_list_from_vec_u8.return_value - mocked_stake_info_list_from_vec_u8.assert_called_once_with( - bytes.fromhex(fake_hex_bytes_result[2:]) - ) + if fake_result: + assert result == mocked_stake_info_list_from_any.return_value + mocked_stake_info_list_from_any.assert_called_once_with(fake_result) else: assert result == response - mocked_ss58_to_vec_u8.assert_called_once_with(fake_coldkey_ss58) mocked_query_runtime_api.assert_called_once_with( runtime_api="StakeInfoRuntimeApi", method="get_stake_info_for_coldkey", - params=[mocked_ss58_to_vec_u8.return_value], + params=[fake_coldkey_ss58], block_hash=None, reuse_block=True, ) @@ -512,25 +502,14 @@ async def test_query_runtime_api(subtensor, mocker): fake_block_hash = None reuse_block = False - mocked_encode_params = mocker.AsyncMock() - subtensor.encode_params = mocked_encode_params - - mocked_rpc_request = mocker.AsyncMock( - autospec=async_subtensor.AsyncSubstrateInterface.rpc_request + mocked_runtime_call = mocker.AsyncMock( + autospec=async_subtensor.AsyncSubstrateInterface.runtime_call ) - subtensor.substrate.rpc_request = mocked_rpc_request + subtensor.substrate.runtime_call = mocked_runtime_call mocked_scalecodec = mocker.Mock(autospec=async_subtensor.scalecodec.ScaleBytes) async_subtensor.scalecodec.ScaleBytes = mocked_scalecodec - mocked_runtime_configuration = mocker.Mock( - autospec=async_subtensor.RuntimeConfiguration - ) - async_subtensor.RuntimeConfiguration = mocked_runtime_configuration - - mocked_load_type_registry_preset = mocker.Mock() - async_subtensor.load_type_registry_preset = mocked_load_type_registry_preset - # Call result = await subtensor.query_runtime_api( runtime_api=fake_runtime_api, @@ -541,32 +520,14 @@ async def test_query_runtime_api(subtensor, mocker): ) # Asserts - - mocked_encode_params.assert_called_once_with( - call_definition={ - "params": [{"name": "coldkey", "type": "Vec"}], - "type": "Vec", - }, - params=[1, 2, 3], - ) - mocked_rpc_request.assert_called_once_with( - method="state_call", - params=[f"{fake_runtime_api}_{fake_method}", mocked_encode_params.return_value], - reuse_block_hash=reuse_block, - ) - mocked_runtime_configuration.assert_called_once() - assert ( - mocked_runtime_configuration.return_value.update_type_registry.call_count == 2 + mocked_runtime_call.assert_called_once_with( + fake_runtime_api, + fake_method, + fake_params, + fake_block_hash, ) - mocked_runtime_configuration.return_value.create_scale_object.assert_called_once_with( - "Vec", mocked_scalecodec.return_value - ) - - assert ( - result - == mocked_runtime_configuration.return_value.create_scale_object.return_value.decode.return_value - ) + assert result == mocked_runtime_call.return_value @pytest.mark.asyncio @@ -993,9 +954,8 @@ async def test_neurons(subtensor, mocker): mocked_query_runtime_api = mocker.patch.object( subtensor, "query_runtime_api", return_value="NOT NONE" ) - mocked_hex_to_bytes = mocker.patch.object(async_subtensor, "hex_to_bytes") mocked_neuron_info_list_from_vec_u8 = mocker.patch.object( - async_subtensor.NeuronInfo, "list_from_vec_u8" + async_subtensor.NeuronInfo, "list_from_any" ) # Call result = await subtensor.neurons( @@ -1012,30 +972,27 @@ async def test_neurons(subtensor, mocker): block_hash=fake_block_hash, reuse_block=fake_reuse_block_hash, ) - mocked_hex_to_bytes.assert_called_once_with(mocked_query_runtime_api.return_value) assert result == mocked_neuron_info_list_from_vec_u8.return_value @pytest.mark.parametrize( - "fake_hex_bytes_result, response", - [(None, []), ("0xaabbccdd", b"\xaa\xbb\xcc\xdd")], + "fake_result, response", + [(None, []), (mock.Mock(), mock.Mock())], ids=["none", "with data"], ) @pytest.mark.asyncio -async def test_neurons_lite(subtensor, mocker, fake_hex_bytes_result, response): +async def test_neurons_lite(subtensor, mocker, fake_result, response): """Tests neurons_lite method.""" # Preps fake_netuid = 1 fake_block_hash = "block_hash" fake_reuse_block_hash = True - mocked_query_runtime_api = mocker.AsyncMock(return_value=fake_hex_bytes_result) + mocked_query_runtime_api = mocker.AsyncMock(return_value=fake_result) subtensor.query_runtime_api = mocked_query_runtime_api - mocked_neuron_info_lite_list_from_vec_u8 = mocker.Mock() - async_subtensor.NeuronInfoLite.list_from_vec_u8 = ( - mocked_neuron_info_lite_list_from_vec_u8 - ) + mocked_neuron_info_lite_list_from_any = mocker.Mock() + async_subtensor.NeuronInfoLite.list_from_any = mocked_neuron_info_lite_list_from_any # Call result = await subtensor.neurons_lite( @@ -1053,13 +1010,11 @@ async def test_neurons_lite(subtensor, mocker, fake_hex_bytes_result, response): block_hash=fake_block_hash, reuse_block=fake_reuse_block_hash, ) - if fake_hex_bytes_result: - mocked_neuron_info_lite_list_from_vec_u8.assert_called_once_with( - bytes.fromhex(fake_hex_bytes_result[2:]) - ) - assert result == mocked_neuron_info_lite_list_from_vec_u8.return_value + if fake_result: + mocked_neuron_info_lite_list_from_any.assert_called_once_with(fake_result) + assert result == mocked_neuron_info_lite_list_from_any.return_value else: - mocked_neuron_info_lite_list_from_vec_u8.assert_not_called() + mocked_neuron_info_lite_list_from_any.assert_not_called() assert result == [] @@ -1079,11 +1034,11 @@ async def test_get_neuron_for_pubkey_and_subnet_success(subtensor, mocker): ) mocker.patch.object( subtensor.substrate, - "rpc_request", - return_value={"result": fake_result}, + "runtime_call", + return_value=fake_result, ) mocked_neuron_info = mocker.patch.object( - async_subtensor.NeuronInfo, "from_vec_u8", return_value="fake_neuron_info" + async_subtensor.NeuronInfo, "from_any", return_value="fake_neuron_info" ) # Call @@ -1100,9 +1055,12 @@ async def test_get_neuron_for_pubkey_and_subnet_success(subtensor, mocker): block_hash=None, reuse_block_hash=False, ) - subtensor.substrate.rpc_request.assert_awaited_once() - subtensor.substrate.rpc_request.assert_called_once_with( - method="neuronInfo_getNeuron", params=[fake_netuid, fake_uid] + subtensor.substrate.runtime_call.assert_awaited_once() + subtensor.substrate.runtime_call.assert_called_once_with( + "NeuronInfoRuntimeApi", + "get_neuron", + [fake_netuid, fake_uid], + None, ) mocked_neuron_info.assert_called_once_with(fake_result) assert result == "fake_neuron_info" @@ -1156,8 +1114,8 @@ async def test_get_neuron_for_pubkey_and_subnet_rpc_result_empty(subtensor, mock ) mocker.patch.object( subtensor.substrate, - "rpc_request", - return_value={"result": None}, + "runtime_call", + return_value=None, ) mocked_get_null_neuron = mocker.patch.object( async_subtensor.NeuronInfo, "get_null_neuron", return_value="null_neuron" @@ -1176,8 +1134,11 @@ async def test_get_neuron_for_pubkey_and_subnet_rpc_result_empty(subtensor, mock block_hash=None, reuse_block_hash=False, ) - subtensor.substrate.rpc_request.assert_called_once_with( - method="neuronInfo_getNeuron", params=[fake_netuid, fake_uid] + subtensor.substrate.runtime_call.assert_called_once_with( + "NeuronInfoRuntimeApi", + "get_neuron", + [fake_netuid, fake_uid], + None, ) mocked_get_null_neuron.assert_called_once() assert result == "null_neuron" @@ -1194,14 +1155,8 @@ async def test_neuron_for_uid_happy_path(subtensor, mocker): mocked_null_neuron = mocker.Mock() async_subtensor.NeuronInfo.get_null_neuron = mocked_null_neuron - # no result in response - mocked_substrate_rpc_request = mocker.AsyncMock( - return_value={"result": b"some_result"} - ) - subtensor.substrate.rpc_request = mocked_substrate_rpc_request - - mocked_neuron_info_from_vec_u8 = mocker.Mock() - async_subtensor.NeuronInfo.from_vec_u8 = mocked_neuron_info_from_vec_u8 + mocked_neuron_info_from_any = mocker.Mock() + async_subtensor.NeuronInfo.from_any = mocked_neuron_info_from_any # Call result = await subtensor.neuron_for_uid( @@ -1210,10 +1165,10 @@ async def test_neuron_for_uid_happy_path(subtensor, mocker): # Asserts mocked_null_neuron.assert_not_called() - mocked_neuron_info_from_vec_u8.assert_called_once_with( - bytes(mocked_substrate_rpc_request.return_value.get("result")) + mocked_neuron_info_from_any.assert_called_once_with( + subtensor.substrate.runtime_call.return_value ) - assert result == mocked_neuron_info_from_vec_u8.return_value + assert result == mocked_neuron_info_from_any.return_value @pytest.mark.asyncio @@ -1249,11 +1204,11 @@ async def test_neuron_for_uid(subtensor, mocker): async_subtensor.NeuronInfo.get_null_neuron = mocked_null_neuron # no result in response - mocked_substrate_rpc_request = mocker.AsyncMock(return_value={}) - subtensor.substrate.rpc_request = mocked_substrate_rpc_request + mocked_substrate_runtime_call = mocker.AsyncMock(return_value=None) + subtensor.substrate.runtime_call = mocked_substrate_runtime_call - mocked_neuron_info_from_vec_u8 = mocker.Mock() - async_subtensor.NeuronInfo.from_vec_u8 = mocked_neuron_info_from_vec_u8 + mocked_neuron_info_from_any = mocker.Mock() + async_subtensor.NeuronInfo.from_any = mocked_neuron_info_from_any # Call result = await subtensor.neuron_for_uid( @@ -1262,7 +1217,7 @@ async def test_neuron_for_uid(subtensor, mocker): # Asserts mocked_null_neuron.assert_called_once() - mocked_neuron_info_from_vec_u8.assert_not_called() + mocked_neuron_info_from_any.assert_not_called() assert result == mocked_null_neuron.return_value @@ -1272,27 +1227,25 @@ async def test_get_delegated_no_block_hash_no_reuse(subtensor, mocker): # Preps fake_coldkey_ss58 = "fake_ss58_address" - mocked_ss58_to_vec_u8 = mocker.Mock(return_value=b"encoded_coldkey") - mocker.patch.object(async_subtensor, "ss58_to_vec_u8", mocked_ss58_to_vec_u8) - - mocked_rpc_request = mocker.AsyncMock(return_value={"result": b"mocked_result"}) - subtensor.substrate.rpc_request = mocked_rpc_request - - mocked_delegated_list_from_vec_u8 = mocker.Mock() - async_subtensor.DelegateInfo.delegated_list_from_vec_u8 = ( - mocked_delegated_list_from_vec_u8 + mocked_delegated_list_from_any = mocker.Mock() + async_subtensor.DelegateInfo.delegated_list_from_any = ( + mocked_delegated_list_from_any ) # Call result = await subtensor.get_delegated(coldkey_ss58=fake_coldkey_ss58) # Asserts - mocked_ss58_to_vec_u8.assert_called_once_with(fake_coldkey_ss58) - mocked_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegated", params=[b"encoded_coldkey"] + subtensor.substrate.runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegated", + [fake_coldkey_ss58], + None, + ) + mocked_delegated_list_from_any.assert_called_once_with( + subtensor.substrate.runtime_call.return_value ) - mocked_delegated_list_from_vec_u8.assert_called_once_with(b"mocked_result") - assert result == mocked_delegated_list_from_vec_u8.return_value + assert result == mocked_delegated_list_from_any.return_value @pytest.mark.asyncio @@ -1302,15 +1255,9 @@ async def test_get_delegated_with_block_hash(subtensor, mocker): fake_coldkey_ss58 = "fake_ss58_address" fake_block_hash = "fake_block_hash" - mocked_ss58_to_vec_u8 = mocker.Mock(return_value=b"encoded_coldkey") - mocker.patch.object(async_subtensor, "ss58_to_vec_u8", mocked_ss58_to_vec_u8) - - mocked_rpc_request = mocker.AsyncMock(return_value={"result": b"mocked_result"}) - subtensor.substrate.rpc_request = mocked_rpc_request - - mocked_delegated_list_from_vec_u8 = mocker.Mock() - async_subtensor.DelegateInfo.delegated_list_from_vec_u8 = ( - mocked_delegated_list_from_vec_u8 + mocked_delegated_list_from_any = mocker.Mock() + async_subtensor.DelegateInfo.delegated_list_from_any = ( + mocked_delegated_list_from_any ) # Call @@ -1319,12 +1266,16 @@ async def test_get_delegated_with_block_hash(subtensor, mocker): ) # Asserts - mocked_ss58_to_vec_u8.assert_called_once_with(fake_coldkey_ss58) - mocked_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegated", params=[fake_block_hash, b"encoded_coldkey"] + subtensor.substrate.runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegated", + [fake_coldkey_ss58], + fake_block_hash, + ) + mocked_delegated_list_from_any.assert_called_once_with( + subtensor.substrate.runtime_call.return_value ) - mocked_delegated_list_from_vec_u8.assert_called_once_with(b"mocked_result") - assert result == mocked_delegated_list_from_vec_u8.return_value + assert result == mocked_delegated_list_from_any.return_value @pytest.mark.asyncio @@ -1334,15 +1285,9 @@ async def test_get_delegated_with_reuse_block(subtensor, mocker): fake_coldkey_ss58 = "fake_ss58_address" subtensor.substrate.last_block_hash = "last_block_hash" - mocked_ss58_to_vec_u8 = mocker.Mock(return_value=b"encoded_coldkey") - mocker.patch.object(async_subtensor, "ss58_to_vec_u8", mocked_ss58_to_vec_u8) - - mocked_rpc_request = mocker.AsyncMock(return_value={"result": b"mocked_result"}) - subtensor.substrate.rpc_request = mocked_rpc_request - - mocked_delegated_list_from_vec_u8 = mocker.Mock() - async_subtensor.DelegateInfo.delegated_list_from_vec_u8 = ( - mocked_delegated_list_from_vec_u8 + mocked_delegated_list_from_any = mocker.Mock() + async_subtensor.DelegateInfo.delegated_list_from_any = ( + mocked_delegated_list_from_any ) # Call @@ -1351,13 +1296,16 @@ async def test_get_delegated_with_reuse_block(subtensor, mocker): ) # Asserts - mocked_ss58_to_vec_u8.assert_called_once_with(fake_coldkey_ss58) - mocked_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegated", - params=["last_block_hash", b"encoded_coldkey"], + subtensor.substrate.runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegated", + [fake_coldkey_ss58], + "last_block_hash", + ) + mocked_delegated_list_from_any.assert_called_once_with( + subtensor.substrate.runtime_call.return_value ) - mocked_delegated_list_from_vec_u8.assert_called_once_with(b"mocked_result") - assert result == mocked_delegated_list_from_vec_u8.return_value + assert result == mocked_delegated_list_from_any.return_value @pytest.mark.asyncio @@ -1366,19 +1314,18 @@ async def test_get_delegated_with_empty_result(subtensor, mocker): # Preps fake_coldkey_ss58 = "fake_ss58_address" - mocked_ss58_to_vec_u8 = mocker.Mock(return_value=b"encoded_coldkey") - mocker.patch.object(async_subtensor, "ss58_to_vec_u8", mocked_ss58_to_vec_u8) - - mocked_rpc_request = mocker.AsyncMock(return_value={}) - subtensor.substrate.rpc_request = mocked_rpc_request + mocked_runtime_call = mocker.AsyncMock(return_value=None) + subtensor.substrate.runtime_call = mocked_runtime_call # Call result = await subtensor.get_delegated(coldkey_ss58=fake_coldkey_ss58) # Asserts - mocked_ss58_to_vec_u8.assert_called_once_with(fake_coldkey_ss58) - mocked_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegated", params=[b"encoded_coldkey"] + mocked_runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegated", + [fake_coldkey_ss58], + None, ) assert result == [] @@ -1892,6 +1839,8 @@ async def test_get_children_success(subtensor, mocker): module="SubtensorModule", storage_function="ChildKeys", params=[fake_hotkey, fake_netuid], + block_hash=None, + reuse_block_hash=False, ) mocked_decode_account_id.assert_has_calls( [mocker.call("child_key_1"), mocker.call("child_key_2")] @@ -1918,6 +1867,8 @@ async def test_get_children_no_children(subtensor, mocker): module="SubtensorModule", storage_function="ChildKeys", params=[fake_hotkey, fake_netuid], + block_hash=None, + reuse_block_hash=False, ) assert result == (True, [], "") @@ -1946,6 +1897,8 @@ async def test_get_children_substrate_request_exception(subtensor, mocker): module="SubtensorModule", storage_function="ChildKeys", params=[fake_hotkey, fake_netuid], + block_hash=None, + reuse_block_hash=False, ) mocked_format_error_message.assert_called_once_with(fake_exception) assert result == (False, [], "Formatted error message") @@ -1957,14 +1910,14 @@ async def test_get_subnet_hyperparameters_success(subtensor, mocker): # Preps fake_netuid = 1 fake_block_hash = "block_hash" - fake_hex_bytes_result = "0xaabbccdd" + fake_result = object() - mocked_query_runtime_api = mocker.AsyncMock(return_value=fake_hex_bytes_result) + mocked_query_runtime_api = mocker.AsyncMock(return_value=fake_result) subtensor.query_runtime_api = mocked_query_runtime_api - mocked_from_vec_u8 = mocker.Mock() + mocked_from_any = mocker.Mock() mocker.patch.object( - async_subtensor.SubnetHyperparameters, "from_vec_u8", mocked_from_vec_u8 + async_subtensor.SubnetHyperparameters, "from_any", mocked_from_any ) # Call @@ -1980,9 +1933,7 @@ async def test_get_subnet_hyperparameters_success(subtensor, mocker): block_hash=fake_block_hash, reuse_block=False, ) - bytes_result = bytes.fromhex(fake_hex_bytes_result[2:]) - mocked_from_vec_u8.assert_called_once_with(bytes_result) - assert result == mocked_from_vec_u8.return_value + assert result == mocked_from_any.return_value @pytest.mark.asyncio @@ -2013,14 +1964,14 @@ async def test_get_subnet_hyperparameters_without_0x_prefix(subtensor, mocker): """Tests get_subnet_hyperparameters when hex_bytes_result is without 0x prefix.""" # Preps fake_netuid = 1 - fake_hex_bytes_result = "aabbccdd" # without "0x" prefix + fake_result = object() - mocked_query_runtime_api = mocker.AsyncMock(return_value=fake_hex_bytes_result) + mocked_query_runtime_api = mocker.AsyncMock(return_value=fake_result) subtensor.query_runtime_api = mocked_query_runtime_api - mocked_from_vec_u8 = mocker.Mock() + mocked_from_any = mocker.Mock() mocker.patch.object( - async_subtensor.SubnetHyperparameters, "from_vec_u8", mocked_from_vec_u8 + async_subtensor.SubnetHyperparameters, "from_any", mocked_from_any ) # Call @@ -2034,9 +1985,8 @@ async def test_get_subnet_hyperparameters_without_0x_prefix(subtensor, mocker): block_hash=None, reuse_block=False, ) - bytes_result = bytes.fromhex(fake_hex_bytes_result) - mocked_from_vec_u8.assert_called_once_with(bytes_result) - assert result == mocked_from_vec_u8.return_value + mocked_from_any.assert_called_once_with(fake_result) + assert result == mocked_from_any.return_value @pytest.mark.asyncio @@ -2376,7 +2326,10 @@ async def test_commit_reveal_enabled(subtensor, mocker): # Assertions mocked_get_hyperparameter.assert_awaited_once_with( - param_name="CommitRevealWeightsEnabled", block_hash=block_hash, netuid=netuid + param_name="CommitRevealWeightsEnabled", + block_hash=block_hash, + netuid=netuid, + reuse_block=False, ) assert result is False diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index a6096c9098..78b0d993eb 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -805,42 +805,16 @@ def test_get_subnet_hyperparameters_success(mocker, subtensor): # Prep netuid = 1 block = 123 - hex_bytes_result = "0x010203" - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - mocker.patch.object(subtensor, "query_runtime_api", return_value=hex_bytes_result) + result = mocker.Mock() + mocker.patch.object(subtensor, "query_runtime_api", return_value=result) mocker.patch.object( subtensor_module.SubnetHyperparameters, - "from_vec_u8", - return_value=["from_vec_u8"], + "from_any", + return_value=["from_any"], ) # Call - result = subtensor.get_subnet_hyperparameters(netuid, block) - - # Asserts - subtensor.query_runtime_api.assert_called_once_with( - runtime_api="SubnetInfoRuntimeApi", - method="get_subnet_hyperparams", - params=[netuid], - block=block, - ) - subtensor_module.SubnetHyperparameters.from_vec_u8.assert_called_once_with( - bytes_result - ) - - -def test_get_subnet_hyperparameters_hex_without_prefix(subtensor, mocker): - """Test get_subnet_hyperparameters correctly processes hex string without '0x' prefix.""" - # Prep - netuid = 1 - block = 123 - hex_bytes_result = "010203" - bytes_result = bytes.fromhex(hex_bytes_result) - mocker.patch.object(subtensor, "query_runtime_api", return_value=hex_bytes_result) - mocker.patch.object(subtensor_module.SubnetHyperparameters, "from_vec_u8") - - # Call - result = subtensor.get_subnet_hyperparameters(netuid, block) + subtensor.get_subnet_hyperparameters(netuid, block) # Asserts subtensor.query_runtime_api.assert_called_once_with( @@ -849,9 +823,7 @@ def test_get_subnet_hyperparameters_hex_without_prefix(subtensor, mocker): params=[netuid], block=block, ) - subtensor_module.SubnetHyperparameters.from_vec_u8.assert_called_once_with( - bytes_result - ) + subtensor_module.SubnetHyperparameters.from_any.assert_called_once_with(result) def test_get_subnet_hyperparameters_no_data(mocker, subtensor): @@ -860,7 +832,7 @@ def test_get_subnet_hyperparameters_no_data(mocker, subtensor): netuid = 1 block = 123 mocker.patch.object(subtensor, "query_runtime_api", return_value=None) - mocker.patch.object(subtensor_module.SubnetHyperparameters, "from_vec_u8") + mocker.patch.object(subtensor_module.SubnetHyperparameters, "from_any") # Call result = subtensor.get_subnet_hyperparameters(netuid, block) @@ -873,7 +845,7 @@ def test_get_subnet_hyperparameters_no_data(mocker, subtensor): params=[netuid], block=block, ) - subtensor_module.SubnetHyperparameters.from_vec_u8.assert_not_called() + subtensor_module.SubnetHyperparameters.from_any.assert_not_called() def test_query_subtensor(subtensor, mocker): @@ -900,32 +872,22 @@ def test_query_runtime_api(subtensor, mocker): fake_runtime_api = "NeuronInfoRuntimeApi" fake_method = "get_neuron_lite" - mocked_state_call = mocker.MagicMock() - subtensor.state_call = mocked_state_call - - mocked_runtime_configuration = mocker.patch.object( - subtensor_module, "RuntimeConfiguration" - ) - mocked_scalecodec = mocker.patch.object(subtensor_module.scalecodec, "ScaleBytes") + mocked_runtime_call = mocker.MagicMock() + subtensor.substrate.runtime_call = mocked_runtime_call # Call result = subtensor.query_runtime_api(fake_runtime_api, fake_method, None) # Asserts - subtensor.state_call.assert_called_once_with( - method=f"{fake_runtime_api}_{fake_method}", data="0x", block=None - ) - mocked_scalecodec.assert_called_once_with( - subtensor.state_call.return_value.__getitem__.return_value - ) - mocked_runtime_configuration.assert_called_once() - mocked_runtime_configuration.return_value.update_type_registry.assert_called() - mocked_runtime_configuration.return_value.create_scale_object.assert_called() - assert ( - result - == mocked_runtime_configuration.return_value.create_scale_object.return_value.decode.return_value + subtensor.substrate.runtime_call.assert_called_once_with( + fake_runtime_api, + fake_method, + None, + None, ) + assert result == mocked_runtime_call.return_value + def test_query_map_subtensor(subtensor, mocker): """Tests query_map_subtensor call.""" @@ -1380,7 +1342,7 @@ def test_neuron_for_uid_response_none(subtensor, mocker): subtensor_module.NeuronInfo, "get_null_neuron" ) - subtensor.substrate.rpc_request.return_value.get.return_value = None + subtensor.substrate.runtime_call.return_value = None # Call result = subtensor.neuron_for_uid( @@ -1388,9 +1350,11 @@ def test_neuron_for_uid_response_none(subtensor, mocker): ) # Asserts - subtensor.substrate.rpc_request.assert_called_once_with( - method="neuronInfo_getNeuron", - params=[fake_netuid, fake_uid, subtensor.substrate.get_block_hash.return_value], + subtensor.substrate.runtime_call.assert_called_once_with( + "NeuronInfoRuntimeApi", + "get_neuron", + [fake_netuid, fake_uid], + subtensor.substrate.get_block_hash.return_value, ) mocked_neuron_info.assert_called_once() @@ -1403,8 +1367,8 @@ def test_neuron_for_uid_success(subtensor, mocker): fake_uid = 1 fake_netuid = 2 fake_block = 123 - mocked_neuron_from_vec_u8 = mocker.patch.object( - subtensor_module.NeuronInfo, "from_vec_u8" + mocked_neuron_from_any = mocker.patch.object( + subtensor_module.NeuronInfo, "from_any" ) mock_get_block_hash = mocker.patch.object(subtensor, "get_block_hash") @@ -1415,15 +1379,17 @@ def test_neuron_for_uid_success(subtensor, mocker): # Asserts mock_get_block_hash.assert_called_once_with(fake_block) - subtensor.substrate.rpc_request.assert_called_once_with( - method="neuronInfo_getNeuron", - params=[fake_netuid, fake_uid, mock_get_block_hash.return_value], + subtensor.substrate.runtime_call.assert_called_once_with( + "NeuronInfoRuntimeApi", + "get_neuron", + [fake_netuid, fake_uid], + mock_get_block_hash.return_value, ) - mocked_neuron_from_vec_u8.assert_called_once_with( - subtensor.substrate.rpc_request.return_value.get.return_value + mocked_neuron_from_any.assert_called_once_with( + subtensor.substrate.runtime_call.return_value ) - assert result == mocked_neuron_from_vec_u8.return_value + assert result == mocked_neuron_from_any.return_value @pytest.mark.parametrize( @@ -2039,13 +2005,12 @@ def test_get_all_subnets_info_success(mocker, subtensor): mocker.patch.object( subtensor.substrate, "get_block_hash", return_value="mock_block_hash" ) - hex_bytes_result = "0x010203" - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - mocker.patch.object(subtensor, "query_runtime_api", return_value=hex_bytes_result) + result = mocker.Mock() + mocker.patch.object(subtensor, "query_runtime_api", return_value=result) mocker.patch.object( subtensor_module.SubnetInfo, - "list_from_vec_u8", - return_value="list_from_vec_u80", + "list_from_any", + return_value="list_from_any", ) # Call @@ -2055,7 +2020,7 @@ def test_get_all_subnets_info_success(mocker, subtensor): subtensor.query_runtime_api.assert_called_once_with( "SubnetInfoRuntimeApi", "get_subnets_info", params=[], block=block ) - subtensor_module.SubnetInfo.list_from_vec_u8.assert_called_once_with(bytes_result) + subtensor_module.SubnetInfo.list_from_any.assert_called_once_with(result) @pytest.mark.parametrize("result_", [[], None]) @@ -2483,9 +2448,7 @@ def test_get_delegates_success(mocker, subtensor): # Mock data fake_block = 123 fake_block_hash = "0xabc123" - fake_json_body = { - "result": "mock_encoded_delegates", - } + fake_response = mocker.Mock() # Mocks mock_get_block_hash = mocker.patch.object( @@ -2493,14 +2456,14 @@ def test_get_delegates_success(mocker, subtensor): "get_block_hash", return_value=fake_block_hash, ) - mock_rpc_request = mocker.patch.object( + mock_runtime_call = mocker.patch.object( subtensor.substrate, - "rpc_request", - return_value=fake_json_body, + "runtime_call", + return_value=fake_response, ) - mock_list_from_vec_u8 = mocker.patch.object( + mock_list_from_any = mocker.patch.object( subtensor_module.DelegateInfo, - "list_from_vec_u8", + "list_from_any", return_value=["delegate1", "delegate2"], ) @@ -2509,11 +2472,13 @@ def test_get_delegates_success(mocker, subtensor): # Assertions mock_get_block_hash.assert_called_once_with(fake_block) - mock_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegates", - params=[fake_block_hash], + mock_runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegates", + [], + fake_block_hash, ) - mock_list_from_vec_u8.assert_called_once_with(fake_json_body["result"]) + mock_list_from_any.assert_called_once_with(fake_response) assert result == ["delegate1", "delegate2"] @@ -2522,7 +2487,7 @@ def test_get_delegates_no_result(mocker, subtensor): # Mock data fake_block = 123 fake_block_hash = "0xabc123" - fake_json_body = {} + fake_response = None # Mocks mock_get_block_hash = mocker.patch.object( @@ -2530,10 +2495,10 @@ def test_get_delegates_no_result(mocker, subtensor): "get_block_hash", return_value=fake_block_hash, ) - mock_rpc_request = mocker.patch.object( + mock_runtime_call = mocker.patch.object( subtensor.substrate, - "rpc_request", - return_value=fake_json_body, + "runtime_call", + return_value=fake_response, ) # Call @@ -2541,9 +2506,11 @@ def test_get_delegates_no_result(mocker, subtensor): # Assertions mock_get_block_hash.assert_called_once_with(fake_block) - mock_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegates", - params=[fake_block_hash], + mock_runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegates", + [], + fake_block_hash, ) assert result == [] @@ -2551,19 +2518,17 @@ def test_get_delegates_no_result(mocker, subtensor): def test_get_delegates_latest_block(mocker, subtensor): """Test when no block is provided (latest block).""" # Mock data - fake_json_body = { - "result": "mock_encoded_delegates", - } + fake_response = mocker.Mock() # Mocks - mock_rpc_request = mocker.patch.object( + mock_runtime_call = mocker.patch.object( subtensor.substrate, - "rpc_request", - return_value=fake_json_body, + "runtime_call", + return_value=fake_response, ) - mock_list_from_vec_u8 = mocker.patch.object( + mock_list_from_any = mocker.patch.object( subtensor_module.DelegateInfo, - "list_from_vec_u8", + "list_from_any", return_value=["delegate1", "delegate2"], ) @@ -2571,11 +2536,13 @@ def test_get_delegates_latest_block(mocker, subtensor): result = subtensor.get_delegates() # Assertions - mock_rpc_request.assert_called_once_with( - method="delegateInfo_getDelegates", - params=[], + mock_runtime_call.assert_called_once_with( + "DelegateInfoRuntimeApi", + "get_delegates", + [], + None, ) - mock_list_from_vec_u8.assert_called_once_with(fake_json_body["result"]) + mock_list_from_any.assert_called_once_with(fake_response) assert result == ["delegate1", "delegate2"]