> ## Documentation Index
> Fetch the complete documentation index at: https://continuum-ec12e897.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Trade

> Three venues - instant book trades, committed large orders, and the legacy instant oracle swap.

Continuum v2 trades L and S tokens against **native protocol venues** - no external AMM. There are three, split by design:

| Venue                   | Instruction                   | Price                                    | Size                            | Latency  |
| ----------------------- | ----------------------------- | ---------------------------------------- | ------------------------------- | -------- |
| **Book trade**          | `pool_swap`                   | Walks the book's bins - real slippage    | Standing depth (lean by design) | Instant  |
| **Committed order**     | `commit_swap` → `settle_swap` | NAV ± 0.10% at the **next oracle print** | No cap                          | \~12-25s |
| **Instant oracle swap** | `clp_swap`                    | NAV ± configured spread (0.30%)          | Rolling window cap              | Instant  |

The split is the point: instant venues carry adverse-selection risk, so their depth and spread are sized for small trades. Large orders take the committed path, where the fill price is set *after* the commitment - latency arbitrage is impossible by construction, so size needs no cap and the spread is the thinnest of the three.

The frontend routes for you: book trade for instant fills, auto-switching to committed mode above \$5k notional (overridable). This page covers all three for builders.

<Note>
  Mint/redeem at NAV remains the canonical way to open or close a *paired* position - see [Mint](/flows/mint) and [Redeem](/flows/redeem). The venues here are for directional entries and exits.
</Note>

## Venue 1: instant book trade (`pool_swap`)

Each market has one native CLMM pool **per side** - `(QQQ, long)` and `(QQQ, short)` are separate pools. The whole book lives inline in the `Pool` account (up to 16 bins, no per-bin rent): `asks` are synth reserves above the base price, `bids` are cUSDC reserves below it. The keeper re-pins `base_price` to NAV whenever drift exceeds a per-market gate (see [Book management](/keeper/book-management)).

Bin geometry is 2-zone: fine core steps near NAV (e.g. QQQ 20bps × 3 core bins), then wide wings (300bps steps) that keep quoting through off-hours drift. A swap walks the bins in order - **the output reflects real slippage**, enforced by your `min_out`.

```
direction: 0 = buy synth (pay cUSDC), 1 = sell synth (receive cUSDC)
```

### Accounts

| Account         | Notes                                                                                    |
| --------------- | ---------------------------------------------------------------------------------------- |
| `user` (signer) | Trader                                                                                   |
| `user_usdc`     | User's cUSDC ATA                                                                         |
| `user_synth`    | User's L or S ATA (matching the pool's side)                                             |
| `pool`          | Pool PDA: seeds `[b"pool", market_pda, [side]]`, clp program. `side` 0 = long, 1 = short |
| `synth_vault`   | Pool's synth ATA (owner = pool PDA)                                                      |
| `usdc_vault`    | Pool's cUSDC ATA (owner = pool PDA)                                                      |
| `token_program` | SPL Token                                                                                |

### TypeScript

```typescript theme={null}
import { Program, BN } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
import clpIdl from "./clp.json";

const clp = new Program(clpIdl, provider);
const side = 0; // long

const [poolPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("pool"), marketPDA.toBuffer(), Buffer.from([side])],
  clp.programId,
);
const pool = await clp.account.pool.fetch(poolPDA);

await clp.methods
  .poolSwap(0 /* buy synth */, new BN(100_000_000) /* 100 cUSDC */, minOut)
  .accounts({
    user: wallet.publicKey,
    userUsdc: getAssociatedTokenAddressSync(pool.usdcMint, wallet.publicKey),
    userSynth: getAssociatedTokenAddressSync(pool.synthMint, wallet.publicKey),
    pool: poolPDA,
    synthVault: getAssociatedTokenAddressSync(pool.synthMint, poolPDA, true),
    usdcVault: getAssociatedTokenAddressSync(pool.usdcMint, poolPDA, true),
    tokenProgram: TOKEN_PROGRAM_ID,
  })
  .rpc();
```

To quote before swapping, read the `Pool` account and walk the bins yourself: bin `k` is priced at `base_price · r^±k` where `r = 1 + step_bps/10_000` (core zone) switching to `wing_step_bps` beyond `core_bins`. See [Reading state](/flows/read-state#native-pool-book) for a depth read.

**Standing depth is deliberately lean** (\~\$5k bids / ≤\$7.5k asks per side) - depth is sized to demand, not TVL, because toxic loss scales with deployed depth. If your size would eat through the book, use a committed order instead - that is what it exists for.

## Venue 2: committed order (`commit_swap` → `settle_swap`)

The large-order path. You escrow the input into an order PDA; the fill executes at the **first oracle print strictly after your commit**, at NAV ± 0.10% (`COMMIT_SPREAD_BPS = 10`). Because the fill price is set after you committed, you cannot pick the protocol off with a stale quote - and the protocol cannot be picked off either, which is why:

* **No size cap, no window cap.** Bounds are oracle health, the collateral floor, and keeper-provisioned inventory.
* **The thinnest spread of the three venues** - a price set after the commitment carries zero adverse selection.

The lifecycle:

<Steps>
  <Step title="Commit">
    `commit_swap(side, direction, amount_in, min_out, nonce)` escrows your input (cUSDC for buys, synth for sells) into an escrow token account owned by the order PDA. The payout ATA must already exist - checked at commit so settlement can never strand on a missing account.
  </Step>

  <Step title="Settle (permissionless)">
    `settle_swap` fills at NAV(now) ± 10bps - valid only when the market's TWAP timestamp is strictly newer than your commit and the oracle is healthy. The keeper cranks this (typical end-to-end **12-25s**, bounded by the \~15s oracle push cadence), but anyone may settle. If the quoted output misses your `min_out`, the order is **fully refunded** - terminal, not a revert loop.
  </Step>

  <Step title="Cancel (after TTL)">
    If unsettled after 180 seconds (`COMMIT_TTL_SECS`), `cancel_swap` refunds unconditionally. It checks **nothing else** - no oracle, keeper, freeze, or market-active state. Escrowed funds are always recoverable after the TTL, regardless of protocol state.
  </Step>
</Steps>

Every terminal path (settle, refund, cancel) closes the order account and escrow - rent returns to you.

### Order account

PDA seeds `[b"order", user, market, nonce_le_bytes]`, clp program. `nonce` is client-supplied; use a timestamp or counter to allow concurrent orders.

```rust theme={null}
pub struct Order {
    pub user: Pubkey,      // offset 8 (after discriminator)
    pub market: Pubkey,    // offset 40
    pub side: u8,          // 0 = long, 1 = short
    pub direction: u8,     // 0 = buy synth, 1 = sell synth
    pub status: u8,        // offset 74; 0 = pending (the only persisted state)
    pub bump: u8,
    pub escrow_bump: u8,
    pub amount_in: u64,
    pub min_out: u64,      // miss → automatic full refund
    pub created_at: i64,   // settle requires twap_updated_at > this
    pub expires_at: i64,   // created_at + 180; settle owns ≤, cancel owns >
    pub nonce: u64,
}
```

### Accounts: `commit_swap`

| Account                           | Notes                                                                |
| --------------------------------- | -------------------------------------------------------------------- |
| `user` (signer, mut)              | Pays rent for order + escrow (refunded on any terminal path)         |
| `market`                          | Market PDA (mint-redeem program) - binds side mints                  |
| `clp`                             | Per-market CLP PDA: seeds `[b"clp", market_pda]`                     |
| `order` (init)                    | Order PDA as above                                                   |
| `in_mint`                         | Mint of the escrowed leg (cUSDC for buys, synth for sells)           |
| `escrow` (init)                   | Token account, seeds `[b"escrow", order_pda]`, authority = order PDA |
| `user_in`                         | Your source token account                                            |
| `user_out`                        | Your payout token account - **must exist now**                       |
| `clp_vault`                       | CLP's cUSDC vault (read-only mint anchor)                            |
| `token_program`, `system_program` |                                                                      |

### Accounts: `settle_swap`

Permissionless - the cranker signs and pays the tx fee, nothing more.

| Account                        | Notes                                 |
| ------------------------------ | ------------------------------------- |
| `cranker` (signer)             | Anyone                                |
| `user` (mut)                   | `order.user` - receives rent on close |
| `order` (mut, close = user)    |                                       |
| `escrow` (mut)                 |                                       |
| `clp` (mut)                    |                                       |
| `clp_vault`, `clp_synth` (mut) | CLP inventory legs                    |
| `market`                       | NAV source                            |
| `user_out`, `user_in` (mut)    | Payout / refund targets               |
| `token_program`                |                                       |

### Accounts: `cancel_swap`

| Account                     | Notes              |
| --------------------------- | ------------------ |
| `user` (signer, mut)        | The order's owner  |
| `order` (mut, close = user) |                    |
| `escrow` (mut)              |                    |
| `user_in` (mut)             | Refund destination |
| `token_program`             |                    |

### TypeScript

```typescript theme={null}
const nonce = new BN(Date.now());
const [orderPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("order"), wallet.publicKey.toBuffer(), marketPDA.toBuffer(),
   nonce.toArrayLike(Buffer, "le", 8)],
  clp.programId,
);
const [escrowPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("escrow"), orderPDA.toBuffer()],
  clp.programId,
);

// Sell 200 QQQL at next print, floor at $95k out
await clp.methods
  .commitSwap(0 /* long */, 1 /* sell */, new BN(200_000_000), new BN(95_000_000_000), nonce)
  .accounts({
    user: wallet.publicKey,
    market: marketPDA,
    clp: clpPDA,
    order: orderPDA,
    inMint: market.longMint,
    escrow: escrowPDA,
    userIn: userLongAta,
    userOut: userUsdcAta, // must exist
    clpVault: clpVault,
    tokenProgram: TOKEN_PROGRAM_ID,
    systemProgram: SystemProgram.programId,
  })
  .rpc();

// Then either: wait for the keeper's settle (watch your userOut balance or the
// OrderSettled event), or after 180s reclaim with cancelSwap.
```

Events: `OrderCommitted`, `OrderSettled` (carries `out`, `nav`, `base_price`), `OrderRefunded` (min\_out miss), `OrderCancelled`.

<Warning>
  **Mainnet prerequisite.** Settlement currently prices off the keeper-relayed TWAP (`market.user_twap_price`). Before any mainnet deploy, `settle_swap` must read Pyth directly and enforce `publish_time > order.created_at` at that single code point.
</Warning>

## Venue 3: instant oracle swap (`clp_swap`)

The original v2 path, retained for small instant trades: a fill at NAV ± a configured spread (30bps) from pre-stocked CLP inventory. No book, no slippage - but guarded hard, because an instant at-oracle fill is exactly what a latency arbitrageur wants:

* **Oracle health breakers** - staleness (60s), confidence width, 25% deviation from the last accepted price.
* **Rolling notional window cap** - bounds stale-price extraction per window. Committed orders bypass this and do not consume it.
* **Collateral floor** - rejects fills that would quote into an under-collateralized market.

Accounts: `user`, `user_usdc`, `user_synth`, `clp` (PDA `[b"clp", market_pda]`), `clp_vault`, `clp_synth`, `market`, `token_program`. Args: `(side, direction, amount_in, min_out)` - same convention as the committed path.

Inventory trades move already-outstanding, fully-backed tokens - supply and collateral are unchanged, only ownership moves.

## Choosing a venue

| You want                                              | Use                                                             |
| ----------------------------------------------------- | --------------------------------------------------------------- |
| Small instant fill at the tightest live quote         | Book trade (`pool_swap`)                                        |
| Size, at the fairest possible price                   | Committed order                                                 |
| A guaranteed-rate small fill regardless of book shape | `clp_swap`                                                      |
| Open/close a paired position at NAV                   | [`mint_paired`](/flows/mint) / [`redeem_paired`](/flows/redeem) |

A useful mental model: the book quotes a *live* price and charges you slippage for immediacy; the committed venue quotes a *future* price and charges you \~15 seconds of patience instead.

## See also

<CardGroup cols={2}>
  <Card title="Reading state" icon="magnifying-glass" href="/flows/read-state">
    Pool books, NAV, pending orders - programmatically.
  </Card>

  <Card title="CLP program reference" icon="file-code" href="/programs/clp">
    Full instruction and account reference.
  </Card>

  <Card title="Book management" icon="chart-line" href="/keeper/book-management">
    How the keeper keeps the books pinned to NAV.
  </Card>

  <Card title="Peg maintenance" icon="route" href="/keeper/arb-paths">
    Why prices stay honest without an arb bot.
  </Card>
</CardGroup>
