Closed BulatSaif closed 2 years ago
1.
ValueError: Element "grandpa" of struct is missing in given value
What I noticed here is there is a duplicate nested key 'keys', the following call worked for me:
call = substrate_client.compose_call(
call_module='Session',
call_function='set_keys',
call_params={
'keys': {
'grandpa':'0x7e4230880436450bc1cc3d65039d83a6a728bd5f7d0364499afaab7a16e79c3d',
'babe':'0x50105b266cd9e427a634d332c26b7d37df8844570a2b5e867d54fa0b1da7771e',
'im_online':'0x723fd195e5a8b60f3f637f5a65840e09dd3e1a2ec1bd2495278783e673b68c29',
'para_validator':'0x323710e92ac2b8068445b6a3bf75fee366e12370a7e365b492dd719b7057954c',
'para_assignment':'0xa8123ed90963ba5f698a3ac230d70d50393dfc9a29d6d07175ed382aaf60fc54',
'authority_discovery':'0x9041e95e6705e800db99caaf787acaadfa7879f9fb979ce44a778e50cb79eb47',
'beefy':'0x035e4cb4dcda61d44cd6107e966e680723f7d5ac6cf8762cff7a35da21a32eb94e'
},
'proof': 'None'
}
)
2.
Storage calls are automatically decoded using the function query()
, other RPC calls have to be decoded manually. What you can do is:
rotate_keys = substrate_client.rpc_request(method="author_rotateKeys", params=[])['result']
rotate_keys_decoded = substrate_client.decode_scale("polkadot_runtime::SessionKeys", rotate_keys)
Caveat here is the path of the SessionKeys
type include the name of the runtime, so for Kusama for example it would polkadot_runtime::SessionKeys
.
Thank you for fast replay!
Is there a way to get the type dynamically? I am testing in rococo and "polkadot_runtime::SessionKeys" did not work.
NotImplementedError: Decoder class for "polkadot_runtime::SessionKeys" not found
Is there a way to get the type dynamically? I am testing in rococo and "polkadot_runtime::SessionKeys" did not work.
Yes unfortunately the runtime name is in the path of some types, for Rococo the type string would be rococo_runtime::SessionKeys
.
Maybe I can figure out if in some cases I can make this more generic, or make types available for their last part SessionKeys
(if unique) as well.
@arjanz, Thank you for helping!
In case someone needs my workaround:
rotate_keys = substrate_client.rpc_request(method="author_rotateKeys", params=[])['result']
# Get type name (rococo_runtime::SessionKeys) from runtime by id
type_id = substrate_client.get_metadata_call_function('Session', 'set_keys')['fields'][0]['type']
print(type_id) # 199
metadata = substrate_client.get_runtime_metadata()['result'][1]
runtime_version = list(metadata.keys())[0]
types = metadata[runtime_version]['types']['types']
type_dict = next(item for item in types if item["id"] == type_id)
print(type_dict) # {'id': 199, 'type': {'path': ['rococo_runtime', 'SessionKeys'], 'params': [], 'def': {'composite': {'fields': [{'name': 'grandpa', 'type': 34,...
type_string = "::".join(type_dict['type']['path'])
# decode rotate_keys
print(substrate_client.decode_scale(type_string, rotate_keys))
# {'grandpa': '0x760cc41f74fd549e8bba788c7202a14eb61e8087b4405e2e1bbd5a68c6fa417a', 'babe': '0x12fc0...
I believe mapping between RPC metod and value type returned should exist somewhere, because in some cases RPC meted returns JSON (example: chain_getHeader
), in another it returns hex (Example: author_rotateKeys
). But I was not able to find such information.
Wanted to add that if you know the type_id
, you can also easily reconstruct the type_string with scale_info::<type_id>
, in this case scale_info::199
Wanted to add that if you know the type_id, you can also easily reconstruct the type_string with scale_info::
, in this case scale_info::199
That's what I was looking for, Thank you!
Hi, I am migrating a scripts from
polkadot-js-api
topython library
I have command:It also works in polkadot.js.org:
But same steps in python does not work: Error:
Script:
As I understand library tries to encode already encoded parameter , so if I replace hex string with map of keys all works.
Questions