Request API access
PRION Engineering / Open source

One Exact OHLCV Core for Eight Solana Protocols

How PRION normalizes realized swaps from Pump.fun, PumpSwap, Raydium and Meteora into exact, fork-aware candles—and what remains disabled.

By Selema10 minute read

A candle looks universal only after the hard work is finished. Every venue has its own event layout, direction convention, fee model and definition of “amount.” If those differences leak into the aggregation layer, two adapters can turn the same economic execution into different prices or volumes.

For the PRION devkit, we built one decoder-neutral Rust core for Pump.fun, PumpSwap, Raydium AMM V4, Raydium CPMM, Raydium LaunchLab, Meteora Dynamic Bonding Curve, and Meteora DAMM V1 and V2. Venue logic stops at a small normalization boundary. Ordering, exact price comparison, idempotency, rollback, finality and candle aggregation belong to the shared core.

Current status: the implementation and evidence are prepared under MIT in the canonical PRION devkit. Its first reviewed public commit and immutable release reference are still publication gates. This work does not enable OHLCV for a market or claim production decoder coverage.

Why one reducer and eight adapters

The protocols do not need one giant decoder. They need one stable trade contract.

A source captures Solana transaction metadata. A version-pinned decoder proves what happened for one program. A thin adapter orients the realized amounts into a configured base and quote pair. Only then may an event enter the reducer.

  1. 01CaptureOrdered transaction and log metadata from a replaceable source
  2. 02DecodeProgram-version-specific bytes into a verified execution
  3. 03NormalizeA thin venue adapter emits one exact canonical trade
  4. 04ReduceIdempotency, chain ordering, rollback, finality and OHLCV
  5. 05PresentDecimal strings cross into an API, database or chart

This is the open/closed boundary. A new venue implements TradeAdapter and calls the validated Trade::from_canonical_amounts constructor. It does not edit a central protocol enum or branch inside the candle engine. The constructor keeps event identity, market, realized amounts and exact price consistent, while read-only accessors prevent an external adapter from assembling a contradictory trade by hand.

The core is closed around the invariants that every venue must share. Protocol knowledge remains open for extension.

Executions, not estimates

An instruction limit is not a fill. A reserve ratio is not a trade. A quote response is not evidence that the transaction succeeded.

The adapters accept only realized execution values:

  • Pump.fun uses successful trade-event token and quote atoms.
  • PumpSwap uses the trader’s realized base and quote atoms.
  • Raydium AMM V4 requires reconciled user token-account deltas; slippage limits are rejected as execution evidence.
  • Raydium CPMM accounts for Token-2022 transfer fees by adding the input transfer fee and subtracting the output transfer fee from the current swap event.
  • Raydium LaunchLab and Meteora DBC orient reconciled user input and output through an explicit direction.
  • Meteora DAMM V1 pairs event amounts with instruction-account mints and user-balance agreement.
  • Meteora DAMM V2 uses reconciled EvtSwap2 user amounts after fee semantics are resolved.

If an event does not contain enough information, the decoder must reconcile pre- and post-transaction token balances. Guessing from reserves is a failure, not a fallback.

Exact arithmetic all the way to presentation

Token amounts stay in u64 atomic units. Prices are reduced positive u128 fractions that include both mint precisions. High and low are compared with a continued-fraction algorithm, avoiding the overflow risk of multiplying two large numerators and denominators across each other. Volumes use checked u128 sums.

The reducer does not use floating point. Its JSON boundary emits deterministic decimal strings and rejects unsupported decimal scales before exponentiation. A chart may convert those strings to JavaScript numbers only at the final presentation boundary.

That separation matters. Floating point is acceptable for drawing pixels; it is not the source of truth for the candle.

Chain order, duplicates and forks

Arrival order cannot define open and close when independent stream workers race. Each execution therefore carries a transaction signature and operation index for identity, plus slot, transaction index and operation index for total chain order. The operation index must flatten inner instructions and multiple events deterministically. Two identities cannot claim the same chain position; an alternate-fork event can use it only after the original is reverted.

Repeated delivery of an identical event is idempotent. Reusing the same identity with different content fails closed. An unfinalized event can be reverted by identity and expected slot; finalized history cannot be mutated, and the finality watermark only moves forward.

Internally, each active bucket has one ordered-event tree and one exact-price multiplicity tree. Apply and rollback are O(log n) in bucket size. Open, close, high and low come from tree endpoints, so a busy candle is never rescanned after every trade.

Test-driven evidence, not a coverage badge

The behavior was developed red-green-refactor. The suite covers all eight adapters in both representative directions, malformed mints and amounts, transfer-fee overflow and underflow, exact decimal scaling, large fraction ordering, identity and chain-position conflicts, out-of-order delivery, rollback, finality, market isolation and presentation output.

A 48-trade regression deliberately submits events out of order, then rolls back a subset. After every change it compares the incremental engine with a direct full recomputation oracle. A separate dense grid compares the fraction ordering algorithm with safe cross-products where the simple oracle is known not to overflow.

The latest source-bound instrumentation covers 100% of named functions and more than 99% of production lines across 27 integration tests. The report binds the measurement to SHA-256 hashes of each Rust source file and records its exclusions. Coverage complements the behavioral assertions; it does not stand in for them.

Surfpool verifies the source boundary

Deterministic fixtures remain the correctness oracle, but a source contract also has to work against a real Solana RPC process. The verification script checks the official Surfpool v1.6.0 archive digest before starting an offline, in-memory Surfnet. It creates temporary in-memory keypairs, requests local test lamports, submits a signed System Program transfer and requires confirmed slot, transaction index, block time, fee, balance delta and compute-unit metadata.

That proves the metadata needed for identity and ordering can cross the source boundary. It does not prove a DEX ABI, a mainnet program version, reorg delivery or durable recovery. Surfpool is a transport and canary lane, not a substitute for protocol fixtures.

The visual boundary is tested too

The public example drives all eight adapters through the real reducer and produces a 16-candle decimal-string fixture. The sequence intentionally contains eight bullish and eight bearish candles.

We rendered that exact fixture through the local KekPro market canvas and checked candle count, horizontal overflow, both color paths, first and last hover readouts and a manually inspected screenshot digest. The chart is GPL-licensed and remains a test-only boundary; no chart source or build output is copied into the MIT devkit.

This catches a class of failure a JSON equality check cannot: data can be mathematically correct and still be unusable when a renderer interprets its shape, scale or time units differently.

Why we did not import Carbon

We reviewed a local Carbon checkout as untrusted input. Its explicit source, decoder and processor separation is a useful architectural idea. We did not execute, import or copy it.

The broader dependency, provider and database surface does not define PRION’s exact event ordering, rollback semantics or venue-specific realized-amount rules. The smaller core keeps the useful separation while remaining runtime-neutral. Carbon or another decoder can still sit above TradeAdapter after its version, license, ABI and output receive independent conformance evidence.

What remains disabled

The open-source core is a useful library and conformance target today. Production OHLCV still requires, per market and program version:

  • pinned raw ABI decoding with successful and failed transaction fixtures;
  • user token-delta agreement for realized amounts;
  • duplicate, reconnect, gap, fork and restart tests;
  • an atomic durable store for checkpoints, normalized events, rollback metadata and candle changes;
  • Surfpool capture and replay of the actual protocol lane;
  • API interval, pagination and retention conformance; and
  • a current-mainnet canary with retained evidence.

Until those gates pass, capability metadata stays disabled. The private Solana indexer will consume the public crate only after the devkit has an immutable reviewed revision; adding a sibling path dependency now would break clean clones and pretend that publication already happened.

The public-good part is not a long protocol list. It is a small, auditable contract that lets another team add a venue without rewriting candle semantics—and lets them see exactly which claims have evidence and which do not.

Private beta

Building a trading product?

Request API access