【问题标题】:How to calculate the total volume transacted for a token on RSK?如何计算 RSK 上代币的总交易量?
【发布时间】:2021-09-01 00:09:53
【问题描述】:

我希望能够找出 RDOC 的总交易量, 从部署到现在。

无法从区块浏览器获取此信息: 0x2d919f19d4892381d58edebeca66d5642cef1a1f

使用 RPC 或 web3.js 获取此信息的最佳方法是什么?

【问题讨论】:

  • 使用web3.eth.Contract 实例并调用.getPastEvents('Transfer'),然后聚合它们应该会给你答案

标签: javascript rpc web3js rsk


【解决方案1】:

你可以得到past logs

  • 合约部署时的区块

  • 直到当前块

  • 由代币合约地址发出

  • topics[0] 是事件签名的 keccak256

    Transfer(address,address,uint256)事件的情况下,keccak256哈希是0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

由于事件的前两个参数被索引,它们出现在每个事件日志的topics[1](发送者)和topics[2](接收者)字段中。第三个参数(金额)未编入索引,因此其值位于每个事件日志的 data 字段(作为十六进制数字)中。

总交易量只是所有转账金额的总和(来自data 字段)。

请注意,大多数 RPC 提供商只允许访问有限数量的历史区块(例如,最多 100 个区块)。因此,您可能必须使用不同的提供商或您自己的完整节点才能访问更深入的历史记录(例如 200 个区块)。

【讨论】:

    【解决方案2】:

    tl;dr= (1) 为 RDOC 部署地址初始化一个 web3.eth.Contract 实例; 然后(2)致电.getPastEvents('Transfer'), 然后 (3) 聚合 Transfer.value 值的总和。

    详细回答:

    (1) 初始化合约实例

    有一个 RPC 数据提供者, GetBlock 您可能会认为它类似于 Infura supports RSK.

    对于查询大量数据,例如历史数据, Websockets 可以比 HTTP 更快/更高效, 所以让我们将他们的 Websockets RPC 端点用于 RSK 主网:

    wss://rsk.getblock.io/mainnet/websocket

    // init web3 instance
    const GETBLOCK_API_KEY = /* copy the API key from GetBlock dashboard */;
    
    const rpcWebsocketsUrl =
      `wss://rsk.getblock.io/mainnet/websocket`;
    const rpcWebsocketsOptions = {
        timeout: 5000, // ms
        headers: {
          'x-api-key': GETBLOCK_API_KEY,
        },
    };
    const web3Provider = new Web3.providers.WebsocketProvider(
      rpcWebsocketsUrl,
      rpcWebsocketsOptions,
    );
    const web3 = new Web3(web3Provider);
    

    一旦我们准备好 web3 实例, 我们需要一个 ABI 和代币智能合约的部署地址:

    // init token contract instance
    const tokenAbi = require('./abi.json'); // any standard ERC20 ABI will suffice for this purpose
    const tokenAddress = '0x2d919f19d4892381d58edebeca66d5642cef1a1f'; // RDOC deployed address
    const token = new web3.eth.Contract(tokenAbi, tokenAddress);
    

    (2) 通过Transfer 事件

    根据 ERC20 规范, 每次在一个账户之间转移一定数量的代币 另一个账户,ERC20 智能合约应该发出一个Transfer 事件。 此事件包含 3 个参数:

    • 发件人地址,
    • 接收方地址,
    • 和金额。

    (我们只关心我们的目标的数量)

    在web3.js中,要获取过去的事件,你应该指定块号的范围, 然后使用.getPastEvents()查询过去的事件。 假设我们要计算总交易量 过去一周的RDOC,我们可以用一周的总秒数 除以每个块的秒数。

    7 * (24 * 60 * 60) / 30 = 20160

    请注意,与其他区块链一样,每个块的时间是近似的, 因此,这给了我们大约 1 周内的块数。 块的确切数量也可以通过检查块时间戳来计算

    // get the range of blocks to query
    const rangeNumberOfBlocks = 20160;
    const latestBlockNumber = await web3.eth.getBlockNumber().toNumber();
    const blockRange = {
      fromBlock: latestBlockNumber - rangeNumberOfBlocks,
      toBlock: latestBlockNumber,
    };
    

    现在我们可以查询过去的事件:

    // get past `Transfer` events
    const events = await token.getPastEvents(
      'Transfer',
      blockRange,
    );
    

    (3) 计算聚合

    events 数组中的每个事件都包含三个事件参数, 但是,根据 ERC20 规范,我们只对 event.returnValues.value 感兴趣。

    请注意,这是作为 BN (BigNumber) 返回的, 并且有充分的理由 - 它是一个 uint256,对于 JavaScript 内置的 Number 类型来说太大了。 另请注意,此数字有一定数量的小数位,应除以,这也在 ERC20 规范中指定。

    // prepare for division for decimal places
    const decimals = await token.methods.decimals().call();
    const decimalsExp = new web3.utils.BN(10).pow(new web3.utils.BN(decimals));
    

    对于大多数令牌,包括 RDOC,我们预计 decimalsExp 为 1e18 (1000000000000000000)。

    最后,我们可以遍历events,并计算聚合值。

    下面我使用.iadd()而不是.add(),以便可以就地进行添加, 以避免重新分配/内存分配开销(但这是可选的)。

      const sum = new web3.utils.BN(0);
      for (let eventIdx = 0; eventIdx < events.length; eventIdx += 1) {
        const event = events[eventIdx];
        sum.iadd(
          new web3.utils.BN(event.returnValues.value),
        );
      }
      const displaySum = sum.div(decimalsExp).toString();
    

    displaySum 应该是选定时间段内交易的 RDOC 总量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 2014-05-19
      • 2021-05-05
      • 1970-01-01
      • 2021-09-20
      • 2017-10-05
      相关资源
      最近更新 更多