Cryptocurrency Exchange API

Open Source Project

Node.js
Express
PostgreSQL
Redis
WebSocket
Docker
Kubernetes

Project Overview

A high-performance, enterprise-grade REST API for cryptocurrency trading operations. Built with Node.js and designed to handle thousands of concurrent users with sub-millisecond response times. Features real-time WebSocket connections, advanced order matching, and comprehensive trading functionality.

The API supports spot trading, margin trading, futures contracts, and advanced order types. It includes robust security measures, rate limiting, and comprehensive monitoring. The system is designed for horizontal scaling and can handle millions of orders per day.

System Architecture

Microservices Architecture


β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Load Balancer β”‚    β”‚   API Gateway   β”‚    β”‚   Auth Service  β”‚
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β”‚  β€’ Nginx        │◄──►│  β€’ Rate Limiting│◄──►│  β€’ JWT Tokens   β”‚
β”‚  β€’ SSL Term.    β”‚    β”‚  β€’ Routing      β”‚    β”‚  β€’ 2FA          β”‚
β”‚  β€’ Health Check β”‚    β”‚  β€’ Validation   β”‚    β”‚  β€’ Permissions  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                        β”‚                        β”‚
         β–Ό                        β–Ό                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Trading Engine β”‚    β”‚  Market Data    β”‚    β”‚  User Service   β”‚
β”‚                 β”‚    β”‚                 β”‚    β”‚  β€’ Profiles     β”‚
β”‚  β€’ Order Match  β”‚    β”‚  β€’ Price Feeds  β”‚    β”‚  β€’ KYC/AML      β”‚
β”‚  β€’ Risk Mgmt    β”‚    β”‚  β€’ Candlesticks β”‚    β”‚  β€’ Wallets      β”‚
β”‚  β€’ Settlement   β”‚    β”‚  β€’ Order Books  β”‚    β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                        β”‚                        β”‚
         β–Ό                        β–Ό                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   PostgreSQL    β”‚    β”‚     Redis       β”‚    β”‚   Message Queue β”‚
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β”‚  β€’ Orders       β”‚    β”‚  β€’ Sessions     β”‚    β”‚  β€’ RabbitMQ     β”‚
β”‚  β€’ Trades       β”‚    β”‚  β€’ Cache        β”‚    β”‚  β€’ Event Stream β”‚
β”‚  β€’ Balances     β”‚    β”‚  β€’ Rate Limits  β”‚    β”‚  β€’ Notificationsβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            

Core Services

  • β€’ Trading Engine: Order matching and execution
  • β€’ Market Data: Real-time price feeds and charts
  • β€’ User Service: Account management and KYC
  • β€’ Wallet Service: Cryptocurrency deposits/withdrawals

Infrastructure

  • β€’ Kubernetes: Container orchestration
  • β€’ Docker: Containerized services
  • β€’ Prometheus: Metrics and monitoring
  • β€’ Grafana: Dashboards and alerting

Data Layer

  • β€’ PostgreSQL: Primary database with replication
  • β€’ Redis: Caching and session storage
  • β€’ InfluxDB: Time-series market data
  • β€’ Elasticsearch: Logging and search

API Endpoints

Trading Endpoints

POST/api/v1/orders
Place new order
GET/api/v1/orders
Get user orders
DELETE/api/v1/orders/:id
Cancel order

Market Data Endpoints

GET/api/v1/ticker/:symbol
24hr ticker statistics
GET/api/v1/orderbook/:symbol
Order book depth
GET/api/v1/klines/:symbol
Candlestick data

Performance Metrics

<1ms
Average Response Time
10K+
Requests/Second
99.99%
Uptime SLA
1M+
Orders/Day

Code Examples

Order Matching Engine

class OrderMatchingEngine {
  constructor() {
    this.buyOrders = new PriorityQueue((a, b) => b.price - a.price);
    this.sellOrders = new PriorityQueue((a, b) => a.price - b.price);
  }

  async processOrder(order) {
    const oppositeBook = order.side === 'buy' ? this.sellOrders : this.buyOrders;
    const matches = [];

    while (!oppositeBook.isEmpty() && order.quantity > 0) {
      const topOrder = oppositeBook.peek();
      
      if (!this.canMatch(order, topOrder)) break;
      
      const matchQuantity = Math.min(order.quantity, topOrder.quantity);
      const matchPrice = topOrder.price;
      
      // Create trade
      const trade = await this.createTrade({
        buyOrderId: order.side === 'buy' ? order.id : topOrder.id,
        sellOrderId: order.side === 'sell' ? order.id : topOrder.id,
        quantity: matchQuantity,
        price: matchPrice
      });
      
      matches.push(trade);
      
      // Update quantities
      order.quantity -= matchQuantity;
      topOrder.quantity -= matchQuantity;
      
      if (topOrder.quantity === 0) {
        oppositeBook.poll();
      }
    }
    
    // Add remaining quantity to order book
    if (order.quantity > 0) {
      const orderBook = order.side === 'buy' ? this.buyOrders : this.sellOrders;
      orderBook.offer(order);
    }
    
    return matches;
  }
}

WebSocket Real-time Updates

const WebSocket = require('ws');
const Redis = require('redis');

class MarketDataStreamer {
  constructor() {
    this.wss = new WebSocket.Server({ port: 8080 });
    this.redis = Redis.createClient();
    this.subscriptions = new Map();
  }

  start() {
    this.wss.on('connection', (ws) => {
      ws.on('message', (message) => {
        const { action, symbol } = JSON.parse(message);
        
        if (action === 'subscribe') {
          this.subscribe(ws, symbol);
        } else if (action === 'unsubscribe') {
          this.unsubscribe(ws, symbol);
        }
      });
      
      ws.on('close', () => {
        this.cleanup(ws);
      });
    });
    
    // Listen for trade updates from Redis
    this.redis.subscribe('trades', 'orderbook', 'ticker');
    this.redis.on('message', (channel, data) => {
      this.broadcast(channel, JSON.parse(data));
    });
  }

  subscribe(ws, symbol) {
    if (!this.subscriptions.has(symbol)) {
      this.subscriptions.set(symbol, new Set());
    }
    this.subscriptions.get(symbol).add(ws);
    
    // Send initial data
    this.sendInitialData(ws, symbol);
  }

  broadcast(channel, data) {
    const symbol = data.symbol;
    const subscribers = this.subscriptions.get(symbol);
    
    if (subscribers) {
      const message = JSON.stringify({ channel, data });
      subscribers.forEach(ws => {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(message);
        }
      });
    }
  }
}