Architecture

JIKA is one Anchor program with four instructions and one account type. Everything else (keepers, apps, consumers) sits outside it.

Components

PartWhereRole
jika programprograms/jikaReads pools, computes spot, band and steady price, serves read
Feed accountPDA ["feed", mint]One per token: venues, buckets, steady price, band
DEX adaptersvenue.rsDecode the seven supported pool layouts into price and depth
Tick mathmath.rslog and pow on 1.0001 in fixed point, Q64.64 prices
Oracle mathoracle.rsWeighted median, band terms, steady step, the three-bucket window
Clientsdk/jika.mjsPDAs, instruction builders, decoders
Keepersdk/keeper.mjsOne update per feed per 10-second bucket

The flow of one update

StepWhoWhat happens
1AnyoneSends update with the feed, the USDC feed if needed, and each stored venue's accounts
2ProgramChecks every venue account is the one the pool names, in stored order
3ProgramReads each pool's price (tick) and depth; converts USDC pools through the USDC feed
4ProgramUpdates each venue's confirmed depth; weight = min(depth now, confirmed)
5ProgramTakes the depth-weighted median (spot) and records it in the current 10-second bucket
6ProgramMoves the steady price toward the least extreme sample of the last three buckets
7ProgramComputes the band and stores everything with last_update_slot, emits FeedUpdated

The flow of one read

StepWhoWhat happens
1Consumer programCPI read(max_age_slots, max_conf_ticks) with the feed and, for dollars, the USDC feed
2JIKAFails with NotLive, Stale or TooUncertain if any check fails
3JIKAReturns PriceView with the steady price as Q64.64

Accounts

The feed account is 720 bytes. Its layout, for readers that do not use Anchor:

OffsetFieldType
0Anchor discriminator[u8; 8]
8mintPubkey
40decimalsu8
41bumpu8
42venue_countu8
43has_spotbool
44steady_setbool
45created_slotu64
53last_update_slotu64
61credited_slotsu64
69steady_x16 (steady tick x 65,536)i64
77spot_ticki32
81conf_ticksu32
85depth (lamports)u64
93top_share_bpsu16
95live_venuesu8
96buckets[3]: id u64, lo i32, hi i3216 bytes each
144venues[8]: pool, kind, base_is_first, quote (0 SOL, 1 USDC), alive, added_slot, tick, depth, depth_ewma, weight72 bytes each

Venue accounts passed to update

Every stored venue, in the feed's order, as the pool followed by:

KindDEXAfter the pool
0Orca Whirlpoolvault A (pool offset 133), vault B (213)
1Raydium CLMMvault 0 (137), vault 1 (169)
2Raydium CPMMvault 0 (72), vault 1 (104)
3Raydium AMM v4coin vault (336), pc vault (368)
4Meteora DLMMthe active bin array: PDA ["bin_array", pool, floor(active_id / 70) as i64 LE] under the DLMM program
5pump.fun curvenothing
6PumpSwapbase vault (139), quote vault (171)

sdk/jika.mjs builds this list from chain state with updateIx(connection, mint).

Units

Every feed is priced in SOL (lamports per base raw unit). wSOL has no feed of its own. USDC pools are converted through the one USDC feed, and a dollar price is a read with the USDC feed as quote_feed.

Compute

InstructionCompute units
update, 3 venues52,162
update, 8 venues74,896
read6,400

Build

Anchor 0.30.1 on cargo-build-sbf 2.1.0. target/deploy/jika.so is 302,952 bytes, sha256 2f6141eafa89c9d6b89bdb8c0654a4df32f24f1e3f461185465fcfe6984ced0a.

NextSecurity and trust