打开钱包就能看见已导入代币的余额,但如果你想查看未导入的代币、别人的钱包,或在某个历史快照查询余额,仅靠钱包远远不够。本文将手把手演示如何不依赖第三方界面,查询任意地址在任何时间点、任何 EVM 链上的 ERC20 代币余额;还会送上开源 CLI 工具,助你一行命令搞定批量检查。
核心关键词:ERC20、代币余额、EVM、钱包、区块高度、API、archive 节点、CLI 工具。
ERC20 代币余额为何能公开查询?
所有 ERC20 合约都会暴露标准函数 balanceOf(address),它永远返回指定钱包在该代币合约上的余额。只要拿到:
- 代币合约地址
- 目标钱包地址
- 可访问的节点或接口
你就能用 balanceOf 直接读取链上数据。
三步快速上手:先学单一代币查询
- 确定代币合约地址
👉 常见代币可以在 查看去中心化链上浏览器 指尖查询合约哈希与标准信息。 获取节点端点
自己部署全节点或租用 RPC,一定要分清 full node vs archive node:- full 只能查当前状态
- archive 才能回溯历史状态
- 用 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:我应该用哪种节点?
- 我只想查今天余额:full node 即可。
- 我要查 2023-10-09 那天的余额:必须用 archive node。
- 免费 RPC 能用吗? 部分平台对 archive 查询有 128 个区块限制,超出会报错,建议购买 archive 套餐。
- CLI 工具能自动切换节点吗? 已内置环境变量检测,写好 archive 端点后它会优先使用。
伸到历史时间轴:用具体日期挖到区块高度
链只是说“第 X 个区块”,而我们习惯用“2024-06-15”。转换思路:
- 把日期 → Unix 时间戳
- 调用 Etherscan 系 API
getblocknobytime,获得离该时间最近的区块号
const time = Math.floor(new Date('2024-06-15').getTime() / 1000);
const url = `${scanApi}?module=block&action=getblocknobytime×tamp=${time}&closest=before&apikey=${key}`;
const block = (await axios.get(url)).data.result;注意:Polygon、BSC、Avalanche 等都有自己的浏览器,地址只需把 etherscan.io 换成对应域名。
批量查询:上万代币怎么办?
人工复制地址?不现实。Github 上已有全链 token list。
抓取主干 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' };- 用
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 余额作为空投权重:
./erc20-cli --chain eth --block-by-date 2024-04-01 --wallet 0xabc...CLI 自动完成
- 下载官方 token list
- 从 Etherscan API 获取 17145555 区块
- 并发查询
balanceOf
- 生成 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 一键起飞:本地安装与使用
简单三步:
- 克隆仓库
npm install- 写入节点端点 + API Key 到
.env 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 余额
总结
- 只要掌握合约地址与区块高度,就能把任何地址的 ERC20 代币余额读得清清楚楚。
- 用开源 token list + 并发查询 + archive 节点,你就能在 5 分钟内拿到数千枚代币、任何历史时间点的详尽清单。
- CLI 工具进一步降低门槛,开发者与普通用户都能用得舒心。
现在就把这篇指南收藏,遇到「怎么查某个日期某地址所有的币」时,打开终端按三回车,数据即刻到手。