Oráculo de precios on-chain · fuentes de precios de activos reales

Oráculo de precios para contratos inteligentes: divisas, oro, índices y acciones on-chain

Obtén un informe de precio firmado de nuestra API y pásalo a tu contrato. Nuestro contrato verificador comprueba la firma on-chain, así tu contrato puede confiar en el precio sin confiar en el mensajero.

Cómo funciona

  1. Obtén un informe firmado: GET /oracle/report con tu clave API.
  2. Envíalo en tu transacción: nuestro contrato verificador comprueba la firma con ecrecover.
  3. Usa el precio verificado; recházalo si es demasiado antiguo para tu caso de uso.

Los informes son datos tipados EIP-712 PriceReport(bytes32 feedId,int256 price,uint64 timestamp,uint64 validUntil,uint8 marketStatus,uint32 spreadBps), ligados a una cadena y a un contrato verificador (sin reutilización en otro sitio) y aceptados solo hasta validUntil, alrededor de un minuto tras la firma (no se pueden acumular informes favorables). Los precios son el punto medio entre compra y venta con 8 decimales; spreadBps es el diferencial compra-venta. Cuando envías un informe en tu propia transacción, pagas ese gas. Nuestro relayer también guarda on-chain de vez en cuando las fuentes con demanda (lectura gratuita), pero comprueba siempre la antigüedad de un precio guardado.

Horario de mercado

Cada informe indica el estado del mercado: OPEN (un precio en vivo, de como máximo 60 segundos), CLOSED (el último precio oficial antes del cierre, igual para todos, firmado en cualquier momento mientras el mercado está cerrado) o HALTED (negociación suspendida). getPriceNoOlderThan solo devuelve precios OPEN, así un precio de cierre nunca puede pasar por uno en vivo. Los tokens respaldados por activos deberían liquidar las órdenes dadas con el mercado cerrado al siguiente precio OPEN (forward pricing, como hacen los fondos y ETF).

Cortacircuitos

Cada fuente puede tener un salto máximo permitido. Un movimiento mayor no se guarda: la fuente se pausa hasta que la hayamos revisado y reabierto, así un precio erróneo o manipulado nunca llega a tu contrato.

Fuentes

SímbolofeedId
AUDUSD0x5577fa17b1be8ae0f1517fe1864ea534d6992f3721000cdb6585b11e7046d5ec
EURGBP0xeaff3420d70d388655273db9b4f3000962445a6f0ea23ec1f04d843e4dbae4b0
EURUSD0x0730076c3c0f5da594eb635c5d5a22116233bdb2a9c2977279cc348b8b8ce917
GBPUSD0xd30842147b60fe333c2700bcae5eee6815b8529847955d19522858806bca8217
IEF0x309dab183458dd939568dca0d68bea45d34aa25d31fa47fc5f12030e8f227f4e
OILCash#0xe21b90a237aa0663c02092eca221a0098c6c477054a61d05ecd3692f6631f6ff
SHY0x78f1083af8e72ddefc2e66fad95680c38a953b3136f413c61ab40f99b72991bc
SPY0xcea23e8f56b5ac447ac08d57e0808e35f468a65f29bb659b3d48934481e7c67a
TLT0x4abd434857e07567d49487ccf888348e55d5cfc15498c09a9dbcba2820e40ee4
USDCAD0xa36f6cf3195abb4e93bf276660acee423f78878e6cfdbad0eab36e455afca97e
USDCHF0xd85af9ebd6fec6b317a7ac07f6d6455c4fc915cc8e1cfe19471faca002582907
USDJPY0x3d6c40e9d821c10e442cb3fc6cb1c589ffd8b906e734a1ab3b3f7d213ac395d6
USDSGD0x8a1375bd16e33aff9be7037f83e076defe9df6efea6d39a51d0b08f17ac9bc6d
XAGUSD0x67107df7f0e95594d9bf8ad8840bbb2ff95617123c227e10aab4d161dd6959b6
XAUUSD0xe21c86d8b6a127bfef214d88fdb0c279e55d27dd8c443733e46c8d3de3c98cd6

Redes

RedID de cadenaContrato verificador
Optimism100xaeF7f701acFB42267015D3F593ce17CF536Afd6B
Optimism Sepolia testnet111554200xBBf36E7Cd75494f28E02C5698EaD35fF4960a943

Dirección del firmante: 0x83fa2d8836525251FAd214A78A72038D0864f877. Lista legible por máquina: /oracle/feeds.

Integrar

1. Obtén un informe firmado

curl -H "Authorization: Bearer $API_KEY" \
  "https://api.marketapi.app/v1/oracle/report?symbols=EURUSD&chain_id=10"

Devuelve report (la tupla codificada en ABI) y signature (65 bytes) por símbolo. Tu clave necesita el ámbito read:oracle.

2. Verifícalo en tu contrato

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);  // verifies, stores if newer
    function getPriceNoOlderThan(bytes32 feedId, uint256 maxAge)
        external view returns (int256 price, uint64 timestamp);   // OPEN and fresh only, else reverts
    function getPrice(bytes32 feedId) external view
        returns (int256 price, uint64 timestamp, uint8 marketStatus, uint32 spreadBps);   // incl. CLOSED
}

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

    function act(IMarketApiOracle.PriceReport calldata r, bytes calldata sig) external {
        oracle.submit(r, sig);                                       // reverts on a bad signature
        (int256 price, ) = oracle.getPriceNoOlderThan(EURUSD, 60);   // 8 decimals
        // ... use price ...
    }
}

Los consumidores al estilo Chainlink pueden leer una fuente mediante el MarketApiFeedAdapter (latestRoundData(), AggregatorV3Interface).

Precios

5 crédito(s) por informe firmado, pagado(s) con tu saldo normal de la API. Leer precios ya guardados on-chain es gratis.

Casos de uso de nuestras fuentes de precios on-chain

¿Por qué un oráculo pull firmado?

Los oráculos push se actualizan según un calendario y alguien paga gas por cada actualización. Con un oráculo pull tu contrato obtiene un precio fresco y firmado criptográficamente justo cuando lo necesita: menor coste, datos más frescos y la misma verificación on-chain. El estado del mercado, el diferencial compra-venta y la caducidad forman parte de cada informe firmado.

Preguntas frecuentes del oráculo de precios

¿Qué es un oráculo de precios blockchain?

Un oráculo de precios lleva precios de mercado off-chain a los contratos inteligentes. Nuestro oráculo firma cada precio con una firma EIP-712; tu contrato la verifica on-chain con ecrecover antes de usarlo, así el precio no puede falsificarse por el camino.

¿Qué activos cubren las fuentes de precios?

Pares de divisas como EUR/USD, metales preciosos como el oro (XAU/USD) y la plata, índices bursátiles y acciones individuales, según la lista de fuentes publicada en esta página. Cada fuente tiene un feedId fijo (keccak256 del símbolo).

¿Sirve para RWA y activos tokenizados?

Sí. Los informes incluyen el estado del mercado (abierto, cerrado, suspendido), así las acciones tokenizadas, las materias primas y otros activos reales pueden aplicar forward pricing fuera del horario de mercado en lugar de operar con un precio desfasado.

¿Es el oráculo compatible con Chainlink?

Cada fuente puede leerse mediante un adaptador que implementa la AggregatorV3Interface de Chainlink (latestRoundData), así el código DeFi existente que lee fuentes de precios al estilo Chainlink funciona con cambios mínimos.

¿Cómo se evita la manipulación?

Los informes caducan en alrededor de un minuto y deben ser más recientes que el precio guardado, un cortacircuitos por fuente pausa una fuente tras un salto anómalo y, con varios brókers, el precio es la mediana de fuentes independientes sin valores atípicos.

¿Quién paga el gas?

Es un oráculo pull: tu aplicación envía el informe firmado en su propia transacción y paga ese gas. Nuestro relayer también guarda on-chain de vez en cuando las fuentes con demanda; leer los precios guardados es gratis, pero comprueba su antigüedad antes de usarlos.

¿Qué blockchains se admiten?

Cualquier cadena EVM donde esté desplegado el contrato verificador, por ejemplo Ethereum, Base, Arbitrum, Optimism, BNB Smart Chain y Polygon y sus testnets; la lista actual se muestra arriba.

Recomendado: el patrón pull (precios siempre frescos)

No confíes en el precio ya guardado on-chain. Obtén un informe recién firmado y envíalo en la misma transacción que lo usa: tu contrato siempre ve el precio actual y solo pagas tus propias actualizaciones.

// 1) off-chain: GET https://api.marketapi.app/v1/oracle/report?symbols=EURUSD&chain_id=CHAIN_ID  (header: Authorization: Bearer KEY)
// 2) on-chain: verify, store and use the report atomically
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 MyVault {
    IMarketApiOracle immutable oracle;
    bytes32 constant EURUSD = keccak256("EURUSD");
    constructor(IMarketApiOracle o) { oracle = o; }

    function settle(IMarketApiOracle.PriceReport calldata r, bytes calldata sig) external {
        oracle.submit(r, sig);                                         // ignored if an equal/newer price is stored
        (int256 price, ) = oracle.getPriceNoOlderThan(EURUSD, 60);    // reverts unless OPEN and fresh
        // ... use price (8 decimals)
    }
}

Los campos report y signature del informe que da la API son exactamente los dos argumentos de submit. Los informes son válidos alrededor de un minuto, así que obténlos justo antes de enviar la transacción.

Aviso de riesgo. Los precios son datos de mercado indicativos de nuestra fuente, no un centro de ejecución. Los contratos inteligentes que mueven fondos según cualquier oráculo deben comprobar la antigüedad, gestionar las actualizaciones que falten y limitar el impacto de un precio erróneo. Lee las condiciones antes de confiar en el oráculo en producción.