如何使用Web3.js统计指定地址向目标钱包转账的代币总金额
功能实现方案
核心逻辑
所有符合ERC20/BEP20标准的代币在发生转账时,都会触发标准的Transfer(address from, address to, uint256 value)事件,你只需要筛选出「转出方为AddressC、接收方为WalletA」的所有TokenB Transfer事件,累加事件中的转账金额即可得到总入账金额。
具体实现步骤(基于Web3.js v4版本)
- 第一步:初始化Web3实例和TokenB合约实例,只需传入包含Transfer事件定义的精简ABI即可,无需完整合约ABI:
const { Web3 } = require('web3'); // 替换为对应链的RPC节点地址(以太坊/BSC等公链公共RPC即可) const web3 = new Web3('https://your-rpc-endpoint'); // ERC20/BEP20标准Transfer事件ABI const tokenABI = [ { "anonymous": false, "inputs": [ {"indexed": true, "name": "from", "type": "address"}, {"indexed": true, "name": "to", "type": "address"}, {"indexed": false, "name": "value", "type": "uint256"} ], "name": "Transfer", "type": "event" } ]; // 替换为TokenB的实际合约地址 const tokenBContract = new web3.eth.Contract(tokenABI, 'TokenBContractAddress');
- 第二步:按过滤条件拉取历史Transfer事件,若转账历史过长可拆分区块范围分批拉取,避免RPC查询超时:
// 替换为AddressC、WalletA的实际地址 const filterOptions = { filter: { from: 'AddressCAddress', to: 'WalletAAddress' }, // 可替换为AddressC首次向WalletA转账的区块高度,减少查询量 fromBlock: 0, toBlock: 'latest' }; const transferEvents = await tokenBContract.getPastEvents('Transfer', filterOptions);
- 第三步:累加所有转账金额,注意处理代币精度,避免大数精度丢失:
let totalAmount = BigInt(0); transferEvents.forEach(event => { totalAmount += BigInt(event.returnValues.value); }); // 转换为用户可读金额,需获取TokenB的精度decimals const decimals = await tokenBContract.methods.decimals().call(); const readableTotal = web3.utils.toNumber( web3.utils.toBN(totalAmount.toString()).div(web3.utils.toBN(10).pow(decimals)) ); console.log('AddressC转给WalletA的TokenB总金额:', readableTotal);
注意事项
- 因你明确AddressC仅转出TokenB,也可以改为拉取AddressC的所有转出Transfer事件,过滤接收方为WalletA的记录累加,结果完全一致。
- 若单次查询区块范围过大触发RPC限制,可将
fromBlock到toBlock拆分为多个小区间分批查询,再合并结果累加即可。 - 所有金额计算优先使用BigInt或者Web3自带的BN类处理,避免JS原生数值类型的精度丢失问题。
内容的提问来源于stack exchange,提问作者mhmd
相关产品推荐
相关产品推荐

