How to get the Ethereum and ERC-20 tokens balance of an address using Wagmi

In this tutorial, we are going to learn how to get the Ethereum balance and the ERC-20 tokens balance of an address in your React application using Wagmi or Ethers JS.

In this tutorial, we are going to learn how to get the Ethereum balance and the ERC-20 tokens balance of an address in your React application using Wagmi.

To do that, we use the useBalance hook and in the parameters we pass the address we want to get the balance of.

If you want to get the balance of an ERC-20 token, you have to pass its address in the parameters as well. If you don't pass a token address, you'll get the Ethereum balance.

If you're not on the Ethereum network, your code will give you the balance of the native token of the blockchain you're on. For example, it will give you the BNB balance on the Binance Smart Chain, the FTM balance on Fantom, the MATIC balance on Polygon and so on...

If you pass a token address, you'll get the balance of that token on the blockchain your app is on.

Here is how to use that hook:

import { useState, useEffect } from 'react';
import { useBalance, useAccount } from 'wagmi';
import { utils } from 'ethers';

export const Home = () => {
  // get the address of the connected wallet
  const { address } = useAccount();

  // get the Ethereum balance of the connected address
  const { data: ethBalanceData, isError: ethBalanceError } = useBalance({
    addressOrName: address,
  });

  // get the UNI balance of the connected address
  const { data: uniBalanceData, isError: uniBalanceError } = useBalance({
    addressOrName: address,
    token: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
  });

  // if there is no wallet connected, ask to connect a wallet
  if (!address) return <p>Please connect a wallet</p>;

  // if there is an error, display it
  if (ethBalanceError || uniBalanceError) return <p>Error while fetching balance</p>;

  if (!ethBalanceData || !uniBalanceData) return <p>Loading balance...</p>;

  return (
    <>
      <p>
        You have {ethBalanceData.formatted} {ethBalanceData.symbol}
      </p>
      <p>
        You have {uniBalanceData.formatted} {uniBalanceData.symbol}
      </p>
    </>
  );
};

In the example above, we get the Ethereum balance and the balance of the Uniswap token of the connected wallet and display it.

The useBalance hook takes in parameter an object that has the following properties (among others):

  • addresOrName: the address or the ENS name of the wallet you want to get the balance of
  • token: the address of the smart contract of the token you want to get the balance of. If you don't pass anything, it will return the Ethereum balance
    (or the native token of the blockchain you're on if you're not on Ethereum)
  • formatUnits: the units in which the balance is returned. It will be in Wei by default. Check out the documentation to see the units you can pass.
  • watch: if true, the balance will be refreshed every new block and update the data returned. It is false by default.

The rest of the properties you can pass can be found here:

useBalance – Nextra
React Hook for fetching balance information for Ethereum or ERC-20 tokens.

In the example above, I pass in the address of the connected wallet which I get from the useAccount hook. In the token property, I pass nothing to get the Ethereum balance and the Uniswap token address to get the Uniswap token balance.

That hook will return an object containing the following properties:

  • data: an object containing data about the balance. null if there was an error while fetching the balance, if it's loading or before fetching the balance. The data object has this format:
      •   decimals: the decimals of precision that the token balance has
      •   formatted: a string containing the balance in Ether (instead of Wei)
      •   symbol: the symbol of the token
      •   value: the balance in wei (a BigNumber)
  • error: an error object if the fetching the balance failed and null otherwise
  • isLoading: true while fetching the balance and false otherwise
  • isError: true if there was an error fetching the balance and false otherwise
  • isSuccess: true if the balance was
  • refetch: a function you can call to refetch the balance

Check out the documentation to see all the values that the hook returns.

The problem with this hook is that you can't get the balance of multiple tokens at once. You can use as many useBalance hooks as you want but it's not very clean and scalable and it generates a log of repeated code.

Instead, we can use the useContractReads hook which allows us to read data from multiple smart contracts (or call multiple read functions from the same smart contract).

In the parameters of that hook, we pass a contracts property which is an array of objects with (at least) the following properties:

  • address: the address of the smart contract to interact with
  • abi: an ABI for the smart contract containing at least the function you want to call
  • functionName: the name of the function to call
  • args: an array containing the arguments to pass to the function you're calling

So in our case, the function we want to call is balanceOf and the ABI should contain this function.

For the ABI, we can just use the ABI that Wagmi exports for ERC-20 tokens:

import { erc20ABI } from 'wagmi'

Here is an example in which I get the balance of 3 tokens of an address:

import { useContractReads } from 'wagmi'
import { erc20ABI } from 'wagmi'
import { utils } from 'ethers'

const addressToCheck = '0x5b8f1310A956ee1521A7bB56160451C786289aa9'

// We are going to re-use that for all the tokens we want to get the balance of
// because we call the same function for all of them, with the same arguments and the same ABI
const callBalanceOfConfig = {
  abi: erc20ABI,
  functionName: 'balanceOf',
  // We need to pass the address to get the balance of in the parameters
  args: [addressToCheck]
}

function GetMultipleBalances() {
  const { data, error, isLoading } = useContractReads({
    contracts: [
      {
        // The LINK token
        address: '0x514910771AF9Ca656af840dff83E8264EcF986CA',
        ...callBalanceOfConfig
      },
      {
        // The UNI token
        address: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
        ...callBalanceOfConfig
      },
      {
        // The AAVE token
        address: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9',
        ...callBalanceOfConfig
      }
    ],
  })
  
  if (error) return <p>Error while fetching balances</p>;

  if (isLoading) return <p>Loading balances...</p>;
  
  const tokensFetched = ['LINK', 'UNI', 'AAVE']

  return (
    <div>
      {data && data.map((balance, i) => (
        <p key={i}>
          {/* make sure there is data before calling utils.formatEther */}
          You have {balance ? utils.formatEther(balance) : '0'} {tokensFetched[i]}
        </p>
      ))}
    </div>
  );
}

As you can see, the useContractReads hook will return an object and we're going to use 3 properties from it:

  • data: an array containing the results of our function calls. In our case it's the results of the balanceOf functions in the same order that we called them.
  • error: if there was an error while calling the functions, that property will contain the error that was thrown. Otherwise it's null.
  • isLoading: will be true while fetching the data and false otherwise

So in this case, the balances will be in the data array and we can simply map it to display the balances that we fetched.

The balances returned are not the objects like we had above with useBalance, it's just the raw result of the balanceOf function which is the balance in Wei.

So we need to convert these balances from Wei to Ether using the formatEther function from the utils in Ethers JS.

And that's it 🎉

Thank you for reading this article