A full-stack cryptocurrency exchange platform with real-time order matching, live charts, and WebSocket depth updates. Currently supports SOL/USDC trading.
Frontend (Next.js :3002)
|
+-- REST API (Express :3000) ---> Redis Queue ---> Matching Engine
| |
+-- WebSocket (WS :3001) <--- Redis Pub/Sub <----------+
|
DB Processor ---> TimescaleDB (:5432)
DB Cron (materialized views)
Market Maker (bot)
| Service | Directory | Port | Description |
|---|---|---|---|
| Engine | engine/ |
- | Core order matching engine. Processes orders via Redis, manages orderbooks and user balances in-memory. Snapshots state to snapshot.json every 3s. |
| API | api/ |
3000 | REST API. Routes for orders, depth, trades, tickers, klines, and user balance. Communicates with the engine via Redis request/response. |
| WebSocket | ws/ |
3001 | WebSocket server. Subscribes to Redis pub/sub and pushes real-time depth, trade, and ticker updates to connected clients. |
| DB Processor | db/ |
- | Consumes TRADE_ADDED messages from Redis and inserts trade data into TimescaleDB (tata_prices table). |
| DB Cron | db/ |
- | Refreshes TimescaleDB materialized views (klines_1m, klines_1h, klines_1w) every 10 seconds for chart aggregation. |
| Frontend | frontend/ |
3002 | Next.js trading UI with TradingView charts, live order book, swap/order panel, and trade history. |
| Market Maker | mm/ |
- | Bot that continuously places buy/sell orders around the current price to provide liquidity. Uses userId "5". |
| Component | Port | Purpose |
|---|---|---|
| TimescaleDB | 5432 | Time-series database for trade/price data and kline aggregation |
| Redis | 6379 | Message queue (engine commands), pub/sub (real-time updates), request/response (API <-> Engine) |
- Node.js (v18+)
- Docker & Docker Compose (for TimescaleDB and Redis)
cd docker
docker-compose up -dThis starts TimescaleDB (port 5432) and Redis (port 6379).
Each service must be started in a separate terminal. Follow this order:
Engine (must start first):
cd engine
npm install
npm run build
# Linux/Mac:
WITH_SNAPSHOT=true node dist/index.js
# Windows (cmd):
set WITH_SNAPSHOT=true&& node dist/index.jsAPI:
cd api
npm install
npm run devWebSocket Server:
cd ws
npm install
npm run devDB Processor:
cd db
npm install
npm run devDB Cron (separate terminal from DB processor):
cd db
npm run refresh:viewsFrontend:
cd frontend
npm install
npx next dev -p 3002Market Maker (start last, after API is confirmed running):
cd mm
npm install
npm run devOpen http://localhost:3002 in your browser.
- Click on SOL_USDC in the Markets table to open the trading page.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/order |
Place a new order ({market, price, quantity, side, userId}) |
DELETE |
/api/v1/order |
Cancel an order ({orderId, market}) |
GET |
/api/v1/order/open |
Get open orders (?userId=5 or ?userId=5&market=SOL_USDC) |
GET |
/api/v1/depth |
Get order book depth (?symbol=SOL_USDC) |
GET |
/api/v1/trades |
Get recent trades (?symbol=SOL_USDC) |
GET |
/api/v1/tickers |
Get 24h ticker data for all markets |
GET |
/api/v1/klines |
Get candlestick data (?symbol=SOL_USDC&interval=1m&startTime=...&endTime=...) |
GET |
/api/v1/balance |
Get user balances (?userId=5) |
- Real-time order book with bid/ask depth visualization
- TradingView candlestick charts with 1m/1h/1w timeframes
- Market and Limit orders with instant fill feedback
- Live wallet balance updated after each trade
- Open Orders panel with cancel functionality (global across all markets)
- Trade History showing recent executed trades
- Market Maker bot for continuous liquidity
- Engine snapshots for state persistence across restarts
Exchange-Trading-System/
api/ # Express REST API
src/routes/ # order, depth, trades, ticker, kline, balance
db/ # Database processor + cron
src/seed-db.ts # Database schema setup
docker/ # Docker Compose for TimescaleDB + Redis
engine/ # Matching engine
src/trade/ # Engine.ts (core), Orderbook.ts (matching)
snapshot.json # Persisted engine state
frontend/ # Next.js frontend
app/components/ # SwapUI, Depth, TradeHistory, MarketBar, TradeView
app/utils/ # httpClient, SignalingManager, ChartManager
mm/ # Market maker bot
ws/ # WebSocket server
The system uses TimescaleDB with a tata_prices hypertable:
| Column | Type | Description |
|---|---|---|
time |
TIMESTAMPTZ |
Trade timestamp |
price |
DOUBLE PRECISION |
Trade price |
volume |
DOUBLE PRECISION |
Trade quantity |
currency_code |
VARCHAR |
Market symbol (e.g., SOL_USDC) |
Materialized views aggregate this into klines_1m, klines_1h, and klines_1w for chart data.
- All services use userId
"5"as the default user (hardcoded for development). - The engine persists state via
snapshot.json. UseWITH_SNAPSHOT=trueto restore on restart. - On Windows, use
set WITH_SNAPSHOT=true&&(no space before&&). - If hot reload doesn't work on the frontend, restart the frontend service.
- The market maker must start after the API is running or it will crash with
ECONNREFUSED.