简体   繁体   English

以去中心化方式从 Chainlink 访问代币历史价格数据的最佳方式是什么?

[英]What is the best way to access historical price data from Chainlink on a token in a decentralised manner?

I need to get the Chainlink prices of a token from a specific time to the most recent round.我需要获取从特定时间到最近一轮的代币的 Chainlink 价格。 This time varies based on user input but will be relatively short windows (1 day to 2 weeks max) based on the heartbeat of the token.此时间根据用户输入而有所不同,但会根据令牌的心跳相对较短 windows(最长 1 天到 2 周)。 This is used to calculate the price of a payout both in the smart contract and on the application homepage.这用于计算智能合约和应用程序主页上的支付价格。

To get historical price data Chainlink needs a 'roundId' which is a non-incremental value.要获取历史价格数据,Chainlink 需要一个“roundId”,它是一个非增量值。

What is the best way to either get all roundIds for the given time window from Chainlink or record them in a way that is open, decentralised and can be accessed in a solidity smart contract?从 Chainlink 获取给定时间 window 的所有 roundId 或以开放、去中心化且可以在可靠智能合约中访问的方式记录它们的最佳方法是什么?

Each proxy contract for a Chainlink Price Feed can have multiple underlying aggregator contracts, with one of them being set as the 'active' one at any given instance. Chainlink Price Feed 的每个代理合约都可以有多个底层聚合器合约,其中一个在任何给定实例中都被设置为“活动”。 Ie whenever the Chainlink Labs team deploys new versions of the aggregator, they update the proxy contract to set the current aggregator version to be the new one, and all new price data starts getting written to the new aggregator.也就是说,每当 Chainlink Labs 团队部署新版本的聚合器时,他们都会更新代理合约以将当前的聚合器版本设置为新版本,并且所有新的价格数据都开始写入新的聚合器。

Based on this, if you want historical price data for a proxy contract/price pair from the last couple weeks or so, you'd need to go to the current aggregator for the proxy contract, then get the current round info (including timestamp), then go back in aggregator rounds in a loop until you get to a round that is less than your search parameter timestamp.基于此,如果您想要过去几周左右的代理合约/价格对的历史价格数据,您需要 go 到代理合约的当前聚合器,然后获取当前轮次信息(包括时间戳) ,然后 go 在循环中返回聚合器轮次,直到您到达小于搜索参数时间戳的轮次。

To find the current aggregator contract address for a proxy contract, you can call the aggregator getter function in the proxy contract.要查找代理合约的当前聚合器合约地址,您可以在代理合约中调用aggregator getter function。

The phase ID can be thought of as an incrementing ID number that the proxy contract uses to identify each aggregator as it gets added to the proxy, so the first one is 1, second is 2 etc. To find out what the current phase ID is of the current aggregator, you can use the phaseId getter function in the proxy contract.阶段 ID 可以被认为是代理合约在添加到代理时用来识别每个聚合器的递增 ID 号,因此第一个是 1,第二个是 2,依此类推。找出当前阶段 ID 是什么对于当前聚合器,您可以在代理合约中使用phaseId getter function。

Aggregator round IDs start from 1 and increase by 1 each time.聚合器轮次 ID 从 1 开始,每次增加 1。 Eg you can use the aggregator latestRound getter function to find the last round that it stored, and then start from that number as an input parameter to getRoundData , and then reduce the number by one and loop through until you reach your point in time.例如,您可以使用聚合器latestRound getter function 来查找它存储的最后一轮,然后从该数字作为getRoundData的输入参数开始,然后将数字减一并循环直到到达您的时间点。

Unlike Aggregator round IDs, proxy round IDs are those big really long numbers like 36893488147419113293 , and are actually just a derived value based on the aggregator phase ID and the aggregator round ID.与聚合器轮 ID 不同,代理轮 ID 是那些非常长的数字,例如36893488147419113293 ,实际上只是基于聚合器阶段 ID 和聚合器轮 ID 的派生值。 This is done to ensure the proxy round IDs are always increasing in value, and that there will never be any overlap between the same rounds across different aggregators, eg round 5000 from aggregator with phase ID 1 should have a lower proxy round ID that round 5000 from aggregator with phase ID 2这样做是为了确保代理轮次 ID 的值始终在增加,并且不同聚合器之间的相同轮次之间永远不会有任何重叠,例如,来自具有阶段 ID 1 的聚合器的第 5000 轮应该具有比第 5000 轮更低的代理轮次 ID来自阶段 ID 为 2 的聚合器

In Solidity you can easily replicate the proxy round ID derived value with the following formula, passing in the phase ID of the aggregator and the aggregator round ID在 Solidity 中,您可以使用以下公式轻松复制代理轮 ID 派生值,传入聚合器的阶段 ID 和聚合器轮 ID

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

You can even then take that derived value and pass it into the proxy contract getRoundData function, and get the same data result as calling getRoundData in the aggregator contract for the given aggregator round ID.您甚至可以获取该派生值并将其传递给代理合约getRoundData function,并获得与在给定聚合器轮 ID 的聚合器合约中调用getRoundData相同的数据结果。

I find A good way to play around with these is to interact with the functions directly on etherescan, and see the data returned.我发现解决这些问题的一个好方法是直接在 etherescan 上与函数交互,并查看返回的数据。 Ie here's the Kovan ETH/USD proxy and its latest aggregator即这里是 Kovan ETH/USD 代理及其最新的聚合器

Regarding the answer your second question, the best way is to start from 'now', ie get the latest aggregator, grab the latest round in the aggregator and then go back in time by reducing the aggregator round ID by 1, and continue to get pricing info until the round timestamp is < your search timestamp.关于第二个问题的答案,最好的方法是从“现在”开始,即获取最新的聚合器,获取聚合器中的最新一轮,然后通过将聚合器轮 ID 减 1 来及时获取 go,然后继续获取直到回合时间戳<您的搜索时间戳的定价信息。

Finally, looping in Solidity is not very gas efficient.最后,Solidity 中的循环并不是很省气。 Another approach you can take is to off-load the external computation to an oracle, and the oracle can give you the correct round ID, and you can then take that and verify the results on-chain.您可以采取的另一种方法是将外部计算卸载到 oracle,oracle 可以为您提供正确的轮 ID,然后您可以使用它并在链上验证结果。 Here's an example of that design pattern in the form of an external adapter that retrieves historical price data based on a timestamp.这是该设计模式的一个示例,采用外部适配器的形式,它根据时间戳检索历史价格数据。 There is a live version of this running on Kovan too, check out the readme for more info Kovan 上也有此运行的实时版本,请查看自述文件以获取更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM