我希望能够找出RDOC的交易总量,从部署到现在。
无法从块资源管理器获取此信息:0x2d919f19d4892381d58edebeca66d5642cef1a1f
使用RPC或web3.js获取此信息的最佳方法是什么?
您可以获得过去的日志
-
当合同部署时从块
-
直到当前块
-
由令牌合约地址发出
-
其中
topics[0]
是事件签名的keccak256在
Transfer(address,address,uint256)
事件的情况下,keccak256哈希为0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
由于事件的前两个参数是索引的,因此它们出现在每个事件日志的topics[1]
(发送方(和topics[2]
(接收方(字段中。第三个参数(amount(未编制索引,因此其值在每个事件日志的data
字段(作为十六进制数(中。
总交易量只是所有转移金额的总和(来自data
字段(。
请注意,大多数RPC提供程序只允许访问有限数量的历史块(例如,最多100个块(。因此,您可能必须使用不同的提供商或您自己的完整节点才能访问更深层次的历史记录(例如200个块(。
tl;dr=(1(初始化RDOC部署地址的web3.eth.Contract
实例;则(2(呼叫CCD_ 10,则(3(聚合CCD_ 11值的总和。
详细答案:
(1( 初始化合同实例
存在RPC数据提供者,GetBlock你可能会认为它类似于Infura支持RSK。
为了查询诸如历史数据之类的大量数据,Websocket可以比HTTP更快/更高效,因此,让我们为RSK主网使用他们的Websockets RPC端点:
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中,要获取过去的事件,您应该指定块号的范围,然后使用CCD_ 15查询过去的事件。假设我们要计算总交易量对于过去一周的RDOC,我们可以使用一周内的总秒数除以每个块的秒数。
7 * (24 * 60 * 60) / 30 = 20160
注意,与其他区块链一样,每个区块的时间是近似的,因此,这给了我们大约一周内的区块数量。块的确切数量也可以通过检查块时间戳来计算
// 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( 计算总
CCD_ 17阵列中的每个事件都包含三个事件参数,然而,根据ERC20规范,我们只对event.returnValues.value
感兴趣。
注意,这作为CCD_ 19(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
上循环,并计算合计值。
下面我使用CCD_ 24而不是CCD_,以避免重新分配/内存分配开销(但这是可选的(。
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的总额。