High-performance order matching engine for Mantis Exchange, written in Rust.
- Price-time priority matching — BTreeMap for price levels, VecDeque for FIFO within each level
- Order types — Limit, Market
- Time-in-force — GTC (Good 'Til Cancelled), IOC (Immediate or Cancel), FOK (Fill or Kill)
- Multi-symbol — Independent order book per trading pair, single-threaded per symbol (no lock contention)
- gRPC API — SubmitOrder, CancelOrder, GetDepth, StreamTrades (via tonic)
- Write-Ahead Log — Crash recovery with WAL replay on startup
- Zero floating point —
rust_decimalfor precise decimal arithmetic - No database in hot path — Pure in-memory matching, WAL for durability
| Benchmark | Result |
|---|---|
| Insert 1,000 limit orders | ~1.2ms (~820K orders/sec) |
| Match against 100 price levels | ~118µs |
Measured on Apple Silicon. Run cargo bench to reproduce.
┌──────────────────────────────────────────────┐
│ Engine │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ OrderBook │ │ OrderBook │ ... │
│ │ BTC-USDT │ │ ETH-USDT │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │ Asks │ │ │ │ Asks │ │ │
│ │ │BTreeMap│ │ │ │BTreeMap│ │ │
│ │ └───────┘ │ │ └───────┘ │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │ Bids │ │ │ │ Bids │ │ │
│ │ │BTreeMap│ │ │ │BTreeMap│ │ │
│ │ └───────┘ │ │ └───────┘ │ │
│ └─────────────┘ └─────────────┘ │
│ │ │
│ ┌────▼────┐ │
│ │ WAL │ Write-ahead log for recovery │
│ └─────────┘ │
└──────────────────────┬───────────────────────┘
│ gRPC (port 50051)
▼
mantis-gateway
graph TD
Client([Client]) -->|REST / WebSocket| GW[mantis-gateway]
GW -->|gRPC| ME[mantis-matching-engine]
GW -->|gRPC| OS[mantis-order]
OS -->|gRPC| ME
ME -->|Trade Events| K[(Kafka)]
K --> MD[mantis-market-data]
K --> OS
OS -->|HTTP| AC[mantis-account]
subgraph mantis-matching-engine
direction TB
GRPC[gRPC Server :50051] --> ENG[Engine]
ENG --> OB1[OrderBook\nBTC-USDT]
ENG --> OB2[OrderBook\nETH-USDT]
ENG --> WAL[Write-Ahead Log]
OB1 --- ASKS1[Asks - BTreeMap]
OB1 --- BIDS1[Bids - BTreeMap]
end
style ME fill:#e94560,color:#fff,stroke:#333
style GW fill:#1e2329,color:#eee,stroke:#555
style OS fill:#1e2329,color:#eee,stroke:#555
style AC fill:#1e2329,color:#eee,stroke:#555
style MD fill:#1e2329,color:#eee,stroke:#555
sequenceDiagram
participant C as Client
participant G as Gateway
participant E as Engine
participant W as WAL
participant K as Kafka
C->>G: POST /api/v1/orders
G->>E: gRPC SubmitOrder
E->>W: Write WAL entry
E->>E: Match against OrderBook
alt Has match
E-->>K: Publish Trade event
E-->>G: Order FILLED + Trades
else No match (limit order)
E->>E: Rest on OrderBook
E-->>G: Order NEW
end
G-->>C: JSON response
| File | Description |
|---|---|
src/types.rs |
Core types: Order, Trade, Side, OrderType, TimeInForce, OrderStatus |
src/orderbook.rs |
OrderBook — per-symbol matching with price-time priority |
src/engine.rs |
Engine — multi-symbol manager, command/event pattern, WAL integration |
src/wal.rs |
Write-ahead log: WalWriter, WalReader, WalEntry |
src/grpc.rs |
gRPC service: SubmitOrder, CancelOrder, GetDepth, StreamTrades |
src/main.rs |
Entry point — WAL recovery, gRPC server on 0.0.0.0:50051 |
- Rust (nightly or stable, edition 2024)
- protoc (
brew install protobufon macOS) - mantis-common proto files (cloned as sibling directory)
git clone https://github.com/mantis-exchange/mantis-matching-engine.git
git clone https://github.com/mantis-exchange/mantis-common.git
cd mantis-matching-engine
cargo build --release
cargo test
cargo bench
# Run the gRPC server
./target/release/mantis-matching-engine
# Listening on 0.0.0.0:50051# From parent directory (needs mantis-common for proto files)
docker build -f mantis-matching-engine/Dockerfile -t mantis-engine .
docker run -p 50051:50051 mantis-enginegRPC (protobuf definitions in mantis-common)
service MatchingEngine {
rpc SubmitOrder(SubmitOrderRequest) returns (SubmitOrderResponse);
rpc CancelOrder(CancelOrderRequest) returns (CancelOrderResponse);
rpc GetDepth(GetDepthRequest) returns (GetDepthResponse);
rpc StreamTrades(StreamTradesRequest) returns (stream TradeEvent);
}curl -X POST http://localhost:8080/api/v1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"symbol": "BTC-USDT",
"side": "buy",
"type": "limit",
"price": "50000",
"qty": "1.5",
"time_in_force": "GTC"
}'$ cargo test
running 21 tests
test engine::tests::test_engine_full_flow ... ok
test engine::tests::test_engine_multi_symbol ... ok
test engine::tests::test_engine_recover_empty_wal ... ok
test engine::tests::test_engine_unknown_symbol ... ok
test engine::tests::test_engine_wal_with_cancel ... ok
test engine::tests::test_engine_wal_write_and_recover ... ok
test orderbook::tests::test_cancel_order ... ok
test orderbook::tests::test_depth ... ok
test orderbook::tests::test_exact_match ... ok
test orderbook::tests::test_fok_insufficient_liquidity ... ok
test orderbook::tests::test_ioc_cancel_remaining ... ok
test orderbook::tests::test_limit_order_rests_on_book ... ok
test orderbook::tests::test_market_order ... ok
test orderbook::tests::test_partial_fill ... ok
test orderbook::tests::test_price_time_priority ... ok
test orderbook::tests::test_spread ... ok
test wal::tests::test_append_after_reopen ... ok
test wal::tests::test_empty_wal ... ok
test wal::tests::test_truncate ... ok
test wal::tests::test_wal_exists ... ok
test wal::tests::test_write_and_read_entries ... ok
test result: ok. 21 passed; 0 failed
This is the core matching engine of Mantis Exchange — a cryptocurrency exchange built with Rust, Go, and React.
| Service | Language | Description |
|---|---|---|
| mantis-matching-engine | Rust | Order matching (this repo) |
| mantis-gateway | Go | REST + WebSocket API gateway |
| mantis-order | Go | Order lifecycle management |
| mantis-account | Go | User auth, JWT, balance management |
| mantis-market-data | Go | K-line aggregation, market data |
| mantis-wallet | Go | Deposit/withdrawal, chain integration |
| mantis-risk | Go | Risk control, circuit breaker |
| mantis-web | React/TS | Trading UI |
| mantis-admin | React/TS | Admin dashboard |
MIT