diff --git a/async_substrate_interface/async_substrate.py b/async_substrate_interface/async_substrate.py index 94bda13..2268667 100644 --- a/async_substrate_interface/async_substrate.py +++ b/async_substrate_interface/async_substrate.py @@ -673,6 +673,7 @@ def __init__( max_retries: int = 5, retry_timeout: float = 60.0, _mock: bool = False, + legacy_account_id_decode: bool = True, ): """ The asyncio-compatible version of the subtensor interface commands we use in bittensor. It is important to @@ -690,6 +691,10 @@ def __init__( max_retries: number of times to retry RPC requests before giving up retry_timeout: how to long wait since the last ping to retry the RPC request _mock: whether to use mock version of the subtensor interface + legacy_account_id_decode: determines whether AccountIds will be encoded as str + i.e. `False` => '5CPpYrrPXVWBpFVPwucyaVz8yHmgEx2gSYsqKxjkpcS6XRTC' + or left as a tuple of ints, i.e. `True` => `((14, 148, 49, 116, 204, 181, 15, 159, 227, 104, 234, 66, + 22, 124, 11, 249, 247, 114, 82, 128, 38, 255, 65, 253, 173, 84, 57, 90, 168, 143, 203, 96),)` """ self.max_retries = max_retries @@ -726,6 +731,7 @@ def __init__( self._initializing = False self.registry_type_map = {} self.type_id_to_name = {} + self.legacy_account_id_decode = legacy_account_id_decode async def __aenter__(self): await self.initialize() @@ -901,7 +907,12 @@ async def decode_scale( return ss58_encode(scale_bytes, SS58_FORMAT) else: await self._wait_for_registry(_attempt, _retries) - obj = decode_by_type_string(type_string, self.runtime.registry, scale_bytes) + obj = decode_by_type_string( + type_string, + self.runtime.registry, + scale_bytes, + self.legacy_account_id_decode, + ) if return_scale_obj: return ScaleObj(obj) else: @@ -3243,6 +3254,7 @@ async def query_map( value_type, key_hashers, ignore_decoding_errors, + legacy_account_id=self.legacy_account_id_decode, ) return AsyncQueryMapResult( records=result, @@ -3641,6 +3653,7 @@ async def get_async_substrate_interface( max_retries: int = 5, retry_timeout: float = 60.0, _mock: bool = False, + legacy_account_id_decode: bool = True, ) -> "AsyncSubstrateInterface": """ Factory function for creating an initialized AsyncSubstrateInterface @@ -3655,6 +3668,7 @@ async def get_async_substrate_interface( max_retries, retry_timeout, _mock, + legacy_account_id_decode=legacy_account_id_decode, ) await substrate.initialize() return substrate diff --git a/async_substrate_interface/substrate_addons.py b/async_substrate_interface/substrate_addons.py index 5edb26a..a81e63f 100644 --- a/async_substrate_interface/substrate_addons.py +++ b/async_substrate_interface/substrate_addons.py @@ -117,6 +117,7 @@ def __init__( max_retries: int = 5, retry_timeout: float = 60.0, _mock: bool = False, + legacy_account_id_decode: bool = True, ): fallback_chains = fallback_chains or [] self.fallback_chains = ( @@ -131,6 +132,7 @@ def __init__( self.max_retries = max_retries self.chain_endpoint = url self.url = url + self.legacy_account_id_decode = legacy_account_id_decode initialized = False for chain_url in [url] + fallback_chains: try: @@ -146,6 +148,7 @@ def __init__( _mock=_mock, retry_timeout=retry_timeout, max_retries=max_retries, + legacy_account_id_decode=self.legacy_account_id_decode, ) initialized = True logger.info(f"Connected to {chain_url}") @@ -243,6 +246,7 @@ def __init__( max_retries: int = 5, retry_timeout: float = 60.0, _mock: bool = False, + legacy_account_id_decode: bool = True, ): fallback_chains = fallback_chains or [] self.fallback_chains = ( @@ -265,6 +269,7 @@ def __init__( _mock=_mock, retry_timeout=retry_timeout, max_retries=max_retries, + legacy_account_id_decode=legacy_account_id_decode, ) self._original_methods = { method: getattr(self, method) for method in RETRY_METHODS diff --git a/async_substrate_interface/sync_substrate.py b/async_substrate_interface/sync_substrate.py index 4c91fd2..ec36cf6 100644 --- a/async_substrate_interface/sync_substrate.py +++ b/async_substrate_interface/sync_substrate.py @@ -483,6 +483,7 @@ def __init__( max_retries: int = 5, retry_timeout: float = 60.0, _mock: bool = False, + legacy_account_id_decode: bool = True, ): """ The sync compatible version of the subtensor interface commands we use in bittensor. Use this instance only @@ -499,6 +500,10 @@ def __init__( max_retries: number of times to retry RPC requests before giving up retry_timeout: how to long wait since the last ping to retry the RPC request _mock: whether to use mock version of the subtensor interface + legacy_account_id_decode: determines whether AccountIds will be encoded as str + i.e. `False` => '5CPpYrrPXVWBpFVPwucyaVz8yHmgEx2gSYsqKxjkpcS6XRTC' + or left as a tuple of ints, i.e. `True` => `((14, 148, 49, 116, 204, 181, 15, 159, 227, 104, 234, 66, + 22, 124, 11, 249, 247, 114, 82, 128, 38, 255, 65, 253, 173, 84, 57, 90, 168, 143, 203, 96),)` """ self.max_retries = max_retries @@ -525,6 +530,7 @@ def __init__( self.ws = self.connect(init=True) self.registry_type_map = {} self.type_id_to_name = {} + self.legacy_account_id_decode = legacy_account_id_decode if not _mock: self.initialize() @@ -668,7 +674,12 @@ def decode_scale( # Decode AccountId bytes to SS58 address return ss58_encode(scale_bytes, SS58_FORMAT) else: - obj = decode_by_type_string(type_string, self.runtime.registry, scale_bytes) + obj = decode_by_type_string( + type_string, + self.runtime.registry, + scale_bytes, + self.legacy_account_id_decode, + ) if return_scale_obj: return ScaleObj(obj) else: @@ -2873,7 +2884,6 @@ def query_map( Returns: QueryMapResult object """ - hex_to_bytes_ = hex_to_bytes params = params or [] block_hash = self._get_current_block_hash(block_hash, reuse_block_hash) if block_hash: @@ -2955,6 +2965,7 @@ def query_map( value_type, key_hashers, ignore_decoding_errors, + legacy_account_id=self.legacy_account_id_decode, ) return QueryMapResult( records=result, diff --git a/async_substrate_interface/utils/decoding.py b/async_substrate_interface/utils/decoding.py index 6dc7f21..ac49771 100644 --- a/async_substrate_interface/utils/decoding.py +++ b/async_substrate_interface/utils/decoding.py @@ -1,8 +1,6 @@ from typing import Union, TYPE_CHECKING from bt_decode import AxonInfo, PrometheusInfo, decode_list -from scalecodec import ss58_encode -from bittensor_wallet.utils import SS58_FORMAT from async_substrate_interface.utils import hex_to_bytes from async_substrate_interface.types import ScaleObj @@ -59,8 +57,11 @@ def _decode_scale_list_with_runtime( scale_bytes_list: list[bytes], runtime_registry, return_scale_obj: bool = False, + legacy_account_id: bool = True, ): - obj = decode_list(type_strings, runtime_registry, scale_bytes_list) + obj = decode_list( + type_strings, runtime_registry, scale_bytes_list, legacy_account_id + ) if return_scale_obj: return [ScaleObj(x) for x in obj] else: @@ -76,6 +77,7 @@ def decode_query_map( value_type, key_hashers, ignore_decoding_errors, + legacy_account_id: bool = True, ): def concat_hash_len(key_hasher: str) -> int: """ @@ -112,6 +114,7 @@ def concat_hash_len(key_hasher: str) -> int: pre_decoded_key_types + pre_decoded_value_types, pre_decoded_keys + pre_decoded_values, runtime.registry, + legacy_account_id=legacy_account_id, ) middl_index = len(all_decoded) // 2 decoded_keys = all_decoded[:middl_index] diff --git a/pyproject.toml b/pyproject.toml index cdfa7e0..6b1977e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ keywords = ["substrate", "development", "bittensor"] dependencies = [ "wheel", "asyncstdlib~=3.13.0", - "bt-decode==v0.6.0", + "bt-decode==0.7.0", "scalecodec~=1.2.11", "websockets>=14.1", "xxhash"