HIKARA

solana mev forensics agent

docs

read-only python 3.9+ rust stable mit solana mainnet

overview

hikara watches every slot on solana mainnet, decodes the swap instructions, and reconstructs jito bundles. it classifies the events — sandwich, jit, backrun, liquidation, atomic arb — attributes leader validators and known searchers, and emits a verdict per event with a confidence in [0.0, 0.95].

detector, not oracle. read-only by design. no wallet, no signer, no executor, no trading. anyone forking to build a sniper does so in their own repo.

how it works

a pipeline of small, independent layers. you can swap any layer without touching the others. the contract between layers is the Event dataclass in src/hakiri/core/types.py.

   shredstream feed                 finalized slots
        │                                  │
        ▼                                  ▼
  ┌──────────────┐                  ┌──────────────┐
  │ ingest-rs    │                  │ getBlock     │
  │ jito shreds  │                  │ getTransac.  │
  └──────┬───────┘                  └──────┬───────┘
         │                                 │
         └──────────────┬──────────────────┘
                        ▼
                ┌──────────────┐
                │ decode  amm  │   raydium · orca · meteora · phoenix
                └──────┬───────┘
                       ▼
                ┌──────────────┐
                │ classify     │   SAND-01, BACK-01, JIT-01, ARB-01
                └──────┬───────┘
                       ▼
                ┌──────────────┐
                │ score        │   rule-based, capped at 0.95
                └──────┬───────┘
                       ▼
                ┌──────────────┐
                │ ai filter    │   optional. only reviews edge cases
                └──────┬───────┘
                       ▼
                ┌──────────────┐
                │ output sinks │   stdout · jsonl · webhook
                └──────────────┘

supported

targetstatus
solana mainnetprimary
raydium amm v4primary
raydium clmmprimary
orca whirlpoolsprimary
jito bundle streamprimary
jito tip account decodeprimary
meteora dlmmlow coverage
phoenix cloblow coverage
lifinity v2low coverage
drift / kamino liquidationsplanned
pyth oracle-update sandwichplanned

detection heuristics

each rule has a numbered id used in event.notes so you can trace what fired. new rules ship with both a positive and a negative fixture or they do not get merged.

idwhat it catchesshipped in
SAND-01classic sandwich: front + victim + back same pool, opposite directionsv0.1
BACK-01one-step backrun arb against a user swapv0.1
JIT-01just-in-time concentrated liquidity around a victim swapv0.2
ARB-01atomic multi-hop arb across 3+ pools in a single txv0.2
LIQ-01drift / kamino / marginfi liquidation w/ priority manipulationv0.3
ORACLE-01sandwich-style prep around a pyth / switchboard updatev0.3

SAND-01 — classic sandwich

three swaps on the same pool: a front-run by a searcher, a victim swap, a back-run by the same searcher. front and back run in opposite directions.

  • front.pool == victim.pool == back.pool
  • front.signer == back.signer != victim.signer
  • front.token_in == victim.token_in and front.token_out == victim.token_out
  • back.token_in == victim.token_out and back.token_out == victim.token_in
  • front.tx_index < victim.tx_index < back.tx_index (within the same slot)

scoring: base 0.70. jito-tip transfer raises by +0.10. presence of a victim record raises by +0.05.

BACK-01 — one-step backrun

two consecutive swaps on the same pool by different signers, same direction. the second swap is treated as an arb candidate against the first.

  • a.pool == b.pool
  • a.signer != b.signer
  • a.token_in == b.token_in and a.token_out == b.token_out
  • a.tx_index + 1 == b.tx_index

scoring: base 0.50. jito-tip transfer raises by +0.10.

JIT-01 — just-in-time liquidity

orca whirlpools and meteora dlmm. a concentrated position is opened (open_position + increase_liquidity) and closed (decrease_liquidity + close_position) within the same slot, surrounding a victim swap. the searcher captures fees from the victim and rebalances out before the slot ends.

ARB-01 — atomic multi-hop arb

a single transaction touches three or more pools across raydium / orca / meteora / phoenix and ends with a profit denominated in the input mint. typical on stable triangles (SOL → USDC → USDT → SOL).

LIQ-01 — liquidation with priority manipulation

drift, kamino, marginfi, or solend liquidation where the searcher front-runs the liquidate instruction with a price-impact swap that pushes the victim past threshold.

ORACLE-01 — oracle-update sandwich

same shape as SAND-01, but the victim is a pyth or switchboard price-update transaction. the searcher positions before the update lands and exits after.

why each rule has a numbered id

users get a verdict; auditors need a reason. quoting a rule id in a forum post or a postmortem is more useful than re-explaining the heuristic each time.

quickstart

requires python 3.9+ and rust stable.

git clone https://github.com/hakiriagent/hakiri.git hikara
cd hikara

# install python package + dev deps
make install

# build the rust ingest crate
cd ingest-rs && cargo build --release && cd ..

# run an offline demo (zero network)
hikara demo investigate

# run the live scanner against your rpc
cp .env.example .env
$EDITOR .env   # set HIKARA_RPC_URL (helius / triton) or HIKARA_SHRED_URL (jito)
hikara scan

no rpc? hikara demo scan shows the full pipeline against synthetic fixtures.

cli reference

hikara version                    # version + active config
hikara scan                       # live shred + slot scan
hikara scan --once                # one slot then exit (smoke test)
hikara investigate <sig|slot>     # walk the pipeline on a specific target

hikara demo scan                  # canned scan against a synthetic slot
hikara demo investigate           # full pipeline trace, prints every step
hikara demo replay <id>           # replay a recorded fixture

example output — hikara demo investigate

─────────────────── step 1. decoded swaps ────────────────────
  slot 285000000 idx 0  signer 4Nd1m7t...  pool 8sLbNZoA... (raydium)  in 8.00 SOL   out 1320.40 USDC
  slot 285000000 idx 1  signer 9XKpMRkB...  pool 8sLbNZoA... (raydium)  in 0.50 SOL   out 82.10 USDC
  slot 285000000 idx 2  signer 4Nd1m7t...  pool 8sLbNZoA... (raydium)  in 1340.00 USDC out 8.07 SOL

─────────────────── step 2. classifier rules ─────────────────
  rules fired: ['SAND-01']
  slot verdict: likely
  events found:  1

─────────────────── step 3. score per event ─────────────────
  sandwich slot 285000000
    base[sandwich]=0.70
    jito_tip>0:+0.10
    bundle.txs>=2:+0.05
    victims_present:+0.05
    -> verdict=confirmed conf=0.900
─────────────────────── done ────────────────────────────────

architecture

hakiri/
├── src/hakiri/                    python package
│   ├── core/                      types · classify · score
│   ├── decode/                    raydium · orca · meteora + program ids
│   ├── enrich/                    leader · searcher · jito tip
│   ├── ingest/                    rpc + shredstream + slot stubs (rust later)
│   ├── output/                    stdout · jsonl · webhook
│   ├── ai/                        optional rule reviewer
│   ├── demo/                      offline scripted demos
│   └── cli.py                     typer entrypoint
├── ingest-rs/                     low-level ingest crate (rust)
│   └── src/ {shreds,bundle,slot}.rs
├── tests/                         pytest suite
└── docs/                          architecture · heuristics · glossary

zones & maintainers

zonelanguagemaintainer
core, scoring, cipython@hakiriagent
ingest-rs, shredstreamrust@0xnova
classify, heuristicspython@mikrohash
decode, outputpython@luka

why polyglot

mev forensics on solana is bottlenecked by shred latency. python is fast enough for classification and scoring (a slot is at most a few hundred swaps) but a poor fit for a high-frequency shred-stream loop. rust handles the hot path; python handles the analysis. they meet at the Event boundary.

pipeline layers

ingest

two sources feed the pipeline:

  1. shredstream (pre-finality). a jito shred-relay subscription. solana has no public mempool — shreds are the earliest signal you can get on a tx before its slot finalizes.
  2. finalized slots (post-finality). either getBlock (batched, full slot) or getTransaction (per-signature, deep instruction trace) over a helius / triton / quicknode rpc.

the live ingest path runs in ingest-rs/. python has stubs at src/hakiri/ingest/{shreds,leader,trace}.py so the rest of the pipeline can be exercised without a node.

decode

instructions and inner-instructions are converted into SwapTx records via program-id dispatch. supported targets:

  • raydium amm v4 — 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 (Swap)
  • raydium clmm — CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK (SwapV2)
  • orca whirlpools — whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc (Swap)

meteora dlmm and phoenix clob are stubs at this stage.

classify

pure functions over SwapTx lists ordered by tx_index. each rule has a numbered id; ids appear in docs/heuristics.md and on the event itself via event.notes.

score

rule-based confidence in [0.0, 0.95]. capped on purpose. the breakdown is returned to the caller so every confidence value is fully traceable.

ai filter

optional. only used when ANTHROPIC_API_KEY is set. the filter reviews edge-case events and returns a minor adjustment, never an upgrade beyond the cap. when disabled, the rule-based score is final.

sinks

three sinks ship in 0.1:

  • stdout — rich-formatted terminal output
  • jsonl — append-only file at the configured path
  • webhook — POST to an arbitrary url, failures swallowed

all runs every configured sink. add your own by implementing an emit method that takes (event, score).

glossary

domain terms used throughout hikara.

backrun
an arbitrage transaction placed immediately after a known price-moving transaction in the same slot.
block leader
the validator scheduled for the current slot. unlike ethereum, solana has no proposer-builder separation — the leader builds the block directly. with the jito-solana client, the leader exposes a bundle slot to searchers in exchange for a tip.
bundle (jito)
an ordered group of up to 5 transactions submitted via the jito relay. atomic by construction — either all txs land or none. searchers pay the leader a tip via one of the well-known jito tip accounts.
confidence cap
hikara scores never exceed 0.95. a detector, not an oracle.
jito relay
public infrastructure that forwards searcher bundles to jito-solana validators. the relay enforces atomicity, dedupes, and exposes the shredstream feed.
jito tip
a sol transfer to one of 8 well-known jito tip accounts. presence and size are the strongest single signal that a transaction is part of a jito bundle.
jit (just-in-time liquidity)
opening a concentrated position, capturing fees from one specific incoming swap, and closing the position in the same slot. on solana, mostly seen on orca whirlpools and meteora dlmm.
priority fee
per-compute-unit fee paid in addition to the base fee. another lever searchers use for inclusion priority alongside (or instead of) jito tips.
sandwich
a front-run + back-run pair surrounding a victim swap on the same pool. the searcher buys before, sells after, captures the spread the victim creates.
searcher
a bot operator submitting bundles to the jito relay. distinct from the validator; pays for inclusion via tips.
shredstream
jito's low-latency shred feed. partial slot data delivered as it's produced, before finalization. hikara reads it to detect bundles in-flight.
slot
solana's notion of a block. lasts ~400ms. a slot can contain hundreds of transactions; ordering inside the slot is set by the leader.
tx_index
the position of a transaction within its slot. ordering matters for bundle reconstruction and sandwich detection.
verdict
hikara's human-readable label for a scored event: confirmed (≥0.85), likely (≥0.65), suspected (≥0.40), noise (<0.40).

roadmap

versionscopestatus
v0.1sandwich + backrun rules. raydium amm v4 + orca whirlpools decode. demo + cli.shipped
v0.2rust ingest wired via pyo3. jit + atomic arb rules. fixture replay.now
v0.3liquidation + oracle rules. meteora dlmm + phoenix clob. drift + kamino support.planned
v0.4per-searcher leaderboard. per-leader tip share. weekly digest.planned
v0.5jito shredstream integration. low-latency local rpc mode.planned

contributing

short version: ship code that passes ci, write a clear pr description, no llm-generated readmes.

new searchers and tip accounts are the easiest path in. open a PR against src/hakiri/enrich/leader.py or src/hakiri/enrich/searcher.py with on-chain evidence in the description.

full guidelines: CONTRIBUTING.md.