The Problem

Centralized exchanges need high‑throughput matching engines, reliable persistence, and a clean API layer. Existing solutions often mix languages or lack clear boundaries between matching logic, persistence, and the network surface. This repo offers a Rust‑centric codebase split into domain, engine, cache, gateway, and worker modules, aiming to isolate concerns while exposing a single HTTP/WebSocket API.

What This Does

The project exposes a REST/WebSocket server (see apps/api) that forwards requests to the gateway crate (packages/gateway/src/lib.rs). Matching logic lives in the engine crate (packages/engine/src/lib.rs), while order persistence is handled by cache (packages/cache/src/lib.rs). Background workers (packages/workers) perform tasks such as snapshotting and event logging. Docker files (infra/kafka, infra/postgres, infra/redis) provide a ready‑to‑run environment.

How It Is Wired

Entry point: bin/server/src/main.rs.

  • main.rs loads config.rs, creates a Tokio runtime, and calls spawner::spawn() to launch the API and background workers.
  • spawner::spawn() starts the gateway HTTP server and registers the workers runtime.
  • Incoming HTTP requests hit gateway::handlers which route to gateway::exchange, a thin façade over engine::exchange.
  • engine::exchange processes orders via engine::orderbook, emitting domain events (domain::events).
  • Domain events are pushed to Kafka by queue::kafka and cached in Redis by cache::lib.
  • The workers module listens to the Kafka topic, executing eg. snapshot_worker to persist state to Postgres (infra/postgres/Dockerfile).

The call chain is linear: main -> spawner -> gateway -> engine -> domain events -> queue -> workers -> DB. The most central file is engine::exchange, as changes here ripple to order validation, matching, and event emission.

How To Use It

Setup

# clone
git clone https://github.com/moses-y/cex
# install Rust toolchain
rustup component add rustfmt
# install Node dependencies for the API
cd apps/api && pnpm install

Configuration Create .env from .env.example. Required variables are listed there (e.g., REDIS_URL, KAFKA_BOOTSTRAP_SERVERS, POSTGRES_URL).

Running

# start services
docker compose up -d
# launch the Rust server
cargo run --manifest-path bin/server/Cargo.toml
# API is reachable at http://localhost:3000

Real‑World Use

A trading firm can spin up the stack locally, publish orders via the API, and observe matching in real time. The gateway::handlers expose endpoints like /orders and /books. A quick example:

// Node client
import axios from 'axios';
await axios.post('http://localhost:3000/orders', {
  symbol: 'BTCUSD',
  side: 'buy',
  qty: 1,
  price: 50000
});

The order travels through the Rust engine, updates the in‑memory orderbook, and persists a snapshot after every batch.

Code Health & Issues

  • Medium – No test files detected – the repository contains no tests/ directories or #[test] annotations.
  • Medium – No CI/CD pipeline – no .github/ or CI config files.
  • Medium – No LICENSE file – usage rights are unclear.
  • Low – No documentation for API endpoints beyond the README; detailed contracts are missing.

The Bottom Line

The repo offers a modular, Rust‑based exchange skeleton with Docker‑ready infrastructure. It is a solid starting point for teams that can fill in tests, CI, and documentation. Without those, the codebase is difficult to ship or maintain at scale.