Before getting started ๐
Web3 applications often need to check users' wallet balances.
You may want to display balances across Ethereum mainnet, Arbitrum, Optimism, BSC, and other chains together.
One useful tool is the
Etherscan V2 API
.
It provides data in a common format for multiple chains, making balances accessible through simple HTTP requests.
This article explains
how to query multichain EOA wallet balances with Etherscan V2
and
implement the feature in React
.
To use the API, obtain an API key from Etherscan.
A separate key is required for each chain, with nearly identical procedures.
๐ Issuing a key for Ethereum mainnet ๐
Register at https://etherscan.io/registerโ .
Sign in and open My Profile
> API Keys
at the upper right.
Click Add
to create a key.
Enter a name to issue the API key.
๐ API-key pages for other chains ๐
Querying balances by chain ๐
Balance requests use the
account module and
balance action of each chain's Etherscan API.
The base URL follows this pattern.
GET https://<์ฒด์ธ>.etherscan.io/api?module=account&action=balance&address=<์ง๊ฐ์ฃผ์>&apikey=<API_KEY>
For example, here is an Ethereum-mainnet balance request.
https://api.etherscan.io/api?module=account&action=balance&address=0x123...abc&apikey=YOUR_API_KEY
For Arbitrum:
https://api.arbiscan.io/api?module=account&action=balance&address=0x123...abc&apikey=YOUR_API_KEY
Responses generally use the following JSON format.
{
"status" : "1" ,
"message" : "OK" ,
"result" : "1234567890000000000"
}
The
result is in
Wei
, so divide by 10 to the power of 18 to convert it to Ether.
React and TypeScript example ๐
Now let's call the APIs from React to retrieve a wallet's balance, with support for several chains.
import React, { useEffect, useState } from 'react' ;
import axios from 'axios' ;
const ETHERSCAN_APIS = {
ethereum: {
baseURL: 'https://api.etherscan.io/api' ,
apiKey: 'YOUR_ETHERSCAN_API_KEY' , // ์ฌ๊ธฐ์ ์์ ์ API Key๋ฅผ ์
๋ ฅํด์ผ ํฉ๋๋ค.
},
arbitrum: {
baseURL: 'https://api.arbiscan.io/api' ,
apiKey: 'YOUR_ARBISCAN_API_KEY' , // ์ฌ๊ธฐ์ ์์ ์ API Key๋ฅผ ์
๋ ฅํด์ผ ํฉ๋๋ค.
},
optimism: {
baseURL: 'https://api-optimistic.etherscan.io/api' ,
apiKey: 'YOUR_OPTIMISM_API_KEY' , // ์ฌ๊ธฐ์ ์์ ์ API Key๋ฅผ ์
๋ ฅํด์ผ ํฉ๋๋ค.
},
};
interface BalanceResult {
chain : string ;
ether : string ;
}
const WalletBalances : React . FC <{ address : string }> = ({ address }) => {
const [ balances , setBalances ] = useState < BalanceResult []>([]);
useEffect (() => {
const fetchBalances = async () => {
const results : BalanceResult [] = [];
for ( const [ chain , config ] of Object. entries ( ETHERSCAN_APIS )) {
try {
const res = await axios. get (config.baseURL, {
params: {
module: 'account' ,
action: 'balance' ,
address,
apikey: config.apiKey,
},
});
const wei = res.data.result;
const ether = ( Number (wei) / 1e18 ). toFixed ( 4 );
results. push ({ chain, ether });
} catch (error) {
console. error ( `${ chain } ์ค๋ฅ ๋ฐ์` , error);
}
}
setBalances (results);
};
if (address) {
fetchBalances ();
}
}, [address]);
return (
< div className = "p-4" >
< h2 className = "text-xl font-bold mb-2" >์ง๊ฐ ์์ก ์ ๋ณด</ h2 >
< ul >
{ balances. map (({ chain , ether }) => (
< li key ={ chain } className = "mb-1" >
* { chain } *: { ether } ETH
</ li >
)) }
</ ul >
</ div >
);
};
export default WalletBalances;
Querying multiple chains concurrently ๐
The example above calls the APIs sequentially in a for...of loop.
You can instead send requests concurrently with
Promise.all() to improve speed.
await Promise . all (Object. entries ( ETHERSCAN_APIS ). map ( async ([ chain , config ]) => {
const res = await axios. get (config.baseURL, {
params: {
module: 'account' ,
action: 'balance' ,
address,
apikey: config.apiKey,
},
});
// ์ดํ ๋ก์ง ๋์ผ...
}))
APIs have rate limits, so making many requests too close together may result in blocking.
For heavier use, consider backend caching or delays between requests.
Etherscan V2 lets you retrieve wallet balances across chains with simple API calls.
With keys issued for each chain, the feature is straightforward to implement in React.
In practice, account for
request rate limits
and design an efficient API-use strategy.
Combining this with automatic retrieval of the user's connected wallet address, such as from MetaMask, makes the feature more useful than using a fixed address.