tl;dr= (1)web3.eth.Contract
为 RDOC 部署地址初始化一个实例;然后 (2) call .getPastEvents('Transfer')
,然后 (3) 聚合Transfer.value
值的总和。
详细解答:
(1) 初始化合约实例
有一个 RPC 数据提供程序
GetBlock
,您可能认为它类似于支持 RSK的 Infura
。
为了查询大量数据,例如历史数据,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 个参数:
(我们在这里只关心我们目标的数量)
In web3.js, to get past events, you should specify the range of block numbers,
and then query the past events using .getPastEvents()
.
Assuming we want to calculate the total transaction volume
of RDOC in the past week, we can use the total number of seconds in a week
divided by the number of seconds per block.
7 * (24 * 60 * 60) / 30 = 20160
Note that as with other blockchains, the time per block is approximate,
therefore this gives us the number of blocks in approximately 1 week.
The exact number of blocks can also be calculated by inspecting block timestamps
// get the range of blocks to query
const rangeNumberOfBlocks = 20160;
const latestBlockNumber = await web3.eth.getBlockNumber().toNumber();
const blockRange = {
fromBlock: latestBlockNumber - rangeNumberOfBlocks,
toBlock: latestBlockNumber,
};
Now we can query past events:
// get past `Transfer` events
const events = await token.getPastEvents(
'Transfer',
blockRange,
);
(3) calculate the aggregate
Each event in the events
array contains the three event parameters,
as per the ERC20 specification, however, we are only interested in event.returnValues.value
.
Note that this is returned as a BN
(BigNumber),
and for good reason - it is a uint256
, which is too large for Javascript's built in Number
type.
Also note that this number has a certain number of decimal places that it should be divided by, also specified in the ERC20 specification.
// 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));
For most tokens, including RDOC, we expect decimalsExp
to be 1e18 (1000000000000000000).
Finally, we can loop over the events
, and calculate the aggregate value.
Below I'm using .iadd()
instead of .add()
so that the addition can occur in-place,
so as to avoid reassignment/ memory allocation overhead (but this is optional).
const sum = new web3.utils.BN(0);
for (let eventIdx = 0; eventIdx const event = events[eventIdx];
sum.iadd(
new web3.utils.BN(event.returnValues.value),
);
}
const displaySum = sum.div(decimalsExp).toString();
displaySum
should be the total amount of transacted RDOC for the selected time period.