6565from async_substrate_interface .utils .decoding import (
6666 _determine_if_old_runtime_call ,
6767 _bt_decode_to_dict_or_list ,
68+ legacy_scale_decode ,
6869)
6970from async_substrate_interface .utils .storage import StorageKey
7071from async_substrate_interface .type_registry import _TYPE_REGISTRY
@@ -816,7 +817,7 @@ async def initialize(self):
816817 )
817818
818819 if ss58_prefix_constant :
819- self .ss58_format = ss58_prefix_constant
820+ self .ss58_format = ss58_prefix_constant . value
820821 self .initialized = True
821822 self ._initializing = False
822823
@@ -908,7 +909,7 @@ async def _get_current_block_hash(
908909
909910 async def _load_registry_at_block (
910911 self , block_hash : Optional [str ]
911- ) -> tuple [MetadataV15 , PortableRegistry ]:
912+ ) -> tuple [Optional [ MetadataV15 ], Optional [ PortableRegistry ] ]:
912913 # Should be called for any block that fails decoding.
913914 # Possibly the metadata was different.
914915 try :
@@ -922,7 +923,11 @@ async def _load_registry_at_block(
922923 "Client error: Execution failed: Other: Exported method Metadata_metadata_at_version is not found"
923924 in e .args
924925 ):
925- raise MetadataAtVersionNotFound
926+ logger .warning (
927+ "Exported method Metadata_metadata_at_version is not found. This indicates the block is quite old, "
928+ "decoding for this block will use legacy Python decoding."
929+ )
930+ return None , None
926931 else :
927932 raise e
928933 metadata_option_hex_str = metadata_rpc_result ["result" ]
@@ -964,6 +969,7 @@ async def decode_scale(
964969 return_scale_obj : bool = False ,
965970 block_hash : Optional [str ] = None ,
966971 runtime : Optional [Runtime ] = None ,
972+ force_legacy : bool = False ,
967973 ) -> Union [ScaleObj , Any ]:
968974 """
969975 Helper function to decode arbitrary SCALE-bytes (e.g. 0x02000000) according to given RUST type_string
@@ -979,6 +985,7 @@ async def decode_scale(
979985 block_hash: Hash of the block where the desired runtime is located. Ignored if supplying `runtime`
980986 runtime: Optional Runtime object whose registry to use for decoding. If not specified, runtime will be
981987 loaded based on the block hash specified (or latest block if no block_hash is specified)
988+ force_legacy: Whether to explicitly use legacy Python-only decoding (non bt-decode).
982989
983990 Returns:
984991 Decoded object
@@ -991,10 +998,10 @@ async def decode_scale(
991998 else :
992999 if not runtime :
9931000 runtime = await self .init_runtime (block_hash = block_hash )
994- runtime_registry = runtime .registry
1001+ if runtime .metadata_v15 is not None or force_legacy is True :
1002+ obj = decode_by_type_string (type_string , runtime .registry , scale_bytes )
9951003 else :
996- runtime_registry = runtime .registry
997- obj = decode_by_type_string (type_string , runtime_registry , scale_bytes )
1004+ obj = legacy_scale_decode (type_string , scale_bytes , runtime )
9981005 if return_scale_obj :
9991006 return ScaleObj (obj )
10001007 else :
@@ -1933,7 +1940,12 @@ def convert_event_data(data):
19331940 )
19341941 if storage_obj :
19351942 for item in list (storage_obj ):
1936- events .append (convert_event_data (item ))
1943+ try :
1944+ events .append (convert_event_data (item ))
1945+ except (
1946+ AttributeError
1947+ ): # indicates this was legacy decoded with scalecodec
1948+ events .append (item )
19371949 return events
19381950
19391951 async def get_metadata (self , block_hash = None ) -> MetadataV15 :
@@ -2909,7 +2921,7 @@ async def _do_runtime_call_old(
29092921 result_vec_u8_bytes = hex_to_bytes (result_data ["result" ])
29102922 result_bytes = await self .decode_scale (
29112923 "Vec<u8>" , result_vec_u8_bytes , runtime = runtime
2912- )
2924+ ) # TODO may need to force_legacy after testing.
29132925
29142926 # Decode result
29152927 # Get correct type
@@ -2945,22 +2957,32 @@ async def runtime_call(
29452957 params = {}
29462958
29472959 try :
2948- metadata_v15_value = runtime .metadata_v15 .value ()
2960+ if runtime .metadata_v15 is None :
2961+ _ = self .runtime_config .type_registry ["runtime_api" ][api ]["methods" ][
2962+ method
2963+ ]
2964+ runtime_api_types = self .runtime_config .type_registry ["runtime_api" ][
2965+ api
2966+ ].get ("types" , {})
2967+ runtime .runtime_config .update_type_registry_types (runtime_api_types )
2968+ return await self ._do_runtime_call_old (
2969+ api , method , params , block_hash , runtime = runtime
2970+ )
29492971
2950- apis = {entry ["name" ]: entry for entry in metadata_v15_value ["apis" ]}
2951- api_entry = apis [api ]
2952- methods = {entry ["name" ]: entry for entry in api_entry ["methods" ]}
2953- runtime_call_def = methods [method ]
2972+ else :
2973+ metadata_v15_value = runtime .metadata_v15 .value ()
2974+
2975+ apis = {entry ["name" ]: entry for entry in metadata_v15_value ["apis" ]}
2976+ api_entry = apis [api ]
2977+ methods = {entry ["name" ]: entry for entry in api_entry ["methods" ]}
2978+ runtime_call_def = methods [method ]
2979+ if _determine_if_old_runtime_call (runtime_call_def , metadata_v15_value ):
2980+ return await self ._do_runtime_call_old (
2981+ api , method , params , block_hash , runtime = runtime
2982+ )
29542983 except KeyError :
29552984 raise ValueError (f"Runtime API Call '{ api } .{ method } ' not found in registry" )
29562985
2957- if _determine_if_old_runtime_call (runtime_call_def , metadata_v15_value ):
2958- result = await self ._do_runtime_call_old (
2959- api , method , params , block_hash , runtime = runtime
2960- )
2961-
2962- return result
2963-
29642986 if isinstance (params , list ) and len (params ) != len (runtime_call_def ["inputs" ]):
29652987 raise ValueError (
29662988 f"Number of parameter provided ({ len (params )} ) does not "
0 commit comments