@@ -631,6 +631,11 @@ def _load_registry_type_map(self, registry):
631
631
type_id = type_entry ["id" ]
632
632
type_def = type_type ["def" ]
633
633
type_path = type_type .get ("path" )
634
+ if type_path and type_path [- 1 ] == "Option" :
635
+ self ._handle_option_type (
636
+ type_entry , type_id , registry_type_map , type_id_to_name
637
+ )
638
+ continue
634
639
if type_entry .get ("params" ) or type_def .get ("variant" ):
635
640
continue # has generics or is Enum
636
641
if type_path :
@@ -686,6 +691,23 @@ def _load_registry_type_map(self, registry):
686
691
self .registry_type_map = registry_type_map
687
692
self .type_id_to_name = type_id_to_name
688
693
694
+ def _handle_option_type (
695
+ self , type_entry , type_id , registry_type_map , type_id_to_name
696
+ ):
697
+ params = type_entry ["type" ].get ("params" , [])
698
+ if params :
699
+ inner_names = []
700
+ for param in params :
701
+ inner_id = param ["type" ]
702
+ inner_name = type_id_to_name .get (inner_id , f"Type{ inner_id } " )
703
+ inner_names .append (inner_name )
704
+ type_name = f"Option<{ ', ' .join (inner_names )} >"
705
+ else :
706
+ type_name = "Option"
707
+
708
+ registry_type_map [type_name ] = type_id
709
+ type_id_to_name [type_id ] = type_name
710
+
689
711
def reload_type_registry (
690
712
self , use_remote_preset : bool = True , auto_discover : bool = True
691
713
):
@@ -815,10 +837,28 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
815
837
except KeyError :
816
838
vec_acct_id = "scale_info::152"
817
839
840
+ try :
841
+ optional_acct_u16 = f"scale_info::{ self .registry_type_map ['Option<(AccountId32, u16)>' ]} "
842
+ except KeyError :
843
+ optional_acct_u16 = "scale_info::573"
844
+
818
845
if type_string == "scale_info::0" : # Is an AccountId
819
846
# encode string into AccountId
820
847
## AccountId is a composite type with one, unnamed field
821
- return bytes .fromhex (ss58_decode (value , SS58_FORMAT ))
848
+ return self ._encode_account_id (value )
849
+
850
+ elif type_string == optional_acct_u16 :
851
+ if value is None :
852
+ return b"\x00 " # None
853
+
854
+ if not isinstance (value , (list , tuple )) or len (value ) != 2 :
855
+ raise ValueError ("Expected tuple of (account_id, u16)" )
856
+ account_id , u16_value = value
857
+
858
+ result = b"\x01 "
859
+ result += self ._encode_account_id (account_id )
860
+ result += u16_value .to_bytes (2 , "little" )
861
+ return result
822
862
823
863
elif type_string == vec_acct_id : # Vec<AccountId>
824
864
if not isinstance (value , (list , tuple )):
@@ -833,12 +873,7 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
833
873
834
874
# Encode each AccountId
835
875
for account in value :
836
- if isinstance (account , bytes ):
837
- result += account # Already encoded
838
- else :
839
- result += bytes .fromhex (
840
- ss58_decode (account , SS58_FORMAT )
841
- ) # SS58 string
876
+ result += self ._encode_account_id (account )
842
877
return result
843
878
844
879
if isinstance (value , ScaleType ):
@@ -852,3 +887,16 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
852
887
encode_by_type_string (type_string , self .runtime .registry , value )
853
888
)
854
889
return result
890
+
891
+ def _encode_account_id (self , account ) -> bytes :
892
+ """Encode an account ID into bytes.
893
+
894
+ Args:
895
+ account: Either bytes (already encoded) or SS58 string
896
+
897
+ Returns:
898
+ bytes: The encoded account ID
899
+ """
900
+ if isinstance (account , bytes ):
901
+ return account # Already encoded
902
+ return bytes .fromhex (ss58_decode (account , SS58_FORMAT )) # SS58 string
0 commit comments