0

I am trying to get the token balances for all of the tokens in my address. To do that I followed the steps in this guide here: https://chainstack.com/the-ultimate-guide-to-getting-multiple-token-balances-on-ethereum/
And I even copied the code from this repo here: https://github.com/chainstack/ethereum-token-balances. I decided to go the web3.js BatchRequest route.

The only changes that I made were to my constant.js file. It looked like this (notice I used dotenv to get bathEndpoint and walletAddress instead of hard coding):

require('dotenv').config()

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

const bathEndpoint = process.env.API_BASE_URL + process.env.API_ID;
const walletAddress = process.env.USER_ADDRESS

module.exports = {
    abi,
    bathEndpoint,
    walletAddress,
};

And I kept batch.js the same as it is in the repo

const Web3 = require('web3');
const { convertToNumber, getTokens } = require('./utils');
const { abi, bathEndpoint, walletAddress } = require('./constant.js');

const web3 = new Web3(new Web3.providers.HttpProvider(bathEndpoint));

const generateContractFunctionList = ({ tokens, blockNumber }) => {
    const batch = new web3.BatchRequest();

    tokens.map(async ({ address: tokenAddress, symbol, decimals }) => {
        const contract = new web3.eth.Contract(abi);
        contract.options.address = tokenAddress;
        batch.add(contract.methods.balanceOf(walletAddress).call.request({}, blockNumber));
    });

    return batch;
};

const main = async () => {
    const { tokens } = await getTokens();

    const batch = generateContractFunctionList({ tokens });
    // query block number
    // const batch = generateContractFunctionList({ tokens, blockNumber: 11633038 });
    const tokenBalances = {};
    const { response } = await batch.execute();
    response.forEach(({ _hex }, index) => {
        const { name, decimals, symbol } = tokens[index];

        tokenBalances[name] = `${convertToNumber(_hex, decimals)} ${symbol}`;
    });

    console.log(tokenBalances);
};

main();

And I kept utils.js the same as it is in the repo

const { toBN } = require('web3-utils');
require('isomorphic-fetch');

const tokenSource = 'https://tokens.coingecko.com/uniswap/all.json';
const getTokens = () => {
    return fetch(tokenSource, {
    methods: 'GET',
    headers: { 'Content-Type': 'application/json', },
    }).then(data => data.json());
};

const convertToNumber = (hex, decimals) => {
    const balance = toBN(hex);
    let balanceDecimal = balance;
    if (decimals && (balance.toLocaleString() === '0' && decimals < 20)) {
        balanceDecimal = balance.div(toBN(10 ** decimals));
    }

    return balanceDecimal.toLocaleString();
};

module.exports = {
    convertToNumber,
    getTokens,
};

Here is the error text that appears in my terminal:

<myusername>@<mycomputername> token-balance-through-time % node batch.js
/Users/<myusername>/Desktop/Dev/token-balance-through-time/node_modules/web3-core-helpers/lib/errors.js:122
        return new Error('This contract object doesn\'t have address set yet, please set an address first.');
               ^

Error: This contract object doesn't have address set yet, please set an address first.
    at Object.ContractNoAddressDefinedError (/Users/<myusername>/Desktop/Dev/token-balance-through-time/node_modules/web3-core-helpers/lib/errors.js:122:16)
    at Object._processExecuteArguments (/Users/<myusername>/Desktop/Dev/token-balance-through-time/node_modules/web3-eth-contract/lib/index.js:728:22)
    at Object._executeMethod (/Users/<myusername>/Desktop/Dev/token-balance-through-time/node_modules/web3-eth-contract/lib/index.js:744:68)
    at /Users/<myusername>/Desktop/Dev/token-balance-through-time/batch.js:13:66
    at Array.map (<anonymous>)
    at generateContractFunctionList (/Users/<myusername>/Desktop/Dev/token-balance-through-time/batch.js:10:12)
    at main (/Users/<myusername>/Desktop/Dev/token-balance-through-time/batch.js:22:19)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
<myusername>@<mycomputername> token-balance-through-time % 

I don't see what's causing the problem. I followed the guide perfectly. Btw I am using Alchemy API, my base url string being https://eth-mainnet.alchemyapi.io/v2/. Why am I getting this error and how do I fix it?

1 Answer 1

3

new versions of web3js have been released with changes in the API so you have to make sure to run the code in the article with the specific versions.

On the other hand, we've released an updated version of this article, you can find it here: https://chainstack.com/ultimate-guide-erc20-token-balance/ It explains how to query multiple balances, from multiple blockchains at any given date 💪

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.