Charli3 class in the order you will actually use them. Copy the snippets, they work as-is against preprod.
Install
BLOCKFROST_PROJECT_IDfrom blockfrost.io (only for the refresh flow, reads do not need it).
Create the client
Constructor options
Reading prices
getOdvReference(pair)
The main read. Returns the current on-chain price for one pair, plus the UTXO it came from so you can cite it.getPrice(pair)
Same asgetOdvReference but returns only the price, no UTXO pointer. Use when you do not need the on-chain citation.
getAllPrices()
Reads every pair in the preset in parallel. Good for a dashboard row.rawValue: 0n and isExpired: true instead of throwing, so you can render the list without wrapping each entry in try/catch.
getOracleReference(pair)
Same shape asgetOdvReference but reads the legacy (non-ODV) oracle address. Only use this if you need a feed that is not on ODV yet.
Listing what is available
listFeeds()
Legacy feed presets.listOdvFeeds()
The ODV pull-oracle feeds, which is probably what you want.Refreshing a stale price
submitRound2(lucid, pair, opts?)
The full refresh flow in one call. Collects signed feeds from the six oracle nodes, builds the Round 2 tx, asks the nodes for signatures, signs with your wallet, and submits. Takes about 30 seconds end to end.isExpired: true. Refreshing a fresh feed is a waste of fees.
Lower-level: run Round 1 on its own
collectFeeds(pair, opts?)
Fetches signed feed messages from the six oracle nodes and verifies them, without building a tx. Use this if you want to show “what the nodes are seeing” without posting anything.feeds.feeds has nodeUrl, value, timestamp, messageCborHex, signatureHex, and verificationKeyHex. You can show them to the user, or use presetFeeds on submitRound2 later to avoid collecting twice.
Types
charli3-js and also in src/types.ts.
Lower-level exports
Anything below theCharli3 class is re-exported for power users:
| Export | Use |
|---|---|
OracleReader | raw datum reader for custom flows |
OracleNodeClient | HTTP client for oracle nodes |
buildOdvTx, selectOracleUtxos, buildVkeyWitnessSetHex | build a Round 2 tx manually |
buildAggregateMessage, medianBigInt, vkhOf | aggregate message + consensus helpers |
consensusNodes, calculateRewardDistribution, calculateMinFeeAmount | IQR internals |
parseOracleSettings, parseAggState, buildAggStateDatumCbor | datum parsers + builders |
verifyEd25519, verifyFeedSignature | signature verification |
buildSignatureRequest, collectTxSignatures | manual /odv/sign round trip |
PRESETS, PREPROD, MAINNET, getPreset | network presets |
Common patterns
Read-or-refresh
Price a USD amount in ADA
Show every pair
Errors
No UTXO found at ODV address
No UTXO found at ODV address
Either the feed has never been posted on this network, or Kupo is slow. Retry, or pass your own
kupoUrl in the constructor.Aggregate build failed: not enough feeds
Aggregate build failed: not enough feeds
Some oracle nodes were offline, so the SDK could not collect enough signed feeds to hit consensus. Usually temporary.
Submit failed with on-chain error
Submit failed with on-chain error
The validator rejected the tx. Common causes: stale validity window (your clock is off), missing signature, or the wallet ran out of tADA.
Next
How it works
Round 1 / Round 2, IQR consensus, datum layout.
AI agents
Plug the SDK into any tool-calling LLM with one markdown file.