Getting started with web3.py: reading token balances

Awbr...Rufb
30 Apr 2022
155

Let's learn how to use web3.py to programmatically interact with the blockchain. This post assumes you are familiar with using a terminal as well as python basics and will cover how to read the token balances of a wallet address.

Firstly, make sure you have python installed from the official python site, if you don't already have it installed.

Then install the following packages (in a virtual environment were applicable):

$ pip install web3.py


Let's also make a new folder for our project.

Let's work with the Ethereum blockchain for now. Since this tutorial is about finding how to read token balances, we must first learn about what a "token" is. Tokens follow the ERC-20 standard and as such all follow the same specification.

For now let's download the ABI for ERC-20 tokens and save it in our project folder as "erc20.json". An ABI or "application binary interface" is an interface that allows interaction with the bytecode of a smart contract in a readable manner. Let's see what functions a ERC-20 contract has:

import json

with open("erc20.json", "r") as fp:
  erc20_abi = json.loads(fp.read())

print([function["name"] for function in erc20_abi if "name" in function])


Spot anything interesting? We have a function called "balanceOf". Now let's try reading the balance of USDT (Tether USD) in the burn address "0x000000000000000000000000000000000000dEaD". To do this, we need to first connect to an RPC for ethereum; RPC, or Remote Procedure Call is an API that programs can communicate with - nodes that are securing the blockchain can choose to expose an RPC that will respond to queries about the state of the blockchain. You can use CoinTool to find the lowest latency RPC for you. Note that some RPCs do not like traffic from scripts :(

from web3 import Web3
import json

# Create a Web3 instance connected to our RPC
w3 = Web3(Web3.HTTPProvider("https://rpc.ankr.com/eth"))

with open("erc20.json", "r") as fp:
  erc20_abi = json.loads(fp.read())

print([function["name"] for function in erc20_abi if "name" in function])

# Contract address for USDT on Ethereum
# https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7
TETHER_USD_CA = "0xdAC17F958D2ee523a2206206994597C13D831ec7"
BURN_ADDRESS = "0x000000000000000000000000000000000000dEaD"

USDT_CONTRACT = w3.eth.contract(TETHER_USD_CA, abi=erc20_abi)
print(dir(USDT_CONTRACT.functions))
print(USDT_CONTRACT.functions.balanceOf(BURN_ADDRESS).call())


As of the time of writing, this script returns a balance of 5413885584 for USDT. However, on Etherscan, USDT balance is reported as 5413.885584. Why is this? Well it is because all balances are represented in whole numbers due to limitations with Solidity and the EVM (Ethereum Virtual Machine), with decimals only shown for cosmetic purposes - you can read more about it here. And guess what, we also have a "decimals()" function in our ERC-20 ABI.

USDT_CONTRACT = w3.eth.contract(TETHER_USD_CA, abi=erc20_abi)
print(dir(USDT_CONTRACT.functions))
balance = USDT_CONTRACT.functions.balanceOf(BURN_ADDRESS).call()
decimals = USDT_CONTRACT.functions.decimals().call()
print(balance)
print(decimals)
print(balance / 10 ** decimals)


And voila, we have a balance of 5413.885584 which matches Etherscan. There you have it - you have now successfully read the token balance for a single address using python. Please note that this only works for ERC-20 tokens and not the gas token ETH (but will work for WETH). To get the ETH balance, you can use this instead:

print(w3.fromWei(w3.eth.get_balance(BURN_ADDRESS), 'ether'))


Useful Links

  • https://web3py.readthedocs.io/en/stable/index.html
  • https://ethereum.stackexchange.com/
  • https://etherscan.io/


What Next?

Can you adapt this code to read the balance of an address that constantly transfers tokens in and out? Try monitoring the balances of a Uniswap LP pool - could you maybe calculate the price of ethereum just by monitoring the WETH-USDC pool?

Can you adapt this code to read balances from BSC (Binance Smart Chain) instead of Ethereum? BSCScan may be useful.

Please let me know if this post was helpful - feel free to ask any questions if you are unsure of anything.

Get fast shipping, movies & more with Amazon Prime

Start free trial

Enjoy this blog? Subscribe to 12Ghast

4 Comments