AMMs (Raydium, Orca, Meteora)
Solana's major AMMs hold concentrated and constant-product liquidity in program-owned pool accounts. Integrate directly when you need custom routing, LP actions, or on-chain CPI swaps outside Jupiter.
Recipe
Quick-reference recipe card - copy-paste ready.
// Orca Whirlpool swap via SDK (off-chain ix build)
import { swapQuoteByInputToken, WhirlpoolContext } from "@orca-so/whirlpools-sdk";
const quote = await swapQuoteByInputToken(whirlpool, inputTokenMint, amountIn, slippageTolerance, programId);// On-chain: validate pool accounts match expected program + mints
require_keys_eq!(pool_state.token_mint_a, expected_mint_a, ErrorCode::MintMismatch);
require_keys_eq!(pool_state.token_mint_b, expected_mint_b, ErrorCode::MintMismatch);When to reach for this:
- Building LP deposit/withdraw flows.
- CPI swaps inside your Anchor 0.32.1 program.
- Accessing concentrated liquidity (Orca Whirlpools, Meteora DLMM).
- Reading reserves for on-chain pricing without an aggregator.
Working Example
import { createSolanaRpc, address } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
// Raydium AMM v4 pool state (example layout - fetch and decode with SDK)
const poolAddress = address("58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2"); // SOL-USDC legacy pool
const poolAccount = await rpc.getAccountInfo(poolAddress, { encoding: "base64" }).send();
if (poolAccount.value) {
console.log("Pool owner:", poolAccount.value.owner);
console.log("Data length:", poolAccount.value.data.length);
}What this demonstrates:
- Pool state is a single account owned by the AMM program.
- Clients decode layout off-chain; on-chain programs validate owner and mint fields.
- Each venue (Raydium, Orca, Meteora) has distinct account layouts and program IDs.
Deep Dive
How It Works
- Raydium - Classic constant-product AMM v4 plus CLMM pools; deep SOL-stable liquidity.
- Orca - Whirlpools use concentrated liquidity with tick arrays; capital-efficient for stable pairs.
- Meteora - DLMM uses discrete price bins; popular for launchpad and volatile pairs.
- Swaps debit input vault, credit output vault, and update fee accumulators atomically.
Venue Comparison
| Venue | Model | Best for | Program note |
|---|---|---|---|
| Raydium AMM v4 | x*y=k | Broad pairs | Mature, high TVL |
| Orca Whirlpool | Concentrated | Stable/volatile tight ranges | Tick array accounts |
| Meteora DLMM | Bin steps | New launches, custom curves | Dynamic fees |
Rust Notes
use anchor_lang::prelude::*;
#[account]
pub struct PoolSnapshot {
pub token_a_reserve: u64,
pub token_b_reserve: u64,
pub fee_numerator: u64,
pub fee_denominator: u64,
}
// Always read reserves at execution time - never trust cached client values on-chainGotchas
- Wrong pool type - Raydium v4 vs CLMM use different instruction layouts. Fix: Match SDK/program ID to pool type.
- Tick array missing - Orca swaps need current tick array accounts in the meta list. Fix: Use Whirlpool SDK to derive remaining accounts.
- Stale reserve reads - Client preview != execution price. Fix: Simulate swap or read reserves in same slot.
- Mint order - Pools store token A/B in canonical order. Fix: Swap direction flag must match mint ordering.
- LP slippage - Adding liquidity can be front-run. Fix: Set min LP tokens out parameter.
- Account volume - CLMM/DLMM swaps need many accounts; use ALTs. Fix: Versioned transactions with lookup tables.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Jupiter aggregator | Best price, fewer integrations | You need LP-only actions |
| Phoenix CLOB | Price-time priority order book | You want passive LP yield |
| On-chain oracle pricing | Lending collateral | Spot swaps |
FAQs
Should I integrate Raydium or just use Jupiter?
Use Jupiter for swaps. Integrate Raydium directly for LP management, farming, or custom CPI paths.
What is concentrated liquidity?
LPs deposit in a price range (ticks/bins). Capital efficiency is higher but inactive ranges earn no fees.
How do I find a pool address?
Use venue explorers, Jupiter routePlan, or SDK getPool helpers - never guess pool PDAs.
Can Anchor programs CPI into AMMs?
Yes - pass all required pool, vault, tick, and oracle accounts. Validate program IDs in your constraints.
How are fees charged?
Each swap deducts a fee from input before applying the invariant. Fee tiers vary by pool and venue.
What about Token-2022 pools?
Growing support on Orca/Meteora - verify mint owner and transfer hook compatibility before routing.
How do I test AMM CPIs locally?
Clone pool accounts into solana-test-validator or use Surfpool 0.12.0 fork for realistic reserves.
Why do Meteora bins matter?
Price moves across bins; each bin holds discrete liquidity. Wrong active bin accounts cause swap failure.
How do I compute price impact?
Compare spot price before/after using reserve or sqrt-price fields from pool state.
Are Raydium route maps stable?
Pool addresses are stable but liquidity migrates. Refresh pool lists from official sources periodically.
Related
- Swaps with Jupiter - aggregated routing
- Oracles - prices for hybrid AMM/lending systems
- DeFi Integrations Best Practices - pool integration policy
- Testing CPIs & PDAs - AMM CPI tests
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.