How to Get Token Balance for an Address

Learn how to get the balance of a single token being held by a specific contract address.

📘

API Endpoint

This tutorial uses the alchemy_getTokenBalances endpoint.

If you just need the script for this tutorial refer to the below Recipe:

The token balances for a user address is a critical data point for almost any web3 use case - be it DeFi platforms, wallets, analytics, exchanges, and many others. A common use case would be displaying the balances as below in your wallet app.

359

Sample wallet screen displaying coin balances

To fetch this data you have 2 options:

  1. Fetch the Transaction History for the token’s contract, for example take USDT, which is millions of records. Then search through for your user’s address among those records (will take hours) and then show that to your user. Not to forget, do this indexing process every second forever to keep it updated for every user.
  2. OR just use Alchemy’s getTokenBalances endpoint.

If you’re like most web3 developers, you probably want to go for the second option!

How to query the token balance of an address

When querying the token balance for a user, you should have couple of key parameters on hand:

  • OwnerAddress: This is the blockchain address that owns the tokens in question. Note that this is not the contract address of the token itself.
  • tokenContractAddress : An array of contract addresses of all the token’s you want the balances for. Or if you specify the string erc20 it will include the entire set of erc20 tokens that the address has ever held.

Example: Get current USDT balance for an Address.

For this particular example we're going to fetch the USDT balance for address 0x00000000219ab540356cbb839cbe05303d7705fa (fun fact: this address has the highest ETH balance among all addresses! )

👍

No-Code Example

For a no-code view of the API request, check out the composer tool

Alchemy SDK (Recommended)

Step 1: Install Alchemy-SDK and create a file

Run the below commands in the command line

npm install alchemy-sdk
touch token-balances-from-alchemy-sdk.js

Step 2: Write the token balance querying script

Inside the token-balances-from-alchemy-sdk.js file, paste the below code

// Setup: npm install alchemy-sdk
import { Alchemy, Network } from "alchemy-sdk";

const config = {
  apiKey: "<-- ALCHEMY APP API KEY -->",
  network: Network.ETH_MAINNET,
};
const alchemy = new Alchemy(config);

//Feel free to switch this wallet address with another address
const ownerAddress = "0x00000000219ab540356cbb839cbe05303d7705fa";

//The below token contract address corresponds to USDT
const tokenContractAddresses = ["0xdAC17F958D2ee523a2206206994597C13D831ec7"];

const data = await alchemy.core.getTokenBalances(
  ownerAddress,
  tokenContractAddresses
);

console.log("Token balance for Address");
console.log(data);

Step 3: Run the code to get the token balance with alchemy-web3.js

node token-balances-from-alchemy-sdk.js

You should see the below output

Token balance for Address
{
  address: '0x00000000219ab540356cbb839cbe05303d7705fa',
  tokenBalances: [
    {
      contractAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
      tokenBalance: '4929853276',
      error: null
    }
  ]
}

Node-Fetch

Step 1: Create a node-fetch file

Run the below commands in the command line

touch token-balances-from-fetch.js

Step 2: Write the script for querying token balances!

Inside the token-balances-from-fetch.js file, paste the below code

import fetch from 'node-fetch';

// Replace with your Alchemy API key:
const apiKey = "demo";

const fetchURL = `https://eth-mainnet.g.alchemy.com/v2/${apiKey}`;

// Replace with the wallet address you want to query:
const ownerAddr = "0x00000000219ab540356cbb839cbe05303d7705fa";

// Replace with the token contract address you want to query:
const tokenAddr = "0xdAC17F958D2ee523a2206206994597C13D831ec7";

var raw = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "alchemy_getTokenBalances",
  "headers": {
    "Content-Type": "application/json"
  },
  "params": [
    `${ownerAddr}`,
    [
      `${tokenAddr}`,
    ]
  ],
  "id": 42
});

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

// Make the request and print the formatted response:
fetch(fetchURL, requestOptions)
  .then(response => response.json())
  .then(response => JSON.stringify(response, null, 2))
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Step 3: Run the code to get the token balance with Node-Fetch

node token-balances-from-fetch.js

You should see the below output

Token balance for Address
{
  address: '0x00000000219ab540356cbb839cbe05303d7705fa',
  tokenBalances: [
    {
      contractAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
      tokenBalance: '4929853276',
      error: null
    }
  ]
}

Axios

Step 1: Install axios and create a file

Run the below commands in the command line

npm install axios
touch token-balances-from-axios.js

Step 2: Write the script to query token balances with Axios

Inside the token-balances-from-axios.js file, paste the below code

import axios from 'axios';

// Replace with your Alchemy API key:
const apiKey = "demo";

const baseURL = `https://eth-mainnet.g.alchemy.com/v2/${apiKey}`;

// Replace with the wallet address you want to query:
const ownerAddr = "0x00000000219ab540356cbb839cbe05303d7705fa";

// Replace with the token contract address you want to query:
const tokenAddr = "0xdAC17F958D2ee523a2206206994597C13D831ec7";

var data = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "alchemy_getTokenBalances",
  "params": [
    `${ownerAddr}`,
    [
      `${tokenAddr}`
    ]
  ],
  "id": 42
});

var config = {
  method: 'post',
  url: baseURL,
  headers: {
    'Content-Type': 'application/json'
  },
  data : data
};

axios(config)
.then(function (response) {
  //This line converts the tokenBalance values from hex to decimal
  response.data["result"]["tokenBalances"][0]["tokenBalance"] = parseInt(response.data["result"]["tokenBalances"][0]["tokenBalance"], 16);
  console.log("Token balance for address\n", JSON.stringify(response.data.result, null, 2))
})
.catch(function (error) {
  console.log(error);
});

Step 4: Run the code to get token balances with Axios

node token-balances-from-axios.js

You should see output like:

Token balance for Address
{
  address: '0x00000000219ab540356cbb839cbe05303d7705fa',
  tokenBalances: [
    {
      contractAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
      tokenBalance: '4929853276',
      error: null
    }
  ]
}

📘

In the above steps, you can replace the ownerAddress with any owner’s address and replace tokenContractAddresses with an array of addresses, to get the right token balance!

How to process the API response

Now that we have made the query and can see the response, let's learn how to handle it.

If you feel like jumping ahead and grabbing some pre-built code, choose and pick a code from the below options that matches your preferred library.

Alchemy Web3 (Recommended)

The below linked Github script is for the Alchemy-Web3.js library and takes the output of the alchemy_getTokenBalances endpoint, joins it with the output of the alchemy_getTokenMetadata endpoint and returns a clean output "The balance of Token X is Y"

Node-Fetch

The below linked Github script uses Node-fetch and takes the output of the alchemy_getTokenBalances endpoint, joins it with the output of the alchemy_getTokenMetadata endpoint, and returns a clean output "The balance of Token X is Y"\

Axios

The below linked Github script uses Axios.js and takes the output of the alchemy_getTokenBalances endpoint, joins it with the output of the alchemy_getTokenMetadata endpoint and returns a clean output "The balance of Token X is Y"\

Raw API Response:

The usual result looks something like this

{
  "address": "0x00000000219ab540356cbb839cbe05303d7705fa",
  "tokenBalances": [
    {
      "contractAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
      "tokenBalance": 4929853276,
      "error": null
    }
  ]
}

Understanding the API Response:

  • Address: The address of the owner for whom you want to pull the balance of the token
  • contractAddress: The contract address of the token in question. To pull the actual name of the token and other details, we will use another API alchemy_getTokenMetadata
  • tokenBalance: balance of the specific contractAddress for the owner address address

The tokenBalance in its raw form as returned by alchemy_getTokenBalances is the number in terms of the smallest unit of the token. In the code below, we do a bit of calculation to get the clear quantity of the token in decimal units.

📘

The Calculation for tokenBalance

The tokenBalance returned by the API is usually a number with several digits (in this case 4929853276 for USDT)

Every ERC20 token has a metadata information called "decimals" which denotes the divisibility of a token (ranges from 0 to 18). For USDT, the value of "decimals" is 6. The response returned by Alchemy's alchemy_getTokenBalances API is as below\

tokenBalance = no. of tokens (quantity) * Math.pow(10, 6)

Hence, the actual quantity of the USDT token, in this case, will be

4929853276/10^6 = 4,929.853276

The same operation needs to be done to obtain the actual quantity for any token. We show the calculation in the code below.

How to calculate & print the tokenName and tokenBalance

Two of the many different response objects you may be interested in parsing are: tokenName and tokenBalance (in USD)

Whether we're querying via alchemy-web3, axios, or node-fetch, we'll have to follow the below steps
1. Save the response of alchemy_getTokenBalances into a constant/variable
2. Get the Token name for the concerned Token Contract address alchemy_getTokenMetadata
3. Convert the tokenBalance into the correct units (using alchemy_getTokenMetadata

Let's walk through the below sample code that parses the returned JSON object.

/*
** Fetching the metadata for the token with Alchemy's getTokenMetadata API
*/
const metadata = await web3.alchemy.getTokenMetadata( 
                     tokenContractAddresses[0]
                 );

//Forming the name of the token that comprises of the Name and the Symbol of the token
const tokenName = metadata.name + "(" + metadata.symbol + ")";

/* Calculating the tokenBalance in decimal. The "decimals" field in the token metadata on line 21 tells us 
how many digits at the end of the tokenBalance in Line 17 are to the right of the decimal. 
so we divide the Full tokenBalance with 10 to the power of the decimal value of the token
*/
const tokenBalance = data["tokenBalances"][0]["tokenBalance"]/Math.pow(10, metadata.decimals)
console.log("Token balance for", tokenName, "is", tokenBalance);
var metadata;

var metadataRaw = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "alchemy_getTokenMetadata",
  "headers": {
    "Content-Type": "application/json"
  },
  "params": [
      `${tokenAddr}`
  ],
  "id": 42
});

var metadataRequestOptions = {
  method: 'POST',
  body: metadataRaw,
  redirect: 'follow'
};

/*
** Fetching the metadata for the token with Alchemy's getTokenMetadata API
*/
fetch(fetchURL, metadataRequestOptions)
  .then(response => response.json())
  .then(response => {
    metadata = response.result;

    //Forming the name of the token that comprises of the Name and the Symbol of the token
    const tokenName = metadata.name + "(" + metadata.symbol + ")";

    /* Calculating the tokenBalance in decimal. The "decimals" field in the token metadata on line 21 tells us 
    how many digits at the end of the tokenBalance in Line 17 are to the right of the decimal. 
    so we divide the Full tokenBalance with 10 to the power of the decimal value of the token
    */
    const tokenBalance = data["tokenBalances"][0]["tokenBalance"]/Math.pow(10, metadata.decimals)
    console.log("Token balance for", tokenName, "is", tokenBalance);
  })
  .catch(error => console.log('error', error));
/*
** Fetching the metadata for the token with Alchemy's getTokenMetadata API
*/
var metadataParams = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "alchemy_getTokenMetadata",
  "params": [
      `${tokenAddr}`
  ],
  "id": 42
});

var metadataConfig = {
  method: 'post',
  url: baseURL,
  headers: {
    'Content-Type': 'application/json'
  },
  data : metadataParams
};  

axios(metadataConfig)
.then(function (response) {
  metadata = response.data.result;

  //Forming the name of the token that comprises of the Name and the Symbol of the token
  const tokenName = metadata.name + "(" + metadata.symbol + ")";

  /* Calculating the tokenBalance in decimal. The "decimals" field in the token metadata on line 21 tells us 
  how many digits at the end of the tokenBalance in Line 17 are to the right of the decimal. 
  so we divide the full tokenBalance with 10 to the power of the decimal value of the token
  */
  const tokenBalance = data["tokenBalances"][0]["tokenBalance"]/Math.pow(10, metadata.decimals)
  console.log("Token balance for", tokenName, "is", tokenBalance);
})

The output that you would see from running the above code is

The token balance for Tether(USDT) is 4929.853276

With this, you're all set to fetch token balances from TokenAPI. This can also be extended to fetching the balance for multiple tokens by passing in an array of token addresses, or using the default list (see example here)!

If you enjoyed this tutorial for getting address transaction history on Ethereum, give us a tweet @AlchemyPlatform! (Or if you have any questions/feedback give the author @ankg404 a shoutout!)

Don't forget to join our Discord server to meet other blockchain devs, builders, and entrepreneurs! \


ReadMe