Skip to content

Commit 94e40c4

Browse files
authored
Merge pull request #82 from opentensor/release/1.0.8
Release/1.0.8
2 parents 7cb06e5 + 77f9ec6 commit 94e40c4

File tree

3 files changed

+65
-9
lines changed

3 files changed

+65
-9
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 1.0.8 /2025-03-17
4+
5+
## What's Changed
6+
* Allows installing on Python 3.13 by @thewhaleking in https://github.com/opentensor/async-substrate-interface/pull/79
7+
* Support Option types by @ibraheem-opentensor in https://github.com/opentensor/async-substrate-interface/pull/80
8+
9+
**Full Changelog**: https://github.com/opentensor/async-substrate-interface/compare/v1.0.7...v1.0.8
10+
311
## 1.0.7 /2025-03-12
412

513
## What's Changed

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

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "async-substrate-interface"
3-
version = "1.0.7"
3+
version = "1.0.8"
44
description = "Asyncio library for interacting with substrate. Mostly API-compatible with py-substrate-interface"
55
readme = "README.md"
66
license = { file = "LICENSE" }
@@ -16,7 +16,7 @@ dependencies = [
1616
"xxhash"
1717
]
1818

19-
requires-python = ">=3.9,<3.13"
19+
requires-python = ">=3.9,<3.14"
2020

2121
authors = [
2222
{ name = "Opentensor Foundation" },

0 commit comments

Comments
 (0)