如何以去中心化的方式访问Chainlink上一个代币的历史价格数据?

3

我需要获取一个特定时间段内某个代币的Chainlink价格,这个时间段根据用户输入而变化,但通常不会太长(最多1天到2周),根据代币的心跳。这用于计算智能合约和应用主页中支付的价格。

要获取历史价格数据,Chainlink需要一个“roundId”,这是一个非递增的值。

在Chainlink中,最佳方法是从给定的时间窗口获取所有roundIds或以开放、分散的方式记录它们,并可以在Solidity智能合约中访问它们?

1个回答

6
每个Chainlink价格数据源的代理合约可以有多个基础聚合器合约,其中一个被设置为任何时刻的“活动”聚合器。即每当Chainlink Labs团队部署聚合器的新版本时,他们会更新代理合约以将当前聚合器版本设置为新版本,并开始将所有新价格数据写入新聚合器。
基于此,如果您需要从过去几周或更长时间内了解代理合约/价格对的历史价格数据,则需要转到代理合约的当前聚合器,然后获取当前轮次信息(包括时间戳),然后在聚合器轮次中循环回溯,直到达到小于搜索参数时间戳的轮次。
要查找代理合约的当前聚合器合约地址,可以调用代理合约中的aggregator getter函数。
阶段ID可视为代理合约用于标识添加到代理的每个聚合器的递增ID编号,因此第一个是1,第二个是2等。要了解当前聚合器的当前阶段ID是什么,您可以使用代理合约中的phaseId getter函数。
聚合器轮次ID从1开始,每次增加1。例如,您可以使用聚合器latestRound getter函数查找它存储的最后一轮,然后从那个数字作为输入参数传递给getRoundData,然后减少这个数字并循环,直到达到您的时间点。
与聚合器轮次ID不同,代理轮次ID是那些像36893488147419113293这样的大而长的数字,实际上只是基于聚合器阶段ID和聚合器轮次ID的派生值。这样做是为了确保代理轮次ID始终增加,并且在不同聚合器之间永远不会有任何重叠,例如来自相位ID为1的聚合器的第5000轮应该具有比来自相位ID为2的聚合器的第5000轮更低的代理轮次ID。
在Solidity中,可以使用以下公式轻松复制代理轮次ID派生值,传递聚合器的相位ID和聚合器轮次ID。
return uint80(uint256(_phaseId) << 64 | _aggregatorRoundId);

您可以将计算出的值传递到代理合约的getRoundData函数中,并获得与给定聚合器轮次ID相应的聚合器合约调用getRoundData相同的数据结果。建议通过在etherescan上直接与这些函数交互并查看返回数据来玩弄它们。例如,在Kovan网络中,ETH/USD代理最新的聚合器
关于您第二个问题的答案,最好的方法是从“现在”开始,即获取最新的聚合器,在聚合器中获取最新的轮次,然后通过减少聚合器轮次ID来回溯时间,并继续获取定价信息,直到轮次时间戳为小于您搜索的时间戳。
最后,使用Solidity进行循环不太节省gas。您可以采取的另一种方法是将外部计算卸载到Oracle上,Oracle可以提供正确的轮次ID,然后您可以获取该ID并在链上验证结果。 这是一个例子,它以外部适配器的形式检索基于时间戳的历史价格数据,并在Kovan上运行了此实时版本,请查看自述文件以获取更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接