Core Functions
createPool
Creates a new standard pool according to a predefined configuration.
Function
async createPool(params: CreatePoolParams): TxBuilder
Parameters
interface CreatePoolParams {
payer: PublicKey; // The wallet paying for the transaction
creator: PublicKey; // The creator of the pool
config: PublicKey; // The configuration account for the pool
positionNft: PublicKey; // The mint for the initial position NFT
tokenAMint: PublicKey; // The mint address for token A
tokenBMint: PublicKey; // The mint address for token B
activationPoint: BN | null; // The slot or timestamp for activation
tokenAAmount: BN; // Initial amount of token A to deposit
tokenBAmount: BN; // Initial amount of token B to deposit
initSqrtPrice: BN; // Initial sqrt price in Q64 format
liquidityDelta: BN; // Initial liquidity delta in Q64 format
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
isLockLiquidity?: boolean; // true if you wanna permanent lock position after pool created.
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
// First, prepare the pool creation parameters
const configState = await cpAmm.getConfigState(configAccount);
const initPrice = 10; // 1 base token = 10 quote token
const {actualInputAmount, consumedInputAmount, outputAmount, liquidityDelta} = cpAmm.getDepositQuote({
inAmount: new BN(5_000_000_000), // 5 tokenA (base token) with 9 decimals
isTokenA: true;
minSqrtPrice: configState.sqrtMinPrice,
maxSqrtPrice: configState.sqrtMinPrice,
sqrtPrice: getSqrtPriceFromPrice(initPrice, tokenADecimal, tokenBDecimal),
inputTokenInfo, // provide if input token is token2022
outputTokenInfo // provide if output token is token2022
})
const createPoolTx = await cpAmm.createPool({
payer: wallet.publicKey,
creator: wallet.publicKey,
config: configAddress,
positionNft: positionNftMint,
tokenAMint,
tokenBMint,
activationPoint: null,
tokenAAmount: consumedInputAmount,
tokenBAmount: outputAmount,
initSqrtPrice: getSqrtPriceFromPrice(initPrice, tokenADecimal, tokenBDecimal);,
liquidityDelta: liquidityDelta,
tokenAProgram,
tokenBProgram
});
Notes
- Both token amounts must be greater than zero
- If using native SOL, it will be automatically wrapped to wSOL
- The
config
parameter should be a valid configuration account
- Pool creation automatically creates an initial position
- Use
preparePoolCreationParams
to calculate proper initSqrtPrice
and liquidityDelta
createCustomPool
Creates a customizable pool with specific fee parameters, reward settings, and activation conditions.
Function
async createCustomPool(params: InitializeCustomizeablePoolParams): Promise<{
tx: Transaction;
pool: PublicKey;
position: PublicKey;
}>
Parameters
interface InitializeCustomizeablePoolParams {
payer: PublicKey; // The wallet paying for the transaction
creator: PublicKey; // The creator of the pool
positionNft: PublicKey; // The mint for the initial position NFT
tokenAMint: PublicKey; // The mint address for token A
tokenBMint: PublicKey; // The mint address for token B
tokenAAmount: BN; // Initial amount of token A to deposit
tokenBAmount: BN; // Initial amount of token B to deposit
sqrtMinPrice: BN; // Minimum sqrt price
sqrtMaxPrice: BN; // Maximum sqrt price
initSqrtPrice: BN; // Initial sqrt price in Q64 format
liquidityDelta: BN; // Initial liquidity in Q64 format
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
poolFees: PoolFees; // Fee configuration
hasAlphaVault: boolean; // Whether the pool has an alpha vault
collectFeeMode: number; // How fees are collected (0: normal, 1: alpha)
activationPoint: BN; // The slot or timestamp for activation
activationType: number; // 0: slot, 1: timestamp
isLockLiquidity?: boolean; // true if you wanna permanent lock position after pool created.
}
interface PoolFees {
baseFee: {
cliffFeeNumerator: BN; // Initial fee numerator
numberOfPeriod: number; // Number of fee reduction periods
reductionFactor: BN; // How much fee reduces each period
periodFrequency: number; // How often fees change
feeSchedulerMode: number; // 0: Linear, 1: Exponential
};
dynamicFee?: { // Optional dynamic fee configuration
binStep: number;
binStepU128: BN;
filterPeriod: number;
decayPeriod: number;
reductionFactor: number;
variableFeeControl: number;
maxVolatilityAccumulator: number;
};
}
Returns
An object containing:
tx
: The transaction to sign and send
pool
: The public key of the created pool
position
: The public key of the initial position
Example
// First, prepare the pool creation parameters
const { initSqrtPrice, liquidityDelta } = cpAmm.preparePoolCreationParams({
tokenAAmount: new BN(5_000_000_000),
tokenBAmount: new BN(20_000_000),
minSqrtPrice: MIN_SQRT_PRICE,
maxSqrtPrice: MAX_SQRT_PRICE
});
const poolFees = {
baseFee: {
feeSchedulerMode: 0, // 0: Linear, 1: Exponential
cliffFeeNumerator: 1_000_000,
numberOfPeriod: 0,
reductionFactor: 0,
periodFrequency: 0
},
partnerFee: {
partnerAddress: partnerWallet.publicKey,
partnerFeeNumerator: 1000,
},
dynamicFee: {
binStep: 1,
binStepU128: new BN("1844674407370955"),
filterPeriod: 10,
decayPeriod: 120,
reductionFactor: 5000,
variableFeeControl: 2000000,
maxVolatilityAccumulator: 100000,
};
};
const { tx, pool, position } = await cpAmm.createCustomPool({
payer: wallet.publicKey,
creator: wallet.publicKey,
positionNft: positionNftMint,
tokenAMint: usdcMint,
tokenBMint: btcMint,
tokenAAmount: new BN(5_000_000_000),
tokenBAmount: new BN(20_000_000),
sqrtMinPrice: MIN_SQRT_PRICE,
sqrtMaxPrice: MAX_SQRT_PRICE,
initSqrtPrice: initSqrtPrice,
liquidityDelta: liquidityDelta,
poolFees,
hasAlphaVault: false,
collectFeeMode: 0, // 0: BothToken, 1: onlyB
activationPoint: new BN(Date.now()),
activationType: 1, // 0: slot, 1: timestamp
tokenAProgram,
tokenBProgram
});
Notes
- Use this function instead of
createPool
when you need custom fee structures
- Use
preparePoolCreationParams
to calculate proper initSqrtPrice
and liquidityDelta
createCustomPoolWithDynamicConfig
Creates a customizable pool with dynamic configuration, allowing for specific fee parameters with specified pool creator authority
Function
async createCustomPoolWithDynamicConfig(params: InitializeCustomizeablePoolWithDynamicConfigParams): Promise<{
tx: Transaction;
pool: PublicKey;
position: PublicKey;
}>
Parameters
interface InitializeCustomizeablePoolWithDynamicConfigParams {
payer: PublicKey; // The wallet paying for the transaction
creator: PublicKey; // The creator of the pool
positionNft: PublicKey; // The mint for the initial position NFT
tokenAMint: PublicKey; // The mint address for token A
tokenBMint: PublicKey; // The mint address for token B
tokenAAmount: BN; // Initial amount of token A to deposit
tokenBAmount: BN; // Initial amount of token B to deposit
sqrtMinPrice: BN; // Minimum sqrt price
sqrtMaxPrice: BN; // Maximum sqrt price
initSqrtPrice: BN; // Initial sqrt price in Q64 format
liquidityDelta: BN; // Initial liquidity in Q64 format
poolFees: PoolFeesParams; // Fee configuration
hasAlphaVault: boolean; // Whether the pool has an alpha vault
collectFeeMode: number; // How fees are collected (0: normal, 1: alpha)
activationPoint: BN | null; // The slot or timestamp for activation (null for immediate)
activationType: number; // 0: slot, 1: timestamp
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
config: PublicKey; // dynamic config account
poolCreatorAuthority: PublicKey; // Authority allowed to create pools with this config
isLockLiquidity?: boolean; // true if you wanna permanent lock position after pool created.
}
Returns
An object containing:
tx
: The transaction to sign and send
pool
: The public key of the created pool
position
: The public key of the initial position
Example
// First, prepare the pool creation parameters
const tokenAAmount = new BN(5_000_000_000);
const tokenBAmount = new BN(20_000_000);
const sqrtPrice = getSqrtPriceFromPrice("172", tokenADecimal, tokenBDecimal);
const sqrtMinPrice = getSqrtPriceFromPrice("4", tokenADecimal, tokenBDecimal);
const sqrtMaxPrice = getSqrtPriceFromPrice("400", tokenADecimal, tokenBDecimal);
const { initSqrtPrice, liquidityDelta } = cpAmm.getLiquidityDelta({
maxAmountTokenA: tokenAAmount,
maxAmountTokenB: tokenBAmount,
sqrtMaxPrice,
sqrtMinPrice,
sqrtPrice,
});
const baseFeeParams = getBaseFeeParams(25, 25, FeeSchedulerMode.Linear, 0, 0); // base fee: 0.25%
const dynamicFeeParams = getDynamicFeeParams(25); // max dynamic fee 0.25%
const poolFees: PoolFeesParams = {
baseFee: baseFeeParams,
protocolFeePercent: 20,
partnerFeePercent: 0,
referralFeePercent: 20,
dynamicFee: dynamicFeeParams,
};
const { tx, pool, position } = await cpAmm.createCustomPoolWithDynamicConfig({
payer
creator,
config: dynamicConfigAddress,
poolCreatorAuthority: poolCreatorAuth.publicKey,
positionNft: positionNftMint,
tokenAMint: usdcMint,
tokenBMint: btcMint,
tokenAAmount,
tokenBAmount,
sqrtMinPrice,
sqrtMaxPrice,
initSqrtPrice,
liquidityDelta,
poolFees,
hasAlphaVault: false,
collectFeeMode: 0, // 0: Both tokens, 1: Only token B
activationPoint: null,
activationType: 1, // 0: slot, 1: timestamp
tokenAProgram: TOKEN_PROGRAM_ID,
tokenBProgram: TOKEN_PROGRAM_ID,
});
createPosition
Creates a new position in an existing pool.
Function
async createPosition(params: CreatePositionParams): TxBuilder
Parameters
interface CreatePositionParams {
owner: PublicKey; // The owner of the position
payer: PublicKey; // The wallet paying for the transaction
pool: PublicKey; // The pool to create a position in
positionNft: PublicKey; // The mint for the position NFT
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const createPositionTx = await cpAmm.createPosition({
owner: wallet.publicKey,
payer: wallet.publicKey,
pool: poolAddress,
positionNft: positionNftMint
});
const tx = await createPositionTx.transaction();
const result = await wallet.sendTransaction(tx, connection);
Notes
- The
positionNft
should be a new mint that doesn’t already have a position
- Creating a position doesn’t automatically add liquidity
- After creating a position, use
addLiquidity
to provide tokens
getLiquidityDelta
Calculates the liquidity delta based on the provided token amounts and price ranges.
Function
async getLiquidityDelta(params: LiquidityDeltaParams): Promise<BN>
Parameters
interface LiquidityDeltaParams {
maxAmountTokenA: BN; // Maximum amount of token A to use
maxAmountTokenB: BN; // Maximum amount of token B to use
sqrtMaxPrice: BN; // Maximum sqrt price for the range
sqrtMinPrice: BN; // Minimum sqrt price for the range
sqrtPrice: BN; // Current sqrt price
}
Returns
A BN representing the liquidity delta in Q64 format.
getQuote
Calculates the expected output amount for a swap, including fees and slippage protection.
Function
async getQuote(params: GetQuoteParams): Promise<{
swapInAmount: BN;
consumedInAmount: BN;
swapOutAmount: BN;
minSwapOutAmount: BN;
totalFee: BN;
priceImpact: number;
}>
Parameters
interface GetQuoteParams {
inAmount: BN; // The amount of input token to swap
inputTokenMint: PublicKey; // The mint of the input token
slippage: number; // Slippage tolerance in percentage (e.g., 0.5 for 0.5%)
poolState: PoolState; // The state of the pool
currentTime: number; // Current timestamp (for time-based fees)
currentSlot: number; // Current slot (for slot-based fees)
inputTokenInfo?: {
mint: Mint,
currentEpoch: number
}; // Token info for Token2022 transfer fee calculations
outputTokenInfo?: {
mint: Mint,
currentEpoch: number
}; // Token info for Token2022 transfer fee calculations
}
Returns
An object containing:
swapInAmount
: The original input amount
consumedInAmount
: The actual input amount used (after transfer fees)
swapOutAmount
: The expected output amount
minSwapOutAmount
: The minimum output amount accounting for slippage
totalFee
: The total fee to be paid
priceImpact
: The price impact of the swap as a percentage
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const currentSlot = await connection.getSlot();
const blockTime = await connection.getBlockTime(currentSlot);
const quote = await cpAmm.getQuote({
inAmount: new BN(100_000_000), // 100 USDC
inputTokenMint: usdcMint,
slippage: 0.5, // 0.5% slippage
poolState,
currentTime: blockTime,
currentSlot
});
console.log(`Expected output: ${quote.swapOutAmount.toString()}`);
console.log(`Minimum output: ${quote.minSwapOutAmount.toString()}`);
console.log(`Fee: ${quote.totalFee.toString()}`);
console.log(`Price impact: ${quote.priceImpact.toFixed(2)}%`);
Notes
- Always check the price impact before executing a swap
- The
slippage
parameter protects users from price movements
- Use the
minSwapOutAmount
as the minimumAmountOut
parameter for swap
- For Token2022 tokens with transfer fees, provide the token info parameters
getDepositQuote
Calculates the deposit quote for adding liquidity to a pool based on a single token input.
Function
async getDepositQuote(params: GetDepositQuoteParams): Promise<DepositQuote>
Parameters
interface GetDepositQuoteParams {
inAmount: BN; // The amount of input token
isTokenA: boolean; // Whether the input token is token A
minSqrtPrice: BN; // Minimum sqrt price
maxSqrtPrice: BN; // Maximum sqrt price
sqrtPrice: BN; // Current sqrt price
inputTokenInfo?: {
mint: Mint,
currentEpoch: number
}; // Token info for Token2022 transfer fee calculations
outputTokenInfo?: {
mint: Mint,
currentEpoch: number
}; // Token info for Token2022 transfer fee calculations
}
Returns
An object containing:
actualInputAmount
: The actual input amount (after transfer fees)
consumedInputAmount
: The full input amount including transfer fees
liquidityDelta
: The amount of liquidity that will be added
outputAmount
: The calculated amount of the other token to be paired
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const depositQuote = await cpAmm.getDepositQuote({
inAmount: new BN(1_000_000_000), // 1,000 USDC
isTokenA: true, // USDC is token A
minSqrtPrice: poolState.sqrtMinPrice,
maxSqrtPrice: poolState.sqrtMaxPrice,
sqrtPrice: poolState.sqrtPrice
});
console.log(`Liquidity delta: ${depositQuote.liquidityDelta.toString()}`);
console.log(`Required token B: ${depositQuote.outputAmount.toString()}`);
Notes
- Use this to calculate how much of token B is needed when adding token A (or vice versa)
- Particularly useful for single-sided liquidity provision
- The function handles Token2022 transfer fees if token info is provided
getWithdrawQuote
Calculates the withdrawal quote for removing liquidity from a pool.
Function
async getWithdrawQuote(params: GetWithdrawQuoteParams): Promise<WithdrawQuote>
Parameters
interface GetWithdrawQuoteParams {
liquidityDelta: BN; // The amount of liquidity to withdraw
sqrtPrice: BN; // Current sqrt price
maxSqrtPrice: BN; // Maximum sqrt price
minSqrtPrice: BN; // Minimum sqrt price
inputTokenInfo?: {
mint: Mint,
currentEpoch: number
}; // Token info for Token2022 transfer fee calculations
outputTokenInfo?: {
mint: Mint,
currentEpoch: number
}; // Token info for Token2022 transfer fee calculations
}
Returns
An object containing:
liquidityDelta
: The amount of liquidity being removed
outAmountA
: The calculated amount of token A to receive
outAmountB
: The calculated amount of token B to receive
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Calculate quote for removing half the liquidity
const liquidityToRemove = positionState.liquidity.div(new BN(2));
const withdrawQuote = await cpAmm.getWithdrawQuote({
liquidityDelta: liquidityToRemove,
sqrtPrice: poolState.sqrtPrice,
minSqrtPrice: poolState.sqrtMinPrice,
maxSqrtPrice: poolState.sqrtMaxPrice,
});
console.log(`Expected token A: ${withdrawQuote.outAmountA.toString()}`);
console.log(`Expected token B: ${withdrawQuote.outAmountB.toString()}`);
Notes
- Use this to estimate the tokens you’ll receive when removing liquidity
- The function handles Token2022 transfer fees if token info is provided
- The calculation accounts for the current price relative to the position’s price range
swap
Executes a token swap in the pool.
Function
async swap(params: SwapParams): TxBuilder
Parameters
interface SwapParams {
payer: PublicKey; // The wallet paying for the transaction
pool: PublicKey; // Address of the pool to swap in
inputTokenMint: PublicKey; // Mint of the input token
outputTokenMint: PublicKey; // Mint of the output token
amountIn: BN; // Amount of input token to swap
minimumAmountOut: BN; // Minimum amount of output token (slippage protection)
tokenAVault: PublicKey; // Pool's token A vault
tokenBVault: PublicKey; // Pool's token B vault
tokenAMint: PublicKey; // Pool's token A mint
tokenBMint: PublicKey; // Pool's token B mint
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
referralTokenAccount?: PublicKey; // Optional referral account for fees
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const currentSlot = await connection.getSlot();
const blockTime = await connection.getBlockTime(currentSlot);
// Get quote first
const quote = await cpAmm.getQuote({
inAmount: new BN(100_000_000), // 100 USDC
inputTokenMint: poolState.tokenAMint,
slippage: 0.5,
poolState,
currentTime: blockTime,
currentSlot
});
// Execute swap
const swapTx = await cpAmm.swap({
payer: wallet.publicKey,
pool: poolAddress,
inputTokenMint: poolState.tokenAMint,
outputTokenMint: poolState.tokenBMint,
amountIn: new BN(100_000_000),
minimumAmountOut: quote.minSwapOutAmount,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAProgram: TOKEN_PROGRAM_ID,
tokenBProgram: TOKEN_PROGRAM_ID
});
Notes
- Get a quote first using
getQuote
to determine the minimumAmountOut
- The SDK handles wrapping/unwrapping of SOL automatically
- Token accounts are created automatically if they don’t exist
- The transaction will fail if the output amount would be less than
minimumAmountOut
- Optional referral tokenAccount will receive a portion of fees if the pool is configured for referrals
addLiquidity
Adds liquidity to an existing position.
Function
async addLiquidity(params: AddLiquidityParams): TxBuilder
Parameters
interface AddLiquidityParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The ata account of position nft
liquidityDelta: BN; // The amount of liquidity to add in Q64 format
maxAmountTokenA: BN; // Maximum amount of token A to use
maxAmountTokenB: BN; // Maximum amount of token B to use
tokenAAmountThreshold: BN; // Minimum acceptable token A amount (slippage protection)
tokenBAmountThreshold: BN; // Minimum acceptable token B amount (slippage protection)
tokenAMint: PublicKey; // The mint of token A
tokenBMint: PublicKey; // The mint of token B
tokenAVault: PublicKey; // The pool's token A vault
tokenBVault: PublicKey; // The pool's token B vault
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Get deposit quote
const depositQuote = await cpAmm.getDepositQuote({
inAmount: new BN(1_000_000_000), // 1,000 USDC
isTokenA: true,
minSqrtPrice: poolState.sqrtMinPrice,
maxSqrtPrice: poolState.sqrtMaxPrice,
sqrtPrice: poolState.sqrtPrice
});
// Add liquidity
const addLiquidityTx = await cpAmm.addLiquidity({
owner: wallet.publicKey,
pool: poolAddress,
position: positionAddress,
positionNftAccount: positionNftAccount,
liquidityDelta: depositQuote.liquidityDelta,
maxAmountTokenA: new BN(1_000_000_000),
maxAmountTokenB: depositQuote.outputAmount,
tokenAAmountThreshold: maxAmountTokenA,
tokenBAmountThreshold: maxAmountTokenB,
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAProgram,
tokenBProgram
});
Notes
- Calculate the liquidity delta first using
getDepositQuote
- The SDK handles wrapping/unwrapping of SOL automatically
- Token accounts are created automatically if they don’t exist
- Set appropriate thresholds to protect against slippage
removeLiquidity
Removes a specific amount of liquidity from an existing position.
Function
async removeLiquidity(params: RemoveLiquidityParams): TxBuilder
Parameters
interface RemoveLiquidityParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftAccount?: PublicKey; // The position NFT account
liquidityDelta: BN; // The amount of liquidity to remove in Q64 format
tokenAAmountThreshold: BN; // Minimum acceptable token A amount (slippage protection)
tokenBAmountThreshold: BN; // Minimum acceptable token B amount (slippage protection)
tokenAMint: PublicKey; // The mint of token A
tokenBMint: PublicKey; // The mint of token B
tokenAVault: PublicKey; // The pool's token A vault
tokenBVault: PublicKey; // The pool's token B vault
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
vestings?: Array<{account: PublicKey}>; // Optional vesting accounts to refresh
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Get withdraw quote for half of the liquidity
const liquidityToRemove = positionState.unlockedLiquidity.div(new BN(2));
const withdrawQuote = await cpAmm.getWithdrawQuote({
liquidityDelta: liquidityToRemove,
sqrtPrice: poolState.sqrtPrice,
minSqrtPrice: poolState.sqrtMinPrice,
maxSqrtPrice: poolState.sqrtMaxPrice,
});
const removeLiquidityTx = await cpAmm.removeLiquidity({
owner: wallet.publicKey,
pool: poolAddress,
position: positionAddress,
positionNftAccount: positionNftAccount,
liquidityDelta: liquidityToRemove,
tokenAAmountThreshold: new BN(0),
tokenBAmountThreshold: new BN(0),
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAProgram,
tokenBProgram
});
Notes
- You can only remove unlocked liquidity
- The SDK handles wrapping/unwrapping of SOL automatically
- Token accounts are created automatically if they don’t exist
- Set appropriate thresholds to protect against slippage
- Removing all liquidity doesn’t close the position
removeAllLiquidity
Removes all available liquidity from a position.
Function
async removeAllLiquidity(params: RemoveAllLiquidityParams): TxBuilder
Parameters
interface RemoveAllLiquidityParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The ata account of position nft
tokenAAmountThreshold: BN; // Minimum acceptable token A amount (slippage protection)
tokenBAmountThreshold: BN; // Minimum acceptable token B amount (slippage protection)
tokenAMint: PublicKey; // The mint of token A
tokenBMint: PublicKey; // The mint of token B
tokenAVault: PublicKey; // The pool's token A vault
tokenBVault: PublicKey; // The pool's token B vault
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
vestings?: Array<{account: PublicKey}>; // Optional vesting accounts to refresh if position has vesting lock
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
const removeAllLiquidityTx = await cpAmm.removeAllLiquidity({
owner: wallet.publicKey,
pool: poolAddress,
position: positionAddress,
positionNftAccount: positionNftAccount,
tokenAAmountThreshold: new BN(0),
tokenBAmountThreshold: new BN(0),
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAProgram,
tokenBProgram
});
Notes
- This removes all unlocked liquidity in one transaction
- The position remains open after removing all liquidity
- You can’t remove locked liquidity (use
refreshVesting
first if needed)
- The SDK handles wrapping/unwrapping of SOL automatically
removeAllLiquidityAndClosePosition
Removes all liquidity from a position and closes it in a single transaction.
Function
async removeAllLiquidityAndClosePosition(params: RemoveAllLiquidityAndClosePositionParams): TxBuilder
Parameters
interface RemoveAllLiquidityAndClosePositionParams {
owner: PublicKey; // The owner of the position
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
positionState: PositionState; // The current position state
poolState: PoolState; // The current pool state
tokenAAmountThreshold: BN; // Minimum acceptable token A amount (slippage protection)
tokenBAmountThreshold: BN; // Minimum acceptable token B amount (slippage protection)
currentPoint: BN; // Current timestamp or slot number for vesting calculations
vestings?: Array<{account: PublicKey, vestingState: VestingState}>; // Optional vesting accounts
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Check if position is locked
if (cpAmm.isLockedPosition(positionState)) {
console.error("Cannot close a locked position");
return;
}
// Build transaction to remove all liquidity and close position
const tx = await cpAmm.removeAllLiquidityAndClosePosition({
owner: wallet.publicKey,
position: positionAddress,
positionNftAccount: positionNftAccount,
positionState: positionState,
poolState: poolState,
tokenAAmountThreshold: new BN(0),
tokenBAmountThreshold: new BN(0)
});
Notes
- This combines multiple operations in a single transaction:
- Claims any accumulated fees
- Removes all liquidity
- Closes the position and returns the rent
- The position must be completely unlocked
- The function will throw an error if the position has any locked liquidity
- This is more gas-efficient than doing these operations separately
- If there are vesting schedules, they must be refreshed before closing the position
mergePosition
Merges liquidity from one position into another in a single transaction.
Function
async mergePosition(params: MergePositionParams): TxBuilder
Parameters
interface MergePositionParams {
owner: PublicKey; // The owner of both positions
positionA: PublicKey; // Target position to merge into
positionB: PublicKey; // Source position to merge from
positionBState: PositionState; // State of the source position
poolState: PoolState; // State of the pool
positionANftAccount: PublicKey; // ata account of target position NFT
positionBNftAccount: PublicKey; // ata account of source position NFT
tokenAAmountAddLiquidityThreshold: BN; // Minimum token A amount for add liquidity
tokenBAmountAddLiquidityThreshold: BN; // Minimum token B amount for add liquidity
tokenAAmountRemoveLiquidityThreshold: BN; // Minimum token A amount for remove liquidity
tokenBAmountRemoveLiquidityThreshold: BN; // Minimum token B amount for remove liquidity
currentPoint: BN; // Current timestamp or slot number for vesting calculations
positionBVestings?: Array<{account: PublicKey, vestingState: VestingState}>; // Optional vesting accounts for position B
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionAState = await cpAmm.fetchPositionState(positionAAddress); // Target position
const positionBState = await cpAmm.fetchPositionState(positionBAddress); // Source position to merge from
// Check if position is locked
if (cpAmm.isLockedPosition(positionBState)) {
console.error("Cannot merge a locked position");
return;
}
// Build transaction to merge positions
const tx = await cpAmm.mergePosition({
owner: wallet.publicKey,
positionA: positionAAddress,
positionB: positionBAddress,
positionBState: positionBState,
poolState: poolState,
positionANftAccount: positionANftAccount,
positionBNftAccount: positionBNftAccount,
tokenAAmountAddLiquidityThreshold: new BN(U64_MAX),
tokenBAmountAddLiquidityThreshold: new BN(u64_MAX),
tokenAAmountRemoveLiquidityThreshold: new BN(0),
tokenBAmountRemoveLiquidityThreshold: new BN(0)
});
Notes
- This function combines multiple operations:
- Claims any accumulated fees from the source position
- Removes all liquidity from the source position
- Adds the liquidity to the target position
- Closes the source position
- Both positions must be owned by the same wallet
- The source position must be completely unlocked
- This is more gas-efficient than performing these operations separately
- Set appropriate thresholds to protect against slippage for both add and remove operations
lockPosition
Builds a transaction to lock a position with vesting schedule.
Function
async lockPosition(params: LockPositionParams): TxBuilder
Parameters
interface LockPositionParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
payer: PublicKey; // The wallet paying for the transaction
vestingAccount: PublicKey; // The vesting account to create
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
cliffPoint: BN | null; // The cliff point (slot or timestamp)
periodFrequency: BN; // How often liquidity unlocks
cliffUnlockLiquidity: BN; // Amount to unlock at cliff
liquidityPerPeriod: BN; // Amount to unlock per period
numberOfPeriod: number; // Number of vesting periods
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const vestingAccount = Keypair.generate();
const lockPositionTx = await cpAmm.lockPosition({
owner: wallet.publicKey,
pool: poolAddress,
payer: wallet.publicKey,
vestingAccount: vestingAccount.publicKey,
position: positionAddress,
positionNftAccount: positionNftAccount,
cliffPoint: new BN(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days cliff
periodFrequency: new BN(24 * 60 * 60 * 1000), // 1 day periods
cliffUnlockLiquidity: new BN(0), // No initial unlock
liquidityPerPeriod: positionState.unlockedLiquidity.div(new BN(30)), // Unlock over 30 days
numberOfPeriod: 30 // 30 periods
});
Notes
- Locking positions is useful for creating various incentive mechanisms
- The vesting schedule controls how quickly liquidity unlocks over time
- Locked liquidity cannot be withdrawn until it becomes unlocked
- The vesting account is a new account that must be created
- The function only locks currently unlocked liquidity
permanentLockPosition
Permanently locks a portion of liquidity in a position.
Function
async permanentLockPosition(params: PermanentLockParams): TxBuilder
Parameters
interface PermanentLockParams {
owner: PublicKey; // The owner of the position
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
pool: PublicKey; // The pool address
unlockedLiquidity: BN; // Amount of liquidity to permanently lock
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Permanently lock half of the unlocked liquidity
const liquidityToLock = positionState.unlockedLiquidity.div(new BN(2));
const lockTx = await cpAmm.permanentLockPosition({
owner: wallet.publicKey,
position: positionAddress,
positionNftAccount: positionNftAccount,
pool: poolAddress,
unlockedLiquidity: liquidityToLock
});
Notes
- Permanently locked liquidity can never be withdrawn
- This is useful for deep liquidity protocols or governance mechanisms
- Once liquidity is permanently locked, this action cannot be reversed
- The owner can still collect fees from permanently locked liquidity
refreshVesting
Refreshes vesting status of a position to unlock available liquidity.
Function
async refreshVesting(params: RefreshVestingParams): TxBuilder
Parameters
interface RefreshVestingParams {
owner: PublicKey; // The owner of the position
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
pool: PublicKey; // The pool address
vestingAccounts: PublicKey[]; // Array of vesting accounts to refresh
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
// Get all vesting accounts for the position
const vestings = await cpAmm.getAllVestingsByPosition(positionAddress);
const refreshVestingTx = await cpAmm.refreshVesting({
owner: wallet.publicKey,
position: positionAddress,
positionNftAccount: positionNftAccount,
pool: poolAddress,
vestingAccounts: vestings.map(v => v.publicKey)
});
Notes
- Call this function to update the vesting state and unlock available liquidity
- Should be called periodically to ensure liquidity is properly unlocked
- If all liquidity is unlocked, the vesting account remains but is no longer used
- Must be called before removing liquidity if position has vesting accounts
claimPositionFee
Claims accumulated fees for a position.
Function
async claimPositionFee(params: ClaimPositionFeeParams): TxBuilder
Parameters
interface ClaimPositionFeeParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
tokenAVault: PublicKey; // The pool's token A vault
tokenBVault: PublicKey; // The pool's token B vault
tokenAMint: PublicKey; // The mint of token A
tokenBMint: PublicKey; // The mint of token B
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
receiver?: Pubkey; // the wallet that will receive the fees (optional)
tempWSolAccount?: Pubkey; // the temporary wallet that will receive the fees (optional)
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const claimFeeTx = await cpAmm.claimPositionFee({
owner: wallet.publicKey,
pool: poolAddress,
position: positionAddress,
positionNftAccount: positionNftAccount,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAProgram,
tokenBProgram
});
Notes
- Fees are collected when trades occur in the pool
- Only the position owner can claim fees
- Fees are earned on both token A and token B based on the amount of liquidity provided
- Fees accumulate over time and should be claimed periodically
- The SDK handles wrapping/unwrapping of SOL automatically
claimPositionFee2
Claims accumulated fees for a position.
Function
async claimPositionFee2(params: ClaimPositionFeeParams2): TxBuilder
Parameters
interface ClaimPositionFeeParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
tokenAVault: PublicKey; // The pool's token A vault
tokenBVault: PublicKey; // The pool's token B vault
tokenAMint: PublicKey; // The mint of token A
tokenBMint: PublicKey; // The mint of token B
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
receiver: Pubkey; // The wallet that will receive the fees
feePayer?: PublicKey; // Specific fee payer for transaction. Default fee payer is position's owner
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const claimFeeTx = await cpAmm.claimPositionFee2({
owner: wallet.publicKey,
pool: poolAddress,
position: positionAddress,
receiver: receiverAddress,
positionNftAccount: positionNftAccount,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAProgram,
tokenBProgram
});
Notes
- Fees are collected when trades occur in the pool
- Only the position owner can claim fees
- Fees will claim to receiver address
- Fees are earned on both token A and token B based on the amount of liquidity provided
- The SDK handles wrapping/unwrapping of SOL automatically
claimPartnerFee
Claims partner fee rewards.
Function
async claimPartnerFee(params: ClaimPartnerFeeParams): TxBuilder
Parameters
interface ClaimPartnerFeeParams {
partner: PublicKey; // Partner address to receive fees
pool: PublicKey; // The pool address
maxAmountA: BN; // Maximum amount of token A to claim
maxAmountB: BN; // Maximum amount of token B to claim
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const claimPartnerFeeTx = await cpAmm.claimPartnerFee({
partner: partnerWallet.publicKey,
pool: poolAddress,
maxAmountA: new BN(1_000_000_000), // 1,000 USDC
maxAmountB: new BN(5_000_000_000) // 5 SOL
});
Notes
- Partner fees are a portion of trading fees directed to a specific account
- Only the configured partner address can claim these fees
- Partner fees must be enabled in the pool configuration
- The SDK handles wrapping/unwrapping of SOL automatically
- Token accounts are created automatically if they don’t exist
claimReward
Claims reward tokens from a position.
Function
async claimReward(params: ClaimRewardParams): TxBuilder
Parameters
interface ClaimRewardParams {
user: PublicKey; // The user claiming rewards
position: PublicKey; // The position address
positionNftAccount: PublicKey; // The position NFT account
rewardIndex: number; // Index of the reward to claim
poolState: PoolState; // The current pool state
positionState: PositionState; // The current position state
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Claim reward at index 0
const claimRewardTx = await cpAmm.claimReward({
user: wallet.publicKey,
position: positionAddress,
positionNftAccount: positionNftAccount,
rewardIndex: 0,
poolState: poolState,
positionState: positionState
});
Notes
- Pools can have multiple reward tokens configured
- The rewardIndex parameter specifies which reward token to claim
- Rewards accrue based on the amount of liquidity provided and duration
- Only the position owner can claim rewards
- The SDK handles wrapping/unwrapping of SOL automatically
closePosition
Closes a position with no liquidity.
Function
async closePosition(params: ClosePositionParams): TxBuilder
Parameters
interface ClosePositionParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftMint: PublicKey; // The position NFT mint
positionNftAccount: PublicKey; // The position NFT account
}
Returns
A transaction builder (TxBuilder
) that can be used to build, sign, and send the transaction.
Example
const positionState = await cpAmm.fetchPositionState(positionAddress);
// Check if position has no liquidity
if (!positionState.unlockedLiquidity.isZero() || !positionState.vestedLiquidity.isZero() || !positionState.permanentLockedLiquidity.isZero()) {
console.error("Position still has liquidity");
return;
}
const closePositionTx = await cpAmm.closePosition({
owner: wallet.publicKey,
pool: positionState.pool,
position: positionAddress,
positionNftMint: positionState.nftMint,
positionNftAccount: positionNftAccount
});
Notes
- Position must have zero liquidity before closing
- Use
removeAllLiquidity
first if the position still has liquidity
- Closing a position returns the rent to the owner
- This function only closes the position account, not the NFT
- For a full cleanup, use
removeAllLiquidityAndClosePosition
instead
State Functions
fetchConfigState
Fetches the Config state of the program.
Function
async fetchConfigState(config: PublicKey): Promise<ConfigState>
Parameters
config
: Public key of the config account.
Returns
Parsed ConfigState.
Example
const configState = await cpAmm.fetchConfigState(configAddress);
console.log(configState);
Notes
- Throws an error if the config account does not exist
fetchPoolState
Fetches the Pool state.
Function
async fetchPoolState(pool: PublicKey): Promise<PoolState>
Parameters
pool
: Public key of the pool.
Returns
Parsed PoolState.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
console.log(`Current Price: ${poolState.sqrtPrice.toString()}`);
console.log(`Liquidity: ${poolState.liquidity.toString()}`);
Notes
- Throws an error if the pool account does not exist
- Contains all essential information about the pool including prices, liquidity, and fees
fetchPositionState
Fetches the Position state.
Function
async fetchPositionState(position: PublicKey): Promise<PositionState>
Parameters
position
: Public key of the position.
Returns
Parsed PositionState.
Example
const positionState = await cpAmm.fetchPositionState(positionAddress);
console.log(`Unlocked Liquidity: ${positionState.unlockedLiquidity.toString()}`);
console.log(`Vested Liquidity: ${positionState.vestedLiquidity.toString()}`);
console.log(`Permanent Locked Liquidity: ${positionState.permanentLockedLiquidity.toString()}`);
Notes
- Throws an error if the position account does not exist
- Contains information about liquidity amounts, fee collection, and rewards
getAllConfigs
Retrieves all config accounts.
Function
async getAllConfigs(): Promise<Array<{ publicKey: PublicKey; account: ConfigState }>>
Returns
Array of config public keys and their states.
Example
const configs = await cpAmm.getAllConfigs();
console.log(`Found ${configs.length} configs`);
configs.forEach((config, i) => {
console.log(`Config ${i}: ${config.publicKey.toString()}`);
});
getAllPools
Retrieves all pool accounts.
Function
async getAllPools(): Promise<Array<{ publicKey: PublicKey; account: PoolState }>>
Returns
Array of pool public keys and their states.
Example
const pools = await cpAmm.getAllPools();
console.log(`Found ${pools.length} pools`);
pools.forEach((pool, i) => {
console.log(`Pool ${i}: ${pool.publicKey.toString()}`);
console.log(`- Token A: ${pool.account.tokenAMint.toString()}`);
console.log(`- Token B: ${pool.account.tokenBMint.toString()}`);
});
getAllPositions
Retrieves all position accounts.
Function
async getAllPositions(): Promise<Array<{ publicKey: PublicKey; account: PositionState }>>
Returns
Array of position public keys and their states.
Example
const positions = await cpAmm.getAllPositions();
console.log(`Found ${positions.length} positions`);
getAllPositionsByPool
Gets all positions for a specific pool.
Function
async getAllPositionsByPool(pool: PublicKey): Promise<Array<{ publicKey: PublicKey; account: PositionState }>>
Parameters
pool
: Public key of the pool.
Returns
List of positions for the pool.
Example
const poolPositions = await cpAmm.getAllPositionsByPool(poolAddress);
console.log(`Pool has ${poolPositions.length} positions`);
getUserPositionByPool
Gets all positions of a user for a specific pool.
Function
async getUserPositionByPool(pool: PublicKey, user: PublicKey): Promise<Array<{ positionNftAccount: PublicKey; position: PublicKey; positionState: PositionState }>>
Parameters
pool
: Public key of the pool.
user
: Public key of the user.
Returns
List of user positions for the pool.
Example
const userPoolPositions = await cpAmm.getUserPositionByPool(poolAddress, wallet.publicKey);
console.log(`User has ${userPoolPositions.length} positions in this pool`);
getPositionsByUser
Gets all positions of a user across all pools.
Function
async getPositionsByUser(user: PublicKey): Promise<Array<{ positionNftAccount: PublicKey; position: PublicKey; positionState: PositionState }>>
Parameters
user
: Public key of the user.
Returns
Array of user positions already sorted by liquidity.
Example
const userPositions = await cpAmm.getPositionsByUser(wallet.publicKey);
console.log(`User has ${userPositions.length} total positions`);
Notes
- Positions are sorted by total liquidity in descending order
- Returns position NFT accounts, position addresses, and full position states
getAllVestingsByPosition
Retrieves all vesting accounts associated with a position.
Function
async getAllVestingsByPosition(position: PublicKey): Promise<Array<{ publicKey: PublicKey; account: VestingState }>>
Parameters
position
: Public key of the position.
Returns
Array of vesting account public keys and their states.
Example
const vestings = await cpAmm.getAllVestingsByPosition(positionAddress);
console.log(`Position has ${vestings.length} vesting accounts`);
isLockedPosition
Checks if a position has any locked liquidity.
Function
isLockedPosition(position: PositionState): boolean
Parameters
position
: The position state.
Returns
Boolean indicating whether the position has locked liquidity.
Example
const positionState = await cpAmm.fetchPositionState(positionAddress);
if (cpAmm.isLockedPosition(positionState)) {
console.log("Position has locked liquidity");
} else {
console.log("Position has no locked liquidity");
}
isPoolExist
Checks if a pool exists.
Function
async isPoolExist(pool: PublicKey): Promise<boolean>
Parameters
pool
: Public key of the pool.
Returns
Boolean indicating whether the pool exists.
Example
const exists = await cpAmm.isPoolExist(poolAddress);
if (exists) {
console.log("Pool exists");
} else {
console.log("Pool does not exist");
}
Helper Functions
preparePoolCreationParams
Prepares parameters required for pool creation, including initial sqrt price and liquidity.
Function
preparePoolCreationParams(params: PreparePoolCreationParams): PreparedPoolCreation
Parameters
interface PreparePoolCreationParams {
tokenAAmount: BN; // Initial amount of token A to deposit
tokenBAmount: BN; // Initial amount of token B to deposit
minSqrtPrice: BN; // Minimum sqrt price
maxSqrtPrice: BN; // Maximum sqrt price
tokenAInfo?: any; // Token info for Token2022 transfer fee calculations
tokenBInfo?: any; // Token info for Token2022 transfer fee calculations
}
Returns
An object containing:
initSqrtPrice
: The initial sqrt price in Q64 format
liquidityDelta
: The initial liquidity in Q64 format
Example
const { initSqrtPrice, liquidityDelta } = cpAmm.preparePoolCreationParams({
tokenAAmount: new BN(1_000_000_000), // 1,000 USDC with 6 decimals
tokenBAmount: new BN(5_000_000_000), // 5 SOL with 9 decimals
minSqrtPrice: MIN_SQRT_PRICE,
maxSqrtPrice: MAX_SQRT_PRICE
});
console.log(`Initial sqrt price: ${initSqrtPrice.toString()}`);
console.log(`Initial liquidity: ${liquidityDelta.toString()}`);
Notes
- This function calculates the correct initial price and liquidity based on the token amounts
- Both token amounts must be greater than zero
- The function handles Token2022 transfer fees if token info is provided
isVestingComplete
Checks if a vesting schedule is ready for full release.
Function
function isVestingComplete(vestingData: VestingState, currentPoint: BN): boolean
Parameters
vestingData
: The vesting account state data
currentPoint
: Current timestamp or slot number
Returns
Boolean indicating whether the vesting schedule is complete and all liquidity can be released.
Example
const vestings = await cpAmm.getAllVestingsByPosition(positionAddress);
if (vestings.length > 0) {
const isComplete = isVestingComplete(vestings[0].account, new BN(Date.now()));
if (isComplete) {
console.log("Vesting schedule is complete, all liquidity can be released");
} else {
console.log("Vesting schedule is still active");
}
}
Notes
- This function checks if the current point (timestamp or slot) has passed the end of the vesting schedule
- The end point is calculated as: cliffPoint + (periodFrequency * numberOfPeriods)
- Returns true if currentPoint >= endPoint, false otherwise
- Useful to determine if a position can be fully unlocked
getTotalLockedLiquidity
Gets the total amount of liquidity in the vesting schedule.
Function
function getTotalLockedLiquidity(vestingData: VestingState): BN
Parameters
vestingData
: The vesting account state data
Returns
The total locked liquidity amount as a BN.
Example
const vestings = await cpAmm.getAllVestingsByPosition(positionAddress);
if (vestings.length > 0) {
const totalLocked = getTotalLockedLiquidity(vestings[0].account);
console.log(`Total locked liquidity: ${totalLocked.toString()}`);
}
Notes
- Calculates the sum of cliff unlock liquidity and periodic unlock liquidity
- Formula: cliffUnlockLiquidity + (liquidityPerPeriod * numberOfPeriod)
- This is the total amount of liquidity that was initially locked in the vesting schedule
- Does not account for already released liquidity
getAvailableVestingLiquidity
Calculates the available liquidity to withdraw based on vesting schedule.
Function
function getAvailableVestingLiquidity(vestingData: VestingState, currentPoint: BN): BN
Parameters
vestingData
: The vesting account state data
currentPoint
: Current timestamp or slot number
Returns
The amount of liquidity available to withdraw as a BN.
Example
const vestings = await cpAmm.getAllVestingsByPosition(positionAddress);
if (vestings.length > 0) {
const availableLiquidity = getAvailableVestingLiquidity(
vestings[0].account,
new BN(Date.now())
);
console.log(`Available liquidity to withdraw: ${availableLiquidity.toString()}`);
}
getMaxAmountWithSlippage
Calculates the maximum amount after applying a slippage rate.
Function
function getMaxAmountWithSlippage(amount: BN, rate: number): BN
Parameters
amount
: The base amount as a BN
rate
: The slippage rate as a percentage (e.g., 0.5 for 0.5%)
Returns
The maximum amount after applying slippage as a BN.
Example
const tokenAmount = new BN(1_000_000_000); // 1,000 tokens
const slippageRate = 0.5; // 0.5% slippage allowance
const maxAmount = getMaxAmountWithSlippage(tokenAmount, slippageRate);
console.log(`Maximum amount with slippage: ${maxAmount.toString()}`);
Notes
- Used when you need to calculate the upper bound of an amount with slippage tolerance
- Formula: amount * (100 + rate) / 100
- Common use case: Setting a maximum deposit amount when adding liquidity
- Slippage rate is expressed as a percentage and supports up to 2 decimal places
getMinAmountWithSlippage
Calculates the minimum amount after applying a slippage rate.
Function
function getMinAmountWithSlippage(amount: BN, rate: number): BN
Parameters
amount
: The base amount as a BN
rate
: The slippage rate as a percentage (e.g., 0.5 for 0.5%)
Returns
The minimum amount after applying slippage as a BN.
Example
const expectedOutput = new BN(1_000_000_000); // 1,000 tokens
const slippageRate = 0.5; // 0.5% slippage allowance
const minAmount = getMinAmountWithSlippage(expectedOutput, slippageRate);
console.log(`Minimum amount with slippage: ${minAmount.toString()}`);
Notes
- Used when you need to calculate the lower bound of an amount with slippage tolerance
- Formula: amount * (100 - rate) / 100
- Common use case: Setting a minimum output amount when swapping tokens
- Slippage rate is expressed as a percentage and supports up to 2 decimal places
getPriceImpact
Calculates the price impact as a percentage.
Function
function getPriceImpact(actualAmount: BN, idealAmount: BN): number
Parameters
actualAmount
: The actual amount after slippage in token units
idealAmount
: The theoretical amount without slippage in token units
Returns
The price impact as a percentage (e.g., 1.5 means 1.5%).
Example
const idealAmount = new BN(1_000_000_000); // 1,000 tokens (theoretical)
const actualAmount = new BN(990_000_000); // 990 tokens (actual)
const impact = getPriceImpact(actualAmount, idealAmount);
console.log(`Price impact: ${impact.toFixed(2)}%`);
Notes
- Used to express how much a transaction will affect the price
- Formula: ((idealAmount - actualAmount) / idealAmount) * 100
- Higher price impact indicates a greater effect on the market price
- Common use case: Showing users the effect of their swap on the pool
Price Conversion Utilities
getPriceFromSqrtPrice
Converts a sqrt price in Q64 format to a human-readable price.
Function
function getPriceFromSqrtPrice(sqrtPrice: BN, tokenADecimal: number, tokenBDecimal: number): string
Parameters
sqrtPrice
: The sqrt price in Q64 format
tokenADecimal
: The number of decimals for token A
tokenBDecimal
: The number of decimals for token B
Returns
The price as a string in human-readable format.
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const price = getPriceFromSqrtPrice(
poolState.sqrtPrice,
6, // USDC has 6 decimals
9 // SOL has 9 decimals
);
console.log(`Current price: ${price} USDC per SOL`);
Notes
- Converts the internal sqrt price representation to a human-readable price
- Formula: (sqrtPrice >> 64)^2 * 10^(tokenADecimal - tokenBDecimal)
- The result represents the price of token B in terms of token A
- Useful for displaying current pool prices to users
getSqrtPriceFromPrice
Converts a human-readable price to a sqrt price in Q64 format.
Function
function getSqrtPriceFromPrice(price: string, tokenADecimal: number, tokenBDecimal: number): BN
Parameters
price
: The price as a string in human-readable format
tokenADecimal
: The number of decimals for token A
tokenBDecimal
: The number of decimals for token B
Returns
The sqrt price as a BN in Q64 format.
Example
const price = "0.05"; // 0.05 USDC per SOL
const sqrtPrice = getSqrtPriceFromPrice(
price,
6, // USDC has 6 decimals
9 // SOL has 9 decimals
);
console.log(`Sqrt price in Q64 format: ${sqrtPrice.toString()}`);
Notes
- Converts a human-readable price to the internal sqrt price representation
- Formula:
sqrt(price / 10^(tokenADecimal - tokenBDecimal)) << 64
- Useful when creating pools with a specific initial price
- Can be used to define price boundaries for concentrated liquidity positions
Fee Calculation Utilities
getUnClaimReward
Calculates unclaimed fees and rewards for a position.
Function
function getUnClaimReward(poolState: PoolState, positionState: PositionState): {
feeTokenA: BN;
feeTokenB: BN;
rewards: BN[];
}
Parameters
poolState
: The current state of the pool
positionState
: The current state of the position
Returns
An object containing:
feeTokenA
: Unclaimed fees in token A
feeTokenB
: Unclaimed fees in token B
rewards
: Array of unclaimed reward amounts for each reward token
Example
const poolState = await cpAmm.fetchPoolState(poolAddress);
const positionState = await cpAmm.fetchPositionState(positionAddress);
const unclaimed = getUnClaimReward(poolState, positionState);
console.log(`Unclaimed token A fees: ${unclaimed.feeTokenA.toString()}`);
console.log(`Unclaimed token B fees: ${unclaimed.feeTokenB.toString()}`);
unclaimed.rewards.forEach((reward, i) => {
console.log(`Unclaimed reward ${i}: ${reward.toString()}`);
});
getBaseFeeNumerator
Calculates the current base fee numerator based on the configured fee scheduler mode and elapsed periods.
Function
function getBaseFeeNumerator(
feeSchedulerMode: FeeSchedulerMode,
cliffFeeNumerator: BN,
period: BN,
reductionFactor: BN
): BN
Parameters
feeSchedulerMode
: The fee reduction mode (Linear or Exponential)
cliffFeeNumerator
: The initial maximum fee numerator (starting point)
period
: The number of elapsed periods since fee reduction began
reductionFactor
: The rate of fee reduction per period
Mathematical Formulas
Linear Mode:
fee = cliffFeeNumerator - (period × reductionFactor)
Exponential Mode:
fee = cliffFeeNumerator × (1 - reductionFactor/BASIS_POINT_MAX)^period
Returns
BN
: The calculated base fee numerator for the current period
getDynamicFeeNumerator
Calculates a dynamic fee component based on market volatility
Function
function getDynamicFeeNumerator(
volatilityAccumulator: BN,
binStep: BN,
variableFeeControl: BN
): BN
Parameters
volatilityAccumulator
: Accumulated measure of market volatility over time
binStep
: The price bin step size used in the liquidity distribution system
variableFeeControl
: Control parameter that determines how much volatility affects fees
Mathematical Formula
squareVfaBin = (volatilityAccumulator × binStep)²
vFee = variableFeeControl × squareVfaBin
dynamicFee = (vFee + 99,999,999,999) ÷ 100,000,000,000
Returns
BN
: The calculated dynamic fee numerator
- Returns
0
if variableFeeControl
is zero (dynamic fees disabled)
bpsToFeeNumerator
Converts basis points to fee numerator format.
Formula
feeNumerator = (bps × FEE_DENOMINATOR) ÷ BASIS_POINT_MAX
feeNumeratorToBps
Converts fee numerator back to basis points.
Formula
bps = (feeNumerator × BASIS_POINT_MAX) ÷ FEE_DENOMINATOR
getBaseFeeParams
Calculates the initial parameters for a base fee
Key Features
- Supports both linear and exponential fee reduction
- Validates parameter consistency
- Calculates period frequency and reduction factors
getDynamicFeeParams
Calculates the parameters needed for dynamic fee.
Key Features
- Configures volatility-based fee parameters
- Sets maximum price change thresholds
- Calculates variable fee control parameters