Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.meteora.ag/llms.txt

Use this file to discover all available pages before exploring further.

Use CPI when your Solana program must call DAMM v2 directly, for example to swap, add or remove liquidity, claim fees or rewards, or manage a DAMM v2 position as part of a larger protocol instruction.
The stable integration contract is the public cp-amm program, the published IDL, and the official SDK behavior. This page is cross-checked against the cp-amm source so account ordering and remaining-account notes match the on-chain handlers.

Program ID

pub const CP_AMM_PROGRAM_ID: Pubkey =
    pubkey!("cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG");
The public program ID is the same for mainnet and devnet.

Generated Bindings

Prefer generated CPI bindings from the cp-amm IDL. The handlers use Anchor accounts, optional accounts, generated instruction args, #[event_cpi], and a custom optimized swap entrypoint with Anchor fallback.
Do not hand-type account order from memory. Generate bindings or compare against SDK-built instructions. Most CPI failures come from one misplaced optional account, event authority account, position NFT account, token program, or rate-limiter remaining account.
The public integration contract is:
ResourceLink
Program sourceMeteoraAg/damm-v2/programs/cp-amm
IDLcp_amm.json
Program IDcpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG
You can generate a client from the IDL or depend on the public cp-amm crate from the DAMM v2 workspace when your build setup allows it. If you depend on the Rust crate for CPI, enable the CPI-compatible features from the workspace:
[dependencies]
cp-amm = { path = "../programs/cp-amm", features = ["cpi"] }
When importing from the public workspace, keep the crate revision aligned with the IDL and SDK version you test against.

CPI Instruction Scope

For the full cp-amm instruction-family map, see DAMM v2 Program Instructions. This page focuses on CPI implementation details for the user instructions most integrations call: swap2, add_liquidity, remove_liquidity, claim_position_fee, claim_reward, and position lock flows. For off-chain apps, bots, and launch scripts, the TypeScript SDK is usually simpler and safer.

Account Planning

FlowRequired planning
SwapPool authority, pool, user input/output token accounts, vaults, mints, payer, token programs, optional referral token account
Rate-limiter swapAdd the instructions sysvar as the first remaining account when the rate limiter is active
Add/remove liquidityPool, position, user token accounts, vaults, mints, position NFT token account, owner signer, token programs
Claim feesPosition NFT ownership, destination token accounts, pool vaults, token programs
Claim rewardsReward vault and reward mint/program for the reward index
Pool creationCorrect pool PDA, vault PDAs, position NFT mint/account, token programs, rent/system accounts, and config where applicable
Read token mint and vault addresses from pool state whenever possible. Avoid reconstructing token A/B assumptions from user input alone.

Event CPI Accounts

Most cp-amm account structs use #[event_cpi]. Generated clients include event CPI accounts after the instruction’s primary accounts:
AccountWhy it appears
event_authorityPDA derived from __event_authority for cp_amm
programThe cp_amm program account used by Anchor event CPI emission
Keep these accounts in the generated order. They are part of Anchor’s account validation even though they are not business-state accounts.

Remaining Accounts

Rate-limiter pools reject swaps that do not include the instructions sysvar because the program validates single-swap behavior for that pool in the transaction.
solana_program::sysvar::instructions::ID
For swap and swap2, the optimized swap path expects the fixed swap account list plus remaining accounts. If the rate limiter is active, put the instructions sysvar as the first remaining account. Normal non-rate-limiter swaps do not need remaining accounts. Token 2022 transfer-hook accounts are not a general DAMM v2 CPI surface for active transfer hooks. DAMM v2 supports Transfer Hook only when the hook program ID and authority are unset. See Token 2022 support.

Swap CPI Shape

For generated Anchor CPI, the account set mirrors SwapCtx:
AccountNotes
pool_authorityPDA derived from pool_authority
poolMutable pool account; must match token vaults
input_token_account, output_token_accountMutable user token accounts
token_a_vault, token_b_vaultMutable pool vaults
token_a_mint, token_b_mintPool mints
payerSigner whose token account is debited
token_a_program, token_b_programSPL Token or Token-2022 programs matching the mints
referral_token_accountOptional referral account; use the generated optional-account representation
event_authority, programEvent CPI accounts
swap2 parameters use the same semantics as the SDK:
Modeamount_0amount_1
ExactInInput amountMinimum output
PartialFillInput amountMinimum output
ExactOutDesired outputMaximum input

Common CPI Failures

ErrorLikely cause
NotEnoughAccountKeysThe CPI account list is shorter than the handler expects. This often means event_authority, program, an optional referral account placeholder, or a remaining account was omitted.
ConstraintAddress / ConstraintSeedsThe pool authority or event authority PDA does not match the cp-amm program seeds.
ConstraintHasOneThe pool, position, vault, or mint account does not match the has_one relationships in the account struct. Read vaults and mints from pool state instead of reconstructing them from user input.
ConstraintTokenMint / ConstraintTokenTokenProgramA vault or token program does not match the mint and token program expected by the pool. Token A and token B can use different token programs.
AccountNotSignerThe expected payer or owner was not a signer. If your program signs with a PDA, forward the correct signer seeds.
FailToValidateSingleSwapInstructionA rate-limiter swap is missing the instructions sysvar, the sysvar is not the first remaining account, the transaction includes another swap for the same pool, or the CPI stack is deeper than the rate-limiter path allows.
UnsupportedSysvarThe first remaining account for an active rate-limiter swap is not solana_program::sysvar::instructions::ID.
ExceededSlippageThe quote is stale, bounds are too tight, or Token 2022 transfer fees were not included in the add, remove, or swap thresholds.
AmountIsZero / InvalidParametersInput amount, liquidity delta, or the rounded token amount is zero. This can happen with very small liquidity changes.
PoolDisabledThe pool status or access validator does not allow the requested action, such as swap, add liquidity, remove liquidity, or lock.
InsufficientLiquidityThe position does not have enough unlocked liquidity, or vesting/lock state was not refreshed before removal.
PositionIsNotEmptyclose_position was called before all liquidity, fees, rewards, and locks were cleared.
InvalidRewardIndex / RewardUninitialized / InvalidRewardVaultThe reward index is outside NUM_REWARDS, the reward slot has not been initialized, or the vault does not match pool reward state.
RewardVaultFrozenSkipRequiredThe reward vault is frozen and claim_reward was called without the skip flag.
InvalidTokenBadgePool creation, reward initialization, or Token 2022 mint handling requires a token badge account that was missing or did not match the mint.
UnsupportNativeMintToken2022The native mint was supplied through Token 2022. Use the normal wrapped SOL mint and token program path.
IncorrectATAOperator or protocol-fee flows expected a canonical ATA but received a different token account or owner.
PriceRangeViolation / InvalidPriceRangeSwap or pool creation parameters would move outside the pool price range, or the range is invalid for the collect-fee mode.

Best Practices

CheckDetail
Quote before CPIQuote off-chain with the TypeScript SDK or Rust quote library, then pass explicit input and slippage bounds into your own program.
Forward generated orderUse generated bindings or compare your account metas against an SDK-built instruction. The main accounts, optional accounts, and event CPI accounts must stay in the generated order.
Read pool state firstUse pool state for token mints, vaults, token flags, collect-fee mode, layout version, activation type, and reward vaults. Do not infer token A/B ordering from user input.
Include event CPI accountsMost user-facing handlers use #[event_cpi]; keep event_authority and program after the primary accounts as generated by Anchor.
Plan rate-limiter swapsDetect rate-limiter pools off-chain. Include the instructions sysvar as the first remaining account and avoid batching multiple swaps for the same pool in one transaction.
Avoid deep CPI nesting for rate-limiter swapsThe rate-limiter validation rejects some deeper CPI stacks. Prefer a direct CPI from your program to cp-amm for those pools.
Handle token programs per mintToken A and token B can be SPL Token or Token 2022 independently. Pass the token program that owns each mint and vault.
Reject active transfer hooksDAMM v2 only supports Token 2022 Transfer Hook mints when the hook program ID and authority are unset. Do not forward active transfer-hook account sets as a DLMM-style remaining-account slice.
Verify position NFT ownershipLiquidity, fee, reward, lock, split, and close flows validate that the position NFT token account has amount 1, matches position.nft_mint, and is owned by the signer.
Refresh lock and vesting stateFor remove, close, split, and merge-style flows, load current slot or timestamp and include vesting state expected by your wrapper before deciding what liquidity is unlocked.
Account for Token 2022 transfer feesAdd-liquidity thresholds are maximum included-fee amounts; remove-liquidity thresholds are minimum post-fee amounts. Quote with mint and epoch data before building CPI inputs.
Check reward stateValidate reward index, reward vault, reward mint program, campaign timing, and frozen-vault behavior before claiming or funding rewards.
Budget computeSwaps with dynamic fees, Token 2022 transfers, pool creation, reward operations, and multi-step wrapper instructions can need extra compute. Add compute budget instructions in the outer transaction when needed.
Simulate against real poolsTest on localnet and devnet, then compare logs and account metas against the same flow built by @meteora-ag/cp-amm-sdk.
Keep revisions alignedTest the cp-amm crate, generated IDL client, TypeScript SDK, and deployed program version together. Mismatched revisions are a common source of account-order and enum-value failures.