Skip to main content

What an IDL is

Anchor programs on Solana publish an IDL (Interface Definition Language) file describing their instructions, account layouts, error enum, and struct schemas. The IDL is the source of truth for client code generation — the TS SDK, Rust CPI crate, and third-party clients are all generated from (or hand-written against) it. Raydium publishes IDLs for CPMM, CLMM, and LaunchLab. AMM v4, Stable AMM, and Farm (v3 / v5 / v6) predate Anchor or are otherwise not Anchor-distributed — their account structures are hand-maintained in the SDK.

Where to find them

IDLs live in a dedicated repository:
The exact files: The IDL files are versioned in the repo’s git history; pin to a specific commit if you need byte-for-byte reproducibility. Some IDLs can also be pulled directly from mainnet:
There are now two on-chain IDL mechanisms, and Raydium’s programs are split across them — which matters because a given Anchor CLI version may only know about one:
CPMM has no legacy anchor:idl account. Its IDL was migrated to the Program Metadata program, so anchor idl fetch CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C fails on any Anchor CLI that only checks the legacy PDA. Use the IDL shipped with the SDK, or read the metadata account above, until your CLI supports the metadata program.
All three legacy IDL accounts are writable by the IDL authority 2XVnob28A5Qnpcy95UVeHWNT6G8Poy3tpA3AFyAMoZDt, which is separate from the programs’ BPF upgrade authority — so an IDL can be refreshed without redeploying, and can also lag a redeploy. Treat the on-chain IDL as a convenience, not as proof of the deployed bytecode’s shape.

Regenerating a TypeScript client

Anchor’s codegen produces a typed client from the IDL:
Most integrators do not do this — they use the higher-level raydium.cpmm.swap(...) helper which wraps the Anchor methods plus all the bookkeeping (ATA creation, transfer-fee adjustment, compute budget, Token-2022 program routing). Regenerate only when you need a layer below the SDK.

Regenerating a Rust client (CPI crate)

Raydium publishes Anchor crates for the programs that have IDLs:
In code, refer to them by their lib names, raydium_cp_swap and raydium_clmm. There is no crate called raydium_amm_v3 under any spelling. Note the branches differ: raydium-cp-swap’s master still pins anchor-lang 0.32.1, so an Anchor-1.0 integration needs chore/upgrade-anchor; CLMM is on 0.32.1 either way, which is why the two cannot share a crate. The cpi feature exposes cpi::accounts::<Ix> account structs and cpi::<ix>() invokers — ready-to-use CPI wrappers. See sdk-api/rust-cpi for usage patterns. If you prefer to generate fresh bindings:

Regenerating a Python client

There is no official Raydium Python SDK. Third-party generators include:
  • anchorpy — Python port of Anchor’s TypeScript client. Generates typed method builders from IDLs.
  • solders — low-level Solana primitives (transactions, keypairs, pubkeys) in Rust bindings; used underneath anchorpy.
See sdk-api/python-integration for a fuller walk-through.

IDL change policy

Raydium follows these rules for IDL stability:
  1. Instruction discriminators never change. Adding new instructions extends the enum at the end; existing discriminators remain stable.
  2. Account sizes are stable; new fields come out of reserved padding. Every Raydium state struct carries a trailing padding region sized at creation, and a new field is carved from that padding rather than appended — so the account’s byte length and the offsets of all pre-existing fields stay fixed. The corollary is that bytes you previously read as padding can become meaningful, and a field can be retired back into padding (as PlatformConfig.curve_params was in the 2026-08-31 release). Re-read the struct definition after an upgrade; do not assume padding stays zero.
  3. Error enum codes are append-only. An existing error code always means the same thing.
  4. Breaking changes ship in new programs. When a redesign is needed, the team deploys a new program ID (e.g. CPMM as a fresh program rather than upgrading AMM v4). Old pools continue to run on the old program; new pools go to the new one.
This policy keeps regenerated clients mostly backward-compatible: a client generated against an older IDL keeps decoding the fields it knows, at the offsets it knows. What it will not see is a field carved out of what it still treats as padding — and, in the rare retirement case, a field it decodes may no longer be written. It does not see “extra trailing bytes”: the account length does not change.

What to do when the IDL changes

  1. Update the SDK. npm update @raydium-io/raydium-sdk-v2.
  2. Regenerate your client code if you use Anchor codegen directly.
  3. Diff the account layout. The new layout’s trailing fields are the only thing your code hasn’t seen; confirm whether you need them.
  4. Don’t assume old instruction discriminators are invalid. Per rule 1, they still work.
  5. Re-run integration tests against devnet before rolling to mainnet.

IDL troubleshooting

”Invalid discriminator” errors

Usually means a client built against version N of the IDL is trying to invoke an instruction that existed only in a pre-deploy version of the program. Re-pull the IDL from the live program:
For CPMM this will not work — see the IDL-location table above; pull the SDK’s bundled IDL instead.

Account decode failures

If program.account.<Name>.fetch(pubkey) throws with “Invalid account discriminator”, the account was created by a previous program version and Anchor is rejecting its 8-byte discriminator. The fix is to use the raw layout parser from the SDK (PoolInfoLayout.decode(accountData)) which does not enforce Anchor discriminators.

Missing instructions in the generated client

Anchor’s TS codegen only generates methods for instructions whose IDL entry has a name that parses as a valid identifier. Raydium’s instructions all satisfy this, but if you see a mismatch, check whether the IDL file is from the current SDK release.

Pointers

Sources: