使用 Web3.js 获取从特定地址收到的令牌总量

Posted

技术标签:

【中文标题】使用 Web3.js 获取从特定地址收到的令牌总量【英文标题】:Get total amount of tokens received from a specific address using Web3.js 【发布时间】:2021-12-04 16:34:18 【问题描述】:

在一个场景中,WalletA 定期从 AddressC 接收 TokenB。 AddressC 只发送 TokenB,没有别的。

在 etherscan 或 bscscan 中,很容易查看 WalletA 中收到了多少 TokenB,并且存在“from”字段,因此您可以做一些数学运算来获得总数。

如何使用 web3 做到这一点?我在 web3 文档中找不到任何相关的 api 调用。 我可以通过 web3.js 获得 WalletA 中 TokenB 的总余额,但我需要从 AddressC 发送的令牌计数。

谢谢。

【问题讨论】:

【参考方案1】:

根据ERC-20 标准,每次令牌传输都会发出一个Transfer() 事件日志,其中包含发送方地址、接收方地址和令牌数量。

您可以使用web3js通用方法web3.eth.getPastLogs()获取过去的事件日志,对输入进行编码和对输出进行解码。

或者您可以提供合约的 ABI JSON(在这种情况下,只使用 Transfer() 事件定义就足够了)并使用 web3js 方法 web3.eth.Contract.getPastEvents(),它根据您对输入进行编码并解码输出在提供的 ABI JSON 上。

const Web3 = require('web3');
const web3 = new Web3('<provider_url>');

const walletA = '0x3cd751e6b0078be393132286c442345e5dc49699'; // sender
const tokenB = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; // token contract address
const addressC = '0xd5895011F887A842289E47F3b5491954aC7ce0DF'; // receiver

// just the Transfer() event definition is sufficient in this case
const abiJson = ["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"];
const contract = new web3.eth.Contract(abiJson, tokenB);

const fromBlock = 10000000;
const toBlock = 13453500;
const blockCountIteration = 5000;

const run = async () => 
    let totalTokensTranferred = 0;

    for (let i = fromBlock; i <= (toBlock - blockCountIteration); i += blockCountIteration) 
        //console.log("Requesting from block", i, "to block ", i + blockCountIteration - 1);
        const pastEvents = await contract.getPastEvents('Transfer', 
            'filter': 
                'from': walletA,
                'to': addressC,
            ,
            'fromBlock': i,
            'toBlock': i + blockCountIteration - 1,
        );
    

    for (let pastEvent of pastEvents) 
        totalTokensTranferred += parseInt(pastEvent.returnValues.value);
    

    console.log(totalTokensTranferred);


run();

【讨论】:

我认为第二个“fromblock”应该是“toblock”,并且我可以使用此代码获得输出,但由于我收到此错误,我不知道结果是否正确。 ///// Uncaught (in promise) 错误:返回错误:超出最大块范围:5000 ///// 我的 fromblock 是创建令牌的块,toblock 是当前块,它肯定高于 5000 个块。有什么解决方法可以覆盖它吗? @mhmd 谢谢,我在我的回答中修复了它......“超过最大块范围”错误消​​息来自您的 RPC 提供商(Infura 或类似的)。您始终可以使用不施加这些限制的自托管节点,否则您需要寻找提供符合您需要的限制的提供商。 我在 bsc 上使用 web3 和这个提供商 web3 = new Web3('bsc-dataseed.binance.org/'); ///// 你知道其他没有块范围限制的 bsc 提供者吗? 或者我可以为每 5000 个块运行一个循环吗?还是它也有一些限制? @mhmd 除了devs page 中列出的“官方”供应商之外,我不知道有任何第三方 BSC 供应商。在同步循环中运行,等待每个批次处理,可能会有所帮助,但随后您可能会遇到其他速率限制,例如每分钟的请求总数。对于这个规模,我真的建议运行你的own fullnode,它不会施加任何限制。

以上是关于使用 Web3.js 获取从特定地址收到的令牌总量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SOLANA 上使用 web3 js 从令牌地址获取元数据

使用 @Solana\web3.js 传输 SPL 令牌

无法使用 web3.js 发送 ERC20 令牌

如何获取在与@solana/web3.js 的交易中转移的自定义令牌数量?

如何使用 @solana/web3.js 从 Solana 中的自定义令牌中删除铸币权限?

Web3j:获取使用交易哈希传输的交易令牌的价值