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 总量。