Skip to main content
CPMM pools hold two tokens and price them by the constant-product invariant reserve0 × reserve1 = k. Each swap pays a 0.3% fee to liquidity providers. Liquidity is represented by a fungible LP token whose token ID equals the pool ID.

Guide: swap on CPMM

Guide: provide CPMM liquidity

Pool lookups

getPoolId(tokenA, tokenB)

Derives the pair’s contract ID offline (tokens are sorted first, so the order doesn’t matter). This is also the LP token ID.

getPoolAddress(tokenA, tokenB)

Returns the pair’s contract address (addressFromContractId(getPoolId(...))).

poolExists(tokenA, tokenB)

getPoolState(tokenA, tokenB)

Fetches reserves and LP supply, and resolves both tokens through the token list. Throws PoolNotFoundError if the pair doesn’t exist. Both tokens must be in the token list.
object

getPoolProtocolFees(poolAddress)

Protocol fees accrued in the pair and not yet collected. Takes the pool address, not token IDs.

Quotes (static, offline)

All quote helpers are static and pure. Pass a CpmmPoolContractState you already fetched.

CpmmModule.computeSwapAmount(params)

CpmmPoolContractState
required
string
required
string
required
bigint
Set for an exact-in quote.
bigint
Set for an exact-out quote (used only when amountIn is undefined).
bigint
required
Slippage tolerance in basis points.
object
Throws InsufficientLiquidityError for exact-out when amountOut >= reserveOut.

CpmmModule.getAmountOut(state, tokenInId, amountIn) / getAmountIn(state, tokenOutId, amountOut)

The raw x·y=k formulas with the 0.3% fee:

CpmmModule.calcPriceImpact(reserve0, reserve1, tokenInId, token0Id, amountIn, amountOut)

Returns the price impact in percent.

CpmmModule.computeLiquidityAmounts(params)

  • Existing pool (poolState set): give the amount of one side (inputType: 'TokenA' uses amountA, 'TokenB' uses amountB) and it derives the other side from the reserves, plus the LP tokens you’d mint.
  • New pool (poolState undefined): both amountA and amountB are required. LP minted = sqrt(amountA × amountB) − MINIMUM_LIQUIDITY (1000 units are locked forever). Throws InsufficientLiquidityError if sqrt(amountA × amountB) <= 1000.
Returns { tokenAId, tokenBId, amountA, amountB, shareAmount, sharePercentage, state? }, where sharePercentage is your share of the pool after the deposit, in percent.

CpmmModule.computeRemoveLiquidityAmounts(state, totalLiquidity, liquidityToRemove)

Token amounts returned for burning liquidityToRemove LP tokens, plus your remaining share. totalLiquidity is your LP balance. Throws if liquidityToRemove > totalLiquidity.

CpmmModule.computeClaimableAmounts(state, liquidityBalance)

The full underlying value of an LP balance: { token0, amount0, token1, amount1, ... }.

CpmmModule.minimalAmount(amount, slippage) / maximalAmount(amount, slippage)

Slippage helpers. See Amounts & slippage.

Swaps

swap(params, balances?)

Fetches fresh pool state, quotes, checks price impact, and executes SwapMinOut (exact-in) or SwapMaxIn (exact-out) through the router. Requires a signer.
string
required
string
required
bigint
Exact-in amount.
bigint
Exact-out amount (used when amountIn is undefined).
bigint
required
Basis points.
string
required
Address that pays and receives. Usually the signer’s address.
number
default:"60"
Deadline.
bigint
Optional integrator fee, in the input token.
string
Required together with fee.
Map<tokenId, bigint>
Optional pre-flight check: if provided and balances.get(tokenIn) < input + fee, throws InsufficientBalanceError before signing. For ALPH, key the map by ALPH_TOKEN_ID.
Throws PriceImpactTooHighError if priceImpact >= 5.

simSwap(params)

Fetches pool state and returns the quote swap would use, without sending anything. slippageBps defaults to 100n if nullish.

swapTo(params)

Computes the exact-in trade that moves the pool price to targetPrice and executes it. Direction is inferred automatically. Skips the price-impact check. Throws if the target equals the current price. Useful for arbitrage and for re-pegging test pools.

Liquidity

addLiquidity(params, balances?)

CpmmPoolContractState
required
Fresh state from getPoolState.
string
required
Must both be pool tokens (any order).
bigint
required
Desired amounts. Both must be greater than 0. Use computeLiquidityAmounts to get a balanced pair.
bigint
required
Applied to both amounts as minimums. Ignored when the pool is empty.
string
required
number
default:"60"
The router deposits the optimal ratio and mints LP tokens to sender.

removeLiquidity(params)

CpmmPoolContractState
required
bigint
required
LP tokens to burn.
bigint
Your LP balance (used for share math). Defaults to poolState.totalSupply.
bigint
required
Applied to both output amounts as minimums.
string
required
number
default:"60"

computeClaimableAmounts(tokenAId, tokenBId, liquidityBalance)

Instance version: fetches pool state, then returns { token0, amount0, token1, amount1 } for an LP balance.

Pool creation

createPool(params)

string
required
string
required
Pays the 1 ALPH contract deposit.
{ tokenAAmount: bigint; tokenBAmount: bigint }
If set, creates the pair and deposits initial liquidity in one transaction (CreatePairAndAddLiquidity). The ratio sets the starting price. If omitted, only the pair is created (CreatePair, which attaches 1 base unit of each token).

Configuration

getConfig() returns the active CpmmConfig (groupIndex, factoryId, routerId). setConfig(config) overrides it. getCpmmConfig() re-reads the bundled deployment.

Constants