polkascan / py-substrate-interface

Python Substrate Interface
https://polkascan.github.io/py-substrate-interface/
Apache License 2.0
241 stars 115 forks source link

Cannot create signed extrinsic on acala network #324

Closed DanielMS93 closed 1 year ago

DanielMS93 commented 1 year ago

I am trying to sign a swap_with_exact_supply transaction on the acala network. I am using code that used to work with no problem on substrate-interface v1.0.5 but now seems to be struggling.

The issue seems to arise during the processing of the generated payload where it expects the nonce to be a Dict whilst of course it is an int.

This is my call

{'call_module': 'Dex', 'call_function': 'swap_with_exact_supply', 'call_params': [{'name': 'path', 'value': [{'Token': 'AUSD'}, {'Token': 'ACA'}]}, {'name': 'supply_amount', 'value': 685233204169165}, {'name': 'min_target_amount', 'value': 2132526743724632}]}

And i get type int is not iterable.

image

Is this an issue you are aware of? any ideas as to what might be causing it?

DanielMS93 commented 1 year ago

further info from some investigations:

image image
DanielMS93 commented 1 year ago

I think the signed extensions are wrong...

image
DanielMS93 commented 1 year ago

ok i think the type for the nonce enum is incorrect? it is currently set to be scale_info::601 whilst i think it should be the same as tip? i.e. scale_info::604?

arjanz commented 1 year ago

Confirmed, I debugged as well and there are currently actually several issues:

arjanz commented 1 year ago

ok i think the type for the nonce enum is incorrect? it is currently set to be scale_info::601 whilst i think it should be the same as tip? i.e. scale_info::604?

The type is correct, because this is retrieved from the embedded metadata (substrate.metadata[1][1]['extrinsic']['signed_extensions'].value), but the issue is that the py-substrate-interface library assumes its an Compact when it passes an int in the encode() method. This needs to be changed to modify the input (or maybe better, to make py-scalecodec tolerate a non-dict input for a Struct when it only has 1 element. (e.g. 6 turns automatically into {'nonce': 6}

arjanz commented 1 year ago

I'm running out of time today, but I will address this asap, as it blocks usage for networks like Acala.

arjanz commented 1 year ago

What you could try as a temporary workaround is:

keypair = Keypair.create_from_uri("//Alice")
nonce = substrate.get_account_nonce(keypair.ss58_address)
extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair, nonce={'nonce': nonce})

This seems to work

DanielMS93 commented 1 year ago

thanks so much for getting back. oh interesting! i will give it a try and let you know

arjanz commented 1 year ago

This seems to work

Too soon.. I forgot I already locally changed https://github.com/polkascan/py-substrate-interface/blob/b96c6124cf3a2ba52413fc4218e78ad5ec9e77d6/substrateinterface/base.py#L1959

to if type(signature_cls.type_mapping) is list:

which is a dirty workaround, but if it's urgent you can get it working now by changing that.

DanielMS93 commented 1 year ago

ok nice, i have an extrinsic!! do let me know when this is more properly fixed :) but all good for now

DanielMS93 commented 1 year ago

no pressure at all of course but helpful for planning, when do u think you'll be able to make a release with these fixes?

arjanz commented 1 year ago

Most likely there will be a release later today, I'm working on a fix right now

arjanz commented 1 year ago

Fix released: https://github.com/polkascan/py-substrate-interface/releases/tag/v1.5.2