Skip to content

Commit 87176b9

Browse files
authored
Merge pull request #47 from opentensor/feat/thewhaleking/dynamically-pull-vec-account-id
Dynamically pulls the info for Vec<AccountId> from the metadata
2 parents 40be8bd + 29e5efc commit 87176b9

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

async_substrate_interface/async_substrate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,8 @@ def __init__(
713713
self.metadata_version_hex = "0x0f000000" # v15
714714
self.reload_type_registry()
715715
self._initializing = False
716+
self.registry_type_map = {}
717+
self.type_id_to_name = {}
716718

717719
async def __aenter__(self):
718720
await self.initialize()
@@ -807,6 +809,7 @@ async def load_registry(self):
807809
metadata_option_bytes
808810
)
809811
self.registry = PortableRegistry.from_metadata_v15(self.metadata_v15)
812+
self._load_registry_type_map()
810813

811814
async def _load_registry_at_block(self, block_hash: str) -> MetadataV15:
812815
# Should be called for any block that fails decoding.

async_substrate_interface/sync_substrate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ def __init__(
518518
self.metadata_version_hex = "0x0f000000" # v15
519519
self.reload_type_registry()
520520
self.ws = self.connect(init=True)
521+
self.registry_type_map = {}
522+
self.type_id_to_name = {}
521523
if not _mock:
522524
self.initialize()
523525

@@ -615,6 +617,7 @@ def load_registry(self):
615617
metadata_option_bytes
616618
)
617619
self.registry = PortableRegistry.from_metadata_v15(self.metadata_v15)
620+
self._load_registry_type_map()
618621

619622
def _load_registry_at_block(self, block_hash: str) -> MetadataV15:
620623
# Should be called for any block that fails decoding.

async_substrate_interface/types.py

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from scalecodec.type_registry import load_type_registry_preset
1414
from scalecodec.types import GenericCall, ScaleType
1515

16+
from .utils import json
17+
1618

1719
logger = logging.getLogger("async_substrate_interface")
1820

@@ -349,6 +351,9 @@ class SubstrateMixin(ABC):
349351
type_registry: Optional[dict]
350352
ss58_format: Optional[int]
351353
ws_max_size = 2**32
354+
registry_type_map: dict[str, int]
355+
type_id_to_name: dict[int, str]
356+
metadata_v15 = None
352357

353358
@property
354359
def chain(self):
@@ -604,6 +609,70 @@ def serialize_module_error(module, error, spec_version) -> dict:
604609
"spec_version": spec_version,
605610
}
606611

612+
def _load_registry_type_map(self):
613+
registry_type_map = {}
614+
type_id_to_name = {}
615+
types = json.loads(self.registry.registry)["types"]
616+
for type_entry in types:
617+
type_type = type_entry["type"]
618+
type_id = type_entry["id"]
619+
type_def = type_type["def"]
620+
type_path = type_type.get("path")
621+
if type_entry.get("params") or type_def.get("variant"):
622+
continue # has generics or is Enum
623+
if type_path:
624+
type_name = type_path[-1]
625+
registry_type_map[type_name] = type_id
626+
type_id_to_name[type_id] = type_name
627+
else:
628+
# probably primitive
629+
if type_def.get("primitive"):
630+
type_name = type_def["primitive"]
631+
registry_type_map[type_name] = type_id
632+
type_id_to_name[type_id] = type_name
633+
for type_entry in types:
634+
type_type = type_entry["type"]
635+
type_id = type_entry["id"]
636+
type_def = type_type["def"]
637+
if type_def.get("sequence"):
638+
sequence_type_id = type_def["sequence"]["type"]
639+
inner_type = type_id_to_name.get(sequence_type_id)
640+
if inner_type:
641+
type_name = f"Vec<{inner_type}>"
642+
type_id_to_name[type_id] = type_name
643+
registry_type_map[type_name] = type_id
644+
elif type_def.get("array"):
645+
array_type_id = type_def["array"]["type"]
646+
inner_type = type_id_to_name.get(array_type_id)
647+
maybe_len = type_def["array"].get("len")
648+
if inner_type:
649+
if maybe_len:
650+
type_name = f"[{inner_type}; {maybe_len}]"
651+
else:
652+
type_name = f"[{inner_type}]"
653+
type_id_to_name[type_id] = type_name
654+
registry_type_map[type_name] = type_id
655+
elif type_def.get("compact"):
656+
compact_type_id = type_def["compact"]["type"]
657+
inner_type = type_id_to_name.get(compact_type_id)
658+
if inner_type:
659+
type_name = f"Compact<{inner_type}>"
660+
type_id_to_name[type_id] = type_name
661+
registry_type_map[type_name] = type_id
662+
elif type_def.get("tuple"):
663+
tuple_type_ids = type_def["tuple"]
664+
type_names = []
665+
for inner_type_id in tuple_type_ids:
666+
inner_type = type_id_to_name.get(inner_type_id)
667+
if inner_type:
668+
type_names.append(inner_type)
669+
type_name = ", ".join(type_names)
670+
type_name = f"({type_name})"
671+
type_id_to_name[type_id] = type_name
672+
registry_type_map[type_name] = type_id
673+
self.registry_type_map = registry_type_map
674+
self.type_id_to_name = type_id_to_name
675+
607676
def reload_type_registry(
608677
self, use_remote_preset: bool = True, auto_discover: bool = True
609678
):
@@ -726,12 +795,19 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
726795
if value is None:
727796
result = b"\x00"
728797
else:
798+
try:
799+
vec_acct_id = (
800+
f"scale_info::{self.registry_type_map['Vec<AccountId32>']}"
801+
)
802+
except KeyError:
803+
vec_acct_id = "scale_info::152"
804+
729805
if type_string == "scale_info::0": # Is an AccountId
730806
# encode string into AccountId
731807
## AccountId is a composite type with one, unnamed field
732808
return bytes.fromhex(ss58_decode(value, SS58_FORMAT))
733809

734-
elif type_string == "scale_info::152": # Vec<AccountId>
810+
elif type_string == vec_acct_id: # Vec<AccountId>
735811
if not isinstance(value, (list, tuple)):
736812
value = [value]
737813

0 commit comments

Comments
 (0)