Somnia Price Feeds
Reference
Every Somnia Price Feeds read, what it returns, and the GraphQL indexer for historical prices.
Every read below is a view on the one proxy address. Prices are scaled by decimals (18), timestamps are Unix milliseconds, and nothing reverts except the *OrRevert helpers: an untracked, removed or never-written pair or index returns zero in every position.
Spot, by pair: IPriceFeed
| Call | Returns |
|---|---|
latest(string symbol) |
(uint256 price, uint256 updatedAtMs) |
latestWithSource(string symbol) |
(uint256 price, uint256 updatedAtMs, uint256 sourceUpdatedAtMs) |
latestBatch(string[] symbols) |
(uint256[] prices, uint256[] updatedAtsMs), in the input's order |
latestBatchWithSource(string[] symbols) |
(uint256[] prices, uint256[] updatedAtsMs, uint256[] sourceUpdatedAtsMs) |
symbols() |
string[]: the current pairs, in the order they were added |
isTracked(string symbol) |
bool |
Mark, by pair: IMarkPriceFeed
| Call | Returns |
|---|---|
latestMark(string symbol) |
(uint256 markPrice, uint256 updatedAtMs); updatedAtMs always matches the spot cell |
latestMarkBatch(string[] symbols) |
(uint256[] markPrices, uint256[] updatedAtsMs) |
By stable index: IIndexedPriceFeed
One SLOAD cheaper. Resolve index → pair once from SymbolAdded.
| Call | Returns |
|---|---|
latestByIndex(uint256 index) |
(uint256 price, uint256 updatedAtMs) |
latestByIndexWithSource(uint256 index) |
(uint256 price, uint256 updatedAtMs, uint256 sourceUpdatedAtMs) |
latestMarkByIndex(uint256 index) |
(uint256 markPrice, uint256 updatedAtMs) |
latestBatchByIndex(uint256[] indices) |
(uint256[] prices, uint256[] updatedAtsMs) |
latestMarkBatchByIndex(uint256[] indices) |
(uint256[] markPrices, uint256[] updatedAtsMs) |
symbolOf(uint256 index) |
(string symbol, bool active); active is false once removed |
activeIndices() |
uint256[]: the live set, in the order sent to the agents each tick |
Safe reads, quality and liveness: IQualifiedPriceFeed
| Call | Returns |
|---|---|
latestOrRevert(string symbol, uint256 maxAgeMs) |
uint256 price; reverts NoPrice() or StalePrice(ageMs, maxAgeMs) |
latestByIndexOrRevert(uint256 index, uint256 maxAgeMs) |
uint256 price, with the same reverts |
latestMarkOrRevert(string symbol, uint256 maxAgeMs) |
uint256 markPrice, with the same reverts |
latestWithQuality(string symbol) |
(uint256 price, uint256 markPrice, uint256 updatedAtMs, uint256 sourceUpdatedAtMs, uint256 validatorCount, uint256 medianControlCount, uint256 flags) |
latestByIndexWithQuality(uint256 index) |
The same seven values |
feedHealth() |
(uint256 lastTickMs, uint256 lastKickMs, uint256 lastIngestMs, uint256 lastFailureMs, uint8 lastFailureCode, bool subscriptionArmed, uint256 balance) |
livenessStatus(uint256 maxTickAgeMs) |
(Liveness status, uint256 lastTickMs, uint256 lastIngestMs); status is 0 Unknown, 1 Healthy, 2 GlobalStale or 3 ChainDead |
FLAG_MARK_RESYNCED() / FLAG_DEVIATION() |
uint256 bit masks (1 and 2) |
Configuration (on the scheduler)
| Call | Returns |
|---|---|
decimals() |
uint8: the price scale exponent (18) |
emaAlpha() |
uint256: the mark's smoothing, in 1e18 fixed point |
emaMaxAgeMs() |
uint64: how old a mark can be before the next one resyncs to spot |
symbolsVersion() |
uint64: increases with every change to the pair set |
intervalMs() |
uint64: the tick period in milliseconds (0 when the schedule isn't running) |
phaseCount() |
uint64: 1 while the schedule runs, 0 when it doesn't |
What comes back
cast call 0x1998C88D54a240b8C671493f27f58eC416b81D7F \
'latestWithQuality(string)(uint256,uint256,uint256,uint256,uint256,uint256,uint256)' \
"BTC/USDC" --rpc-url https://api.infra.mainnet.somnia.network
64984750000000000000000 price → 64,984.75 USDC (÷ 1e18)
64985417937502157000642 markPrice → 64,985.42 USDC
1786359310000 updatedAtMs → when the cell was written (always ...000)
1786359308831 sourceUpdatedAtMs → the agent took in the data 1.17 s before the write
3 validatorCount → three validators backed this median
0 medianControlCount → unknown (not "no venues")
0 flags → no mark resync this tick
Divide by 10 ** decimals() for a human-readable price. In Solidity, keep the fixed point and scale at the last step; never go through a float. The typed equivalent is one line:
uint256 btc = FEED.latestOrRevert("BTC/USDC", 5_000); // 64984750000000000000000
Historical data
An indexer serves the feed's history over GraphQL, for charts, backtests and monitoring:
| Network | Endpoint |
|---|---|
| Mainnet | https://price-feed.prd.oracle.somnia.host/v1/graphql |
| Testnet | https://price-feed.dev.oracle.somnia.host/v1/graphql |
Warning
For observation only. Don't settle, liquidate or price anything from GraphQL: it lags the chain, can be resynced, and isn't part of what the feed guarantees. Anything that moves value reads the feed onchain.
| Entity | One row per |
|---|---|
Feed |
Pair: its latest state, like Chainlink's latestRoundData |
PricePoint |
Tick and pair: every price written |
Candle |
Pair and period: OHLC at M1, H1 and D1 |
Symbol |
Index: the index → pair registry |
Copied from somnia-oracle's price feed integration guide, until the oracle's docs manifest publishes it.Edit this page