Real-time trade feed client for Polymarket (RTDS — Real-Time Data Socket).
Connects to wss://ws-live-data.polymarket.com and forwards every trade
on Polymarket to a callback PID as
{:polymarket_rtds, :trade, payload}. The payload is the raw map sent
by Polymarket; normalization (typed structs, snake_case keys) is left to
the caller — typically by feeding the same map shape into
Polymarket.Activity.normalize/1.
The surface is deliberately narrow:
- No backpressure / batching / debouncing. Every trade event is
forwarded as a separate Erlang message. Busy markets can produce
5–20 events/second and a slow callback can flood. If this is a
problem, debounce in the callback or migrate to a future
demand-driven (
GenStage/Broadway) shape. - Reconnects on transient drops, stays closed on deliberate
close. A network drop reconnects (with exponential backoff so a
hard-down endpoint does not storm); a deliberate close — e.g. the
callback PID dying — stays closed. This module is not embedded in
a
Supervisorhere — callers that want crash-and-restart guarantees should add their own supervisor. - No topic generalization. Only the global trades feed
(
{"topic": "activity", "type": "trades"}) is subscribed. New Polymarket RTDS topics (resolutions, liquidity events) are not modeled. - No payload normalization. Forwarded payloads are the raw maps
from Polymarket. Pair with
Polymarket.Activity.normalize/1if you need typed structs. - Callback is PID-only. The
{module, function}callback form is not supported.
Usage
{:ok, _pid} = Polymarket.RTDS.start_link(callback: self())
receive do
{:polymarket_rtds, :trade, payload} ->
IO.inspect(payload, label: "rtds trade")
endTrade payload fields (raw, from Polymarket)
proxyWallet— trader's wallet address.pseudonym— trader's display name.side—"BUY"or"SELL".outcome—"Yes","No", or named outcome.price— execution price (number).size— trade size (number).asset— outcome token id (decimal string).conditionId— market condition id (hex).eventSlug— market slug.title— human-readable market name.transactionHash— on-chain tx hash.timestamp— Unix timestamp.
Options
:callback(required) — PID to receive trade events.:url— Override the WebSocket URL (default"wss://ws-live-data.polymarket.com").:ping_interval— PING frame interval in milliseconds (default5_000).:name— Optional process name passed toWebSockex.start_link/4.
Summary
Functions
Default ping interval in milliseconds.
Default RTDS production URL. Exposed so tests can compare against it.
Starts the RTDS client and connects.
Functions
@spec default_ping_interval_ms() :: pos_integer()
Default ping interval in milliseconds.
@spec default_url() :: String.t()
Default RTDS production URL. Exposed so tests can compare against it.
Starts the RTDS client and connects.
Raises ArgumentError if :callback is missing or not a PID.