Estimate gas fees with Web3.py

Estimate gas fees with Web3.py

Learn the basics of blockchain development

·

7 min read

This tutorial shows how you can estimate gas fees on an EVM blockchain, using a Chainstack node. You can use it to simply retrieve information to create an app like eth gas station, or to calculate how much the gas fee should be when sending a transaction using a bot written using web3.py.

It includes a bonus at the end!

You can also check my Skillshare class where I show the fundamentals about web3.py. WEB3.py: Interact with the Blockchain Get 30 days for free using this link! skl.sh/3McEymV

The estimate gas fees repository holds two files:

  • estimate_gas.py --> Retrieve and display information: Gas limit, base gas fee, priority gas fee(standard 2 Gwei, modifiable by the user), calculate how much ETH will be used in gas.

  • transaction_gas.py --> Uses a function to estimate how many Gwei are needed for sending ETH to another address, and shows it as built transaction as an example.

Note that much of the code is just to make it look better once printed on the console. Like converting the Wei values into Gwei and Ether.

Requirements

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

Install web3.py in your environment:

pip install web3

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

What is Web3.py?

Web3.py is a Python library for interacting with the Ethereum network (Or other networks based on the EVM).

It’s commonly found in decentralized apps (dapps) to help with sending transactions, interacting with smart contracts, reading block data, and a variety of other use cases.

The original API was derived from the Web3.js Javascript API but has since evolved toward the needs and creature comforts of Python developers. (source: Web3.py docs.)

This tutorial is based on the Ethereum network.

Explain the code

Python is a great way to start interacting with the blockchain. The following code is very easy to understand!

Connect to the blockchain

The first step is to connect to our node, and we use the following code.

Note that the connection check is not required, but I like to include it since it is user-friendly.

from web3 import Web3

node_url = "CHAINSTACK NODE URL"

web3 = Web3(Web3.HTTPProvider(node_url))

# verify if the connection is successful
if web3.isConnected():
    print("Connection Succsessful")
else:
    print("Connection Failed")

This allows us to use our node endpoint to connect to an EVM network.

Make requests to the blockchain

With this code, we retrieve the number of the latest block; it's nice to see that our node is up to date.

# retrieve the latest block
last = web3.eth.block_number
print('Latest block:', last)

Estimate the gas limit

The gas limit indicates how many units of gas we spend for the transaction. The eth_estimateGas method simulates a transaction between two addresses and, with the parameters that we need, gives us back an estimate.

For a regular transfer between two accounts, it is 21000.

# retrieve the gas limit for this simulated transaction.
gas_limit = web3.eth.estimate_gas(({"from":"0x43e4715ae093a4C86B5eCdDb52216c4f879e9672","to":"0xA090e606E30bD747d4E6245a1517EbE430F0057e"}), "latest")
print('Gas limit:', gas_limit)

Retrieve network fee and set up miner fee

On the Ethereum network, we have two type of fees:

  • Network fee, based on network usage (which is burnt).
  • Miner fee, selected by the user as an incentive to miners.

This part of the code uses eth_gasPrice to retrieve the network fee, then we set up the miner fee as a variable and generate a total fee.

# retrieve the base fee in wei, then displays it in Gwe
base_fee = web3.eth.gas_price
print('Base fee: ' + str(web3.fromWei(base_fee, 'gwei')) + ' Gwei')

# set up the miner tip in wei
priority_fee = 2000000000       # 2 Gwei in wei
print('Priority fee: ' + str(web3.fromWei(priority_fee, 'gwei')) + ' Gwei')

# generate a total fee 
total_fee = base_fee + priority_fee
fee_gwei = web3.fromWei(total_fee, 'gwei')
print('Reasonable fee: ' + str(fee_gwei) + ' Gwei')

Calculate ETH used as gas

The last step will be to calculate how much ETH is going to be used as gas fee.

# calculate how much ETH will be used as gas for this transaction
gas_fee = total_fee * gas_limit
print('Ether paid as gas fee: ' + str(web3.fromWei(gas_fee, 'ether')) + ' ETH')

The full script

from web3 import Web3

node_url = "CHAINSTACK NODE URL"

web3 = Web3(Web3.HTTPProvider(node_url))

# verify if the connection is successful
if web3.isConnected():
    print("Connection Succsessful")
else:
    print("Connection Failed")

# retrieve the latest block
last = web3.eth.block_number
print('Latest block:', last)

# retrieve the gas limit for this simulated transaction. "value" is the latest block encoded in hex
gas_limit = web3.eth.estimate_gas(({"from":"0x43e4715ae093a4C86B5eCdDb52216c4f879e9672","to":"0xA090e606E30bD747d4E6245a1517EbE430F0057e"}), "latest")
print('Gas limit:', gas_limit)

# retrieve the base fee in wei, then displays it in Gwe
base_fee = web3.eth.gas_price
print('Base fee: ' + str(web3.fromWei(base_fee, 'gwei')) + ' Gwei')

# set up the miner tip in wei
priority_fee = 2000000000       # 2 Gwei in wei
print('Priority fee: ' + str(web3.fromWei(priority_fee, 'gwei')) + ' Gwei')

# generate a total fee 
total_fee = base_fee + priority_fee
fee_gwei = web3.fromWei(total_fee, 'gwei')
print('Reasonable fee: ' + str(fee_gwei) + ' Gwei')

print('-' * 30)

# calculate how much ETH will be used as gas for this transaction
gas_fee = total_fee * gas_limit
print('Ether paid as gas fee: ' + str(web3.fromWei(gas_fee, 'ether')) + ' ETH')

The result when you run the program will look like this.

Connection Successful
Latest block: 14934388
Gas limit: 21000
Base fee: 72.960051418 Gwei
Priority fee: 2 Gwei
Reasonable fee: 74.960051418 Gwei
------------------------------
Ether paid as gas fee: 0.001574161079778 ETH

How do I use this program to estimate gas fees?

  1. Have access to an HTTPS endpoint that allows creating the connection to the EVM. For the connection, it is recommended to use the service provided by chainstack.com, where you can create your personal node on the cloud. You can register and create one node for free. This is the recommended option as not all the HTTPS endpoints that can be found online support the methods that can be used through Web3.py.

  2. Sign up with Chainstack.

  3. Deploy a node.
  4. View node access and credentials.

162478127-94cd2344-72f1-4136-a220-8b2c8e52d194

Insert the URL you get from your Chainstack node in the 'node_url' variable.

# Node endpoint
node_url = "CHAINSTACK_NODE_URL"

# Create the node connection
web3 = Web3(Web3.HTTPProvider(node_url))

# Verify if the connection is successful
if web3.isConnected():
    print("Connection Successful")
    print('-' * 50)
else:
    print("Connection Failed")

Customize the priority fee if you want. On Ethereum, 2 Gwei is generally the minimum required for your transaction to be picked by the miners. This is referred as 'miner tip' as well, you can increase it to incentivize them to pick up and process your transaction faster.

# set up the miner tip in wei
priority_fee = 2000000000       # 2 Gwei in wei
print('Priority fee: ' + str(web3.fromWei(priority_fee, 'gwei')) + ' Gwei')

Now, you can run the program and you will receive a result like this in the console:

Connection Successful
Latest block: 14934388
Gas limit: 21000
Base fee: 72.960051418 Gwei
Priority fee: 2 Gwei
Reasonable fee: 74.960051418 Gwei
------------------------------
Ether paid as gas fee: 0.001574161079778 ETH

Bonus

The following script is a bonus, showing how you can use the gas estimation script to send a transaction.

from web3 import Web3

node_url = "CHAINSTACK NODE URL"

web3 = Web3(Web3.HTTPProvider(node_url))

# verify if the connection is successful 
if web3.isConnected():
    print("Connection Succsessful")
else:
    print("Connection Failed")

# function to estimate how many gwei to use for gas.     
def estimate_gas():
    base_fee = web3.eth.gas_price
    priority_fee = 2000000000 # 2 Gwei in wei
    total_fee = base_fee + priority_fee   

    return total_fee  # this is returned in wei

# retrieve the latest block number  
last = web3.eth.block_number
print('Latest block:', last)

# simulate a transaction and retrieve gas limit
gas_limit = web3.eth.estimate_gas(({"from":"0x43e4715ae093a4C86B5eCdDb52216c4f879e9672","to":"0xA090e606E30bD747d4E6245a1517EbE430F0057e"}), "latest")
print('Gas limit:', gas_limit)

# use the function to retrieve how many gwei to use for gas
total_fee = estimate_gas()

# convert Wei to Gwei
fee_gwei = web3.fromWei(total_fee, 'gwei')
print('Reasonable fee: ' + str(fee_gwei) + ' Gwei')

print('-' * 30)

# calculate and display how much ETH is used as gas 
gas_fee = estimate_gas() * gas_limit
print('Ether paid as gas fee:' + str(web3.fromWei(gas_fee, 'ether')) + ' ETH')

# this is not the most secure way to keep these, but it works for the example
# fill up with your data
sender = 'SENDER ADDRESS'
receiver = 'RECEIVER ADDRESS'
privateKey = 'PRIVATE KEY'      # used to sign the transaction

#nonce, retrieve how many transactions the sender address has made
nonce = web3.eth.getTransactionCount(sender)

# build the transaction
tx = {
    'nonce' : nonce,
    'to': receiver,
    'value': web3.toWei(0.01, 'ether'),   # value to send
    'gas': gas_limit,
    'gasPrice' : estimate_gas()           # use the function to estimate the gas fee live
}

# sign tx using the private key 
signed_tx = web3.eth.account.signTransaction(tx, privateKey)

# send transaction, and print the tx hash
tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
print('Transaction hash:', web3.toHex(tx_hash))

Conclusion

Now you are ready to programmatically estimate gas requirements for a transaction, including knowing beforehand how much you will spend!

Congrats on learning something new today and advancing your web3 journey 🚀

Did you find this article valuable?

Support Davide by becoming a sponsor. Any amount is appreciated!