Somnia Price Feeds
Pairs and events
Which pairs Somnia Price Feeds tracks, the events it emits each tick, and how to request a new pair.
Tracked pairs
Read the live set from the contract: symbols() for the list of pairs, activeIndices() with symbolOf(index) for the indexed form, and isTracked(pair) for a single check. The current sets, as an indication only:
| Network | Pairs (as of 10 Aug 2026; read the contract, this list drifts) |
|---|---|
| Mainnet | 10 pairs: BTC/USDC, ETH/USDC, SOL/USDC, SOMI/USDC, HYPE/USDC, XRP/USDC, DOGE/USDC, BNB/USDC, ADA/USDC, SUI/USDC |
| Testnet | 28 pairs: the mainnet ten plus LINK/USDC, AVAX/USDC, XLM/USDC, NEAR/USDC, ZEC/USDC, WLD/USDC, TAO/USDC, FIL/USDC, AAVE/USDC, LTC/USDC, ENA/USDC, UNI/USDC, ONDO/USDC, PEPE/USDC, XMR/USDC, PUMP/USDC, ASTER/USDC, BCH/USDT |
Changes emit SymbolAdded(index, symbol) and SymbolRemoved(index, symbol). A removal retires its index rather than reusing it, so a cached index → pair mapping never shifts.
The one case that does invalidate your cache is setSymbols, which replaces the whole set: every pair is retired and added again under a new index, even one that appears in both lists. It emits SymbolsReplaced(newCount) alongside the events for each pair. If you cache indices, watch for it and resolve them again.
Events
| Event | When |
|---|---|
PricesUpdated(requestId, updatedAtMs, indices[], prices[], marks[], sourceUpdatedAtsMs[], resyncedBits) |
Once per tick: one batched log covering every pair written |
SymbolAdded(index, symbol) / SymbolRemoved(index, symbol) |
A pair is added or removed |
SymbolsReplaced(newCount) |
The whole set is replaced |
The PricesUpdated arrays line up by position. Only pairs priced in this tick appear: a tracked pair the agents left unpriced is simply missing, and its absence is the signal that it went unpriced. Bit p of resyncedBits is set when the mark of indices[p] resynced. sourceUpdatedAtsMs here is at full precision, taken before the onchain age cap, so offchain consumers get exact market ages.
Other events, such as AgentRequestKicked, SubscriptionScheduled, SubscriptionChainBroken and AgentResponseDropped, are for operators and are not part of what consumers can rely on.
Requesting a new pair
Adding a pair is an owner-only onchain call made by the protocol multisig, so you can't add one yourself. Ask in the #dev-chat channel of the Somnia Discord with:
- The pair, ccxt-style, with the quote asset you want (
SOL/USDC, notSOL). Ask forUSDCunless you need another quote: every mainnet pair is quoted inUSDC, and testnet has a single exception,BCH/USDT. - The venues you consider authoritative, and any you want excluded.
- What you're building: settlement, liquidation or display. This sets how much thin-book behaviour matters for the pair.
- The network: mainnet, testnet or both.
What to expect:
- A liquidity check. A pair with thin or single-venue depth is often priced by one exchange alone, and may go unpriced when too few of its venues are fresh. That is checked on the agents' receipts before listing, and you'll be told rather than given a pair that voids your protocol.
- A running cost. Every pair raises the gas the feed burns continuously. The protocol pays it, not you per read, and it is the main limit on how many pairs the feed tracks.
- Your integration must handle the addition. A new pair gets a new stable index at the end; existing indices don't change.
- It lands in one tick. The addition is a single transaction, with no agent release, no redeploy and no downtime. The batch in flight at that moment is discarded, so you may see one skipped tick across all pairs; the next tick prices the new pair with everything else. Existing cells are untouched.
Copied from somnia-oracle's price feed integration guide, until the oracle's docs manifest publishes it.Edit this page