Swap on terms that never move.
Pina AMM is a permissionless constant-product market maker for Solana. A pool locks its fee rates when it is created, with no pause switch and no admin path to its funds, and a swap costs about 4,700 compute units.
pAMMvXaqR2VVFqznf6dgvUFQjLXXAEeL9cb48cXsGeVTry the curve
SOL / USDC pool
- You receive
- 7,125.85 USDC
- Average price
- 142.52 USDC per SOL
- Fee
- 0.125 SOL (0.105 to LPs)
- Pool price
- 150 → 136.07 (−9.28%)
Fees stay in the pool. Replay a burst of trades to watch k grow.
Built to be read, not trusted
It keeps the shape of Raydium's CP-Swap and removes everything an integration does not need.
Nothing to trust after creation
A pool copies its tier's fee rates when it is created. Updating a tier only affects new pools, and no instruction can pause a pool or reach its funds.
Read more →Small and fast
A swap costs about 4,700 compute units including both token transfers, and the whole program is about 81 KB.
Read more →Creator fees built in
Any tier can add a creator fee, paid to the pool's creator in the token they choose. A launchpad can route post-launch trading income without another program.
Read more →Token-2022 ready
SPL Token and Token-2022 mints both work, as long as their extensions cannot change how many tokens a transfer moves.
Read more →
Measured on the real program
- per swap, both transfers included
- 4,700CU
- deployed program
- 81KB
- instructions with fixed account lists
- 10
- admin paths to a pool's funds
- 0
The end-to-end suite runs every instruction against the compiled program and fails if a swap exceeds 6,000 compute units. See the measurements.
A client for your stack
Rust, TypeScript, Dart, and on-chain CPI clients are generated from the program's IDL, so they always match it. A hand-written CLI covers everything else.
@pina-rs/ammnpmTypeScript client for @solana/kit
pina_amm_clientcrates.ioRust client: builders, decoders, PDAs, events
pina_amm_cpicrates.iono_std client for cross-program calls
pina_ammpub.devDart and Flutter client for solana_kit
pina_amm_clicrates.ioThe pina-amm command-line tool
import { fetchPool, getSwapExactInInstruction } from "@pina-rs/amm";
import { TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";
import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const { data: pool } = await fetchPool(rpc, poolAddress);
const instruction = getSwapExactInInstruction({
trader: wallet,
pool: poolAddress,
inputToken: walletToken0,
outputToken: walletToken1,
inputVault: pool.vault0,
outputVault: pool.vault1,
inputTokenProgram: TOKEN_PROGRAM_ADDRESS,
outputTokenProgram: TOKEN_PROGRAM_ADDRESS,
amountIn: 1_000_000n,
minimumAmountOut: 990_000n,
});TypeScript guide →use pina_amm_client::instructions::{SwapExactIn, SwapExactInInstructionData};
let data = SwapExactInInstructionData::new(|data| {
data.amount_in.set(1_000_000);
data.minimum_amount_out.set(minimum_out);
})?;
let instruction = SwapExactIn::new(
trader,
pool,
trader_token_0, // input: selling token 0
trader_token_1, // output
state.vault0,
state.vault1,
token_program_0,
token_program_1,
)
.instruction(data);Rust client guide →final instruction = getSwapExactInInstruction(
programAddress: pinaAmmProgramAddress,
trader: wallet.address,
pool: pool,
inputToken: walletToken0,
outputToken: walletToken1,
inputVault: state.vault0,
outputVault: state.vault1,
inputTokenProgram: tokenProgramAddress,
outputTokenProgram: tokenProgramAddress,
amountIn: BigInt.from(1000000),
minimumAmountOut: minimumOut,
);Dart guide →use pina_amm_cpi::{SwapExactIn, SwapExactInIx};
SwapExactIn {
trader: self.vault_authority,
pool: self.pool,
input_token: self.program_token_0,
output_token: self.program_token_1,
input_vault: self.pool_vault_0,
output_vault: self.pool_vault_1,
input_token_program: self.token_program,
output_token_program: self.token_program,
ix: SwapExactInIx {
amount_in,
minimum_amount_out,
},
}
.invoke_signed(&amm, &[vault_authority_seeds.to_signer().as_signer()])?;CPI guide →cargo install pina_amm_cli
# Quote a trade, then send it with a 0.5% slippage limit.
pina-amm quote --pool <POOL> --sell <MINT> --amount-in 1000000
pina-amm swap --pool <POOL> --sell <MINT> --amount-in 1000000 --slippage-bps 50CLI guide →Pools no one can front-run
A tier can be reserved for a single pool creator, such as a launchpad program's PDA. Only that program can open pools in it, so its graduation pools cannot be created first by someone else.
Read the details
- ArchitectureAccounts, PDAs, lifecycle, and the design decisions behind them.
- MathReproduce any quote and check every rounding rule.
- FeesFee tiers, protocol fees, creator fees, and restricted tiers.
- InstructionsData, accounts, errors, and events for all ten instructions.
- SecurityThe threat model and the invariants the program enforces.
- DeployingDeploy the program and create the first fee tiers.