How to get the balances of ERC-20 tokens of a wallet using web3

In this guide, we will see how to get the balance of ERC-20 tokens of a wallet from your dApp using web3. We will also see how you can use the same code to get BEP-20 tokens on the BSC or any other tokens deployed in other blockchains.

In this guide, we will see how to get the balance of ERC-20 tokens of a wallet from your dApp using web3. We will also see how you can use the same code to get BEP-20 tokens on the Binance Smart chain or any other tokens deployed in other blockchains.

If you haven't already, you need to install the web3 dependency in your project using the following command:

npm install web3

Then, to interact with a blockchain (Ethereum or BSC or any other) you need to create an instance of Web3 and give it a provider.

If you want to use the user's browser wallet you can simply do:

const web3 = new Web3(window.ethereum);

to get your instance created.

Then you need to connect to the user's wallet using any method you want. You can check out our guides if you want to learn how to connect to a wallet.

Once it's done, to get the balance of the main currency in the selected network (for example, if the selected network is Ethereum you would get the balance of Ethereum),

you can use the following method:

const balance = await web3.eth.getBalance(account)
const balanceInEth = web3.utils.fromWei(balance, "ether")

The getBalance method will fetch the balance for the address you passed in the parameters.

If you use a web3 instance connected to the Ethereum blockchain, you will get the amount of Ethereum that is in this address and if you use an instance connected to the BSC, then you will get the amount of BNB in the address.

If you want to get the balance of other coins, it's a bit more complex because you have no way to get all balances for all tokens at once. You have to get them separately.

The first step is to get the contract address of the token you want to check the balance for. In our example, we are to check the balance for USDT so the address for this token is 0xdac17f958d2ee523a2206206994597c13d831ec7

The next step is to create an ABI for the contract. Basically it is like an interface that will tell what properties and methods are supported by the contract. In the ABI, you can specify all the methods and properties of a contract or only the ones you need.

You can have the list of all the methods and properties of a contract by looking at its definition on https://etherscan.io/. All you have to do is search the token you want and then go to the contract section

In our case, we only need to use the balanceOf method so we only put that in the ABI. The minimal ABI we need looks like this:

const ABI = [
  {
    constant: true,
    inputs: [
      {
        name: "_owner",
        type: "address",
      },
    ],
    name: "balanceOf",
    outputs: [
      {
        name: "balance",
        type: "uint256",
      },
    ],
    payable: false,
    type: "function",
  },
];

And you can use the same ABI for the BSC.

Then, to get the balance for a specific token, we use the following code:

const address = '0xdac17f958d2ee523a2206206994597c13d831ec7'
const contract = new web3.eth.Contract(ABI, address)
const balance = await contract.methods.balanceOf(account).call()
const balanceInEth = web3.utils.fromWei(balance, "ether")

In the code above, we create an instance of a contract using its address and the ABI. Depending on the ABI we provided, we will have access to specific methods and properties.

In our case, we have the balanceOf method in our ABI so we can use this function by accessing it through the methods property of our contract instance.

After that we can convert the balance we get to ether so that the unit of the balance matches the token, i.e. 1 in the balance equals 1 token.

Unfortunately, if you want to get all balances of all the tokens in a wallet, you have to repeat the code above for every token you want to check the balance for.

Usually, to solve this problem, I use a list of the most popular tokens (like the top 200) and I put all the addresses and token names in a file.

Instead of checking all the balances one by one what I do is that I use maps and Promise.all

const tokenAddresses = [
  {
    address: '0xdac17f958d2ee523a2206206994597c13d831ec7',
    token: 'USDT'
  },
  {
    address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
    token: 'USDC'
  },
  {
    address: '0x514910771af9ca656af840dff83e8264ecf986ca',
    token: 'LINK'
  }
]

const contracts = tokenAddresses.map((token) => (new web3.eth.Contract(ABI, token.address)))

Promise.all(contracts.map((contract) => (contract.methods.balanceOf(account).call())))
.then((responses) => {
  res.send({
    const balances = responses.map((balance, i) => ({
      balance: ethWeb3.utils.fromWei(balance, "ether"), token: tokenAddresses[i].token 
    })
  })
})

If you want a list of the top contracts by market cap, check out this Github repository https://github.com/ethereum-lists/tokens

and this folder in the Github repository for the tokens in the Ethereum network: https://github.com/ethereum-lists/tokens/tree/master/tokens/eth

Thanks for following this tutorial!