Оракул Chainlink

Oksana Kalanchina
7 min readMar 29, 2021

Вступление

Теперь разработчики могут использовать децентрализованную сеть Оракулов Chainlink, для сбора данных в Moonbase Alpha TestNet. В этом уроке рассматриваются два способа использования Оракулов Chainlink:

  • Базовая модель запроса — конечный пользователь отправляет запрос провайдеру Оракулов, который извлекает данные через API и выполняет запрос, сохраняя эти данные on-chain.
  • Price Feeds (Прайс Фиды) — данные постоянно обновляются операторами Оракулов в смарт-контракте так, чтобы другие смарт-контракты могли их получать

Базовая Модель Запроса

Прежде чем мы перейдем к извлечению самих данных, важно понять основы “базовой модели запроса”.

Нода Оракула имеет набор job ID, каждый из которых соответствует задаче, выполнение которой пользователь может запросить, например, чтобы получить прайс-фид. Для этого пользователю необходимо отправить запрос через контракт, назовем его Клиентским контрактом, передав следующую информацию:

· Адрес Оракула: адрес контракта, размещённого нодой Оракула

· Job ID: задача, которая должна быть выполнена

· Оплата: оплата в LINK токенах, которые Оракул получит за выполнение запроса

Этот запрос фактически отправляет TransferAndCall в контракт LINK токена, который обрабатывает платеж и ретранслирует запрос в контракт Оракула. Здесь вместе с запросом выдается событие, которое подхватывается нодой Оракула. Затем нода извлекает необходимые данные и выполняет функцию fulfilOracleRequest, которая выполняет колбек, хранящий запрошенную информацию в Клиентском контракте. Следующая диаграмма объясняет данный процесс.

Клиентский Контракт

Клиентский контракт — это элемент, который запускает интеграцию с Оракулом путем отправки запроса. Как показано на диаграмме, он вызывает метод TransferAndCall из контракта LINK токена, но для отслеживания запроса к Оракулу требуется дополнительная обработка. Для этого примера вы можете использовать код из данного файла и разместить его на Remix в качестве теста. Давайте рассмотрим основные функции контракта:

  • constructor: запускается при размещении контракта. Он устанавливает адрес LINK токена и владельца контракта
  • requestPrice: требует адрес контракта в Оракуле, job ID и токены оплаты (LINK) исполнителя запроса. Создает новый запрос, который отправляется с помощью функции sendChainlinkRequestTo из импорта ChainlinkClient.sol
  • fulfill: колбек, используемый нодой Оракула для выполнения запроса путем сохранения запрашиваемой информации в контракте.
pragma solidity ^0.6.6; import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";contract Client is ChainlinkClient {   
//... there is mode code here

constructor(address _link) public {
// Set the address for the LINK token for the network setChainlinkToken(_link);
owner = msg.sender;
}
function requestPrice(address _oracle, string memory _jobId, uint256 _payment)
public
onlyOwner
{
// newRequest takes a JobID, a callback address, and callback function as input Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), address(this), this.fulfill.selector);
// Sends the request with the amount of payment specified to the oracle sendChainlinkRequestTo(_oracle, req, _payment);
}

function fulfill(bytes32 _requestId, uint256 _price)
public
recordChainlinkFulfillment(_requestId)
{
currentPrice = _price;
}
//... there is more code here
}

Обратите внимание, что Клиентский контракт должен иметь LINK токены на балансе, чтобы иметь возможность оплатить данный запрос. Однако при размещении сетапа можно установить значение LINK равным 0 в контракте ChainlinkClient.sol, но вам все равно необходимо иметь размещенный LINK токен контракт.

Протестируйте это в Moonbase Alpha

Если вы хотите обойти стороной сложности, связанные с размещением всех контрактов, настройкой ноды Оракула, созданием job ID и т. д., то мы вам поможем.

Для вас доступен кастомный Клиентский контракт на Moonbase Alpha, который делает все запросы к нашему контракту в Оракуле с 0 оплатой. Эти запросы исполняются нодой Оракула, которую мы запускаем. Вы можете попробовать выполнить это на следующем Клиентском контракте, размещенном по адресу 0xe88ec866D05e637074B5a0D0d931f292d7871613:

pragma solidity ^0.6.6;  /**  
* @title Simple Interface to interact with Universal Client Contract
* @notice Client Address 0xe88ec866D05e637074B5a0D0d931f292d7871613
*/
interface ChainlinkInterface {

/**
* @notice Creates a Chainlink request with the job specification ID,
* @notice and sends it to the Oracle.
* @notice _oracle The address of the Oracle contract fixed top
* @notice _payment For this example the PAYMENT is set to zero
* @param _jobId The job spec ID that we want to call in string format
*/
function requestPrice(string calldata _jobId) external;

function currentPrice() external view returns (uint);
}

Это дает нам две функции. requestPrice(), которой нужен только job ID данных, которые вы хотите запросить. Эта функция запускает цепь событий, описанных ранее. currentPrice () — это функция представления, которая возвращает последнюю цену, хранящуюся в контракте.

В настоящее время в ноде Оракула имеется набор Job ID для различных прайсов по следующим парам:

Двинемся далее и используем интерфейсный контракт с Job ID BTC в USD в Remix.

После создания файла и компиляции контракта перейдите на вкладку “Deploy and Run Transactions”, введите адрес Клиентского контракта и нажмите кнопку “At Address”. Убедитесь, что вы установили “Environment” в “Injected Web3” для подключения к Moonbase Alpha. Это создаст экземпляр клиентского контракта, с которым вы сможете взаимодействовать. Используйте функцию requestPrice() для запроса данных соответствующего Job ID. После подтверждения транзакции мы должны ждать, пока не завершится весь процесс, указанный ранее. Мы можем проверить цену с помощью функции currentPrice().

Если у вас есть какая — то конкретная пара, которую вы хотите, чтобы мы включили в список, не стесняйтесь обращаться к нам через наш сервер в Discord.

Запуск собственного Клиентского контракта

Если вы хотите запустить свой Клиентский контракт, но используете нашу ноду Оракула, вы можете сделать это с помощью данных, указанных ниже:

Обратите внимание, что оплата LINK токенами = 0.

Другие Запросы

Оракулы Chainlink могут предоставлять множество различных типов каналов данных с использованием внешних адаптеров. Однако для простоты наша нода Оракула настроена на предоставление только прайс-фидов.

Если вы заинтересованы в запуске собственной ноды Оракула в Moonbeam, пожалуйста, прочитайте этот гайд. Кроме того, мы рекомендуем ознакомиться с документацией Chainlink на сайте.

Прайс-фиды

Прежде чем мы перейдем к извлечению самих данных, важно понять основы прайс-фидов.

В стандартной конфигурации каждый прайс-фид обновляется децентрализованной сетью Оракула. Каждая нода Оракула получает вознаграждение за публикацию прайс-фидов в контракте Агрегатора. Однако информация обновляется только в том случае, если получено минимальное количество ответов от нод Оракулов (во время раунда агрегации).

Конечный пользователь может получать прайс-фиды с помощью read-only операций через Потребительский контракт, ссылаясь на правильный интерфейс агрегатора (Прокси-контракт). Прокси выступает в качестве промежуточного программного обеспечения для предоставления Потребителю наиболее актуального Агрегатора для конкретного прайс-фида.

Протестируйте это в Moonbase Alpha

Если вы хотите обойти стороной сложности, связанные с размещением всех контрактов, настройкой ноды Оракула, созданием job ID и т. д., то мы вам поможем.

Мы разместили все необходимые контракты на Moonbase Alpha, чтобы упростить процесс запроса прайс-фидов. В нашей текущей конфигурации мы запускаем только одну ноду Оракула, которая получает цену из одного источника API. Данные по ценам проверяются каждую минуту и обновляются в смарт-контрактах каждый час, если только отклонение цены не составляет 1%.

Данные хранятся в серии смарт-контрактов (по одному на прайс-фид) и могут быть извлечены с помощью следующего интерфейса:

pragma solidity ^0.6.6;interface ConsumerV3Interface {
/**
* Returns the latest price
*/
function getLatestPrice() external view returns (int);
/**
* Returns the decimals to offset on the getLatestPrice call
*/
function decimals() external view returns (uint8);

/**
* Returns the description of the underlying price feed aggregator
*/
function description() external view returns (string memory);
}

Это обеспечивает три функции. getLatestPrice() будет считывать последние данные по ценам, доступные в контракте Агрегатора через Прокси. Мы добавили функцию decimals(), которая возвращает количество десятичных знаков данных, и функцию description(), которая возвращает краткое описание прайс-фида, доступного в запрашиваемом контракте Агрегатора.

В настоящее время существует Потребительский контракт для следующих ценовых пар:

Давайте двинемся дальше и используем интерфейсный контракт для получения прайс-фида BTC в USD с помощью Remix.

После создания файла и компиляции контракта перейдите на вкладку “Deploy and Run Transactions”, введите адрес Потребительского контракта, соответствующий BTC to USD, и нажмите кнопку “At Address”. Убедитесь, что вы установили “Environment” в “Injected Web3”для подключения к Moonbase Alpha.

Это создаст экземпляр Потребительского контракта, с которым вы сможете взаимодействовать. Используйте функцию getLatestPrice() для запроса данных соответствующего прайс-фида.

Обратите внимание, что для получения реальной цены необходимо учитывать десятичные дроби прайс-фида, доступные при вызове метода decimals().

Если у вас есть какая-то конкретная пара, которую вы хотите, чтобы мы включили в список, не стесняйтесь обращаться к нам через наш сервер в Discord.

Обратная связь

Если у вас есть фидбек относительно реализации Chainlink в вашем проекте или по любой другой теме, связанной с Moonbeam, не стесняйтесь обращаться к нам через наш официальный сервер в Discord.

--

--