# CLAUDE.md ## Project Overview LFJ Liquidity Book LP Auto-Rebalancer for Monad mainnet. Provides narrow-range concentrated liquidity for MON/USDC pair on LFJ DEX, auto-rebalances when price moves out of range. ## Tech Stack - **Framework**: Next.js 16 (App Router, standalone output) - **Language**: TypeScript (ES2020 target) - **Chain**: viem (Monad mainnet, chain ID 143) - **Database**: SQLite via better-sqlite3 (WAL mode) - **UI**: Tailwind CSS v4 + shadcn/ui (base-ui) - **Real-time**: Server-Sent Events (SSE) - **Package manager**: pnpm ## Code Style - Prettier: single quotes, no semicolons, 100 print width, trailing commas, 2-space indent - Config: `.prettierrc` at project root - Format: `pnpm prettier --write "src/**/*.{ts,tsx}"` ## Architecture ``` src/ lib/ config.ts — env-based config, BotConfig interface, constants chain/ client.ts — viem public/wallet clients, Monad chain definition abi.ts — LB_PAIR_ABI, LB_ROUTER_ABI, ERC20_ABI pair.ts — LBPair read helpers (getActiveId, bins, price) router.ts — LBRouter write helpers (add/remove liquidity, swap) balances.ts — wallet balance queries (MON native, USDC ERC20) liquidity.ts — high-level orchestrators (openPosition, closePosition, rebalanceSwap) engine/ engine.ts — RebalancerEngine singleton (while-loop, not setInterval) types.ts — EngineStatus, EngineState, RebalanceResult db/ index.ts — SQLite singleton schema.ts — table definitions (rebalance_log, current_position, rewards_log, engine_state) queries.ts — prepared statement CRUD (logRebalance uses null-defaulted params) notifications/ index.ts — Bark/Ntfy/Pushover dispatcher app/ page.tsx — Dashboard (SSE real-time status) config/page.tsx — Engine control + strategy settings history/page.tsx — Rebalance history table api/ status/route.ts — SSE endpoint (ReadableStream) control/route.ts — POST start/pause/stop config/route.ts — GET current strategy config emergency/route.ts — POST emergency withdraw history/route.ts — GET paginated rebalance_log rewards/route.ts — GET rewards history hooks/ useEngineStatus.ts — EventSource SSE hook ``` ## Key Design Decisions - **tokenX = WMON (18 decimals), tokenY = USDC (6 decimals)** — confirmed on-chain - **Price formula needs decimal adjustment**: `rawPrice * 10^(18-6)` to get human-readable USDC/MON - **addLiquidityNATIVE**: msg.value = amountX (MON), contract auto-wraps to WMON - **removeLiquidityNATIVE**: token param = USDC address (not WMON) - **Single-sided liquidity supported**: if user only has MON or USDC, allocates what's available - **Engine uses sequential while-loop**: not setInterval, prevents concurrent poll cycles - **Error cooldown 30s**: prevents spam on failures - **better-sqlite3 named params**: all keys must exist (use null, not undefined) - **Distribution calc**: divide PRECISION by count of eligible bins per side (not total bins) ## Confirmed Contract Addresses (Monad Mainnet) | Contract | Address | |----------|---------| | LBRouter V2.2 | 0x18556DA13313f3532c54711497A8FedAC273220E | | LBPair (MON/USDC) | 0x5afd3ec861f6104af26e8755abcc1f876de77620 | | WMON | 0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A | | USDC | 0x754704bc059f8c67012fed69bc8a327a5aafb603 | | BinStep | 5 (0.05% per bin) | ## Common Commands ```bash pnpm dev # development server pnpm build # production build pnpm start # production server pnpm prettier --write "src/**/*.{ts,tsx}" # format code ``` ## Known Issues / Gotchas - External drive (Lexar) creates macOS `._*` resource fork files — added to .gitignore - Monad chain ID is **143** (mainnet), not 10143 (testnet) - `Hooks__CallFailed (0x6c93cb9b)` revert happens when amounts are heavily imbalanced - Gas reserve: 0.5 MON held back from position to cover tx fees