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.
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)
| 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 |
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.
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.
Swap Parser (src/lib/helius/parseSwap.ts): Extracts SwapEvent from Helius parsed transaction response (events.swap field).
DB Writer (src/lib/db/writer.ts): Registers as batch parser listener, writes swap batches to SQLite transactionally. Prune job runs every 5 minutes.
SSE Endpoint (src/app/api/stream/route.ts): Streams real-time swaps to browser via Server-Sent Events. Supports AMM source filtering.
REST API (src/app/api/swaps/route.ts): Returns historical swaps from SQLite for selected timeframe (5m/30m/1h/12h/24h).
Client Store (src/lib/store.ts): Zustand store with swapBuffer, aggregation, graph nodes/links, timeframe/filter state.
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.
Graph Builder (src/lib/graph/graphBuilder.ts): Converts aggregated data to GraphNode[] + GraphLink[] with log-scale sizing, green/red coloring by net flow.
Force Graph Engine (src/components/ForceGraph/ForceGraphEngine.ts): D3 force simulation with Canvas rendering. SOL fixed at center. Supports zoom/pan/drag/click/hover.
src/
├── app/
│ ├── layout.tsx # Root layout, dark theme, Geist Mono font
│ ├── page.tsx # Renders <Dashboard />
│ ├── 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.