Skip to content

Architecture

Zenith is built in four layers. Each layer depends only on the ones below it.

┌─────────────────────────────────────────────────────────────┐
│  app/            Vite + React web app                        │
│                  Swap · Pools · Positions · DLMM · Yield     │
└───────────────────────────┬─────────────────────────────────┘
                            │  imports
┌───────────────────────────▼─────────────────────────────────┐
│  @zenith/sdk     account decoders · exact-math quotes ·      │
│                  transaction builders (amm / dlmm / camm)    │
└───────────────────────────┬─────────────────────────────────┘
                            │  mirrors + reads
┌──────────────┬────────────┴───────────┬─────────────────────┐
│  zenith-amm  │      zenith-dlmm        │     zenith-camm     │
│  (Anchor)    │       (Anchor)          │      (Anchor)       │
└──────────────┴────────────┬───────────┴─────────────────────┘
                            │  depends on
┌───────────────────────────▼─────────────────────────────────┐
│  zenith-math     Q64.64 fixed point · U256 · pow / isqrt ·   │
│                  tick math · bin price · fee / LP / yield     │
└─────────────────────────────────────────────────────────────┘

Layers

crates/zenith-math — the exact-math core

A no_std-friendly Rust crate of pure, integer-exact math: Q64.64 fixed point, U256 intermediate arithmetic, pow / integer sqrt, tick ↔ sqrt-price conversion, bin pricing, constant-product swaps, LP-share math, and yield accrual. No floating point anywhere. Every function is deterministic and its results are exported as golden vectors the SDK re-checks (see Math).

programs/* — three Anchor programs

Three independent on-chain programs, each a full market:

ProgramModelSee
zenith-ammConcentrated liquidity (ticks)engines/amm.md
zenith-dlmmLiquidity book (bins)engines/dlmm.md
zenith-cammConstant product + yieldengines/camm.md

They share zenith-math but nothing else — no cross-program calls. Each owns its own account types, PDAs, instructions, and fee accounting.

sdk/@zenith/sdk

TypeScript that mirrors the programs:

  • Decoders read the zero-copy account layouts by byte offset (guarded by discriminator + length).
  • Quotes replay the on-chain swap math exactly — the same fixed-point operations, ported and pinned to the crate's golden vectors.
  • Transaction builders produce instructions with the precise account order, signer/writable flags, and argument encoding each handler expects.

The SDK is namespaced: the AMM API is top-level; DLMM and CAMM live under dlmm and camm. See SDK.

app/ — the web app

Vite + React + TypeScript + Tailwind. It imports @zenith/sdk and renders a tab per engine: Swap / Pools / Positions (AMM), DLMM, and Yield (CAMM). Each screen quotes with the SDK, builds a transaction, and has the connected wallet sign it. The live market addresses come from committed manifests (app/src/devnet.json, dlmm-devnet.json, camm-devnet.json).

How a swap flows

Taking an AMM swap as the example — the other engines follow the same shape:

  1. The app fetches the pool (and the tick arrays around the price) via SDK decoders.
  2. quoteSwap walks the tick curve in TypeScript and returns the exact output, fee, and end state — identical to what the program will compute.
  3. A transaction builder assembles the swap instruction with the pool, vaults, and the tick arrays the walk will cross.
  4. The wallet signs; the program re-runs the same math and settles.

Because steps 2 and 4 share the same fixed-point math, the quoted output equals the realized output to the token unit. This equality is enforced by parity tests that run the SDK quote against the real compiled program (see Math and Contributing).

The account model, briefly

All three programs use the Solana/Anchor pattern of program-derived accounts (PDAs):

  • A config or pair account holds market-wide parameters.
  • A pool / lb_pair account holds live state (price, liquidity, fee accumulators).
  • A pool authority PDA signs for token movements out of the program-owned vault token accounts.
  • Positions are per-LP accounts (the AMM's are position-NFT-gated).
  • Engine-specific accounts hold the rest: the AMM's tick arrays, the DLMM's bin arrays and oracle, the CAMM's yield-source vaults.

Exact fields, PDAs, and instruction lists are documented per engine.

Built on Solana devnet. Integer-exact math, no floats.