CLAUDE.md 4.0 KB

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

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