- A vault program that mints Continuum positions on its users’ behalf.
- A structured product that bundles long/short tokens across multiple markets.
- An automated portfolio rebalancer that reads NAV and acts.
mint-redeem, clp, etc.) are normal Anchor programs, so any caller that satisfies the account list can invoke them.
Important caveats first
Most users don’t need CPI. If your integration is off-chain (a bot, a frontend), you don’t need CPI - you sign transactions directly. CPI is for cases where the protocol you’re building is itself on-chain. Privileged ixns can’t be CPI’d by random callers.keeper_mint_single requires signer == market.keeper_authority. CPI doesn’t change this - your program would need to be the keeper authority to call it. Privileged paths are not designed for general CPI integration.
The mint_paired and redeem_paired paths can be CPI’d freely because they have no signer privilege beyond the user’s own signature.
Calling mint_paired via CPI
The receiving program treats whoever signed the outer instruction as user. So if your program builds the inner ix correctly, your user’s signature carries through as long as your program passes the user as a signer.
Sketch (Rust / Anchor in your own program):
mint_redeem::cpi types come from declaring the program as a dependency in your Cargo.toml; see Anchor’s CPI docs.)
The user signs the outer instruction; the inner CPI inherits that signature. mint_redeem debits user_collateral, mints to user_long and user_short. There’s no PDA-signed CPI required.
Calling on behalf of a PDA
If your program holds the collateral (e.g., a vault), then your PDA needs to sign. You’ll need to allocate a PDA whose ATAs hold the collateral and the resulting L+S tokens, and useCpiContext::new_with_signer:
mint_paired with the CLP PDA as signer.
Reading state via CPI
If your program needs deterministic read of NAV from the same instruction (not just a recent fetch), call the oracle’s read-only helpers:programs/oracle/src/state.rs.)
Calling redeem_paired
Symmetric to mint. Your program calls mint_redeem::cpi::redeem_paired(cpi_ctx, l_amount, s_amount). Whoever holds the L+S tokens (user or PDA) needs to sign.
When you cannot CPI
Some flows are not CPI-friendly:keeper_mint_single/keeper_redeem_single- requiresigner == market.keeper_authority. You’d need to be the keeper authority. Generally, only the canonical keeper has this, and on mainnet it’ll be a multisig.- CLP book and inventory ixns (
set_pool_shape,pool_sweep_*,vault_mint_pairs, …) - CLP authority requirement. Notepool_swap,commit_swap, andsettle_swapare public and CPI-friendly. - Admin ixns (
update_market,admin_fund, etc.) - admin authority required.
Gotchas
Account list ordering. Anchor’s CPI account context expects a specific order. If you build the account list manually (e.g., from a TypeScript instruction), order must match the IDL’saccounts array exactly.
#[account(mut)] correctness. Forgetting to mark accounts mutable in your wrapping context - when they need to be mutated by the inner CPI - produces AccountNotMutable errors. Match the inner program’s account constraints.
Compute budget. mint_paired is moderate-CU. Wrapping it adds your program’s overhead. If you bundle multiple Continuum CPIs in one outer ix, you may need to set a compute budget instruction:
Worked example: Auto-redeem on close
A program that holds user positions and auto-redeems them at a target price:See also
Composability
Off-chain integration patterns: arb bots, structured products.
Programs overview
Authority model - who can call what.

