Как лучше всего децентрализованно получить доступ к историческим ценовым данным из Chainlink по токену?
Мне нужно получить цены на токен Chainlink с определенного времени до самого последнего раунда. Это время зависит от ввода пользователя, но будет относительно коротким (максимум от 1 дня до 2 недель) в зависимости от такта токена. Это используется для расчета цены выплаты как в смарт-контракте, так и на домашней странице приложения.
Чтобы получить исторические данные о ценах, Chainlink нужен roundId, который не является инкрементным значением.
Как лучше всего получить все roundId для заданного временного окна из Chainlink или записать их открытым, децентрализованным способом, к которому можно получить доступ в надежном смарт-контракте?
1 ответ
Каждый прокси-контракт для канала цен Chainlink может иметь несколько базовых контрактов агрегатора, причем один из них устанавливается как «активный» в любой момент времени. То есть всякий раз, когда команда Chainlink Labs развертывает новые версии агрегатора, они обновляют прокси-контракт, чтобы установить текущую версию агрегатора в качестве новой, и все новые данные о ценах начинают записываться в новый агрегатор.
Исходя из этого, если вам нужны исторические данные о ценах для пары прокси-контракт/цена за последние пару недель или около того, вам нужно перейти к текущему агрегатору для прокси-контракта, а затем получить информацию о текущем раунде (включая метку времени) , затем возвращайтесь к раундам агрегатора в цикле, пока не дойдете до раунда, который меньше временной метки параметра поиска.
Чтобы узнать текущий адрес контракта агрегатора для прокси-контракта, вы можете вызвать
aggregator
функция getter в прокси-контракте.
Идентификатор фазы можно рассматривать как увеличивающийся идентификационный номер, который прокси-контракт использует для идентификации каждого агрегатора по мере его добавления к прокси, поэтому первый — 1, второй — 2 и т. д. Чтобы узнать, какой текущий идентификатор фазы текущего агрегатора, вы можете использовать функцию получения PhaseId в прокси-контракте.
Идентификаторы раундов агрегатора начинаются с 1 и каждый раз увеличиваются на 1. Например, вы можете использовать агрегатор
latestRound
getter, чтобы найти последний раунд, который он сохранил, а затем начать с этого числа в качестве входного параметра до , а затем уменьшить число на единицу и выполнять цикл, пока не достигнете нужного момента времени.
В отличие от идентификаторов раундов агрегатора, прокси-идентификаторы раундов — это очень длинные числа, такие как
36893488147419113293
, и на самом деле являются производным значением, основанным на идентификаторе фазы агрегатора и идентификаторе раунда агрегатора. Это делается для того, чтобы идентификаторы прокси-раундов всегда увеличивались в значении и чтобы никогда не было перекрытия между одними и теми же раундами на разных агрегаторах, например, раунд 5000 от агрегатора с идентификатором фазы 1 должен иметь более низкий идентификатор раунда прокси, чем раунд 5000. от агрегатора с идентификатором фазы 2
В Solidity вы можете легко реплицировать полученное значение идентификатора раунда прокси с помощью следующей формулы, передавая идентификатор фазы агрегатора и идентификатор раунда агрегатора.
return uint80(uint256(_phaseId) << 64 | _aggregatorRoundId);
Вы даже можете затем взять это производное значение и передать его в функцию прокси-контракта и получить тот же результат данных, что и при вызове
getRoundData
в контракте агрегатора для данного идентификатора раунда агрегатора.
Я считаю, что хорошим способом поиграть с ними является взаимодействие с функциями непосредственно на etherescan и просмотр возвращенных данных. То есть вот прокси Kovan ETH/USD и его последний агрегатор
Что касается ответа на ваш второй вопрос, лучше всего начать с «сейчас», т.е. получить последний агрегатор, получить последний раунд в агрегаторе, а затем вернуться во времени, уменьшив идентификатор раунда агрегатора на 1, и продолжить получать информацию о ценах до тех пор, пока временная метка раунда не станет < временной метки вашего поиска.
Наконец, зацикливание в Solidity не очень экономично. Другой подход, который вы можете использовать, — это передать внешние вычисления оракулу, и оракул может дать вам правильный идентификатор раунда, а затем вы можете взять его и проверить результаты в цепочке. Вот пример этого шаблона проектирования в виде внешнего адаптера, который извлекает исторические данные о ценах на основе метки времени. На Коване также есть живая версия, ознакомьтесь с информацией для получения дополнительной информации.