Документация оракула

Подписанные цены на валюты и драгоценные металлы, которые ваши смарт-контракты проверяют on-chain. Обзор: страница оракула · машиночитаемо: /v1/oracle/feeds, /v1/oracle/catalog.

1. Как это работает

  1. Ваш бэкенд запрашивает подписанный отчёт: GET https://api.marketapi.app/v1/oracle/report?symbols=XAUUSD&chain_id=10 (ключ API с областью read:oracle; оплата за каждый подписанный отчёт).
  2. Ваша транзакция передаёт отчёт и подпись контракту-верификатору, который проверяет подпись EIP-712, срок действия, сеть и свой стоп-механизм, а затем сохраняет цену.
  3. В той же транзакции ваш контракт читает цену с требованием актуальности. Эта pull-схема всегда использует текущую цену.

Цены, запрошенные через API, также время от времени автоматически отправляются on-chain, но никогда не полагайтесь на сохранённую цену без проверки актуальности.

2. Сети и контракты

СетьID сетиКонтракт-верификатор
Optimism100xaeF7f701acFB42267015D3F593ce17CF536Afd6B · обозреватель
Optimism Sepolia тестнет111554200xBBf36E7Cd75494f28E02C5698EaD35fF4960a943 · обозреватель

Адрес подписанта: 0x83fa2d8836525251FAd214A78A72038D0864f877. Тестнеты предназначены для бесплатного тестирования без гарантий обслуживания.

3. Фиды

У каждого фида постоянный ID: feedId = keccak256(symbol). Цены используют 8 знаков после запятой.

СимволfeedId
AUDUSD0x5577fa17b1be8ae0f1517fe1864ea534d6992f3721000cdb6585b11e7046d5ec
EURGBP0xeaff3420d70d388655273db9b4f3000962445a6f0ea23ec1f04d843e4dbae4b0
EURUSD0x0730076c3c0f5da594eb635c5d5a22116233bdb2a9c2977279cc348b8b8ce917
GBPUSD0xd30842147b60fe333c2700bcae5eee6815b8529847955d19522858806bca8217
IEF0x309dab183458dd939568dca0d68bea45d34aa25d31fa47fc5f12030e8f227f4e
OILCash#0xe21b90a237aa0663c02092eca221a0098c6c477054a61d05ecd3692f6631f6ff
SHY0x78f1083af8e72ddefc2e66fad95680c38a953b3136f413c61ab40f99b72991bc
SPY0xcea23e8f56b5ac447ac08d57e0808e35f468a65f29bb659b3d48934481e7c67a
TLT0x4abd434857e07567d49487ccf888348e55d5cfc15498c09a9dbcba2820e40ee4
USDCAD0xa36f6cf3195abb4e93bf276660acee423f78878e6cfdbad0eab36e455afca97e
USDCHF0xd85af9ebd6fec6b317a7ac07f6d6455c4fc915cc8e1cfe19471faca002582907
USDJPY0x3d6c40e9d821c10e442cb3fc6cb1c589ffd8b906e734a1ab3b3f7d213ac395d6
USDSGD0x8a1375bd16e33aff9be7037f83e076defe9df6efea6d39a51d0b08f17ac9bc6d
XAGUSD0x67107df7f0e95594d9bf8ad8840bbb2ff95617123c227e10aab4d161dd6959b6
XAUUSD0xe21c86d8b6a127bfef214d88fdb0c279e55d27dd8c443733e46c8d3de3c98cd6

4. Подписанный отчёт

Домен EIP-712: имя MarketAPI Oracle, версия 2, ID сети и адрес верификатора. Тип:

PriceReport(bytes32 feedId,int256 price,uint64 timestamp,uint64 validUntil,uint8 marketStatus,uint32 spreadBps)

Ответ API содержит report (ABI-кодированный) и signature (65 байт) — ровно два аргумента submit.

5. Функции контракта

У каждого фида есть стоп-механизм: скачок больше его лимита приостанавливает фид до проверки.

6. Пример на Solidity (pull-схема)

interface IMarketApiOracle {
    struct PriceReport { bytes32 feedId; int256 price; uint64 timestamp; uint64 validUntil; uint8 marketStatus; uint32 spreadBps; }
    function submit(PriceReport calldata r, bytes calldata sig) external returns (bool);
    function getPriceNoOlderThan(bytes32 feedId, uint256 maxAge) external view returns (int256 price, uint64 timestamp);
}

contract GoldVault {
    IMarketApiOracle immutable oracle;
    bytes32 constant XAUUSD = keccak256("XAUUSD");
    constructor(IMarketApiOracle o) { oracle = o; }

    function settle(IMarketApiOracle.PriceReport calldata r, bytes calldata sig) external {
        oracle.submit(r, sig);
        (int256 price, ) = oracle.getPriceNoOlderThan(XAUUSD, 60);   // reverts unless OPEN and at most 60 s old
        // ... use price (8 decimals)
    }
}

7. Пример на JavaScript (ethers v6)

const res = await fetch("https://api.marketapi.app/v1/oracle/report?symbols=XAUUSD&chain_id=10",
  { headers: { Authorization: `Bearer ${process.env.API_KEY}` } });
const { data, refused } = await res.json();
if (!data.length) throw new Error(refused[0]?.reason);            // e.g. market closed or stale
const r = data[0];
const report = ethers.AbiCoder.defaultAbiCoder().decode(
  ["tuple(bytes32,int256,uint64,uint64,uint8,uint32)"], r.report)[0];
await vault.settle(report, r.signature);                          // your contract calls oracle.submit(...)

8. Отказы и ошибки

9. Рекомендации