RILoracle — Integration Docs
● XDC MainnetLive, multi-source price & data feeds — multi-chain: anchored on the XDC Network and published natively to the XRP Ledger (XLS-47). Chainlink AggregatorV3-compatible, signed payloads, public REST API. Integrate in minutes.
Overview
RILoracle publishes verified feeds two ways:
- On-chain — read directly from smart contracts on XDC mainnet. Headline pairs expose a drop-in Chainlink
AggregatorV3proxy; every feed is also readable from the core oracle vialatestRoundData(bytes32 feedId). - XRP Ledger (native) — the same feeds publish to XRPL mainnet via the built-in
Oracleledger object (XLS-47). XRPL apps read them on L1 withget_aggregate_price— no EVM, no contract, no key. - Off-chain — one public
GETreturns every feed with value, source attribution, an Ed25519 signature, and a SHA-256 content hash.
Every value is the median of multiple independent sources (the same robustness model Chainlink uses), pushed on-chain on a deviation + heartbeat schedule. All amounts use 8 decimals (Chainlink convention): on_chain_value = round(real_value × 1e8).
Network & contracts
| Item | Value |
|---|---|
| Network | XDC Network — Mainnet (chainId 50) |
| RPC | https://rpc.ankr.com/xdc · https://erpc.xinfin.network |
| Core oracle contract | loading… |
| Decimals | 8 (all feeds) |
AggregatorV3 proxy addresses
Testnet — integrate risk-free (Apothem)
A copy of the oracle runs on XDC Apothem testnet with drop-in AggregatorV3 proxies for the headline pairs. Point your dApp here to test integration without spending real XDC — grab free test XDC from the Apothem faucet. The live JSON map (mainnet + testnet, always current) is at /api/oracle/addresses.
| Item | Value |
|---|---|
| Network | XDC Apothem testnet (chainId 51) |
| RPC | https://erpc.apothem.network · https://rpc.apothem.network |
| Core oracle contract | 0xeB5C2437E22CD9028FD31e2Efa668c55B75C8aC1 |
| Faucet | https://faucet.apothem.network |
| Decimals | 8 (all feeds) |
Testnet AggregatorV3 proxies:
| Pair | Testnet proxy address |
|---|---|
| XDC / USD | 0xb5e1595a8464299bC7fCfC2750A963972ce0d01f |
| BTC / USD | 0xb0c9D091a417726870D086cAF0a0707eC4D04E7d |
| ETH / USD | 0x96a7297d8dd8f59a485785044209c443d961b4fb |
| USD / EUR | 0xB27D1314067724402748f026B659F4D467439bc8 |
| Gold XAU / USD | 0xDA9995163286aEeb9e11106b861E5715775925a6 |
| CGO NAV (USD/g) | 0x191ef525D59A90f522C30a7cc49f2d8C5620fCA2 |
Quickstart
Fastest path — read XDC/USD off-chain, no key, no wallet:
# every feed, with values, sources, signatures curl https://riloracle.ripitlabs.com/api/oracle/public
On-chain · AggregatorV3 proxies (drop-in Chainlink)
For the headline feeds (XDC/USD, BTC/USD, ETH/USD, USD/EUR, Gold XAU/USD, CGO NAV, CBOE VIX, Fed Funds Rate, Natural Gas) point any existing Chainlink integration at the proxy address — zero code changes. The live address list (9 proxies) loads above and at /api/oracle/addresses.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface AggregatorV3Interface { function decimals() external view returns (uint8); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); } contract PriceConsumer { // XDC/USD proxy — see address list above AggregatorV3Interface public constant feed = AggregatorV3Interface(0x…); function xdcUsd() external view returns (int256) { (, int256 answer,,,) = feed.latestRoundData(); return answer; // 8 decimals → divide by 1e8 } }
On-chain · read ANY feed via the core oracle
Every feed (gold, CGO NAV, FX, commodity, logistics…) is readable from the core oracle by its bytes32 feed id. The feed id is simply the ASCII feed key, right zero-padded to 32 bytes — so bytes32("rwa_cgo_usd") works directly in Solidity.
interface IXDCOracle { function latestRoundData(bytes32 feedId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); function decimals(bytes32 feedId) external view returns (uint8); } IXDCOracle constant ORACLE = IXDCOracle(0x…); // ComTech Gold NAV — USD per gram (1 CGO = 1g fine gold) function cgoNav() external view returns (int256) { (, int256 answer,,,) = ORACLE.latestRoundData(bytes32("rwa_cgo_usd")); return answer; // e.g. 13409000000 = $134.09 (8 dp) }
bytes32("…") — all current keys fit. The exact bytes32 id for every feed is in the reference table.On-chain · ethers.js
import { ethers } from "ethers"; const provider = new ethers.JsonRpcProvider("https://rpc.ankr.com/xdc"); const abi = ["function latestRoundData(bytes32) view returns (uint80,int256,uint256,uint256,uint80)"]; const oracle = new ethers.Contract("0x…", abi, provider); const feedId = ethers.encodeBytes32String("commodity_xau_usd"); // gold XAU/USD const [, answer] = await oracle.latestRoundData(feedId); console.log("gold $/oz =", Number(answer) / 1e8);
XRP Ledger · native Price Oracle (XLS-47)
The same feeds publish natively to the XRP Ledger using XRPL's built-in Price Oracle (XLS-47) — not an EVM sidechain or wrapper contract. XRPL apps read them straight off L1 with the get_aggregate_price method: no gas token, no ABI, no API key. The live account + per-feed pair map is always at /api/oracle/addresses under xrpl.
| Item | Value |
|---|---|
| Network | XRPL Mainnet |
| Standard | XLS-47 native Price Oracle (Oracle ledger objects) |
| Oracle account | loading… |
| Public RPC | https://s1.ripple.com:51234 · wss://s1.ripple.com |
| Layout | 47 pairs across 5 oracle objects (≤10 each), addressed by oracle_document_id |
base_asset/quote_asset pair under a fixed oracle_document_id. 3-character symbols (BTC, USD, XAU) are standard XRPL currency codes; longer ones (SOFR, UST10Y) are 160-bit hex codes — but you don't compute any of it: the exact base, quote and oracleDocumentId for every feed are in /api/oracle/addresses → xrpl.pairs. XRPL prices are unsigned, so the two spread feeds that can go negative aren't published on XRPL.Read a feed — Python (xrpl-py)
from xrpl.clients import JsonRpcClient from xrpl.models.requests import GetAggregatePrice client = JsonRpcClient("https://s1.ripple.com:51234") ORACLE = "rJatUN1GtyqvdtG46QuPYftkUWu1wifcxc" # RILoracle # BTC/USD lives in oracle_document_id 0 (see /api/oracle/addresses → xrpl.pairs) resp = client.request(GetAggregatePrice( base_asset="BTC", quote_asset="USD", oracles=[{"account": ORACLE, "oracle_document_id": 0}])) print(resp.result["entire_set"]["mean"]) # live BTC/USD off the ledger
Read a feed — JavaScript (xrpl.js)
import { Client } from "xrpl"; const client = new Client("wss://s1.ripple.com"); await client.connect(); const ORACLE = "rJatUN1GtyqvdtG46QuPYftkUWu1wifcxc"; const res = await client.request({ command: "get_aggregate_price", base_asset: "BTC", quote_asset: "USD", oracles: [{ account: ORACLE, oracle_document_id: 0 }] }); console.log(res.result.entire_set.mean); // live BTC/USD await client.disconnect();
base_asset/quote_asset and use that feed's oracleDocumentId from the addresses map. e.g. gold = XAU/USD, SOFR & the Treasury curve use hex codes you can copy straight from xrpl.pairs.Off-chain · REST API
Base URL https://riloracle.ripitlabs.com. No auth. JSON. Rate-limited (see below).
| Endpoint | Returns |
|---|---|
| GET /api/oracle/public | All feeds: value, unit, source, real flag, decimals, answer_raw, signature, SHA-256 hash + on-chain meta (contract, proxies) |
| GET /api/oracle/feeds | Feed list with metadata |
| GET /api/oracle/feeds/{key} | A single feed |
| GET /api/oracle/feeds/{key}/onchain | The exact on-chain value (latestRoundData) any contract sees |
| GET /api/oracle/onchain/status | Contract address, operator balance, last-push status |
| GET /api/oracle/pubkey | Ed25519 public key + how to verify signatures |
| GET /api/oracle/methodology | Per-feed source list & aggregation method |
| GET /api/oracle/history | Historical values |
| GET /api/oracle/health | Oracle uptime / freshness |
| GET /api/oracle/iso20022/{key} | ISO 20022 proof as camt.052 (BankToCustomerAccountReport) XML |
| GET /api/oracle/iso20022/{key}?type=camt.053 | ISO 20022 proof as camt.053 (BankToCustomerStatement) XML |
JavaScript
const r = await fetch("https://riloracle.ripitlabs.com/api/oracle/public").then(r => r.json()); console.log(r.feeds.commodity_xau_usd.value); // gold $/oz console.log(r.feeds.rwa_cgo_usd.value); // CGO NAV $/g
Python
import requests d = requests.get("https://riloracle.ripitlabs.com/api/oracle/public").json() gold = d["feeds"]["commodity_xau_usd"] print(gold["value"], gold["source"], gold["sources"], "sources")
Off-chain · signature verification
Each feed in /public is signed with Ed25519. Reconstruct the message and verify against the published public key (signing.pubkey or /api/oracle/pubkey):
# message format
v1:{feed_key}:{answer_raw}:{decimals}:{signed_at}
from nacl.signing import VerifyKey import requests, binascii d = requests.get("https://riloracle.ripitlabs.com/api/oracle/public").json() pk = VerifyKey(binascii.unhexlify(d["signing"]["pubkey"])) f = d["feeds"]["rwa_cgo_usd"] msg = f"v1:rwa_cgo_usd:{f['answer_raw']}:{f['decimals']}:{f['signed_at']}".encode() pk.verify(msg, binascii.unhexlify(f["signature"])) # raises if tampered print("verified ✓")
ISO 20022 · bank-native proof messages
Every proof is also served as a genuine ISO 20022 message — the standard banks and market infrastructures run on — so a counterparty can ingest a Proof-of-Reserve / Proof-of-Record straight into their existing pipeline and independently verify it. The attested value becomes the reported Balance/Amt; the Ed25519 signature, SHA-256 hash and on-chain anchor (contract, chainId, Merkle root) travel in the report fields.
| Message | ISO 20022 type | Live sample |
| Intraday report | camt.052.001.08 | /api/oracle/iso20022/rwa_cgo_usd |
| End-of-day statement | camt.053.001.08 | …/iso20022/rwa_cgo_usd?type=camt.053 |
# pull a Proof-of-Reserve as an ISO 20022 camt.052 message
curl https://riloracle.ripitlabs.com/api/oracle/iso20022/rwa_cgo_usd
<!-- camt.052.001.08 (abbreviated) --> <Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08"> <BkToCstmrAcctRpt><Rpt> <Acct><Id><Othr><Id>rwa_cgo_usd</Id></Othr></Id><Ccy>USD</Ccy></Acct> <Bal><Amt Ccy="USD">133.24</Amt><CdtDbtInd>CRDT</CdtDbtInd></Bal> <AddtlRptInf>… algo=ed25519 signature=… sha256=… contract=0x17e46C96… merkleRoot=… …</AddtlRptInf> </Rpt></BkToCstmrAcctRpt> </Document>
Feed reference
Live feeds and their on-chain ids. ● LIVE = real multi-source market data.
| Feed | Key | bytes32 feed id | Dec | Value | Status |
|---|---|---|---|---|---|
| loading live feeds… | |||||
Rate limits & support
- Public endpoints are rate-limited per IP — cache the
/publicresponse (feeds update on a heartbeat, not every block). - Need a feed we don't list (FX pair, commodity, RWA reference, proof-of-reserve)? Get in touch — custom feeds for DeFi & RWA teams on XDC.
RILoracle by Rip It Labs · built on XDC Network.