Documentation Index Fetch the complete documentation index at: https://continuum-ec12e897.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
This page is a cheat-sheet. Bookmark it.
IDL sources
Program Path in protocol repo Embedded program ID (devnet) mint-redeemtarget/idl/mint_redeem.json5MBjhNUUguLTPNR5WG6YBUUw7vUcxQ14ARw3NsS3rKu4oracletarget/idl/oracle.json5vxiCrDpFnQ2W5QtgZBC66K2XTC19bjVBjinGYYBsadCclptarget/idl/clp.json8xauDRjw9XRyk4FE3hW1JKjD8nC87gfr59Xig1dJqLESfaucettarget/idl/faucet.json9tUeQAPEtVSB68NSfvFAqfwaB74GuVxm6Zbp1hrMiNKYregistrytarget/idl/registry.json (regenerate via anchor build)REGnHqnJMxLoRAKX5RqPd9VJGcZBNgmg4xs5bVGGTap
Get them via:
git clone https://github.com/continuum-markets/continuum.git
cd continuum
anchor build # regenerates target/idl/*
ls target/idl/
The frontend/lib/idl/ directory packages the same IDLs for the official frontend - copy from there if you don’t want to clone the full protocol repo.
PDA derivation cheatsheet
All PDAs use findProgramAddressSync(seeds, programId). In @solana/web3.js:
import { PublicKey } from "@solana/web3.js" ;
const [ pda , bump ] = PublicKey . findProgramAddressSync ( seeds , programId );
mint-redeem PDAs
// Market
const [ marketPDA ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "market" ), Buffer . from ( symbol )], // symbol as ASCII bytes
mintRedeem . programId ,
);
// User multi-collateral position (rare)
const [ userPos ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "user_collateral" ), owner . toBuffer (), marketPDA . toBuffer ()],
mintRedeem . programId ,
);
// Fee waiver
const [ feeWaiver ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "fee_waiver" ), donor . toBuffer (), marketPDA . toBuffer ()],
mintRedeem . programId ,
);
oracle PDAs
// OracleConfig (per market)
const [ oracleConfig ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "oracle_config" ), marketPDA . toBuffer ()],
oracle . programId ,
);
// OracleFeed (per (config, pyth feed))
const [ oracleFeed ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "oracle_feed" ), oracleConfig . toBuffer (), pythFeed . toBuffer ()],
oracle . programId ,
);
In practice you don’t derive oracle_config - you read market.oracle_address directly from the Market account. The derivation is here for completeness.
clp PDAs
// GlobalClp (singleton)
const [ globalClp ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "global_clp" )],
clp . programId ,
);
// Per-market Clp
const [ clpPDA ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "clp" ), marketPDA . toBuffer ()],
clp . programId ,
);
// Admin withdraw rate-limit window
const [ withdrawWindow ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "admin_withdraw_window" )],
clp . programId ,
);
registry PDAs
// RegistryState (singleton)
const [ registryState ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "registry" )],
registry . programId ,
);
// MarketEntry - symbol padded to 16 bytes
const symbol = "QQQ" ;
const padded = Buffer . alloc ( 16 );
padded . write ( symbol );
const [ marketEntry ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "market" ), padded ],
registry . programId ,
);
Note the registry uses a 16-byte zero-padded symbol , while mint-redeem uses the raw symbol bytes. They are different PDA seeds - don’t confuse them.
faucet PDAs
// FaucetState (per mint)
const [ faucetState ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "faucet" ), cusdcMint . toBuffer ()],
faucet . programId ,
);
// DripRecord (per (mint, recipient))
const [ dripRecord ] = PublicKey . findProgramAddressSync (
[ Buffer . from ( "drip" ), cusdcMint . toBuffer (), recipient . toBuffer ()],
faucet . programId ,
);
Token accounts (ATAs)
ATAs are not PDAs of Continuum’s programs but you’ll derive them constantly:
import { getAssociatedTokenAddressSync } from "@solana/spl-token" ;
const userCusdc = getAssociatedTokenAddressSync ( cusdcMint , owner );
const userLong = getAssociatedTokenAddressSync ( longMint , owner );
const userShort = getAssociatedTokenAddressSync ( shortMint , owner );
Composing a mint call
For mint_paired, you need:
{
market : marketPDA , // PDA derived from symbol
user : owner , // signer
userCollateral : getAssociatedTokenAddressSync ( cusdcMint , owner ),
userLong : getAssociatedTokenAddressSync ( market . longMint , owner ),
userShort : getAssociatedTokenAddressSync ( market . shortMint , owner ),
longMint : market . longMint , // from Market account
shortMint : market . shortMint ,
collateralVault : market . collateralVault ,
devTokenAccount : getAssociatedTokenAddressSync ( cusdcMint , market . feeRecipient ),
oracleAddress : market . oracleAddress ,
tokenProgram : TOKEN_PROGRAM_ID ,
}
Note the dependency chain:
Derive marketPDA from symbol.
Fetch market (one RPC call).
From the fetched market, derive all child accounts.
In production, batch the market fetch with the user’s ATA balance fetch via getMultipleAccountsInfo.
Account-fetch helpers
const market = await mintRedeem . account . market . fetch ( marketPDA );
const oracle = await oracleProgram . account . oracleConfig . fetch ( market . oracleAddress );
const clpAcc = await clp . account . clp . fetch ( clpPDA );
const global = await clp . account . globalClp . fetch ( globalClpPDA );
For multi-market batched reads:
const accounts = await mintRedeem . account . market . fetchMultiple ( marketPDAs );
// returns (Market | null)[]
Discriminators
Each Anchor account / instruction has an 8-byte discriminator. You don’t compute these by hand - Anchor handles it. But if you need to manually decode account data without an IDL:
const buf = ( await connection . getAccountInfo ( marketPDA )) ! . data ;
const discriminator = buf . slice ( 0 , 8 ); // 8 bytes
const accountData = buf . slice ( 8 ); // the actual fields, Borsh-encoded
The discriminator is sha256("account:Market").slice(0, 8). The keeper uses these manually for performance reasons; clients should rely on Anchor’s coder.accounts.decode.
See also
SDK setup Project bootstrap + first read.
End-to-end example Mint and redeem in one script.