Template arsitektur microservices untuk Centralized Crypto Exchange (CEX) dengan Laravel Octane (FrankenPHP), PostgreSQL, Redis, Blockchain Worker, dan gRPC Inter-service Communication (C++, Node.js, Laravel).
┌────────────────────────────────────────────────────────────────────────┐
│ CLIENT │
│ Web UI / Mobile Apps (REST & WebSocket) │
└──────────────────┬───────────────────────────────▲─────────────────────┘
│ HTTP / REST │ WSS (Orderbook/Ticker)
▼ │
┌──────────────────────┐ ┌───────────────────────┐
│ Laravel Octane API │ │ Node.js Realtime GW │
│ (Port 8000) │ │ (WebSocket 3001) │
└──────────┬───────────┘ └──────────▲────────────┘
│ │
┌──────────┴───────────────────────────────┴────────────┐
│ gRPC & Redis Pub/Sub │
└──────▲───────────────────────▲─────────────────▲──────┘
│ gRPC │ │ gRPC / Events
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ C++ Matching │ │ Redis 7 Cluster │ │Blockchain Worker │
│ Engine │ │ (Cache & Streams)│ │ (Deposit/Sweeper)│
│ (Port 50051) │ └────────▲─────────┘ │ (Port 50052) │
└─────────┬────────┘ │ └─────────┬────────┘
│ │ │
└──────────────┐ │ ┌──────────────┘
▼ ▼ ▼
┌───────────────────────────┐
│ PostgreSQL 16 Database │
│ (Ledger, Balance, Users) │
└───────────────────────────┘
.
├── docker-compose.yml # Definisi service container
├── .env.example # Template konfigurasi environment
├── proto/ # Shared gRPC Protobuf definitions
│ └── exchange.proto # Schema order matching & blockchain RPC
├── services/
│ ├── laravel-api/ # Core REST API (Laravel Octane FrankenPHP)
│ │ └── Dockerfile
│ ├── blockchain-worker/ # EVM / BTC Scanner & Withdrawal Service
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ └── src/index.js
│ ├── matching-engine/ # (Future) C++ Low-Latency Orderbook Engine
│ └── realtime-gateway/ # (Future) Node.js / Go WebSocket Server
└── README.md
Salin file .env.example ke .env:
cp .env.example .envJika Anda belum memiliki file Laravel di services/laravel-api/:
- Buat project Laravel baru di direktori tersebut:
composer create-project laravel/laravel services/laravel-api
- Salin
Dockerfilekembali keservices/laravel-api/Dockerfilejika tertimpa. - Install Laravel Octane di dalam project Laravel:
cd services/laravel-api composer require laravel/octane php artisan octane:install --server=frankenphp cd ../..
Build dan jalankan seluruh container di background:
docker compose up -d --buildPeriksa status container:
docker compose psLihat log container:
docker compose logs -fSemua service terhubung dalam satu docker network (cex_network), sehingga bisa berkomunikasi menggunakan internal DNS:
matching-engine:50051(C++)blockchain-worker:50052(Node.js)laravel-api:8000(Laravel)redis:6379postgres:5432
File kontrak gRPC tersimpan di ./proto/exchange.proto.
Dockerfile laravel-api sudah dilengkapi compiler protobuf-compiler dan extension grpc + protobuf.
Untuk meng-generate class PHP dari proto:
docker compose exec laravel-api protoc \
--proto_path=/app/proto \
--php_out=/app/app/Grpc \
--grpc_out=/app/app/Grpc \
--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \
/app/proto/exchange.protoLalu tambahkan package gRPC di Laravel:
docker compose exec laravel-api composer require grpc/grpc google/protobufBuat client gRPC di Laravel:
use App\Grpc\Exchange\MatchingEngineServiceClient;
use App\Grpc\Exchange\OrderRequest;
use Grpc\ChannelCredentials;
$client = new MatchingEngineServiceClient(
env('MATCHING_ENGINE_GRPC_HOST', 'matching-engine:50051'),
['credentials' => ChannelCredentials::createInsecure()]
);
$request = new OrderRequest([
'order_id' => (string) Str::uuid(),
'user_id' => auth()->id(),
'symbol' => 'BTC_USDT',
'side' => 'BUY',
'order_type' => 'LIMIT',
'price' => '65000.50',
'quantity' => '0.25',
'timestamp' => now()->getTimestampMs(),
]);
[$response, $status] = $client->PlaceOrder($request)->wait();JANGAN PERNAH menggunakan tipe data
floatataudoubleuntuk balance, harga, atau order kripto karena risiko floating point precision error.
- Di Database (PostgreSQL): Gunakan
NUMERIC(36, 18)(36 digit total, 18 digit desimal). - Di Laravel (PHP): Gunakan fungsi bawaan
bcmath(bcadd,bcsub,bcmul,bcdiv,bccomp) atau package sepertibrick/math. - Di gRPC: Kirim harga dan kuantitas dalam format string atau fixed-point integer (misal satuan Satoshi / Wei).
Seluruh transaksi saldo (deposit, withdrawal, trading, fee, lock/freeze order) harus dicatat dengan prinsip double-entry ledger:
- Saldo akun adalah hasil agregasi (SUM) dari riwayat mutasi jurnal, bukan sekadar mengedit field
balancelangsung di database. - Terapkan database locking (
SELECT ... FOR UPDATE) atau optimistic locking jika memutasi saldo.
- Matching Engine harus berjalan 100% in-memory (menggunakan Red-Black Tree / B-Tree atau SkipList) untuk mencapai throughput > 100.000 trades/detik.
- State matching engine di-backup secara real-time via event log / journal ke Redis Streams atau Kafka.
- Deposit: Scan block header baru dari RPC node, filter transaksi ke address deposit user. Berikan status
CONFIRMING(misal 12 konfirmasi) sebelum mengkredit balance ke akun user. - Cold/Hot Wallet: Pisahkan dana:
- Hot Wallet (5-10% dana): Terhubung ke Blockchain Worker otomatis untuk melayani withdrawal kecil.
- Cold Wallet (90-95% dana): Disimpan offline (Multisig / Hardware Security Module) untuk keamanan dari ancaman eksploitasi.
| Aksi | Perintah |
|---|---|
| Menjalankan semua service | docker compose up -d |
| Mematikan semua service | docker compose down |
| Melihat status service | docker compose ps |
| Masuk ke shell Laravel | docker compose exec laravel-api bash |
| Jalankan Artisan Laravel | docker compose exec laravel-api php artisan <command> |
| Masuk ke Redis CLI | docker compose exec redis redis-cli -a secretredis |
| Masuk ke PostgreSQL CLI | docker compose exec postgres psql -U cex_user -d cex_db |