Как рассчитать общий объем транзакций для токена на RSK?
Я хотел бы узнать общий объем транзакций для RDOC с момента развертывания до настоящего момента.
Невозможно получить эту информацию из проводника блоков:0x2d919f19d4892381d58edebeca66d5642cef1a1f
Как лучше всего добиться этого с помощью RPC или web3.js?
2 ответа
Вы можете получить прошлые журналы
из блока при развертывании контракта
до текущего блока
излучается адресом контракта токена
где
topics[0]
является keccak256 подписи событияВ случае
Transfer(address,address,uint256)
событие, хеш keccak2560xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
Поскольку первые два параметра события индексируются, они присутствуют в
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 за выбранный период времени.