Transfer tokens between accounts using web3.py

DavideDavide
3 min read

This tutorial teaches you the basics in web3.py to send tokens between accounts. In this case, tokens native to a blockchain, such as ETH, AVAX, FTM, etc.

Find the repository on GitHub.

Requirements

To make this code work you will need to have installed:

You can install web3.py with:

pip install web3

Note that on Windows, you will need to install the Microsoft C++ Build Tools to make it work.

  • Access to a node endpoint, I recommend to use Chainstack:

Follow these steps to sign up on Chainstack, deploy a node, and find your endpoint credentials:

  1. Sign up with Chainstack.
  2. Deploy a node.
  3. View node access and credentials.

How to send a transaction

Once you have access to your Chainstack endpoint credentials, you can use it to connect to the node using web3.py.

This code was tested on the Fantom testnet, but it will be compatible with all the EMV based networks.

The first step is to create a new Python file, I named it transfers.py.

The first section of the code is to connect to a blockchain.

from web3 import Web3

node_url = "FANTOM_TESTNET_ENDPOINT"  # endpoint URL
web3 = Web3(Web3.HTTPProvider(node_url))  # establish connection to a node

Paste your node endpoint URL in the node_url variable.

This creates a connection to your node so that you can send and retrieve data.

Then initialize the addresses that you want to use to make the transfer. Don't forget to include the private key from the address used to send the tokens; it is recommended to use an environment variable instead of hardcoding it like in this example!

sender = "SENDER_ADDRESS"
receiver = "RECEIVER_ADDRESS"
private_key = "YOUR_PRIVATE_KEY"

Create a nonce variable to retrieve the sender address transactions count; this is essential to ensure that the transaction cannot be replayed by someone with malicious intent.

# nonce
nonce = web3.eth.getTransactionCount(sender)

We can now estimate the gas limit using the eth_estimateGas method, which simulates a transfer between accounts.

# retrieve the gas limit for this simulated transaction.
gas_limit = web3.eth.estimate_gas(({"from":sender,"to":"receiver}), "latest")
#print("The gas limit is:", gas_limit)

Then we build the transaction object, where we specify the amount of FTM you want to transfer to the other account. (1 FTM in this example)

tx = {
    "nonce": nonce,
    "to": receiver,
    "value": web3.toWei(1, "ether"),  # measure unit of 1 full token
    "gas": gas_limit,                 # 21000 is good for a simple transfer
    "gasPrice": web3.toWei(10, "gwei"),
    "chainId": web3.eth.chain_id,
}

The last step is to sign and send the transaction.

# sign tx
signed_tx = web3.eth.account.signTransaction(tx, private_key)

# send transaction
tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
print("Transaction hash:", web3.toHex(tx_hash))

This will also print the transaction hash so you can see it on the block explorer😉

Now you only need to run the script and see the magic happens!

python transfers.py

The full script

Here is the full script, you can find the same on the GitHub repo.

from web3 import Web3

node_url = "ENDPOINT_URL" #endpoint URL
web3 = Web3(Web3.HTTPProvider(node_url))  # establish connection to a node

# verify the connection is successful (will return true)
if web3.isConnected():
    print("Connection Successful")
else:
    print("Connection Failed")

# initialize the addresses and private key
sender = "SENDER_ADDRESS"
receiver = "RECEIVER_ADDRESS"
private_key = "YOUR_PRIVATE_KEY"

# nonce
nonce = web3.eth.getTransactionCount(sender)

# retrieve the gas limit for this simulated transaction.
gas_limit = web3.eth.estimate_gas(({"from":sender,"to":receiver}), "latest")
#print("The gas limit is:", gas_limit)

# build the transaction
tx = {
    "nonce": nonce,
    "to": receiver,
    "value": web3.toWei(1, "ether"),  # measure unit of 1 full token
    "gas": gas_limit,
    "gasPrice": web3.toWei(10, "gwei"),
    "chainId": web3.eth.chain_id,
}

# sign tx
signed_tx = web3.eth.account.signTransaction(tx, private_key)

# send transaction
tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
print("Transaction hash:", web3.toHex(tx_hash))
0
Subscribe to my newsletter

Read articles from Davide directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Davide
Davide

Hey there! I'm Davide, a passionate developer advocate at Chainstack, the leading suite of blockchain infrastructure services. I'm dedicated to empowering current and aspiring web3 developers by sharing valuable content and resources. Within my articles, you'll discover a treasure trove of straightforward projects designed to bolster your understanding of fundamental Python, Solidity, JavaScript, and web3 skills. Whether you're a seasoned developer or just starting out, these projects offer an ideal learning path for honing your abilities in the exciting world of blockchain development. Feel free to explore my articles, and let's embark on this remarkable journey of mastering web3 together!