[Ethereum] How to build a raw transaction to interact with a contract, with web3.py

offlinepythonweb3.py

Thanks to the support of this community I am able to create transactions on the network using the guidance provided in this post:
How to send a transaction to myetherapi.com with Web3.py

To send a transaction I need to reference the allowed methods shown at http://www.myetherapi.com/. With that in mind I am able to sign a transaction locally and use the sendRawTransaction method to broadcast it to the network.

My question now is how would I create a transaction that invokes a function within a contract that is already deployed on the network. How would you modify the transaction arguments to invoke a specific contract and call a specific function within that contract.

This is the example of a simple transaction. What is needed to create the raw transaction that calls an existing contract?

transaction = {
        'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55',
        'value': 1000000000,
        'gas': 2000000,
        'gasPrice': 234567897654321,
        'nonce': 0,
        'chainId': 1
    }

I am having trouble because the typically contract API methods in web3.py are not available through MyEtherAPI. Also I am okay with using v4 of web3.py if that is critical.

Best Answer

Check out the new buildTransaction() method in the contract API of version 4 of Web3.py.

After creating a Contract instance, you can build a transaction for a contract function like so:

>>> gas_price = w3.toWei(21, 'gwei')
>>> a_contract.functions.a_method().buildTransaction({'gasPrice': gas_price})
{
    'to': '0x6Bc272FCFcf89C14cebFC57B8f1543F5137F97dE',
    'data': '0x81752d63',
    'value': 0,
    'gas': 43242,
    'gasPrice': 21000000000
}

It's a much bigger question for how to generate that data field manually. At a high level, you have to determine the function selector, and concatenate that with the ABI-encoded arguments.