Dynamic AMM v2 (DAMM v2) is a brand new constant-product AMM program for liquidity pools, with a set of features to optimize transaction fees and provide greater flexibility for liquidity providers, launchpads, and token launches. Read an overview of .
Below we provide the steps to use Bun to configure and run sample scripts to conveniently set up a DAMM v2 Launch Pool on your own.
Getting Started
Clone repo:
Config list to reference:
Readme:
Dependencies
We need to run the scripts, install it via . Then install the dependencies by running the command bun install
Scripts
The following code examples can be used to initialize and seed a DAMM v2 pool on Meteora. It allows you to configure parameters for the pool, including fees, pricing, and activation conditions, before executing initialization and seeding commands.
Create customizable DAMM V2 pool
Clone repo:
Configuration file example here:
Run the script with the config file (specified in the CLI) which is updated with your preferred parameters.
bun run src/create_damm_v2_customizable_pool.ts --config ./config/create_damm_v2_customize_pool.json
Note: you have to Replace <./config/create_damm_v2_customize_pool.json> with the path to your config file, after you have set your config parameters.
Configuration Details
General configuration
rpcUrl: Solana RPC URL to get data and send transactions.
keypairFilePath: Keypair file path to send transactions.
dryRun: Set to false to send transactions.
computeUnitPriceMicroLamports: CU price in micro lamports unit. For example: 100000.
createBaseToken: Configuration to create base token.
baseMint: Base token address if the createBaseToken field is not set.
quoteSymbol: Quote token symbol, only SOL or USDC is supported.
quoteMint: Quote token mint, in case the user wants to create a DLMM launch pool with a token other than SOL or USDC.
dynamicAmm: Dynamic AMM pool configuration.
dynamicAmmV2: Dynamic AMM V2 pool configuration.
dlmm: DLMM pool configuration.
alphaVault: Fcfs or Prorata Alpha Vault configuration.
Some configuration constraints:
createBaseToken and baseMint cannot be used together.
dynamicAmm and dlmm cannot be used together.
Create Base Token configuration
mintBaseTokenAmount: Base token amount to be minted.
baseDecimals: Base token decimal.
Dynamic AMM V2 configuration
baseAmount: Base token amount.
quoteAmount: Quote token amount (Nullable value)
initPrice: Initial price for the pool
maxPrice: Max price range setup (null to use default)
poolFees:
maxBaseFeeBps: Starting fee in basis points (e.g., 25 = 0.25%). It is base fee if scheduler is not set.
minBaseFeeBps: Target fee after reduction periods. Should be equal maxBaseFeeBps when fee scheduler is not used.
numberOfPeriod: Number of periods for fee reduction schedule
totalDuration: Total duration of the fee schedule (in slots or seconds based on activation type). totalDuration == 0 if the FeeScheduler not be set up.
useDynamicFee: Whether to use dynamic fee calculation based on price volatility (true/false)
dynamicFeeConfig: Configuration when useDynamicFee is true if not provide will use as default params in scripts
filterPeriod: Period for filtering price updates
decayPeriod: Period for decaying volatility accumulator
reductionFactor: Factor for reducing the volatility impact
variableFeeControl: Parameter controlling the variable fee response
maxVolatilityAccumulator: Maximum value for the volatility accumulator
collectFeeMode: Fee collection mode (0 = base + quote, 1 = only quote)
activationType: To activate pool trading base on slot or timestamp.
activationPoint: To activate pool trading at a point, either slot value or timestamp value base on activationType.
hasAlphaVault: Whether alpha vault is enabled or not for this pool.
Alpha Vault configuration
poolType: dynamic or dlmm pool type.
alphaVaultType: Alpha Vault type, could be fcfs or prorata
depositingPoint: Absolute value that, the slot or timestamp that allows deposit depend on the pool activation type.
startVestingPoint: Absolute value, the slot or timestamp that start vesting depend on the pool activation type.
endVestingPoint: Absolute value, the slot or timestamp that end vesting depend on the pool activation type.
maxDepositCap: Maximum deposit cap.
individualDepositingCap: Individual deposit cap.
escrowFee: Fee to create stake escrow account.
whitelistMode: permissionless or permission_with_merkle_proof or permission_with_authority.
Pro rata configuration
depositingPoint: Absolute value that, the slot or timestamp that allows deposit depend on the pool activation type.
startVestingPoint: Absolute value, the slot or timestamp that start vesting depend on the pool activation type.
endVestingPoint: Absolute value, the slot or timestamp that end vesting depend on the pool activation type.
maxBuyingCap: Maximum buying cap.
escrowFee: Fee to create stake escrow account.
whitelistMode: permissionless or permission_with_merkle_proof or permission_with_authority.
Alternative: Using TypeScript SDK to create a DAMM v2 Pool
Getting Started
Program ID (mainnet-beta): cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG
Program ID (devnet): cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG
Below you can find the main functions to for a new pool:
createPool
createCustomPool
createCustomPoolWithDynamicConfig
createPosition
addLiquidity
1. Install dependencies and initialize instance
1.1 Install
pnpm install @meteora-ag/cp-amm-sdk
# or
yarn add @meteora-ag/cp-amm-sdk
1.2 Initialization
import { Connection } from "@solana/web3.js";
import { CpAmm } from "@meteora-ag/cp-amm-sdk";
// Initialize a connection to the Solana network
const connection = new Connection("https://api.mainnet-beta.solana.com");
// Create a new instance of the CpAmm SDK
const cpAmm = new CpAmm(connection);
1.3 Test
pnpm install
pnpm test
1.4 Faucets
2. Core Functions and Use Cases
createPool
Creates a new standard pool according to a predefined configuration.
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; // 0: slot, 1: timestamp
tokenAAmount: BN; // Initial amount of token A to deposit
tokenBAmount: BN; // Initial amount of token B to deposit
minSqrtPrice: BN; // Minimum sqrt price (typically MIN_SQRT_PRICE)
maxSqrtPrice: BN; // Maximum sqrt price (typically MAX_SQRT_PRICE)
tokenADecimal: number; // Decimal places for token A
tokenBDecimal: number; // Decimal places for token B
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 createPoolTx = await cpAmm.createPool({
payer: wallet.publicKey,
creator: wallet.publicKey,
config: configAddress,
positionNft: positionNftMint,
tokenAMint: usdcMint,
tokenBMint: solMint,
activationPoint: new BN(Date.now()),
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,
tokenADecimal: 6,
tokenBDecimal: 9,
tokenAProgram: TOKEN_PROGRAM_ID,
tokenBProgram: TOKEN_PROGRAM_ID
});
const tx = await createPoolTx.transaction();
const Function = await wallet.sendTransaction(tx, connection);
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
createCustomPool
Creates a customizable pool with specific fee parameters, reward settings, and activation conditions.
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
minSqrtPrice: BN; // Minimum sqrt price
maxSqrtPrice: BN; // Maximum sqrt price
tokenADecimal: number; // Decimal places for token A
tokenBDecimal: number; // Decimal places 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
tokenAProgram: PublicKey; // Token program for token A
tokenBProgram: PublicKey; // Token program for token B
}
interface PoolFees {
baseFee: {
feeSchedulerMode: number; // 0: Linear, 1: Exponential
cliffFeeNumerator: number;
numberOfPeriod: number;
reductionFactor: number;
periodFrequency: number;
};
partnerFee?: {
partnerAddress: PublicKey;
partnerFeeNumerator: number;
};
dynamicFee?: {
initialized: boolean;
volatilityAccumulator?: number;
binStep?: number;
variableFeeControl?: {
maxFeeNumerator: number;
minFeeNumerator: number;
volatilityThreshold: number;
feeDamper: number;
};
};
}
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
}
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.
interface AddLiquidityParams {
owner: PublicKey; // The owner of the position
pool: PublicKey; // The pool address
position: PublicKey; // The position address
positionNftMint: PublicKey; // The position NFT mint
liquidityDeltaQ64: 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
// Calculate liquidity delta first
const liquidityDelta = await cpAmm.getLiquidityDelta({
maxAmountTokenA: new BN(1_000_000_000), // 1,000 USDC
maxAmountTokenB: new BN(5_000_000_000), // 5 SOL
sqrtPrice: poolState.sqrtPrice,
sqrtMinPrice: MIN_SQRT_PRICE,
sqrtMaxPrice: MAX_SQRT_PRICE
});
// Add liquidity
const addLiquidityTx = await cpAmm.addLiquidity({
owner: wallet.publicKey,
pool: poolAddress,
position: positionAddress,
positionNftMint: positionNftMint,
liquidityDeltaQ64: liquidityDelta,
maxAmountTokenA: new BN(1_000_000_000),
maxAmountTokenB: new BN(5_000_000_000),
tokenAAmountThreshold: new BN(0),
tokenBAmountThreshold: new BN(0),
tokenAMint: poolState.tokenAMint,
tokenBMint: poolState.tokenBMint,
tokenAVault: poolState.tokenAVault,
tokenBVault: poolState.tokenBVault,
tokenAProgram: TOKEN_PROGRAM_ID,
tokenBProgram: TOKEN_PROGRAM_ID
});
const tx = await addLiquidityTx.transaction();
const Function = await wallet.sendTransaction(tx, connection);
Notes
Calculate the liquidity delta first using getLiquidityDelta
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
The TypeScript SDK provides a set of tools and methods to interact with the program.
Program Repo on Github:
TypeScript SDK on Github:
To set your Pool and Fee Config, please read the instructions in
For more documentation on DAMM v2 integration, please .
For a high level overview of DAMM v2, please read .