Как рассчитать общий объем транзакций для токена на RSK?

Я хотел бы узнать общий объем транзакций для RDOC с момента развертывания до настоящего момента.

Невозможно получить эту информацию из проводника блоков:0x2d919f19d4892381d58edebeca66d5642cef1a1f

Как лучше всего добиться этого с помощью RPC или web3.js?

2 ответа

Вы можете получить прошлые журналы

  • из блока при развертывании контракта

  • до текущего блока

  • излучается адресом контракта токена

  • где topics[0] является keccak256 подписи события

    В случае Transfer(address,address,uint256) событие, хеш keccak256 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

Поскольку первые два параметра события индексируются, они присутствуют в topics[1] (отправитель) и topics[2](получатель) каждого журнала событий. Третий параметр (количество) не проиндексирован, поэтому его значение указывается в поле (в виде шестнадцатеричного числа) каждого журнала событий.

Общий объем транзакций - это просто сумма всех переведенных сумм (от data поле).

Имейте в виду, что большинство провайдеров RPC разрешают доступ только к ограниченному количеству исторических блоков (например, максимум 100 блоков). Таким образом, вам, возможно, придется использовать другого провайдера или ваш собственный полный узел, чтобы получить доступ к более глубокой истории (например, 200 блоков).

tl; dr = (1) инициализация web3.eth.Contractэкземпляр для развернутого адреса RDOC; затем (2) позвонить .getPastEvents('Transfer'), то (3) суммируем сумму Transfer.value значения.

Подробный ответ:

(1) Инициируйте экземпляр контракта

Существует поставщик данных RPC,GetBlock, который вы можете считать похожим на Infura, поддерживающий RSK.

Для запроса больших объемов данных, таких как исторические данные,Websockets может быть быстрее / эффективнее, чем HTTP, поэтому давайте воспользуемся их конечной точкой RPC Websockets для RSK Mainnet:

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) Получить прошлые события

Согласно спецификации 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) рассчитать совокупный

Каждое событие в массиве содержит три параметра события в соответствии со спецификацией 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 за выбранный период времени.

Другие вопросы по тегам