Getting started
This page takes a token from no price to a live price you can read: create its feed, add its pools, keep it fresh, read it.
The program is not deployed to devnet or mainnet yet. Everything below runs today on a local validator that clones the real DEX programs and pool accounts from mainnet.
1. Run the local chain
cd engine
scripts/build.sh # builds target/deploy/jika.so and the IDL
scripts/localnet.sh up # Agave test validator on http://127.0.0.1:51899
node sdk/bootstrap.mjs # feeds for USDC, TERMINAL, USELESS and two pump.fun tokens
node sdk/keeper.mjs # one update per feed every 10 seconds
2. Create a feed
One feed per mint, at PDA ["feed", mint]. Anyone can create it; a second one for the same mint fails.
import { createFeedIx } from "./sdk/jika.mjs"
const tx = new Transaction().add(createFeedIx({ payer: payer.publicKey, mint }))
await sendAndConfirmTransaction(connection, tx, [payer])
The USDC feed must exist before any pool quoted in USDC can be added anywhere.
3. Add its pools
Each feed takes up to 8 pools from the seven supported DEX programs. The program checks the owner, the layout and both mints.
import { addVenueIx } from "./sdk/jika.mjs"
for (const pool of pools) {
await sendAndConfirmTransaction(connection, new Transaction().add(addVenueIx({ mint, pool })), [payer])
}
A new pool starts with zero weight. It earns weight by keeping its depth for about 10 minutes.
4. Update it
import { updateIx } from "./sdk/jika.mjs"
const tx = new Transaction()
.add(ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 }))
.add(await updateIx(connection, mint))
await sendAndConfirmTransaction(connection, tx, [payer])
updateIx reads the feed and each pool from chain and passes every account the program needs, in order. A feed is live after 600 credited slots, about 4 to 5 minutes of updates.
5. Read it
From a client, simulate read and decode the return data:
import { readIx, decodePriceView, tickToPrice, bandFraction } from "./sdk/jika.mjs"
const ix = readIx({ mint, maxAgeSlots: 150n, maxConfTicks: 300 })
// simulate, then decode the transaction's return data
const view = decodePriceView(returnData)
const solPerToken = tickToPrice(view.steadyTick, view.baseDecimals)
const band = bandFraction(view.confTicks) // 0.012 means plus or minus 1.2%
From a program, see Integration.
What the local run produced
| Feed | Venues | Price in SOL | Price in USD | Band |
|---|---|---|---|---|
| USDC | Whirlpool, Raydium CLMM, AMM v4, DLMM, PumpSwap | 0.00826306 (SOL = $121.02) | plus or minus 0.01% | |
| TERMINAL | PumpSwap, 2 DLMM | 0.0000119386 | $0.00144482 | plus or minus 1.28% |
| USELESS | CPMM, Whirlpool, DLMM, DLMM vs USDC | 0.00201630 | $0.244014 | plus or minus 0.19% |
| a live pump.fun curve | curve | 2.73478e-7 | $0.0000330965 | plus or minus 6.05% |
| a graduated token | complete curve, PumpSwap | 8.04054e-7 | $0.0000973071 | plus or minus 4.90% |