Documentation Index
Fetch the complete documentation index at: https://docs.meteora.ag/llms.txt
Use this file to discover all available pages before exploring further.
These examples are based on the local damm-v1-sdk/ts-client/src/examples files and public SDK methods. They focus on transaction construction patterns. For the full method catalog, see the SDK Reference.
Setup
import AmmImpl from "@meteora-ag/dynamic-amm-sdk";
import { Connection, Keypair, PublicKey, sendAndConfirmTransaction } from "@solana/web3.js";
import BN from "bn.js";
const connection = new Connection(process.env.RPC_URL!, "confirmed");
// Replace with your wallet adapter, backend signer, or key management flow.
const user = Keypair.generate();
const poolAddress = new PublicKey("...");
Use devnet while testing. The DAMM v1 program ID is the same for devnet and mainnet:
// Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB
Fetch Pool State
const pool = await AmmImpl.create(connection, poolAddress, {
cluster: "mainnet-beta",
});
await pool.updateState();
const lockedLpAmount = await pool.getLockedLpAmount();
const lpSupply = await pool.getLpSupply();
console.log({
pool: pool.address.toBase58(),
lpMint: pool.getPoolTokenMint().toBase58(),
tokenA: pool.tokenAMint.address.toBase58(),
tokenB: pool.tokenBMint.address.toBase58(),
tokenAAmount: pool.poolInfo.tokenAAmount.toString(),
tokenBAmount: pool.poolInfo.tokenBAmount.toString(),
virtualPriceRaw: pool.poolInfo.virtualPriceRaw.toString(),
lockedLpAmount: lockedLpAmount.toString(),
lpSupply: lpSupply.toString(),
});
AmmImpl.create reads the pool, both Dynamic Vault accounts, vault token accounts, vault LP mints, pool-held vault LP token accounts, clock, and depeg accounts when required.
Quote And Swap
The recommended swap flow is:
- Load the pool.
- Quote with
getSwapQuote.
- Build the swap transaction with
minSwapOutAmount.
- Sign, simulate when appropriate, and send.
const pool = await AmmImpl.create(connection, poolAddress, {
cluster: "devnet",
});
const inTokenMint = pool.tokenAMint.address;
const inAmount = new BN(10_000_000);
const slippagePercent = 1;
const quote = pool.getSwapQuote(inTokenMint, inAmount, slippagePercent);
const tx = await pool.swap(
user.publicKey,
inTokenMint,
quote.swapInAmount,
quote.minSwapOutAmount,
);
const signature = await sendAndConfirmTransaction(connection, tx, [user]);
console.log({
signature,
outAmount: quote.swapOutAmount.toString(),
minOutAmount: quote.minSwapOutAmount.toString(),
fee: quote.fee.toString(),
priceImpact: quote.priceImpact.toString(),
});
Pass a referralOwner as the optional fifth pool.swap argument when routing a host fee account for referral flows.
Deposit Liquidity
For a balanced deposit, provide one token-side amount to getDepositQuote with balance = true; the SDK computes the other side from pool state.
const pool = await AmmImpl.create(connection, poolAddress);
const tokenBInAmount = new BN(1_000_000);
const slippagePercent = 1;
const quote = pool.getDepositQuote(
new BN(0),
tokenBInAmount,
true,
slippagePercent,
);
const tx = await pool.deposit(
user.publicKey,
quote.tokenAInAmount,
quote.tokenBInAmount,
quote.minPoolTokenAmountOut,
);
const signature = await sendAndConfirmTransaction(connection, tx, [user]);
console.log(signature);
For stable pools, the SDK can also quote imbalanced deposits by calling getDepositQuote(tokenAAmount, tokenBAmount, false, slippagePercent).
Withdraw Liquidity
const pool = await AmmImpl.create(connection, poolAddress);
const lpTokenAmount = new BN(100_000);
const slippagePercent = 1;
const quote = pool.getWithdrawQuote(lpTokenAmount, slippagePercent);
const tx = await pool.withdraw(
user.publicKey,
quote.poolTokenAmountIn,
quote.minTokenAOutAmount,
quote.minTokenBOutAmount,
);
const signature = await sendAndConfirmTransaction(connection, tx, [user]);
console.log(signature);
For stable pools, pass a token mint as the third getWithdrawQuote argument to quote a single-sided withdrawal.
Create A Config-Based Pool
createPermissionlessConstantProductPoolWithConfig returns an array of transactions because vault creation, pool creation, optional locking, and optional initial swap can require multiple transactions.
import AmmImpl, { PROGRAM_ID } from "@meteora-ag/dynamic-amm-sdk";
import { derivePoolAddressWithConfig } from "@meteora-ag/dynamic-amm-sdk/dist/cjs/src/amm/utils";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
const tokenAMint = new PublicKey("...");
const tokenBMint = new PublicKey("...");
const config = new PublicKey("...");
const tokenAAmount = new BN(100_000);
const tokenBAmount = new BN(500_000);
const poolAddress = derivePoolAddressWithConfig(
tokenAMint,
tokenBMint,
config,
new PublicKey(PROGRAM_ID),
);
const transactions = await AmmImpl.createPermissionlessConstantProductPoolWithConfig(
connection,
user.publicKey,
tokenAMint,
tokenBMint,
tokenAAmount,
tokenBAmount,
config,
{
cluster: "devnet",
lockLiquidity: true,
},
);
for (const tx of transactions) {
const signature = await sendAndConfirmTransaction(connection, tx, [user]);
console.log(signature);
}
console.log("pool", poolAddress.toBase58());
Use createPermissionlessConstantProductPoolWithConfig2 when you need to pass an activationPoint accepted by the selected config.
Find Authorized Configs
const configs = await AmmImpl.getPoolConfigsWithPoolCreatorAuthority(
connection,
user.publicKey,
);
for (const config of configs) {
console.log({
config: config.publicKey.toBase58(),
tradeFeeNumerator: config.account.poolFees.tradeFeeNumerator.toString(),
activationDuration: config.account.activationDuration.toString(),
});
}
Public configs have pool_creator_authority set to the default pubkey. Private configs require the configured creator signer.
Lock LP And Claim Fees
const pool = await AmmImpl.create(connection, poolAddress);
const lpAmount = new BN(100_000);
const lockTx = await pool.lockLiquidity(
user.publicKey,
lpAmount,
user.publicKey,
);
await sendAndConfirmTransaction(connection, lockTx, [user]);
const escrow = await pool.getUserLockEscrow(user.publicKey);
console.log(escrow?.fee.unClaimed);
if (escrow?.fee.unClaimed.lp?.gt(new BN(0))) {
const claimTx = await pool.claimLockFee2(
user.publicKey,
escrow.fee.unClaimed.lp,
user.publicKey,
user.publicKey,
);
await sendAndConfirmTransaction(connection, claimTx, [user]);
}
claimLockFee2 is the newer claim helper. Use claimLockFee only when you need the older wrapped-SOL receiver behavior.