Skip to content

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

ComponentRole
UpstreamBinance public WebSocket (btcusdt@miniTicker, ethusdt@miniTicker, bnbusdt@miniTicker). No API key.
Main streamLogical stream main. Subscribers receive every tick as-is.
ChannelsCreated 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.
BroadcastOn 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
ResourceURL
Docshttp://localhost:4000/docs
OpenAPIhttp://localhost:4000/openapi
WebSocketws://localhost:4000/ws
RESTGET /prices, GET /stats, `GET

REST API (Summary)

MethodPathDescription
GET/pricesLast price per symbol (snapshot).
GET/statsConnection, stream, subscription counts.
GET/channelsList all channels.
GET/channels/:idGet one channel.
POST/channelsCreate channel. Body: { "margins": { "BTCUSDT": 50, "ETHUSDT": 10 } }.
PATCH/channels/:idUpdate margins.
DELETE/channels/:idDelete 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" } with tick.price = main price + margin for that symbol.


Flow: Main vs Channel

  1. Upstream sends e.g. ETHUSDT last price 3500.00.
  2. 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.
  3. 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)

Star the repo on GitHub if this documentation is useful — link in the navbar above.