Skip to main content
A cheat sheet: where the IDLs live, how to derive each PDA, and how to build the mint and redeem account lists.

IDL files

The program source is private. The IDLs, generated from the source of the deployed programs, are published in the docs repository (browse).
Each IDL’s address field holds the program ID, and Anchor 0.32 reads it from there. Three details trip people up:
  • Pass the type explicitly, as in new Program<MintRedeem>(idl as MintRedeem, provider). Without it TypeScript falls back to the generic Idl type and program.account.market doesn’t type-check.
  • Anchor TS decodes base_price_1e6, gamma_day_decay_1e9 and short_payoff_cap_c_1e9 as basePrice1E6, gammaDayDecay1E9 and shortPayoffCapC1E9, but anchor idl type names them with a lowercase e. Read those three fields by their runtime names.
  • The registry IDL has no PDA seeds, so Anchor can’t fill in registry or marketEntry for you. Pass them explicitly, using the seeds below.

PDA derivation cheatsheet

Every PDA is PublicKey.findProgramAddressSync(seeds, programId). This script derives them all for one market and one wallet, then checks them with a single getMultipleAccountsInfo call. It needs only @solana/web3.js. Save it as pdas.ts, set your wallet, and run npx tsx pdas.ts.
Output for QQQ on devnet (11 Oct 2026); the wallet-specific rows depend on the wallet you pass:
Some rows can show “no account”, and that is expected:
  • order and escrow exist only while that order is open. settle_swap and cancel_swap close both, except for a held order, which stays open until claim. A claim account, PDA [b"claim", order], exists only while a settle holds a payout.
  • dripRecord exists after the wallet’s first faucet drip.
  • faucetMintAuthority is a signing PDA that holds no data. It is the cUSDC mint’s mint authority.
  • registryEntry is empty because the Registry holds no markets yet. Get market addresses from Addresses.
The Market account is allocated 891 bytes on devnet, and the struct can need up to 899. Its collateral_vaults list is variable-length, so read Market fields through the IDL, never at fixed offsets (see Market account). The two market seeds differ. mint-redeem uses the raw symbol bytes (QQQ), while the Registry uses the symbol uppercased and zero-padded to 16 bytes.

Token accounts (ATAs)

Associated token accounts aren’t PDAs of Continuum’s programs, but you derive them constantly:
Pass true as the third argument when the owner can be a PDA, as market.feeRecipient can. As of 10 Oct 2026 QQQ’s fee recipient is the GlobalClp PDA, and without the flag getAssociatedTokenAddressSync throws TokenOwnerOffCurveError.

Composing a mint call

mint_paired takes 11 accounts. You derive the Market PDA from the symbol, fetch the market once, and derive the rest from its fields:
The user’s cUSDC, L and S token accounts must exist before the call; otherwise Anchor fails with AccountNotInitialized (3012). Add createAssociatedTokenAccountIdempotentInstruction for each one to the same transaction. In production, batch the market fetch with the user’s token-account reads through getMultipleAccountsInfo.

Account-fetch helpers

With mintRedeem and clp as typed Program instances and the PDAs from the script above:
For several markets at once:
Don’t fetch OracleConfig for prices: the oracle program isn’t updated on devnet. The live price is market.userTwapPrice.

Discriminators

Every Anchor account and instruction starts with an 8-byte discriminator: the first 8 bytes of sha256("account:<AccountName>") for accounts and sha256("global:<instruction_name>") for instructions. The IDLs list them, and Anchor checks them for you. Market’s discriminator is [219, 190, 213, 55, 0, 227, 198, 154]. To decode raw account data without fetch, use the program’s coder with the camelCase account name:

See also

SDK setup

Project bootstrap and a first read.

End-to-end example

Mint and redeem in one script.