Skip to main content

Check USDC Balance

Updated on
Jun 29, 2024

Overview

To retrieve the balance of an ERC20 token, you need to interact with the token's smart contract. This requires the contract's address, ABI, and access to a blockchain node for data retrieval.

Fetching token balances across multiple blockchain networks can be time-consuming and complex. For a faster and more efficient approach, we've created this Function example. Here, we'll use QuickNode RPC to obtain the USDC balances of a wallet address on several EVM blockchain networks.

Sample Function

We will be using the ethers.js library to interact with the EVM blockchains. Thus, we will need to create a zip file and upload it to our Functions dashboard.

We will need to install ethers and dotenv with the following command:

npm i ethers dotenv

Create a .env file to store RPC endpoint URLs from QuickNode. Create new endpoints on QuickNode.

ARBITRUM_RPC_URL=REPLACE_WITH_RPC_URL
AVALANCHE_RPC_URL=REPLACE_WITH_RPC_URL
BASE_RPC_URL=REPLACE_WITH_RPC_URL
BSC_RPC_URL=REPLACE_WITH_RPC_URL
CELO_RPC_URL=REPLACE_WITH_RPC_URL
ETHEREUM_RPC_URL=REPLACE_WITH_RPC_URL
OPTIMISM_RPC_URL=REPLACE_WITH_RPC_URL
POLYGON_RPC_URL=REPLACE_WITH_RPC_URL
ZKSYNC_RPC_URL=REPLACE_WITH_RPC_URL

Replace the REPLACE_WITH_RPC_URL placeholder with a URL for the specified chain.

Now, create an index.js file and paste the following code into it:

// Import dotenv and ethers packages
require('dotenv').config();
const { ethers } = require("ethers");

// Environment variable names for various blockchains
const envVarNames = {
arbitrum: "ARBITRUM_RPC_URL",
avalanche: "AVALANCHE_RPC_URL",
base: "BASE_RPC_URL",
bsc: "BSC_RPC_URL",
celo: "CELO_RPC_URL",
ethereum: "ETHEREUM_RPC_URL",
optimism: "OPTIMISM_RPC_URL",
polygon: "POLYGON_RPC_URL",
zksync: "ZKSYNC_RPC_URL"
};

// USDC contract addresses on various blockchains
const usdcAddresses = {
arbitrum: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
avalanche: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
base: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
bsc: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d",
celo: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
optimism: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
polygon: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
zksync: "0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4"
};

// ABI for balanceOf of ERC20 tokens to interact with USDC contract
const abi = [
"function balanceOf(address owner) view returns (uint256)"
];

async function getUSDCBalance(providerUrl, contractAddress, walletAddress) {
const provider = new ethers.JsonRpcProvider(providerUrl); // Create new ethers JsonRpcProvider provider
const contract = new ethers.Contract(contractAddress, abi, provider); // Create new contract intance using contract address, abi, provider
const balance = await contract.balanceOf(walletAddress); // Fetch balance for specified wallet
return ethers.formatUnits(balance, 6); // USDC has 6 decimal places
}

async function main(params) {
console.log('Starting main function with params:', params); // Log input params

const walletAddress = params.user_data.wallet_address; // Get wallet address from user

try {
const balances = {}; // Empty balances object
let missingRpcUrls = false; // variable flag for missing URLs

/* - A function to iterate over mentioned chains in the envVarNames
- Fetch RPC URLs from .env file and check if the URL is set
- If URL is set run getUSDCBalance function
- Handle missing URLs by setting missingRpcUrls true
*/

for (const [chain, envVarName] of Object.entries(envVarNames)) {
const rpcUrl = process.env[envVarName];
if (rpcUrl) {
const usdcAddress = usdcAddresses[chain];
const balance = await getUSDCBalance(rpcUrl, usdcAddress, walletAddress);
balances[chain] = balance;
} else {
balances[chain] = `Add ${envVarName} in the .env file.`;
missingRpcUrls = true;
}
}

//Log final results and return the balances with a message
console.log('Final balances:', balances); // Log final results
return {
message: "USDC Balances across EVM blockchains.",
balances: balances,
};
} catch (error) {
console.error('Error in main function:', error); // Log any errors encountered in the main function
throw error;
}
}

module.exports = { main };

Zip the Files

QuickNode Functions supports several Node.js v20 core modules, but since we've used ethers.js and dotenv which are third-party libraries, we will need to upload a .zip file of index.js, .env, package.json, and package-lock.json along with node_modules folder so that our function can work on the QuickNode Functions platform.

Learn more about QuickNode Functions Code Editor and .Zip file uploading.

Request

We will invoke the function with the following cURL command. Be sure to replace the YOUR_API_KEY with your own QuickNode API key and the POST URL with the URL of your Function. You can send the request with any wallet address to check the balance.

curl -X POST "https://api.quicknode.com/functions/rest/v1/namespaces/0f6812dd-a17f-4cbc-9ab4-7a529eb33940/functions/usdc-balances/call" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"network": "ethereum-mainnet",
"dataset": "block",
"block": "latest",
"user_data": {
"wallet_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
}
}'

Response

Resulting in the following response:

{
"response" : {
"activationId" : "28b6912a79f74ad8b6912a79f77ad866",
"annotations" : [
{
"key" : "path",
"value" : "ca43f206-1786-4d85-8521-952f2a528f49/usdc-balances"
},
{
"key" : "waitTime",
"value" : 142
},
{
"key" : "kind",
"value" : "nodejs:20"
},
{
"key" : "timeout",
"value" : false
},
{
"key" : "limits",
"value" : {
"concurrency" : 1,
"logs" : 10,
"memory" : 256,
"timeout" : 60000
}
},
{
"key" : "initTime",
"value" : 313
}
],
"duration" : 406,
"end" : 1719555581845,
"logs" : [],
"name" : "usdc-balances",
"namespace" : "ca43f206-1786-4d85-8521-952f2a528f49",
"publish" : false,
"response" : {
"result" : {
"balances" : {
"arbitrum" : "Add ARBITRUM_RPC_URL in the .env file.",
"avalanche" : "Add AVALANCHE_RPC_URL in the .env file.",
"base" : "Add BASE_RPC_URL in the .env file.",
"bsc" : "Add BSC_RPC_URL in the .env file.",
"celo" : "Add CELO_RPC_URL in the .env file.",
"ethereum" : "7065.377042",
"optimism" : "Add OPTIMISM_RPC_URL in the .env file.",
"polygon" : "70.052053",
"zksync" : "Add ZKSYNC_RPC_URL in the .env file."
},
"message" : "USDC Balances across EVM blockchains."
},
"size" : 447,
"status" : "success",
"success" : true
},
"start" : 1719555581439,
"subject" : "0f6812dd-a17f-4cbc-9ab4-7a529eb33940",
"version" : "0.0.3"
}
}

Learn more about QuickNode Functions.

We ❤️ Feedback!

If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!

Share this doc