【问题标题】:What is the best way to access historical price data from Chainlink on a token in a decentralised manner?以去中心化方式从 Chainlink 访问代币历史价格数据的最佳方式是什么?
【发布时间】:2023-03-16 15:42:01
【问题描述】:

我需要获取代币从特定时间到最近一轮的 Chainlink 价格。此时间根据用户输入而有所不同,但根据令牌的心跳,将是相对较短的窗口(最多 1 天到 2 周)。这用于计算智能合约和应用程序主页上的支付价格。

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

从 Chainlink 获取给定时间窗口的所有 roundId 或以开放、去中心化且可在 Solidity 智能合约中访问的方式记录它们的最佳方式是什么?

【问题讨论】:

    标签: blockchain ethereum solidity chainlink thegraph


    【解决方案1】:

    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 轮应该具有比第 5000 轮更低的代理轮次 ID来自阶段 ID 为 2 的聚合器

    在 Solidity 中,您可以使用以下公式轻松复制代理轮 ID 派生值,传入聚合器的阶段 ID 和聚合器轮 ID

    return uint80(uint256(_phaseId) << 64 | _aggregatorRoundId);
    

    您甚至可以获取该派生值并将其传递给代理合约 getRoundData 函数,并获得与在给定聚合器轮 ID 的聚合器合约中调用 getRoundData 相同的数据结果。

    我发现解决这些问题的一个好方法是直接在 etherescan 上与函数进行交互,并查看返回的数据。即这里是 Kovan ETH/USD proxy 和它的 latest aggregator

    关于第二个问题的答案,最好的方法是从“现在”开始,即获取最新的聚合器,获取聚合器中的最新一轮,然后通过将聚合器轮次 ID 减 1 来及时返回,以及继续获取定价信息,直到回合时间戳为

    最后,在 Solidity 中循环并不是很省油。您可以采取的另一种方法是将外部计算卸载到预言机,预言机可以为您提供正确的轮 ID,然后您可以使用它并在链上验证结果。 Here's an example 采用外部适配器形式的该设计模式,该适配器根据时间戳检索历史价格数据。 Kovan 上也有这个运行的实时版本,查看自述文件了解更多信息

    【讨论】:

      猜你喜欢
      • 2020-09-22
      • 1970-01-01
      • 2010-10-11
      • 2013-12-03
      • 2017-12-20
      • 2018-02-24
      • 2011-06-16
      • 2010-09-22
      相关资源
      最近更新 更多