Send ERC20 token with web3.py using a local private key
Asked Answered
T

1

10

I am trying to send ERC20 tokens in python with web3.py using a local private key.

With this code I can send ether:

w3 = Web3(HTTPProvider('https://api.myetherapi.com/eth'))
signed_txn = w3.eth.account.signTransaction(dict(
                nonce=w3.eth.getTransactionCount(from_address),
                gasPrice=w3.eth.gasPrice,
                gas=100000,
                to=to_address,
                value=12345,
                data=b'',
            ),
                private_key,
            )
w3.eth.sendRawTransaction(signed_txn.rawTransaction)

Then I found this too, but always get an error for the estimateGas and it seems to me that I can't specify the address where I am sending from like this or prove that its my address by some kind of signing?

contract = w3.eth.contract(address=address, abi=EIP20_ABI, bytecode=bytecode)
contract.functions.transfer(to_address, 121212).transact()

So I have the JSON abi, the bytecode, the addresses and my private key, can I somehow build a working script out of the code I found?

Tay answered 8/6, 2018 at 16:15 Comment(1)
C
12

always get an error for the estimateGas

You will get errors, sometimes, if your transaction would fail. That can happen if you are sending "from" the wrong address while estimating gas. Try specifying the from address in estimateGas() like so:

acct = w3.eth.account.privateKeyToAccount(private_key)
contract.functions.transfer(to_address, 121212).estimateGas({'from': acct.address})

can I somehow build a working script out of the code I found?

One problem with the second approach is that transact() will try to use your node to sign the transaction. Since you have a local private key, you'll want to use buildTransaction() to then sign locally.

See this Web3.py guide, which is generally about locally signing contract transactions, but happens to use an ERC20 example.

Outline

  1. Initialize your Contract object
  2. Build the transaction
  3. Sign the transaction, with w3.eth.account.signTransaction()
  4. Broadcast the transaction with sendRawTransaction()

Example

>>> from ethtoken.abi import EIP20_ABI
>>> from web3.auto import w3

>>> unicorns = w3.eth.contract(address="0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", abi=EIP20_ABI)

>>> nonce = w3.eth.getTransactionCount('0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E')  

# Build a transaction that invokes this contract's function, called transfer
>>> unicorn_txn = unicorns.functions.transfer(
...     '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
...     1,
... ).buildTransaction({
...     'chainId': 1,
...     'gas': 70000,
...     'gasPrice': w3.toWei('1', 'gwei'),
...     'nonce': nonce,
... })

>>> unicorn_txn
{'value': 0,
 'chainId': 1,
 'gas': 70000,
 'gasPrice': 1000000000,
 'nonce': 0,
 'to': '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
 'data': '0xa9059cbb000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d3590000000000000000000000000000000000000000000000000000000000000001'}

>>> private_key = b"\xb2\\}\xb3\x1f\xee\xd9\x12''\xbf\t9\xdcv\x9a\x96VK-\xe4\xc4rm\x03[6\xec\xf1\xe5\xb3d"
>>> signed_txn = w3.eth.account.signTransaction(unicorn_txn, private_key=private_key)
>>> signed_txn.hash
HexBytes('0x4795adc6a719fa64fa21822630c0218c04996e2689ded114b6553cef1ae36618')
>>> signed_txn.rawTransaction
HexBytes('0xf8a980843b9aca008301117094fb6916095ca1df60bb79ce92ce3ea74c37c5d35980b844a9059cbb000000000000000000000000fb6916095ca1df60bb79ce92ce3ea74c37c5d359000000000000000000000000000000000000000000000000000000000000000125a00fb532eea06b8f17d858d82ad61986efd0647124406be65d359e96cac3e004f0a02e5d7ffcfb7a6073a723be38e6733f353cf9367743ae94e2ccd6f1eba37116f4')
>>> signed_txn.r
7104843568152743554992057394334744036860247658813231830421570918634460546288
>>> signed_txn.s
20971591154030974221209741174186570949918731455961098911091818811306894497524
>>> signed_txn.v
37

>>> w3.eth.sendRawTransaction(signed_txn.rawTransaction)  

# When you run sendRawTransaction, you get the same result as the hash of the transaction:
>>> w3.toHex(w3.sha3(signed_txn.rawTransaction))
'0x4795adc6a719fa64fa21822630c0218c04996e2689ded114b6553cef1ae36618'
Christianna answered 12/6, 2018 at 23:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.