如何查询任意地址的 ERC20 代币余额:终极指南

·

打开钱包就能看见已导入代币的余额,但如果你想查看未导入的代币、别人的钱包,或在某个历史快照查询余额,仅靠钱包远远不够。本文将手把手演示如何不依赖第三方界面,查询任意地址在任何时间点、任何 EVM 链上的 ERC20 代币余额;还会送上开源 CLI 工具,助你一行命令搞定批量检查。

核心关键词:ERC20、代币余额、EVM、钱包、区块高度、API、archive 节点、CLI 工具。


ERC20 代币余额为何能公开查询?

所有 ERC20 合约都会暴露标准函数 balanceOf(address),它永远返回指定钱包在该代币合约上的余额。只要拿到:

你就能用 balanceOf 直接读取链上数据。


三步快速上手:先学单一代币查询

  1. 确定代币合约地址
    👉 常见代币可以在 查看去中心化链上浏览器 指尖查询合约哈希与标准信息。
  2. 获取节点端点
    自己部署全节点或租用 RPC,一定要分清 full node vs archive node

    • full 只能查当前状态
    • archive 才能回溯历史状态
  3. 用 ethers.js 发起一次调用
const provider = new ethers.providers.JsonRpcProvider('https://my-node.org');
const erc20 = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
const balance = await erc20.balanceOf(walletAddress);

FAQ:我应该用哪种节点?


伸到历史时间轴:用具体日期挖到区块高度

链只是说“第 X 个区块”,而我们习惯用“2024-06-15”。转换思路:

  1. 把日期 → Unix 时间戳
  2. 调用 Etherscan 系 API getblocknobytime,获得离该时间最近的区块号
const time = Math.floor(new Date('2024-06-15').getTime() / 1000);
const url = `${scanApi}?module=block&action=getblocknobytime&timestamp=${time}&closest=before&apikey=${key}`;
const block = (await axios.get(url)).data.result;

注意:Polygon、BSC、Avalanche 等都有自己的浏览器,地址只需把 etherscan.io 换成对应域名。


批量查询:上万代币怎么办?

人工复制地址?不现实。Github 上已有全链 token list。

  1. 抓取主干 repo:

    const TOKEN_LISTS = {
      Ethereum: 'https://raw.githubusercontent.com/viaprotocol/tokenlists/main/tokenlists/ethereum.json',
      Avalanche: 'https://raw.githubusercontent.com/viaprotocol/tokenlists/main/tokenlists/avax.json',
      Polygon:  'https://raw.githubusercontent.com/viaprotocol/tokenlists/main/tokenlists/polygon.json'
    };
  2. Promise.allSettled() 并发查询,平均 1200 个地址只需 3-4 秒即可全部跑完:
const proms = tokenList.map(t => erc20.balanceOf(wallet, {blockTag: block}));
const packs = await Promise.allSettled(proms);

场景案例:一键复盘某空投猎人全仓快照

假设团队要求 2024-04-01 所有用户持有的 USDC、DAI、WETH 余额作为空投权重:

  1. ./erc20-cli --chain eth --block-by-date 2024-04-01 --wallet 0xabc...
  2. CLI 自动完成

    • 下载官方 token list
    • 从 Etherscan API 获取 17145555 区块
    • 并发查询 balanceOf
  3. 生成 JSON/CSV,导出即用

常见问题 FAQ(续)

Q:USDC、USDT 精度是多少?
A:都是 6 位,查看代币合约的 :decimals() 即可动态捕获。

Q:余额是 BigNumber,怎样变成正常小数?
A:

const readable = ethers.utils.formatUnits(bigNum, decimals);

Q:我能直接调用 CLI 去除隐私 API Key 吗?
A:可以!CLI 支持通过 .env 动态注入,仓库模版已写明模板 key。


CLI 一键起飞:本地安装与使用

开源仓库:token-balance-ultimate

简单三步:

  1. 克隆仓库
  2. npm install
  3. 写入节点端点 + API Key 到 .env
  4. node index.js --chain polygon --wallet 0x123... --date 2024-05-01

进阶:获取代币名称、符号、精度

一条链上可能同名不同合约,所以必须校验以下字段:

const { name, symbol, decimals } = await getTokenDetails(tokenAddress);
console.log(`${name}(${symbol}), decimals ${decimals}, balance ${readableBalance}`);

函数内部就是三次 RPC 调用 name(), symbol(), decimals(),非常轻量。


前文提到的 CLI 已将上述逻辑封装,你只需关心业务场景。👉 立即体验极速查询任意 ERC20 余额


总结

现在就把这篇指南收藏,遇到「怎么查某个日期某地址所有的币」时,打开终端按三回车,数据即刻到手。