technical-research.md 4.6 KB

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)

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

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.