1
- from typing import Union , TYPE_CHECKING
1
+ from typing import Union , TYPE_CHECKING , Any
2
2
3
3
from bt_decode import AxonInfo , PrometheusInfo , decode_list
4
- from scalecodec import ScaleBytes
4
+ from scalecodec import ScaleBytes , ss58_encode
5
5
6
6
from async_substrate_interface .utils import hex_to_bytes
7
7
from async_substrate_interface .types import ScaleObj
@@ -120,24 +120,35 @@ def concat_hash_len(key_hasher: str) -> int:
120
120
)
121
121
middl_index = len (all_decoded ) // 2
122
122
decoded_keys = all_decoded [:middl_index ]
123
- decoded_values = [ScaleObj (x ) for x in all_decoded [middl_index :]]
124
- for dk , dv in zip (decoded_keys , decoded_values ):
123
+ decoded_values = all_decoded [middl_index :]
124
+ for (kts , vts ), (dk , dv ) in zip (
125
+ zip (pre_decoded_key_types , pre_decoded_value_types ),
126
+ zip (decoded_keys , decoded_values ),
127
+ ):
125
128
try :
126
129
# strip key_hashers to use as item key
127
130
if len (param_types ) - len (params ) == 1 :
128
131
item_key = dk [1 ]
132
+ if kts [kts .index (", " ) + 2 : kts .index (")" )] == "scale_info::0" :
133
+ item_key = ss58_encode (bytes (item_key [0 ]), runtime .ss58_format )
134
+
129
135
else :
130
136
item_key = tuple (
131
137
dk [key + 1 ] for key in range (len (params ), len (param_types ) + 1 , 2 )
132
138
)
139
+ # TODO handle decoding here, but first figure out what triggers this
133
140
134
141
except Exception as _ :
135
142
if not ignore_decoding_errors :
136
143
raise
137
144
item_key = None
138
-
139
- item_value = dv
140
- result .append ([item_key , item_value ])
145
+ try :
146
+ value_type_str_int = int (vts .split ("::" )[1 ])
147
+ decoded_type_str = runtime .type_id_to_name [value_type_str_int ]
148
+ item_value = convert_account_ids (dv , decoded_type_str , runtime .ss58_format )
149
+ except (ValueError , KeyError ) as e :
150
+ item_value = dv
151
+ result .append ([item_key , ScaleObj (item_value )])
141
152
return result
142
153
143
154
@@ -154,3 +165,68 @@ def legacy_scale_decode(
154
165
obj .decode (check_remaining = runtime .config .get ("strict_scale_decode" ))
155
166
156
167
return obj .value
168
+
169
+
170
+ def is_accountid32 (value : Any ) -> bool :
171
+ return (
172
+ isinstance (value , tuple )
173
+ and len (value ) == 32
174
+ and all (isinstance (b , int ) and 0 <= b <= 255 for b in value )
175
+ )
176
+
177
+
178
+ def convert_account_ids (value : Any , type_str : str , ss58_format = 42 ) -> Any :
179
+ if "AccountId32" not in type_str :
180
+ return value
181
+
182
+ # Option<T>
183
+ if type_str .startswith ("Option<" ) and value is not None :
184
+ inner_type = type_str [7 :- 1 ]
185
+ return convert_account_ids (value , inner_type )
186
+ # Vec<T>
187
+ if type_str .startswith ("Vec<" ) and isinstance (value , (list , tuple )):
188
+ inner_type = type_str [4 :- 1 ]
189
+ return tuple (convert_account_ids (v , inner_type ) for v in value )
190
+
191
+ # Vec<Vec<T>>
192
+ if type_str .startswith ("Vec<Vec<" ) and isinstance (value , (list , tuple )):
193
+ inner_type = type_str [8 :- 2 ]
194
+ return tuple (
195
+ tuple (convert_account_ids (v2 , inner_type ) for v2 in v1 ) for v1 in value
196
+ )
197
+
198
+ # Tuple
199
+ if type_str .startswith ("(" ) and isinstance (value , (list , tuple )):
200
+ inner_parts = split_tuple_type (type_str )
201
+ return tuple (convert_account_ids (v , t ) for v , t in zip (value , inner_parts ))
202
+
203
+ # AccountId32
204
+ if type_str == "AccountId32" and is_accountid32 (value [0 ]):
205
+ return ss58_encode (bytes (value [0 ]), ss58_format = ss58_format )
206
+
207
+ # Fallback
208
+ return value
209
+
210
+
211
+ def split_tuple_type (type_str : str ) -> list [str ]:
212
+ """
213
+ Splits a type string like '(AccountId32, Vec<StakeInfo>)' into ['AccountId32', 'Vec<StakeInfo>']
214
+ Handles nested generics.
215
+ """
216
+ s = type_str [1 :- 1 ]
217
+ parts = []
218
+ depth = 0
219
+ current = ""
220
+ for char in s :
221
+ if char == "," and depth == 0 :
222
+ parts .append (current .strip ())
223
+ current = ""
224
+ else :
225
+ if char == "<" :
226
+ depth += 1
227
+ elif char == ">" :
228
+ depth -= 1
229
+ current += char
230
+ if current :
231
+ parts .append (current .strip ())
232
+ return parts
0 commit comments