23
23
SubstrateRequestException ,
24
24
BlockNotFound ,
25
25
MaxRetriesExceeded ,
26
- MetadataAtVersionNotFound ,
27
26
StateDiscardedError ,
28
27
)
29
28
from async_substrate_interface .protocols import Keypair
45
44
_determine_if_old_runtime_call ,
46
45
_bt_decode_to_dict_or_list ,
47
46
decode_query_map ,
47
+ legacy_scale_decode ,
48
48
)
49
49
from async_substrate_interface .utils .storage import StorageKey
50
50
from async_substrate_interface .type_registry import _TYPE_REGISTRY
@@ -576,17 +576,6 @@ def metadata(self):
576
576
else :
577
577
return self .runtime .metadata
578
578
579
- @property
580
- def implements_scaleinfo (self ) -> Optional [bool ]:
581
- """
582
- Returns True if current runtime implements a `PortableRegistry` (`MetadataV14` and higher). Returns `None` if
583
- no currently loaded runtime.
584
- """
585
- if self .runtime and self .runtime .metadata :
586
- return self .runtime .metadata .portable_registry is not None
587
- else :
588
- return None
589
-
590
579
@property
591
580
def properties (self ):
592
581
if self ._properties is None :
@@ -669,7 +658,7 @@ def _load_registry_at_block(self, block_hash: Optional[str]) -> MetadataV15:
669
658
"Client error: Execution failed: Other: Exported method Metadata_metadata_at_version is not found"
670
659
in e .args
671
660
):
672
- raise MetadataAtVersionNotFound
661
+ return None , None
673
662
else :
674
663
raise e
675
664
metadata_option_hex_str = metadata_rpc_result ["result" ]
@@ -701,7 +690,12 @@ def decode_scale(
701
690
# Decode AccountId bytes to SS58 address
702
691
return ss58_encode (scale_bytes , SS58_FORMAT )
703
692
else :
704
- obj = decode_by_type_string (type_string , self .runtime .registry , scale_bytes )
693
+ if self .runtime .metadata_v15 is not None :
694
+ obj = decode_by_type_string (
695
+ type_string , self .runtime .registry , scale_bytes
696
+ )
697
+ else :
698
+ obj = legacy_scale_decode (type_string , scale_bytes , self .runtime )
705
699
if return_scale_obj :
706
700
return ScaleObj (obj )
707
701
else :
@@ -714,7 +708,7 @@ def load_runtime(self, runtime):
714
708
self .runtime .reload_type_registry (use_remote_preset = False , auto_discover = True )
715
709
716
710
self .runtime_config .set_active_spec_version_id (runtime .runtime_version )
717
- if self .implements_scaleinfo :
711
+ if self .runtime . implements_scaleinfo :
718
712
logger .debug ("Add PortableRegistry from metadata to type registry" )
719
713
self .runtime_config .add_portable_registry (runtime .metadata )
720
714
# Set runtime compatibility flags
@@ -754,7 +748,8 @@ def init_runtime(
754
748
if runtime := self .runtime_cache .retrieve (block = block_id ):
755
749
self .runtime = runtime
756
750
self .runtime .load_runtime ()
757
- self .runtime .load_registry_type_map ()
751
+ if self .runtime .registry :
752
+ self .runtime .load_registry_type_map ()
758
753
return self .runtime
759
754
block_hash = self .get_block_hash (block_id )
760
755
@@ -765,7 +760,8 @@ def init_runtime(
765
760
if runtime := self .runtime_cache .retrieve (block_hash = block_hash ):
766
761
self .runtime = runtime
767
762
self .runtime .load_runtime ()
768
- self .runtime .load_registry_type_map ()
763
+ if self .runtime .registry :
764
+ self .runtime .load_registry_type_map ()
769
765
return self .runtime
770
766
771
767
runtime_version = self .get_block_runtime_version_for (block_hash )
@@ -780,12 +776,14 @@ def init_runtime(
780
776
if runtime := self .runtime_cache .retrieve (runtime_version = runtime_version ):
781
777
self .runtime = runtime
782
778
self .runtime .load_runtime ()
783
- self .runtime .load_registry_type_map ()
779
+ if self .runtime .registry :
780
+ self .runtime .load_registry_type_map ()
784
781
return runtime
785
782
else :
786
783
self .runtime = self .get_runtime_for_version (runtime_version , block_hash )
787
784
self .runtime .load_runtime ()
788
- self .runtime .load_registry_type_map ()
785
+ if self .runtime .registry :
786
+ self .runtime .load_registry_type_map ()
789
787
return self .runtime
790
788
791
789
def get_runtime_for_version (
@@ -819,9 +817,15 @@ def get_runtime_for_version(
819
817
metadata_v15 , registry = self ._load_registry_at_block (
820
818
block_hash = runtime_block_hash
821
819
)
822
- logger .debug (
823
- f"Retrieved metadata v15 for { runtime_version } from Substrate node"
824
- )
820
+ if metadata_v15 is not None :
821
+ logger .debug (
822
+ f"Retrieved metadata and metadata v15 for { runtime_version } from Substrate node"
823
+ )
824
+ else :
825
+ logger .debug (
826
+ f"Exported method Metadata_metadata_at_version is not found for { runtime_version } . This indicates the "
827
+ f"block is quite old, decoding for this block will use legacy Python decoding."
828
+ )
825
829
826
830
runtime = Runtime (
827
831
chain = self .chain ,
@@ -1204,7 +1208,7 @@ def decode_block(block_data, block_data_hash=None) -> dict[str, Any]:
1204
1208
block_data ["header" ]["digest" ]["logs" ][idx ] = log_digest
1205
1209
1206
1210
if include_author and "PreRuntime" in log_digest .value :
1207
- if self .implements_scaleinfo :
1211
+ if self .runtime . implements_scaleinfo :
1208
1212
engine = bytes (log_digest [1 ][0 ])
1209
1213
# Retrieve validator set
1210
1214
parent_hash = block_data ["header" ]["parentHash" ]
@@ -1609,7 +1613,12 @@ def convert_event_data(data):
1609
1613
)
1610
1614
if storage_obj :
1611
1615
for item in list (storage_obj ):
1612
- events .append (convert_event_data (item ))
1616
+ try :
1617
+ events .append (convert_event_data (item ))
1618
+ except (
1619
+ AttributeError
1620
+ ): # indicates this was legacy decoded with scalecodec
1621
+ events .append (item )
1613
1622
return events
1614
1623
1615
1624
def get_metadata (self , block_hash = None ) -> MetadataV15 :
@@ -2530,20 +2539,28 @@ def runtime_call(
2530
2539
params = {}
2531
2540
2532
2541
try :
2533
- metadata_v15_value = runtime .metadata_v15 .value ()
2542
+ if runtime .metadata_v15 is None :
2543
+ _ = self .runtime_config .type_registry ["runtime_api" ][api ]["methods" ][
2544
+ method
2545
+ ]
2546
+ runtime_api_types = self .runtime_config .type_registry ["runtime_api" ][
2547
+ api
2548
+ ].get ("types" , {})
2549
+ runtime .runtime_config .update_type_registry_types (runtime_api_types )
2550
+ return self ._do_runtime_call_old (api , method , params , block_hash )
2551
+ else :
2552
+ metadata_v15_value = runtime .metadata_v15 .value ()
2553
+
2554
+ apis = {entry ["name" ]: entry for entry in metadata_v15_value ["apis" ]}
2555
+ api_entry = apis [api ]
2556
+ methods = {entry ["name" ]: entry for entry in api_entry ["methods" ]}
2557
+ runtime_call_def = methods [method ]
2558
+ if _determine_if_old_runtime_call (runtime_call_def , metadata_v15_value ):
2559
+ return self ._do_runtime_call_old (api , method , params , block_hash )
2534
2560
2535
- apis = {entry ["name" ]: entry for entry in metadata_v15_value ["apis" ]}
2536
- api_entry = apis [api ]
2537
- methods = {entry ["name" ]: entry for entry in api_entry ["methods" ]}
2538
- runtime_call_def = methods [method ]
2539
2561
except KeyError :
2540
2562
raise ValueError (f"Runtime API Call '{ api } .{ method } ' not found in registry" )
2541
2563
2542
- if _determine_if_old_runtime_call (runtime_call_def , metadata_v15_value ):
2543
- result = self ._do_runtime_call_old (api , method , params , block_hash )
2544
-
2545
- return result
2546
-
2547
2564
if isinstance (params , list ) and len (params ) != len (runtime_call_def ["inputs" ]):
2548
2565
raise ValueError (
2549
2566
f"Number of parameter provided ({ len (params )} ) does not "
@@ -2745,7 +2762,7 @@ def get_type_registry(self, block_hash: str = None, max_recursion: int = 4) -> d
2745
2762
"""
2746
2763
self .init_runtime (block_hash = block_hash )
2747
2764
2748
- if not self .implements_scaleinfo :
2765
+ if not self .runtime . implements_scaleinfo :
2749
2766
raise NotImplementedError ("MetadataV14 or higher runtimes is required" )
2750
2767
2751
2768
type_registry = {}
0 commit comments