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?