# Meteora DLMM Technical Research ## Meteora DLMM Program - **Program ID:** `LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo` - **SDK:** `@meteora-ag/dlmm` (v1.9.3 in project) - **GitHub:** MeteoraAg/dlmm-sdk ## Key SDK Methods - `DLMM.create(connection, poolAddress)` - get pool instance - `dlmm.initializePositionAndAddLiquidityByStrategy()` - open position + add liquidity in one tx - `dlmm.addLiquidityByStrategy({ positionPubKey, totalXAmount, totalYAmount, strategy: { minBinId, maxBinId, strategyType } })` - `dlmm.removeLiquidity({ user, position, fromBinId, toBinId, bps, shouldClaimAndClose })` - `dlmm.closePosition({ owner, position })` - close position account, recover rent - Strategy types: SpotBalanced, BidAsk, Curve ## Position Account Structure - Positions are program accounts (NOT NFTs/tokens) - Key fields: lowerBinId, upperBinId (computed), lbPair, owner, totalClaimedFees - LbPair holds pool data: activeId, binStep, tokenMintX, tokenMintY, reserveX, reserveY ## Instructions to Monitor | Instruction | Purpose | |---|---| | `initializePosition` / `initializePosition2` | Create position account | | `addLiquidityByStrategy` / `addLiquidityByStrategy2` | Add liquidity with strategy | | `removeLiquidity` / `removeLiquidityByRange` / `removeLiquidityByRange2` | Remove liquidity | | `closePosition` / `closePosition2` | Close position account | ## Instruction Discriminators (Anchor 8-byte prefix) ```typescript const DISCRIMINATORS = { addLiquidity: [181, 157, 89, 67, 143, 182, 52, 72], addLiquidityByStrategy: [7, 3, 150, 127, 148, 40, 61, 200], addLiquidityByStrategy2: [3, 221, 149, 218, 111, 141, 118, 213], addLiquidityByStrategyOneSide: [41, 5, 238, 175, 100, 225, 6, 205], removeLiquidity: [80, 85, 209, 72, 24, 206, 177, 108], removeLiquidityByRange: [26, 82, 102, 152, 240, 74, 105, 26], removeLiquidityByRange2: [204, 2, 195, 145, 53, 145, 145, 205], closePosition: [123, 134, 81, 0, 49, 68, 98, 98], closePosition2: [174, 90, 35, 115, 186, 40, 147, 226], initializePosition: [219, 192, 234, 71, 190, 191, 102, 80], initializePosition2: [143, 19, 242, 145, 213, 15, 104, 115], }; ``` ## Instruction Account Layouts (key accounts by index) | Instruction | Accounts | |---|---| | `addLiquidityByStrategy` | [0] position, [1] lbPair, [11] sender | | `addLiquidityByStrategy2` | [0] position, [1] lbPair, [9] sender | | `initializePosition` | [0] payer, [1] position, [2] lbPair, [3] owner | | `removeLiquidity` | [0] position, [1] lbPair, [11] sender | | `removeLiquidityByRange` | [0] position, [1] lbPair, [11] sender | | `closePosition` | [0] position, [1] lbPair, [4] sender | ## Transaction Monitoring - **Method:** `connection.onLogs(walletPubkey, callback, 'confirmed')` per monitored wallet - Filter callback logs for DLMM program ID mentions - Fetch full tx with `getTransaction(signature, { maxSupportedTransactionVersion: 0 })` - **WebSocket keepalive:** ping every 30s, auto-reconnect with exponential backoff - `logsSubscribe` mentions filter only supports ONE address per subscription ## Transaction Parsing Approach - Use `BorshInstructionCoder` from `@coral-xyz/anchor` with DLMM IDL - IDL exported from `@meteora-ag/dlmm` package - Handle versioned transactions (v0) with address lookup tables - `instructionCoder.decode(Buffer.from(ix.data))` returns `{ name, data }` ## Copy Trade Execution Flow ### Open Position: 1. Detect leader `addLiquidityByStrategy` on pool X 2. Extract: lbPairAddress, minBinId, maxBinId, strategyType, amountX, amountY 3. Apply copy ratio: `followerAmount = leaderAmount * COPY_RATIO` 4. Cap at MAX_POSITION_SIZE_SOL 5. Call `dlmm.initializePositionAndAddLiquidityByStrategy()` 6. Record LeaderPosition + FollowerPosition + CopyTrade in DB ### Close Position: 1. Detect leader `removeLiquidity` or `closePosition` 2. Look up follower position from DB 3. Remove follower's liquidity (100% bps if close) 4. Call `dlmm.closePosition()` if leader closed 5. Update statuses in DB ## Proportional Sizing ``` followerAmountX = leaderAmountX * (COPY_RATIO * 10000) / 10000 followerAmountY = leaderAmountY * (COPY_RATIO * 10000) / 10000 ``` Using BN integer math to avoid floating point issues. ## Reference Projects - machenxi/meteora-dlmm-copytrading-bot - leader-follower architecture - cutupdev/Solana-Copytrading-bot - multi-DEX support - Bitquery Meteora DLMM API for querying historical data ## Dependencies to Install ```bash npm install prisma tsx @coral-xyz/anchor @types/bn.js --save-dev ``` `@coral-xyz/anchor` is already a transitive dep of `@meteora-ag/dlmm` but needs explicit install for types.