# Agents Guide This document describes the key components of the Meteora DLMM Copy Trading Bot and how they interact. ## Architecture Overview ``` ┌─────────────────┐ ┌──────────────────────────────────────────┐ │ Next.js Web │ │ Worker Process │ │ │ │ │ │ Dashboard UI │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ (page.tsx) │ │ │ Monitor │──│ Tracker │──│Executor │ │ │ │ │ └────┬────┘ └─────────┘ └────┬────┘ │ │ API Routes │ │ │ │ │ │ /api/wallets │◄────┤ │ WebSocket │ DLMM │ │ /api/positions │ │ │ onLogs │ SDK │ │ /api/trades │ │ ▼ ▼ │ │ /api/settings │ │ Solana RPC ◄───────────── Solana RPC │ └────────┬────────┘ └──────────────────────────────────────────┘ │ │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ SQLite │◄─────────────────│ SQLite │ │ Database │ (shared volume) │ Database │ └──────────┘ └──────────┘ ``` ## Components ### 1. Transaction Monitor (`src/worker/monitor.ts`) **Role**: Watches leader wallets for DLMM transactions in real-time. **How it works**: - Subscribes to Solana `onLogs` WebSocket for each active monitored wallet - Filters logs for mentions of the DLMM program ID (`LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo`) - On match, fetches the full transaction and passes it to the transaction parser - Emits `meteoraTx` events with parsed operations - Maintains a dedup set to avoid processing the same signature twice **Key behaviors**: - Subscription sync runs every 30 seconds to pick up new wallets added via the dashboard - Processes only `confirmed` commitment level transactions ### 2. Transaction Parser (`src/lib/solana/transaction-parser.ts`) **Role**: Decodes raw Solana transactions into structured DLMM operations. **How it works**: - Resolves all account keys from the transaction message, including address lookup tables (v0 transactions) - Iterates through all instructions, matching by DLMM program ID - Uses Anchor's `BorshInstructionCoder` with the DLMM IDL to decode instruction data - Maps decoded instruction names to action types (ADD_LIQUIDITY, REMOVE_LIQUIDITY, etc.) - Extracts account addresses (position, lbPair, sender) from account indices using predefined account maps - Extracts parameters (bin ranges, amounts, BPS) from decoded instruction data **Supported instructions**: | Instruction | Action | |---|---| | `addLiquidity`, `addLiquidityByStrategy`, `addLiquidityByStrategy2`, `addLiquidityByStrategyOneSide` | ADD_LIQUIDITY | | `removeLiquidity`, `removeLiquidityByRange`, `removeLiquidityByRange2` | REMOVE_LIQUIDITY | | `closePosition`, `closePosition2`, `closePositionIfEmpty` | CLOSE_POSITION | | `initializePosition`, `initializePosition2` | INIT_POSITION | | `rebalanceLiquidity` | REBALANCE_LIQUIDITY | ### 3. Position Tracker (`src/worker/position-tracker.ts`) **Role**: Maintains the state of leader and follower positions in the database. **How it works**: - On INIT_POSITION / ADD_LIQUIDITY: creates or updates leader position records with bin range and strategy info - On REMOVE_LIQUIDITY: logs activity (position stays open) - On CLOSE_POSITION: marks leader position as closed - On REBALANCE_LIQUIDITY: updates leader position bin range - Provides lookup for follower positions mapped to leader positions ### 4. Copy Executor (`src/worker/executor.ts`) **Role**: Mirrors leader operations on the follower wallet. **Supported operations**: | Leader Action | Follower Action | |---|---| | ADD_LIQUIDITY | Open new position + add scaled liquidity | | REMOVE_LIQUIDITY | Remove liquidity (same BPS ratio) | | CLOSE_POSITION | Remove all liquidity + close position | | REBALANCE_LIQUIDITY | Remove liquidity + re-add in new bin range | | INIT_POSITION | Track only (no copy, waits for ADD_LIQUIDITY) | **Scaling**: The copy ratio (`COPY_RATIO` env var, default 1.0) scales the leader's deposit amounts. For example, if the leader deposits 1 SOL and the ratio is 0.5, the follower deposits 0.5 SOL. **Safety**: Each copy trade is recorded in the database with status tracking (PENDING → SUCCESS/FAILED) and error messages for debugging. ### 5. DLMM Client (`src/lib/meteora/dlmm-client.ts`) **Role**: Wraps the `@meteora-ag/dlmm` SDK for copy trading operations. **Functions**: - `copyOpenPosition`: Creates a new DLMM position and adds liquidity using the leader's strategy type and bin range - `copyRemoveLiquidity`: Removes liquidity from a follower position (by BPS) - `copyClosePosition`: Closes a follower position - `copyRebalanceLiquidity`: Removes all liquidity and re-adds in a new bin range matching the leader's rebalance ### 6. WebSocket Heartbeat (`src/worker/heartbeat.ts`) **Role**: Keeps the Solana WebSocket connection alive and handles reconnection. **How it works**: - Sends periodic `getSlot` ping requests (every 30 seconds) - Detects stale connections (no response within timeout) - On connection loss, triggers a reconnection callback that re-subscribes all wallets - Uses exponential backoff for reconnection attempts ### 7. Web Dashboard (`src/app/page.tsx`) **Role**: Provides a UI for managing monitored wallets. **Features**: - Add new wallets by Solana address (with optional label) - View all monitored wallets with status (Active/Paused) - Toggle wallet active state - Delete wallets - Validates Solana addresses (base58, 32-44 chars) ### 8. API Routes (`src/app/api/`) **Role**: REST API for CRUD operations on wallets, positions, trades, and settings. **Routes**: - `/api/wallets` — Wallet CRUD with Solana address validation - `/api/positions` — Read leader and follower positions - `/api/trades` — Read copy trade history (with status and error info) - `/api/settings` — Read/update worker settings (copy ratio, slippage, max size, auto-copy toggle) - `/api/health` — Health check returning wallet count and worker status ## Data Flow ### Copy Trade Lifecycle ``` 1. Leader wallet sends DLMM transaction on Solana ↓ 2. Monitor detects tx via WebSocket onLogs (confirmed) ↓ 3. Monitor fetches full tx → Parser decodes DLMM instructions ↓ 4. Tracker updates leader position state in DB ↓ 5. Executor checks if follower should copy: - Is auto_copy enabled? - Is there already a follower position? (skip duplicate adds) - Is there a follower position to modify? (for remove/close/rebalance) ↓ 6. Executor creates CopyTrade record (status: PENDING) ↓ 7. Executor calls DLMM SDK to mirror the operation ↓ 8. CopyTrade updated to SUCCESS or FAILED ``` ## Database Schema | Table | Purpose | |---|---| | `MonitoredWallet` | Wallets to watch (address, label, active flag) | | `LeaderPosition` | Leader's DLMM positions (pair, bins, status) | | `FollowerPosition` | Follower's mirrored positions (linked to leader) | | `CopyTrade` | Record of every copy attempt (action, status, tx sigs) | | `ActivityLog` | General activity logging (worker start/stop, errors) | ## Environment Configuration | Variable | Required | Default | Description | |---|---|---|---| | `RPC_ENDPOINT` | Yes | `https://api.mainnet-beta.solana.com` | Solana RPC URL | | `WS_ENDPOINT` | No | Derived from RPC | Solana WebSocket URL | | `FOLLOWER_PRIVATE_KEY` | Yes | — | Base58 private key of the follower wallet | | `DATABASE_URL` | Yes | `file:./dev.db` | SQLite database path | | `COPY_RATIO` | No | `1.0` | Amount scaling factor | | `MAX_POSITION_SIZE_SOL` | No | `10` | Maximum SOL per position | | `SLIPPAGE_BPS` | No | `100` | Slippage tolerance (basis points) | | `AUTO_COPY_ENABLED` | No | `true` | Enable/disable automatic copy trading |