Oracle & Prices
Base URL: https://service.leverup.xyz
Price updates by position
The oracle payload required by price-sensitive contract calls. Do not fetch this from Pyth directly — this endpoint selects the correct feeds for the pair and collateral and returns the fee to attach.
POST /v1/oracle/price/updates/by-position
Content-Type: application/jsonRequest
{
"pairBase": "0xcf5a6076cfa32686c0df13abada2b40dec133f1d",
"collateral": "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
"blockChain": "MONAD",
"options": {
"includeEncodingData": true,
"includeFee": true,
"includePrice": true,
"includePublishTime": false,
"includeEncodingDataByOracleId": false,
"includePriceSafety": false,
"allowPartial": false
}
}| Field | Required | Notes |
|---|---|---|
pairBase | yes | Market identifier |
collateral | yes | The collateral token. For native MON, pass the WMON address. |
blockChain | no | Defaults to MONAD |
options.includeEncodingData | Return the update payloads — required for transactions | |
options.includeFee | Return updateFee and verifition_fee — required for transactions | |
options.includePrice | Also return current prices | |
options.includePublishTime | Also return publish timestamps |
Response
{
"pythPriceUpdateData": ["0x..."],
"pythProPriceUpdateData": ["0x..."],
"updateFee": "123456789",
"verifition_fee": "0",
"pythCorePrice": { "0xe62d...": "100123450000000000000000" },
"pythCorePublishTime": { "0xe62d...": 1785312000 },
"failures": []
}| Field | Notes |
|---|---|
pythPriceUpdateData | Pass as updateData.pythPriceUpdateData |
pythProPriceUpdateData | Pass as updateData.pythProPriceUpdateData |
updateFee | Wei of native MON |
verifition_fee | Additional verification fee, wei. The spelling is intentional — the field is named that way in the API. |
pythCorePrice | Keyed by oracle id, 1e18 |
failures | Non-empty when a feed could not be resolved |
Attach updateFee + verifition_fee as the transaction value:
const value = BigInt(data.updateFee ?? '0') + BigInt(data.verifition_fee ?? '0')Fetch late
Payloads are short-lived. Request immediately before sending the transaction, not at the start of a long-running flow.
Not needed for 1CT
Gasless trading fetches oracle data server-side. Intents never carry payloads.
Latest pair prices
Current prices for several markets at once.
POST /v1/oracle/price/pairs/latest
Content-Type: application/json{
"pairBases": [
"0xcf5a6076cfa32686c0df13abada2b40dec133f1d",
"0xb5a30b0fdc5ea94a52fdc42e3e9760cb8449fb37"
],
"blockChain": "MONAD"
}Response
{
"prices": {
"0xcf5a6076cfa32686c0df13abada2b40dec133f1d": "100123450000000000000000",
"0xb5a30b0fdc5ea94a52fdc42e3e9760cb8449fb37": "3456780000000000000000"
},
"failures": []
}Prices are 1e18 strings, keyed by lowercase pairBase. Pairs that could not be resolved appear in failures with a reason rather than failing the whole request:
{ "failures": [{ "pairBase": "0xdead…", "reason": "latest oracle price not found" }] }pairBases must not be empty. Duplicates are collapsed.
const res = await fetch(`${API}/v1/oracle/price/pairs/latest`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ pairBases: [btcBase, ethBase] }),
})
const { prices } = await res.json()
const btcUsd = Number(BigInt(prices[btcBase.toLowerCase()])) / 1e18Historical price
Price at a point in the past — used for 24h change calculations.
GET /v1/oracle/price/pair-24h-ago?pair_base=0x…
GET /v1/oracle/price/pair-hours-ago?pair_base=0x…&hours_ago=6| Parameter | Required | Notes |
|---|---|---|
pair_base | yes | |
hours_ago | no | 1–24, defaults to 24. Values outside the range return 400. |
block_chain | no | Defaults to MONAD |
Response
{
"pairBase": "0xcf5a6076cfa32686c0df13abada2b40dec133f1d",
"hoursAgo": 24,
"blockChain": "MONAD",
"oracleId": { "kind": "PYTH_CORE", "id": "0xe62d…", "oracle": null },
"pricePoint": {
"price": "98765430000000000000000",
"publishTime": 1785225600,
"capturedAt": 1785225605
}
}price is 1e18. publishTime is the oracle's timestamp; capturedAt is when LeverUp recorded it.
Returns 404 if no snapshot exists for that window.
async function priceChange24h(pairBase: string) {
const [nowRes, thenRes] = await Promise.all([
fetch(`${API}/v1/oracle/price/pairs/latest`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ pairBases: [pairBase] }),
}),
fetch(`${API}/v1/oracle/price/pair-24h-ago?pair_base=${pairBase}`),
])
const now = Number(BigInt((await nowRes.json()).prices[pairBase.toLowerCase()])) / 1e18
const then = Number(BigInt((await thenRes.json()).pricePoint.price)) / 1e18
return ((now - then) / then) * 100
}Oracle kinds
Feeds are identified by an OracleIdInput:
{ "kind": "PYTH_CORE", "id": "0x…", "oracle": null }kind is one of NONE, PYTH_CORE, PYTH_PRO, DEX_ORACLE. You rarely need to construct these — the position-based endpoint resolves them for you.