预言机文档
经签名的外汇和贵金属价格,由您的智能合约在链上验证。概览:预言机页面 · 机器可读:/v1/oracle/feeds、/v1/oracle/catalog。
1. 工作原理
- 您的后端请求签名报告:
GET https://api.marketapi.app/v1/oracle/report?symbols=XAUUSD&chain_id=10(需具有read:oracle权限范围的 API 密钥;按签名报告计费)。 - 您的交易将报告和签名传给验证合约,它会检查 EIP-712 签名、到期时间、链及其熔断机制,然后存储价格。
- 在同一笔交易中,您的合约按时效要求读取价格。这种拉取模式始终使用当前价格。
通过 API 请求的价格也会不定期自动推送到链上,但切勿在未检查时效的情况下依赖已存储的价格。
2. 网络与合约
| 网络 | 链 ID | 验证合约 |
|---|---|---|
| Optimism | 10 | 0xaeF7f701acFB42267015D3F593ce17CF536Afd6B · 浏览器 |
| Optimism Sepolia 测试网 | 11155420 | 0xBBf36E7Cd75494f28E02C5698EaD35fF4960a943 · 浏览器 |
签名者地址:0x83fa2d8836525251FAd214A78A72038D0864f877。测试网用于免费测试,不提供服务保证。
3. 价格源
每个价格源都有永久 ID:feedId = keccak256(symbol)。价格使用 8 位小数。
| 代码 | 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. 签名报告
EIP-712 域:名称 MarketAPI Oracle、版本 2、链 ID 和验证合约地址。类型:
PriceReport(bytes32 feedId,int256 price,uint64 timestamp,uint64 validUntil,uint8 marketStatus,uint32 spreadBps)
- price:中间价,8 位小数。
- timestamp:价格时间(UTC 秒);validUntil:报告约一分钟后过期。
- marketStatus:1 OPEN,2 CLOSED(官方最后价格,例如周末),3 HALTED。
- spreadBps:以基点表示的买卖价差;有多个经纪商时,也反映它们之间的差距。
API 响应包含 report(ABI 编码)和 signature(65 字节):正是 submit 的两个参数。
5. 合约函数
submit(PriceReport r, bytes sig) returns (bool):验证并存储;如已存储相同或更新的价格则忽略。submitBatch(PriceReport[] rs, bytes[] sigs):一笔交易提交多个价格源;无效条目会被跳过。getPrice(bytes32 feedId):最新存储的价格和时间戳;价格源尚无价格时会回滚(revert)。getPriceNoOlderThan(bytes32 feedId, uint256 maxAge):除非市场为 OPEN 且价格足够新,否则回滚。交易操作请使用此函数。
每个价格源都有熔断机制:超过其限制的跳动会暂停该价格源,直到审核完成。
6. Solidity 示例(拉取模式)
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. 拒绝与错误
refused条目列出未签名的代码及原因,例如当前没有可靠价格(STALE)或市场休市。这些不计费。oracle_unavailable(503):签名服务暂时不可用;请以退避方式重试。- 链上回滚:
InvalidSignature(签名者、链或合约错误)、ReportExpired、FutureTimestamp、InvalidPrice、InvalidStatus、NoPrice(价格源尚无价格)、FeedTripped(熔断)、MarketNotOpen和PriceTooOld(来自getPriceNoOlderThan)、IsPaused。
9. 最佳实践
- 在发送交易前即时获取报告;报告约一分钟后过期。
- 始终使用
getPriceNoOlderThan并设置适合您产品的最大时效来读取。 - 显式处理 CLOSED 市场(周末、节假日),例如在下一次开市时结算。
- 先在测试网上测试,然后只需更改合约地址和链 ID。
- 将 API 密钥保存在您的服务器上,切勿放在网页中。