# AGENTS.md - Solana Swap Flow ## Project Overview Real-time Solana DEX swap flow visualization dashboard. Displays a force-directed network graph showing token trading flows across Solana DEXes (Pump, Raydium, Meteora, Orca, Jupiter), powered by Helius API. ## Architecture ``` Helius WebSocket (logsSubscribe for 9 DEX programs) → Collect tx signatures from logsNotification → Batch parse via Helius Enhanced Transactions API (100/batch, 3 concurrent, every 1.5s) → Extract SwapEvent { signature, timestamp, source, tokenIn, tokenOut } → Emit to listeners: ├── SSE endpoint → browser EventSource → Zustand store → D3 force graph └── DB writer → SQLite (swaps.db, 24h retention) ``` ## Tech Stack | Technology | Purpose | |---|---| | Next.js 16 (App Router) + TypeScript | Framework | | D3.js (d3-force) + Canvas | Force-directed network graph rendering | | Tailwind CSS v4 | Dark theme styling | | Zustand | Client state management | | better-sqlite3 | Persistent swap storage (24h retention) | | ws | Server-side WebSocket to Helius RPC | | lru-cache | Token metadata caching | ## Key Data Flow 1. **WebSocket** (`src/lib/helius/websocket.ts`): Connects to Helius RPC, subscribes to DEX program logs, collects transaction signatures. Includes ping/pong heartbeat (30s) and 60s silence auto-reconnect. 2. **Batch Parser** (`src/lib/helius/batchParser.ts`): Queues signatures, processes 3x100 batches every 1.5s via Helius Enhanced Transactions REST API. Caps pending queue at 3000. 3. **Swap Parser** (`src/lib/helius/parseSwap.ts`): Extracts SwapEvent from Helius parsed transaction response (events.swap field). 4. **DB Writer** (`src/lib/db/writer.ts`): Registers as batch parser listener, writes swap batches to SQLite transactionally. Prune job runs every 5 minutes. 5. **SSE Endpoint** (`src/app/api/stream/route.ts`): Streams real-time swaps to browser via Server-Sent Events. Supports AMM source filtering. 6. **REST API** (`src/app/api/swaps/route.ts`): Returns historical swaps from SQLite for selected timeframe (5m/30m/1h/12h/24h). 7. **Client Store** (`src/lib/store.ts`): Zustand store with swapBuffer, aggregation, graph nodes/links, timeframe/filter state. 8. **Aggregator** (`src/lib/graph/aggregator.ts`): Rolling window aggregation. Computes per-token inflow/outflow/netFlow, top pairs by volume. Limits graph to top 100 tokens by volume. 9. **Graph Builder** (`src/lib/graph/graphBuilder.ts`): Converts aggregated data to GraphNode[] + GraphLink[] with log-scale sizing, green/red coloring by net flow. 10. **Force Graph Engine** (`src/components/ForceGraph/ForceGraphEngine.ts`): D3 force simulation with Canvas rendering. SOL fixed at center. Supports zoom/pan/drag/click/hover. ## Project Structure ``` src/ ├── app/ │ ├── layout.tsx # Root layout, dark theme, Geist Mono font │ ├── page.tsx # Renders │ ├── globals.css # Tailwind v4 CSS config │ └── api/ │ ├── stream/route.ts # SSE endpoint (real-time swaps) │ ├── swaps/route.ts # REST endpoint (historical from SQLite) │ └── token/route.ts # Token metadata (Helius DAS API) ├── components/ │ ├── Dashboard.tsx # Main layout + historical fetch effect │ ├── Header.tsx # Status, stats, timeframe selector │ ├── TimeframeSelector.tsx # 5m/30m/1h/12h/24h buttons │ ├── AMMFilter.tsx # Pump/Raydium/Meteora/Orca/Jupiter toggle │ ├── ForceGraph/ │ │ ├── ForceGraph.tsx # React canvas wrapper │ │ └── ForceGraphEngine.ts # D3 force simulation + Canvas render │ └── Sidebar/ │ ├── TopPairs.tsx # Top 30 trading pairs by volume │ └── TokenDetail.tsx # Token info card on click ├── hooks/ │ ├── useSwapStream.ts # Client SSE hook + auto metadata fetch │ └── useTokenMetadata.ts # Single token metadata fetch └── lib/ ├── store.ts # Zustand store ├── timeframes.ts # Timeframe type + config ├── utils.ts # Formatters ├── db/ │ ├── index.ts # SQLite singleton (WAL mode, prepared stmts) │ └── writer.ts # Batch parser → DB writer ├── graph/ │ ├── aggregator.ts # Rolling window aggregation (top 100 tokens) │ └── graphBuilder.ts # Aggregated data → graph nodes/links └── helius/ ├── constants.ts # DEX program IDs, API URLs, known tokens ├── websocket.ts # Helius WebSocket (logsSubscribe) ├── batchParser.ts # Batch signature parser ├── parseSwap.ts # Helius tx → SwapEvent └── tokenMetadata.ts # DAS API getAsset + LRU cache ## Environment Variables - `HELIUS_API_KEY` — Required. Helius API key for WebSocket and REST API access. ## Development ```bash npm install cp .env.example .env.local # Set HELIUS_API_KEY npm run dev # Starts on port 3456 ``` ## Important Patterns - **globalThis singleton**: `websocket.ts`, `batchParser.ts`, `db/index.ts` all use `globalThis` to persist state across Next.js HMR reloads. - **Canvas rendering**: D3 force graph uses HTML Canvas (not SVG) for performance with 100+ nodes. - **Top 100 filter**: Aggregator limits displayed tokens to top 100 by total volume. SOL always included. - **WAL mode SQLite**: Allows concurrent reads (REST API) while writes (batch parser) happen. ```