PromleeBlog
sitemapaboutMe

posting thumbnail
Etherscan API로 여러 체인 잔액 조회하기
Querying Multichain Balances with Etherscan API

📅

🚀

들어가기 전에🔗

웹3 애플리케이션을 개발하다 보면 사용자의 지갑 잔액을 확인해야 하는 경우가 많습니다. 특히, 이더리움 메인넷뿐 아니라 Arbitrum, Optimism, BSC 등 여러 체인의 잔액을 한 번에 보여주고 싶을 때도 있지요.
이럴 때 사용할 수 있는 유용한 도구 중 하나가
Etherscan V2 API
입니다. 이 API는 여러 체인에 대해 공통된 형식으로 데이터를 제공하며, 간단한 HTTP 요청만으로도 잔액 정보를 쉽게 가져올 수 있습니다.
이번 글에서는
Etherscan V2 API를 이용해 여러 체인의 EOA 지갑 잔액을 조회하는 방법
과,
React 환경에서 이를 어떻게 구현할 수 있는지
를 순서대로 설명드립니다.

🚀

API Key 생성하기🔗

먼저 API를 사용하기 위해서는 Etherscan에서 제공하는 API Key가 필요합니다. 이 키는 각 체인별로 따로 발급받아야 하며, 절차는 거의 동일합니다.

📍 발급 절차 (Ethereum Mainnet 기준)🔗

  1. https://etherscan.io/register 에서 회원가입합니다.
  2. 로그인 후 우측 상단
    My Profile
    >
    API Keys
    메뉴로 이동합니다.
  3. Add
    버튼을 눌러 새로운 키를 생성합니다.
  4. 원하는 이름을 입력하면 API Key가 발급됩니다.

📍 다른 체인에서의 API Key 발급 링크🔗


🚀

체인별 잔액 조회 흐름🔗

잔액 조회는 각 체인의 Etherscan API의 account 모듈과 balance 액션을 사용합니다. 기본 URL은 다음과 같은 형식을 따릅니다.
GET https://<체인>.etherscan.io/api?module=account&action=balance&address=<지갑주소>&apikey=<API_KEY>
예를 들어, 이더리움 메인넷의 잔액을 조회하는 API는 다음과 같습니다:
https://api.etherscan.io/api?module=account&action=balance&address=0x123...abc&apikey=YOUR_API_KEY
Arbitrum의 경우:
https://api.arbiscan.io/api?module=account&action=balance&address=0x123...abc&apikey=YOUR_API_KEY
응답은 일반적으로 다음과 같은 JSON 형식으로 옵니다:
{
  "status": "1",
  "message": "OK",
  "result": "1234567890000000000"
}
여기서 result
Wei 단위
이므로, 이를 Ether 단위로 변환하려면 18자리를 소수점으로 나눠야 합니다.

🚀

React + TypeScript 예제🔗

이제 실제로 React에서 위 API를 호출해 지갑 잔액을 불러오는 예제를 만들어 보겠습니다. 여러 체인을 지원하도록 구성하겠습니다.
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;

🚀

여러 체인 동시 조회 전략🔗

위 예제에서는 for...of 반복문을 사용하여 순차적으로 API를 호출했지만, Promise.all()을 사용하여 동시에 요청을 보내는 것도 가능합니다. 이렇게 하면 속도를 더 빠르게 개선할 수 있습니다.
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,
    },
  });
  // 이후 로직 동일...
}))
API rate limit이 존재하므로 너무 짧은 간격으로 여러 요청을 보낼 경우 블록될 수 있으니, 사용량이 많다면 백엔드 캐시나 딜레이 로직을 추가하는 것도 고려해 주세요.

🚀

결론🔗

Etherscan V2 API를 활용하면 여러 체인의 지갑 잔액을 간단한 API 호출만으로 가져올 수 있습니다. 체인별로 발급받은 API Key만 있다면, React 환경에서도 어렵지 않게 구현할 수 있습니다.
실제 사용 시에는
요청 횟수 제한(rate limit)
을 고려하여 효율적인 API 사용 전략을 함께 고민해야 합니다. 또한, 고정된 주소가 아닌 사용자의 연결된 지갑 주소(MetaMask 등)를 자동으로 불러오는 로직과 결합하면 더욱 유용한 기능을 제공할 수 있습니다.

참고🔗