|
13 | 13 | from scalecodec.type_registry import load_type_registry_preset
|
14 | 14 | from scalecodec.types import GenericCall, ScaleType
|
15 | 15 |
|
| 16 | +from .utils import json |
| 17 | + |
16 | 18 |
|
17 | 19 | logger = logging.getLogger("async_substrate_interface")
|
18 | 20 |
|
@@ -349,6 +351,9 @@ class SubstrateMixin(ABC):
|
349 | 351 | type_registry: Optional[dict]
|
350 | 352 | ss58_format: Optional[int]
|
351 | 353 | ws_max_size = 2**32
|
| 354 | + registry_type_map: dict[str, int] |
| 355 | + type_id_to_name: dict[int, str] |
| 356 | + metadata_v15 = None |
352 | 357 |
|
353 | 358 | @property
|
354 | 359 | def chain(self):
|
@@ -604,6 +609,70 @@ def serialize_module_error(module, error, spec_version) -> dict:
|
604 | 609 | "spec_version": spec_version,
|
605 | 610 | }
|
606 | 611 |
|
| 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 | + |
607 | 676 | def reload_type_registry(
|
608 | 677 | self, use_remote_preset: bool = True, auto_discover: bool = True
|
609 | 678 | ):
|
@@ -726,12 +795,19 @@ def _encode_scale(self, type_string, value: Any) -> bytes:
|
726 | 795 | if value is None:
|
727 | 796 | result = b"\x00"
|
728 | 797 | 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 | + |
729 | 805 | if type_string == "scale_info::0": # Is an AccountId
|
730 | 806 | # encode string into AccountId
|
731 | 807 | ## AccountId is a composite type with one, unnamed field
|
732 | 808 | return bytes.fromhex(ss58_decode(value, SS58_FORMAT))
|
733 | 809 |
|
734 |
| - elif type_string == "scale_info::152": # Vec<AccountId> |
| 810 | + elif type_string == vec_acct_id: # Vec<AccountId> |
735 | 811 | if not isinstance(value, (list, tuple)):
|
736 | 812 | value = [value]
|
737 | 813 |
|
|
0 commit comments