py-substrate-interface
py-substrate-interface copied to clipboard
Error composing call using latest substrate
When using using substrate on branch polkadot-0.9.42 we got the following error trying to compose a call:
File "/home/dylan/Projects/tfchain/substrate-node/tests/TfChainClient.py", line 178, in create_farm
call = substrate.compose_call("TfgridModule", "create_farm",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dylan/.local/lib/python3.11/site-packages/substrateinterface/base.py", line 1380, in compose_call
call.encode({
File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/base.py", line 925, in encode
self.data = self.process_encode(self.value_serialized)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/types.py", line 1687, in process_encode
data += arg_obj.encode(param_value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/base.py", line 925, in encode
self.data = self.process_encode(self.value_serialized)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/types.py", line 663, in process_encode
raise ValueError('Element count of value ({}) doesn\'t match type_definition ({})'.format(
ValueError: Element count of value (0) doesn't match type_definition (1)
I'm not sure which runtime you are connecting to, but it seems the parameter structure changed/is incorrect for that call.
What you can do is to check the composition of the params for that call: https://polkascan.github.io/py-substrate-interface/usage/extrinsics/#type-decomposition-of-call-params
More information how to interpret that info: https://polkascan.github.io/py-substrate-metadata-docs/
If your runtime is already listed there you can directly lookup the call param composition info.
Seems like on latest polkadot if a call has like a vector of something (some objects) as input, the input needs to be wrapped with another [ ] when using this library. See: https://github.com/threefoldtech/tfchain/blob/5605bca61c79742317d21f48c4689370392b9c2d/substrate-node/tests/TfChainClient.py#L250
That is indeed strange. I can examine the structure in the PortableRegistry to see why, if it would be possible for you to share a public endpoint or the hex-data of state_getMetadata RPC call here?
I ran some tests on the product endpoint I found on the tfchain Github, I could compose the call above as followed:
Retrieve the type composition with:
call_function = substrate.get_metadata_call_function("TfgridModule", "create_node")
params = call_function.get_param_info()
# {'farm_id': 'u32', 'resources': {'hru': 'u64', 'sru': 'u64', 'cru': 'u64', 'mru': 'u64'}, 'location': {'city': 'Bytes', 'country': 'Bytes', 'latitude': 'Bytes', 'longitude': 'Bytes'}, 'interfaces': [{'name': 'Bytes', 'mac': 'Bytes', 'ips': ['Bytes']}], 'secure_boot': 'bool', 'virtualized': 'bool', 'serial_number': (None, 'Bytes')}
Then entered some dummy data:
call = substrate.compose_call("TfgridModule", "create_node", {
'farm_id': 1,
'resources': {'hru': 1, 'sru': 1, 'cru': 1, 'mru': 1},
'location': {'city': 'Test', 'country': 'Test', 'latitude': 'Test', 'longitude': 'Test'},
'interfaces': [{'name': 'Test', 'mac': 'Test', 'ips': ['Test', 'Test2']}, {'name': 'Test2', 'mac': 'Test2', 'ips': ['Test', 'Test2']}],
'secure_boot': True, 'virtualized': True, 'serial_number': None
})
# 0x0b0801000000010000000000000001000000000000000100000000000000010000000000000010546573741054657374105465737410546573740810546573741054657374081054657374145465737432145465737432145465737432081054657374145465737432010100
Seems my interface param is a bit more complex than the nested list you provided, or are you on a different network?