Skip to content

Commit 286afb1

Browse files
authored
Merge pull request #80 from opentensor/feat/handle-option-types
Support Option types
2 parents 117b757 + b5c8efa commit 286afb1

File tree

1 file changed

+55
-7
lines changed

1 file changed

+55
-7
lines changed

Diff for: async_substrate_interface/types.py

+55-7
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,11 @@ def _load_registry_type_map(self, registry):
631631
type_id = type_entry["id"]
632632
type_def = type_type["def"]
633633
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
634639
if type_entry.get("params") or type_def.get("variant"):
635640
continue # has generics or is Enum
636641
if type_path:
@@ -686,6 +691,23 @@ def _load_registry_type_map(self, registry):
686691
self.registry_type_map = registry_type_map
687692
self.type_id_to_name = type_id_to_name
688693

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+
689711
def reload_type_registry(
690712
self, use_remote_preset: bool = True, auto_discover: bool = True
691713
):
@@ -815,10 +837,28 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
815837
except KeyError:
816838
vec_acct_id = "scale_info::152"
817839

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+
818845
if type_string == "scale_info::0": # Is an AccountId
819846
# encode string into AccountId
820847
## 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
822862

823863
elif type_string == vec_acct_id: # Vec<AccountId>
824864
if not isinstance(value, (list, tuple)):
@@ -833,12 +873,7 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
833873

834874
# Encode each AccountId
835875
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)
842877
return result
843878

844879
if isinstance(value, ScaleType):
@@ -852,3 +887,16 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
852887
encode_by_type_string(type_string, self.runtime.registry, value)
853888
)
854889
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

Comments
 (0)