24
24
import asyncstdlib as a
25
25
from bittensor_wallet .keypair import Keypair
26
26
from bittensor_wallet .utils import SS58_FORMAT
27
- from bt_decode import (
28
- MetadataV15 ,
29
- PortableRegistry ,
30
- decode as decode_by_type_string ,
31
- encode as encode_by_type_string ,
32
- )
27
+ from bt_decode import MetadataV15 , PortableRegistry , decode as decode_by_type_string
33
28
from scalecodec .base import ScaleBytes , ScaleType , RuntimeConfigurationObject
34
29
from scalecodec .types import (
35
30
GenericCall ,
@@ -805,14 +800,58 @@ async def load_registry(self):
805
800
)
806
801
self .registry = PortableRegistry .from_metadata_v15 (self .metadata_v15 )
807
802
803
+ async def _wait_for_registry (self , _attempt : int = 1 , _retries : int = 3 ) -> None :
804
+ async def _waiter ():
805
+ while self .registry is None :
806
+ await asyncio .sleep (0.1 )
807
+ return
808
+
809
+ try :
810
+ if not self .registry :
811
+ await asyncio .wait_for (_waiter (), timeout = 10 )
812
+ except TimeoutError :
813
+ # indicates that registry was never loaded
814
+ if not self ._initializing :
815
+ raise AttributeError (
816
+ "Registry was never loaded. This did not occur during initialization, which usually indicates "
817
+ "you must first initialize the AsyncSubstrateInterface object, either with "
818
+ "`await AsyncSubstrateInterface.initialize()` or running with `async with`"
819
+ )
820
+ elif _attempt < _retries :
821
+ await self .load_registry ()
822
+ return await self ._wait_for_registry (_attempt + 1 , _retries )
823
+ else :
824
+ raise AttributeError (
825
+ "Registry was never loaded. This occurred during initialization, which usually indicates a "
826
+ "connection or node error."
827
+ )
828
+
829
+ async def encode_scale (
830
+ self , type_string , value : Any , _attempt : int = 1 , _retries : int = 3
831
+ ) -> bytes :
832
+ """
833
+ Helper function to encode arbitrary data into SCALE-bytes for given RUST type_string
834
+
835
+ Args:
836
+ type_string: the type string of the SCALE object for decoding
837
+ value: value to encode
838
+ _attempt: the current number of attempts to load the registry needed to encode the value
839
+ _retries: the maximum number of attempts to load the registry needed to encode the value
840
+
841
+ Returns:
842
+ encoded bytes
843
+ """
844
+ await self ._wait_for_registry (_attempt , _retries )
845
+ return self ._encode_scale (type_string , value )
846
+
808
847
async def decode_scale (
809
848
self ,
810
849
type_string : str ,
811
850
scale_bytes : bytes ,
812
851
_attempt = 1 ,
813
852
_retries = 3 ,
814
853
return_scale_obj = False ,
815
- ) -> Any :
854
+ ) -> Union [ ScaleObj , Any ] :
816
855
"""
817
856
Helper function to decode arbitrary SCALE-bytes (e.g. 0x02000000) according to given RUST type_string
818
857
(e.g. BlockNumber). The relevant versioning information of the type (if defined) will be applied if block_hash
@@ -828,95 +867,19 @@ async def decode_scale(
828
867
Returns:
829
868
Decoded object
830
869
"""
831
-
832
- async def _wait_for_registry ():
833
- while self .registry is None :
834
- await asyncio .sleep (0.1 )
835
- return
836
-
837
870
if scale_bytes == b"\x00 " :
838
871
obj = None
839
872
if type_string == "scale_info::0" : # Is an AccountId
840
873
# Decode AccountId bytes to SS58 address
841
874
return bytes .fromhex (ss58_decode (scale_bytes , SS58_FORMAT ))
842
875
else :
843
- try :
844
- if not self .registry :
845
- await asyncio .wait_for (_wait_for_registry (), timeout = 10 )
846
- obj = decode_by_type_string (type_string , self .registry , scale_bytes )
847
- except TimeoutError :
848
- # indicates that registry was never loaded
849
- if not self ._initializing :
850
- raise AttributeError (
851
- "Registry was never loaded. This did not occur during initialization, which usually indicates "
852
- "you must first initialize the AsyncSubstrateInterface object, either with "
853
- "`await AsyncSubstrateInterface.initialize()` or running with `async with`"
854
- )
855
- elif _attempt < _retries :
856
- await self .load_registry ()
857
- return await self .decode_scale (
858
- type_string , scale_bytes , _attempt + 1
859
- )
860
- else :
861
- raise AttributeError (
862
- "Registry was never loaded. This occurred during initialization, which usually indicates a "
863
- "connection or node error."
864
- )
876
+ await self ._wait_for_registry (_attempt , _retries )
877
+ obj = decode_by_type_string (type_string , self .registry , scale_bytes )
865
878
if return_scale_obj :
866
879
return ScaleObj (obj )
867
880
else :
868
881
return obj
869
882
870
- async def encode_scale (self , type_string , value : Any ) -> bytes :
871
- """
872
- Helper function to encode arbitrary data into SCALE-bytes for given RUST type_string
873
-
874
- Args:
875
- type_string: the type string of the SCALE object for decoding
876
- value: value to encode
877
-
878
- Returns:
879
- encoded SCALE bytes
880
- """
881
- if value is None :
882
- result = b"\x00 "
883
- else :
884
- if type_string == "scale_info::0" : # Is an AccountId
885
- # encode string into AccountId
886
- ## AccountId is a composite type with one, unnamed field
887
- return bytes .fromhex (ss58_decode (value , SS58_FORMAT ))
888
-
889
- elif type_string == "scale_info::151" : # Vec<AccountId>
890
- if not isinstance (value , (list , tuple )):
891
- value = [value ]
892
-
893
- # Encode length
894
- length = len (value )
895
- if length < 64 :
896
- result = bytes ([length << 2 ]) # Single byte mode
897
- else :
898
- raise ValueError ("Vector length too large" )
899
-
900
- # Encode each AccountId
901
- for account in value :
902
- if isinstance (account , bytes ):
903
- result += account # Already encoded
904
- else :
905
- result += bytes .fromhex (
906
- ss58_decode (value , SS58_FORMAT )
907
- ) # SS58 string
908
- return result
909
-
910
- if isinstance (value , ScaleType ):
911
- if value .data .data is not None :
912
- # Already encoded
913
- return bytes (value .data .data )
914
- else :
915
- value = value .value # Unwrap the value of the type
916
-
917
- result = bytes (encode_by_type_string (type_string , self .registry , value ))
918
- return result
919
-
920
883
async def _first_initialize_runtime (self ):
921
884
"""
922
885
TODO docstring
0 commit comments