Chuyển đến nội dung chính

Web3.js: How to Retrieve the Balance of an ERC-20 Token

Almost all tokens deployed on Ethereum follow the same specification: ERC-20.

This token standard allows you to create web3 applications offering interoperability, so the same code will enable you to interact with almost every token contract.

Every single ERC-20 token contract will have at least the following functions;

  • totalSupply() — returns the total tokens issued for this token
  • balanceOf(address \_owner) — returns the balance of an account
  • transfer(address \_to, uint \_value) — creates a transfer of _value amount of tokens to another account
  • transferFrom(address \_from, address \_to, uint \_value) — transfers _value amount of tokens to another address per its allowance
  • approve(address \_spender, uint \_value) — allows _spender to transfer _value tokens from the sender’s address
  • allowance(address \_owner, address \_spender) — returns the remaining number of tokens that _spender is still allowed to spend

Some ERC-20 token contracts might have additional functionality, but this would differ from the standard, and you can't rely on every token contract having these other functions.

This tutorial will use the balanceOf() function to retrieve the token balance of an address. You'll use Web3.js to do so.

Installing Web3.js

thông tin

This tutorial makes use of Web3.js v1.x.x. Not all functionality might work with Web3.js v4.

Create a new folder in which you can work on your project, then install Web3.js using npm.

npm install web3

You'll notice that npm will create a package.json and package-lock.json file in your working folder. Additionally, it will make a folder called node_modules.

Next, create a .js file in which you can write your code; call it main.js. You can use any text editor or IDE to work in your .js file.

Connecting to Infura

Ensure you got your Infura account set up and have access to your endpoint URL. Feel free to read more about getting started with Infura.

At the top of your new main.js file, you can add the following to import the Web3.js library that you just installed:

const Web3 = require('web3');

Next, you can add the following to connect to your Infura endpoint so that you can interact with the Ethereum blockchain:

const web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/v3/API_KEY'));

Make sure to replace API_KEY with your actual Infura API key.

Setting the ABI

The ABI, or application binary interface, reads the bytecode of smart contracts on the Ethereum network. This might sound confusing and daunting - don't worry about it too much at this time.

Bytecode?!

However, if you want to learn more, bytecode is compiled code (usually from Solidity), the actual smart contract code. It's unreadable for you and me but readable for a machine. Here's a small example of bytecode:

6101406040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610120908152503480156200003a57600080fd5b5060405162005bf838038062005bf8833981810160405281019062000060

An ABI is an interface which defines a scheme of how you can call specific functions in your specified smart contract.

Since you will only use the balanceOf method, you don't need the entire ABI for ERC-20 smart contracts. Hence, you're only going to define the ABI for the balanceOf method. You can add the following to your script:

const balanceOfABI = [
{
constant: true,
inputs: [
{
name: '_owner',
type: 'address',
},
],
name: 'balanceOf',
outputs: [
{
name: 'balance',
type: 'uint256',
},
],
payable: false,
stateMutability: 'view',
type: 'function',
},
]

Selecting a contract address

Every token on the Ethereum network has its own contract address. You need a contract address for each token whose balance you want to request. You can easily find these with a block explorer such as etherscan.io.

For this tutorial, you'll use the DAI token contract. However, you can choose to use any ERC-20 token address. Copy the address you wish to use, and save it somewhere as you will use this in your code later.

Requesting your token balance

Now that you've installed Web3.js, connected it to your Infura endpoint, learned about ABIs, and found the contract address of your token, you're ready to actually request your token balance.

Let's define the addresses you're going to use in your code:

const tokenContract = '0x6b175474e89094c44da98b954eedeac495271d0f'
const tokenHolder = '0xf326e4de8f66a0bdc0970b79e0924e33c79f1915'

tokenContract holds the address of the token contract you're going to call the balanceOf function on, and tokenHolder holds the account address you're requesting the token balance of.

You can define your contract with web3.eth.Contract(), and passing the ABI and contract address as parameters:

const contract = new web3.eth.Contract(balanceOfABI, tokenContract)

Next, you can create an async function in which you actually interact with the smart contract.

You can call methods.balanceOf() on your contract, which will send a request to your Infura endpoint to request the token balance.

async function getTokenBalance() {
let result = await.contract.methods.balanceOf(walletAddress).call();

console.log(result)
}

getTokenBalance();

You can already execute your code by running the following command in a terminal:

node main.js

Result:

➜  retrieve-erc-20-balance node main.js
3142422965167994254806984

The address you specified doesn't actually hold this amount of DAI in its wallet, so why is this number so large? By default, calling balanceOf will return the balance value in wei, which is the smallest unit in Ethereum (equal to 0.000000000000000001 Ether). You can read more about Ethereum's units here.

To get the actual number of DAI tokens, you can convert this number with:

web3.utils.fromWei(result, "ether"):
const formattedResult = web3.utils.fromWei(result, 'ether')

Make sure to update your console.log(format) too:

console.log(formattedResult);

If you run node main.js again, you get the proper DAI token balance of your specified address:

3142422.965167994254806984

Complete code overview

// Import the web3js library, set Infura as our provider
const Web3 = require('web3')
const web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/v3/<YOUR_API_KEY>'))

// Set the ERC-20 balanceOf() ABI
const balanceOfABI = [
{
constant: true,
inputs: [
{
name: '_owner',
type: 'address',
},
],
name: 'balanceOf',
outputs: [
{
name: 'balance',
type: 'uint256',
},
],
payable: false,
stateMutability: 'view',
type: 'function',
},
]

const tokenContract = '0x6b175474e89094c44da98b954eedeac495271d0f'
const tokenHolder = '0xf326e4de8f66a0bdc0970b79e0924e33c79f1915'

// Define the ERC-20 token contract
const contract = new web3.eth.Contract(balanceOfABI, tokenContract)

async function getTokenBalance() {
// Execute balanceOf() to retrieve the token balance
const result = await contract.methods.balanceOf(tokenHolder).call() // 29803630997051883414242659

// Convert the value from Wei to Ether
const formattedResult = web3.utils.fromWei(result, 'ether') // 29803630.997051883414242659

console.log(formattedResult)
}

getTokenBalance()
Was this helpful?
Connect MetaMask to provide feedback
What is this?
This is a trial feedback system that uses Verax to record your feedback as onchain attestations on Linea Mainnet. When you vote, submit a transaction in your wallet.