LaunchLab exposes a tight instruction set: six user-facing calls plus a handful of admin primitives. The SDK wraps all of them; this page documents the raw surface for aggregators, monitoring tools, and programs that need CPI.
Instruction inventory
The “ExactIn/ExactOut” split mirrors CPMM’s
SwapBaseInput / SwapBaseOutput — on-chain they are separate instruction discriminators with slightly different rounding.
Graduation path selection. Every new Initialize, InitializeV2, and InitializeWithToken2022 call must set migrate_type = 1 (CPSWAP). Any attempt to initialize a new AMM v4-bound pool returns MigrateTypeNotMatch. amm_creator_fee_on only selects whether the resulting CPMM creator fee applies to the quote token or both tokens; it does not select the target program.
MigrateToAmm remains callable for an existing PoolState that was initialized with migrate_type = 0 before this restriction. The release does not rewrite existing pool state or remove the legacy instruction.
Quote-side token program. The quote mint may be owned by either the SPL Token program or Token-2022. Every instruction that touches it — CreateConfig, InitializeV2, InitializeWithToken2022, all four trade instructions, CollectFee, CollectMigrateFee, ClaimCreatorFee, ClaimPlatformFee, and ClaimPlatformFeeFromVault — takes the owning program in its quote-program account slot. Account positions did not change; only the accepted value did. Pass the program that actually owns GlobalConfig.quote_mint, which you can read from PoolState.token_program_flag bit1 for an existing launch (see accounts) or from the mint account’s owner otherwise.
The deprecated Initialize is the exception: its quote-program account is still typed to SPL Token, so a config whose quote mint is Token-2022 must be launched through InitializeV2 or InitializeWithToken2022.
MigrateToCpswap is the other exception, in the opposite direction — it takes both programs unconditionally rather than one per mint. See the migration accounts below.
Initialize
Create a new launch.
Arguments
Preconditions
quote_mint ∈ launch_config.allowed_quote_mints.base_supply_graduation ≤ base_supply_max.- Fee parameters pass
launch_config.max_*_fee_ratechecks. open_time ≥ now − slop(SDK enforces≥ now; program tolerates slight backdating).curve_typeis recognized.
base_minthassupply = base_supply_max, all inbase_vault.base_mint.mint_authority = launch_authority,freeze_authority = None.LaunchStateinitialized withstatus = Active,base_sold = 0,quote_reserve_real = 0.quote_reserve_targetcomputed from curve params +base_supply_graduation+buy_numerator(approximately).- For
InitializeWithToken2022with aTransferFeeConfigattached:transfer_fee_config_authority = launch_authority, andwithdraw_withheld_authority = PlatformConfig.transfer_fee_extension_authwhen that field is set, otherwiselaunch_authority. The withdraw side is written at mint creation precisely so the platform can sweep withheld fees before graduation. Seeplatform-config.
InvalidQuoteMint, FeeRateTooHigh, InvalidCurveParams, MathOverflow.
Buy (canonical variant: BuyExactIn)
User provides a fixed quote_in; the curve computes base_out.
Arguments
Preconditions
launch_state.status == Active.now ≥ open_time.user_quote_ata.balance ≥ quote_in.quote_in > 0.
- Split
quote_inintoquote_in_after_feeand the fee parts. - Newton-solve the curve for
base_outgiven the post-fee quote. require(base_out ≥ minimum_base_out)else revertExceededSlippage.- Move
quote_inuser → vault. Movebase_outvault → user. - Update
base_sold += base_out,quote_reserve_real += quote_in_after_fee × (lp_share / total_share). - Update fee counters (
protocol_fees_quote,creator_fees_quote). state_data.num_buys += 1.- If
quote_reserve_real ≥ quote_reserve_targetafter the update, the SDK typically chains aGraduateix in the same transaction. The program does not auto-graduate insideBuy— a subsequentGraduateis required.
BuyExactOut
User specifies the exact base_out; program computes quote_in.
Arguments
BuyExactIn. Uses the closed-form quadratic integral (or CPMM inverse, for curve_type 1) rather than Newton iteration.
Sell / SellExactIn / SellExactOut
Mirror of Buy. User returns base_in to the curve and receives quote_out. The fee is deducted from quote_out, so the user receives less than the raw integrated proceeds.
Preconditions —
user_base_ata.balance ≥ base_in.- Selling cannot push
base_soldbelow 0 (redundant with the above given accounting is consistent). - Launch is
Active.
Buy. base_sold decreases, quote_reserve_real decreases. Fees still accrue.
Quote-side transfer fees
When the quote mint carries aTransferFeeConfig, the amount the vault moves and the amount the payer is debited or credited differ, and the slippage bound is checked against the payer’s side. On a quote mint without the extension every case below is identical to a plain legacy mint.
Two consequences for quoting:
- A bound computed as if the mint were fee-free is rejected. Passing the fee-free cost as
maximum_amount_in, or the fee-free proceeds asminimum_amount_out, reverts withExceededSlippage. real_quoteadvances only by what reached the vault. ABuyExactInofamount_inon a 5% quote mint movesreal_quotebyamount_in × 0.95.
10000 basis points) cannot be inverted and reverts with CalculateOverflow on the exact-out paths.
Both trade-side mints are also constrained to the program passed in their matching slot, so a mismatched base_token_program now fails rather than being ignored. See algorithms/token-2022-transfer-fees for the underlying fee math.
MigrateToAmm / MigrateToCpswap
Graduate a launch into a tradeable pool once the curve has hit total_quote_fund_raising. New launches are CPMM-only. MigrateToAmm is retained for existing pools whose stored migrate_type is 0.
Who signs
MigrateToAmm— themigrate_to_amm_walletrecorded on the bindingGlobalConfig.MigrateToCpswap— themigrate_to_cpswap_walletrecorded on the bindingGlobalConfig.
MigrateToAmm takes three (mainly OpenBook market parameters that the program forwards to AMM v4):
MigrateToCpswap takes none.
Effect (common to both)
- Verify
pool_state.status == Migrate(i.e.,quote_reserve_targethas been reached). Otherwise revert withPoolMigrated(status was alreadyMigrated) orPoolFunding(still in funding). - Verify
pool_state.migrate_typematches the instruction (0for AMM,1for CPMM). Otherwise revert withMigrateTypeNotMatch. - Compute the post-graduation reserves:
base_amount_out = base_vault.amount − vesting_schedule.total_locked_amountquote_amount_out = quote_vault.amount − quote_protocol_fee − migrate_fee − platform_fee
- CPI into the target program (
AMM v4 Initialize2orCPMM InitializeWithPermission) with those reserves to create the post-graduation pool. - For CPMM migrations executed after the 2026-08-17 upgrade, combine
platform_scale + creator_scaleinto one platform-owned locked-LP share and mint at most one Fee Key NFT toplatform_nft_wallet. Burn theburn_scaleremainder. Before the upgrade,creator_scalewas locked separately and its Fee Key went to the token creator. Completed historical migrations are not modified. For legacy AMM v4 graduation, the LP disposition follows that instruction’s existing flow. - Revoke
base_mint.mint_authority(set toNone). - Flip
pool_state.status = Migrated, setvesting_schedule.start_time = block_time + cliff_period.
TransferFeeConfig and PlatformConfig.transfer_fee_extension_auth is non-default, migration also reassigns that extension’s authorities to the platform key:
transfer_fee_config_authorityis always reassigned. The launchauthorityPDA holds it for the whole pre-graduation phase, so there is always something to move.WithheldWithdrawis reassigned only when theauthorityPDA still holds it. Launches created from 2026-08-27 onward already carrytransfer_fee_extension_authon that authority from mint creation, so the step is skipped. The guard is what keeps migration from reverting on those mints — the PDA cannot sign away an authority it no longer holds.
transfer_fee_extension_auth is Pubkey::default() at migration time, neither authority moves and both stay with the authority PDA permanently. See platform-config.
Postconditions — BuyExactIn, BuyExactOut, SellExactIn, SellExactOut will reject from this point on with PoolMigrated. The resulting AMM pool is canonical and trades like any other AMM v4 / CPMM pool.
Common errors — PoolFunding, PoolMigrated, MigrateTypeNotMatch, InvalidCpSwapConfig, MathOverflow.
CPMM migration remaining accounts
Clients buildingMigrateToCpswap must use these fixed remaining_accounts indices:
The instruction requires at least ten remaining accounts on the upgraded path. The support-mint accounts are read-only CPI inputs. Derive both addresses even when the mint has no initialized support record. Older builders that still append creator-lock accounts or omit indices 8–9 must be updated.
CPMM migration token programs
MigrateToCpswap takes both token programs unconditionally and works out which one owns each mint itself. Its two token-program accounts were renamed accordingly:
They replace the former
base_token_program (whichever program owned the base mint) and quote_token_program (always legacy). Positions are unchanged, so this is a value change rather than a layout change — but the two values are close to inverted, and a builder that keeps passing its old pair will supply Token-2022 where the legacy program is required as soon as either mint is a Token-2022 mint.
The legacy program is required even when neither mint uses it, because the CPMM LP mint and the locked-liquidity Fee Key NFT always live on it.
Platform GlobalConfig allowlist
PlatformConfig.restrict_global_config controls the check:
0: the platform accepts any otherwise-validGlobalConfig; no allow account is required.1:Initialize,InitializeV2, andInitializeWithToken2022must include the matchingPlatformAllowConfiganywhere inremaining_accounts.
CreatePlatformAllowConfig and ClosePlatformAllowConfig. Its seeds are [b"platform_allow_config", platform_config, global_config]. The former admin-managed PlatformGlobalAccess instructions and PDA are retired.
Platform launch-parameter rules
Four instructions manage onePlatformCurveRule account. All four are signed by PlatformConfig.curve_rule_manager or by the platform admin — the program accepts the admin by re-deriving the PlatformConfig PDA from the signer, so no separate account proves it. A signer that is neither returns InvalidCurveRuleAuthority.
platform_curve_rule is the PDA at [b"platform_curve_rule", platform_config, global_config].
Createallocates the account holding no group. That state does not restrict anything.Updateupserts the group with thatgroup_id, replacing it wholesale if it exists. It resizes the account to fit, so the signer tops up the rent it grows by and receives back the rent it shrinks by. A new group beyond the tenth returnsCurveRuleGroupsExceeded; more than 25 constraints, an unknown field or operator, or the same(field, op)pair twice in one group returnsInvalidCurveRuleConstraint; the fourTotalSellA-derived fields on a non-constant-product config returnCurveRuleFieldNotSupportedByCurve.Removedrops one group by id, shrinking the account and refunding the difference. An unknown id returnsCurveRuleGroupNotExist.Closereturns the whole rent to the signer. The config is then unrestricted again even whilerestrict_curve_paramstays1.
UpdatePlatformConfig::RestrictCurveParam(0 | 1), which only the platform admin can call.
On the launch path. While restrict_curve_param is 1, InitializeV2 and InitializeWithToken2022 require the rule PDA in remaining_accounts — including when it does not exist, so that omitting it cannot skip the check. A missing account is NotEnoughRemainingAccounts; a launch that satisfies no group is CurveParamNotMatchPlatformRule. The check runs before GlobalConfig’s own limits and can only narrow them. Model and playbooks: products/launchlab/curve-rules. Both errors are avoidable client-side — the SDK mirrors this check as a pure function, see Check before you send.
CollectFee
Admin sweep of the protocol’s accrued trade fees on a single launch.
Arguments — none.
Accounts
Effect — transfer
pool_state.quote_protocol_fee from quote_vault to recipient_token_account, then zero the counter. Callable any time after the first buy.
CollectMigrateFee
Admin sweep of the migration fee accumulated at graduation. Same account shape as CollectFee with migrate_fee_owner as the signer (instead of protocol_fee_owner) and pool_state.migrate_fee as the drained counter.
ClaimCreatorFee
Per-creator sweep of accrued creator fees across every launch the creator owns that uses the same quote mint. Drains the per-creator fee vault, not the per-pool one.
Arguments — none.
Accounts
Effect — transfer the entire balance of
creator_fee_vault to recipient_token_account. Reverts with a require-greater-than-zero check if the vault is empty.
ClaimPlatformFee
Per-platform sweep that drains a launch’s quote vault directly. Use this when a platform wants to claim its slice for one specific launch without going through the aggregated platform vault.
Arguments — none.
Accounts
Effect — transfer
pool_state.platform_fee from quote_vault to recipient_token_account, zero the counter.
ClaimPlatformFeeFromVault
Per-platform aggregated sweep. Drains the platform’s per-quote-mint fee vault that accumulates fees from every launch routed through the platform.
Arguments — none.
Accounts
Effect — transfer the full balance of
platform_fee_vault to recipient_token_account. Reverts if the vault is empty.
Vesting and platform-config instructions
These are documented on dedicated pages because each has its own state model:CreateVestingAccount,CreatePlatformVestingAccount,ClaimVestedTokenCreatePlatformConfig,UpdatePlatformConfig,CreatePlatformAllowConfig,ClosePlatformAllowConfigCreatePlatformCurveRule,UpdatePlatformCurveRule,RemovePlatformCurveRule,ClosePlatformCurveRuleCreateConfig,UpdateConfig
State-change matrix
Where to go next
products/launchlab/code-demos— TypeScript examples for each instruction.products/launchlab/accounts— full state shape.reference/error-codes— LaunchLab error enum.
- Raydium SDK v2
LaunchLabmodule - Raydium LaunchLab program source

