Real-time arbitrage engine for Iranian cryptocurrency exchanges.
Three independently buildable projects in one repository: an async Rust
engine that streams live prices from exchange WebSockets into Kafka and a
real-time WS feed, a CLI (sc) to control it, and a Dioxus web UI to watch
it.
Each exchange adapter parses its own WebSocket stream into a common Price
type. Every tick is published to Kafka (for downstream arbitrage detection)
and broadcast over WebSocket to connected clients at the same time. The CLI
and UI both talk to the same REST control plane to start/stop/list tickers.
See ARCHITECTURE.md for the full data-flow diagram.
stream-coin/
├── engine/ # the server — actix-web, exchange adapters, Postgres, Kafka, Redis, WS feed
├── cli/ # `sc` — controls the engine over REST, zero dependency on engine
└── ui/ # Dioxus SPA — shared core + a web launcher, consumes the WS feed
Persistent state (users, exchanges/pairs, candles, strategies, orders, subscriptions) lives in PostgreSQL; Redis is an optional ticker cache, and Kafka carries the price/candle/signal streams for downstream processing.
| Exchange | Price feed (WS) | Order placement |
|---|---|---|
| Tabdeal | ✅ | ✅ |
| Hitobit | ✅ | ✅ |
| CoinEx | ✅ (seeded disabled) | — |
| Exir | — | ✅ |
New price feeds are added by implementing one trait (ExchangeAdapter); new
order venues implement OrderAdapter. Nothing else in the engine changes.
Infra (Postgres, Redis, Kafka, Kafka UI):
cp .env.example .env # fill in passwords (POSTGRES_PASSWORD is required)
docker compose up -dThe engine applies its SQL migrations to Postgres automatically on startup.
Engine:
just run # cargo run --bin stream-coinCLI:
just sc auth login # authenticate first (saves a token)
just sc ticker start tabdeal USDT/IRT # exchange and pair are positional
just sc ticker listUI (dev server with hot reload):
just ui-devThis project uses just as its task runner.
just check # fmt + clippy -D warnings + unit tests + integration tests
just test # unit tests only
just sc --helpThe ui/ workspace has its own test/lint targets: cd ui && just ui-test /
ui-lint.
Tagged pushes (vX.Y.Z) trigger a CI pipeline that builds and publishes,
independently: the engine (stream-coin, tar/deb/rpm/msi/AppImage + Docker
image), the CLI (sc, tar/deb/rpm), and the web UI (static bundle) — see
Releases.
Outstanding standardization work is tracked in ROADMAP.md.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) just checkbefore opening a PR- Open a Pull Request
GPL-3.0 — see LICENSE.