Price Feed Gateway Example
A Micro Socket–style gateway that consumes a live Bitcoin/crypto price feed (Binance WebSocket) and exposes:
- Main socket: Raw price stream (single source of truth).
- Sub sockets (channels): Each channel applies per-symbol margins (spread) to the main feed; different clients can subscribe to different channels and receive different prices (e.g. raw vs. ETH+10, BTC+50).
Overview
| Component | Role |
|---|---|
| Upstream | Binance public WebSocket (btcusdt@miniTicker, ethusdt@miniTicker, bnbusdt@miniTicker). No API key. |
| Main stream | Logical stream main. Subscribers receive every tick as-is. |
| Channels | Created via REST (POST /channels with margins). Each channel has an id and a map of symbol → margin (e.g. ETHUSDT: 10). Subscribers of channel:<id> receive ticks with price + margin for that symbol. |
| Broadcast | On each upstream tick: send raw to main; for each channel, compute adjusted price and send to channel:<id>. |
So: one feed, one main stream, many channel streams; each client sees either raw or margin-adjusted prices depending on what they subscribe to.
Run the Example
bash
cd examples/price-feed-gateway
bun install
bun run dev| Resource | URL |
|---|---|
| Docs | http://localhost:4000/docs |
| OpenAPI | http://localhost:4000/openapi |
| WebSocket | ws://localhost:4000/ws |
| REST | GET /prices, GET /stats, `GET |
REST API (Summary)
| Method | Path | Description |
|---|---|---|
| GET | /prices | Last price per symbol (snapshot). |
| GET | /stats | Connection, stream, subscription counts. |
| GET | /channels | List all channels. |
| GET | /channels/:id | Get one channel. |
| POST | /channels | Create channel. Body: { "margins": { "BTCUSDT": 50, "ETHUSDT": 10 } }. |
| PATCH | /channels/:id | Update margins. |
| DELETE | /channels/:id | Delete channel. |
WebSocket Protocol
Connect to ws://localhost:4000/ws, then send one subscribe message:
Main (raw):
{ "type": "subscribe", "stream": "main" }
You receive:{ "stream": "main", "tick": { "symbol", "price", "priceNum", "eventTime", ... }, "at": "ISO8601" }.Channel (adjusted):
{ "type": "subscribe", "stream": "channel", "channelId": "<uuid>" }
You receive:{ "stream": "channel", "channelId": "<id>", "tick": { ... }, "margin": <number>, "at": "ISO8601" }withtick.price= main price + margin for that symbol.
Flow: Main vs Channel
- Upstream sends e.g. ETHUSDT last price 3500.00.
- Gateway updates price store and broadcasts:
- To main subscribers:
tick.price = "3500.00". - To channel:X subscribers (if channel X has
margins.ETHUSDT = 10):tick.price = "3510.00",margin = 10.
- To main subscribers:
- So the same feed drives both the main socket and all sub sockets; only the applied margin differs per channel.
Project Layout
examples/price-feed-gateway/
src/
index.ts - Elysia: REST, WS /ws, /docs
config.ts - PORT, BINANCE_WS_URL
feed-client.ts - Binance WSS, normalize, price-store + broadcastTick
price-store.ts - Last price per symbol
channels.ts - Channel CRUD
stream-store.ts - main + channel:<id> subscribers; broadcastTick
types.ts - PriceTick, Channel, payloads
docs-html.ts - /docs page
README.md - Full documentation (English)Related
- Elysia Example — Generic Micro Socket gateway.
- Sub-Socket Model — Scale unit and broadcast model.
- Architecture — Diagrams and data flow.