Documentation de l’oracle
Des prix signés de devises et de métaux précieux que vos smart contracts vérifient on-chain. Aperçu : page de l’oracle · lisible par machine : /v1/oracle/feeds, /v1/oracle/catalog.
1. Fonctionnement
- Votre backend demande un rapport signé :
GET https://api.marketapi.app/v1/oracle/report?symbols=XAUUSD&chain_id=10(clé API avec la portéeread:oracle; facturé par rapport signé). - Votre transaction transmet le rapport et la signature au contrat vérificateur, qui contrôle la signature EIP-712, l’expiration, la chaîne et son coupe-circuit, puis enregistre le prix.
- Dans la même transaction, votre contrat lit le prix avec une exigence de fraîcheur. Ce modèle pull utilise toujours le prix actuel.
Les prix demandés via l’API sont aussi poussés on-chain automatiquement de temps en temps, mais ne vous fiez jamais à un prix enregistré sans contrôle de fraîcheur.
2. Réseaux et contrats
| Réseau | ID de chaîne | Contrat vérificateur |
|---|---|---|
| Optimism | 10 | 0xaeF7f701acFB42267015D3F593ce17CF536Afd6B · explorateur |
| Optimism Sepolia testnet | 11155420 | 0xBBf36E7Cd75494f28E02C5698EaD35fF4960a943 · explorateur |
Adresse du signataire : 0x83fa2d8836525251FAd214A78A72038D0864f877. Les testnets servent à des tests gratuits sans garantie de service.
3. Flux
Chaque flux a un ID permanent : feedId = keccak256(symbol). Les prix utilisent 8 décimales.
| Symbole | feedId |
|---|---|
AUDUSD | 0x5577fa17b1be8ae0f1517fe1864ea534d6992f3721000cdb6585b11e7046d5ec |
EURGBP | 0xeaff3420d70d388655273db9b4f3000962445a6f0ea23ec1f04d843e4dbae4b0 |
EURUSD | 0x0730076c3c0f5da594eb635c5d5a22116233bdb2a9c2977279cc348b8b8ce917 |
GBPUSD | 0xd30842147b60fe333c2700bcae5eee6815b8529847955d19522858806bca8217 |
IEF | 0x309dab183458dd939568dca0d68bea45d34aa25d31fa47fc5f12030e8f227f4e |
OILCash# | 0xe21b90a237aa0663c02092eca221a0098c6c477054a61d05ecd3692f6631f6ff |
SHY | 0x78f1083af8e72ddefc2e66fad95680c38a953b3136f413c61ab40f99b72991bc |
SPY | 0xcea23e8f56b5ac447ac08d57e0808e35f468a65f29bb659b3d48934481e7c67a |
TLT | 0x4abd434857e07567d49487ccf888348e55d5cfc15498c09a9dbcba2820e40ee4 |
USDCAD | 0xa36f6cf3195abb4e93bf276660acee423f78878e6cfdbad0eab36e455afca97e |
USDCHF | 0xd85af9ebd6fec6b317a7ac07f6d6455c4fc915cc8e1cfe19471faca002582907 |
USDJPY | 0x3d6c40e9d821c10e442cb3fc6cb1c589ffd8b906e734a1ab3b3f7d213ac395d6 |
USDSGD | 0x8a1375bd16e33aff9be7037f83e076defe9df6efea6d39a51d0b08f17ac9bc6d |
XAGUSD | 0x67107df7f0e95594d9bf8ad8840bbb2ff95617123c227e10aab4d161dd6959b6 |
XAUUSD | 0xe21c86d8b6a127bfef214d88fdb0c279e55d27dd8c443733e46c8d3de3c98cd6 |
4. Le rapport signé
Domaine EIP-712 : nom MarketAPI Oracle, version 2, l’ID de chaîne et l’adresse du vérificateur. Type :
PriceReport(bytes32 feedId,int256 price,uint64 timestamp,uint64 validUntil,uint8 marketStatus,uint32 spreadBps)
- price : prix médian avec 8 décimales.
- timestamp : heure du prix (secondes UTC) ; validUntil : le rapport expire au bout d’environ une minute.
- marketStatus : 1 OPEN, 2 CLOSED (dernier prix officiel, p. ex. le week-end), 3 HALTED.
- spreadBps : écart achat-vente en points de base ; avec plusieurs courtiers, il reflète aussi leur écart entre eux.
La réponse de l’API contient report (encodé en ABI) et signature (65 octets) : exactement les deux arguments de submit.
5. Fonctions du contrat
submit(PriceReport r, bytes sig) returns (bool): vérifier et enregistrer ; ignoré si un prix égal ou plus récent est enregistré.submitBatch(PriceReport[] rs, bytes[] sigs): plusieurs flux en une transaction ; les entrées invalides sont ignorées.getPrice(bytes32 feedId): dernier prix enregistré et horodatage ; échoue (revert) tant qu’un flux n’a pas encore de prix.getPriceNoOlderThan(bytes32 feedId, uint256 maxAge): échoue sauf si le marché est OPEN et le prix assez frais. Utilisez-la pour les actions de trading.
Chaque flux a un coupe-circuit : un saut supérieur à sa limite met le flux en pause jusqu’à vérification.
6. Exemple Solidity (modèle 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. Exemple 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. Refus et erreurs
- Les entrées
refusedlistent les symboles qui n’ont pas été signés, avec un motif, par exemple aucun prix fiable pour le moment (STALE) ou un marché fermé. Elles ne sont pas facturées. oracle_unavailable(503) : le service de signature est brièvement indisponible ; réessayez avec un délai croissant.- Revert on-chain :
InvalidSignature(mauvais signataire, chaîne ou contrat),ReportExpired,FutureTimestamp,InvalidPrice,InvalidStatus,NoPrice(le flux n’a pas encore de prix),FeedTripped(coupe-circuit),MarketNotOpenetPriceTooOld(degetPriceNoOlderThan),IsPaused.
9. Bonnes pratiques
- Récupérez le rapport juste avant d’envoyer la transaction ; les rapports expirent au bout d’environ une minute.
- Lisez toujours avec
getPriceNoOlderThanet un âge maximal adapté à votre produit. - Gérez explicitement les marchés CLOSED (week-ends, jours fériés), par exemple en réglant à la prochaine ouverture.
- Testez d’abord sur le testnet, puis ne changez que l’adresse du contrat et l’ID de chaîne.
- Gardez les clés API sur votre serveur, jamais dans une page web.