Skip to content

feat(stream): add RTDS and Sports WebSocket streams - #40

Open
yluoc wants to merge 11 commits into
SebastianBoehler:mainfrom
yluoc:RTDS-and-sports-WS
Open

yluoc wants to merge 11 commits into
SebastianBoehler:mainfrom
yluoc:RTDS-and-sports-WS

Conversation

@yluoc

@yluoc yluoc commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the public RTDS and Sports WebSocket streams (#10).

  • SportsStream: typed live game results from wss://sports-api.polymarket.com/ws. It answers the server's ping with pong and reconnects after 30 s without frames.
  • RtdsStream: comment and reaction subscriptions, plus Binance and Chainlink crypto prices, Chainlink 30/60 s TWAPs and Pyth equity prices from wss://ws-live-data.polymarket.com.
    • Subscriptions combine into one server subscription, which is diffed while connected and replayed after every reconnect.
    • Filtering happens on the client, as in the official SDKs.
    • Price values keep the exact decimal text, with Chainlink's 18-decimal integers scaled exactly, alongside a double.
  • WebSocketOptions gains a configurable ping text, a reply to a server text ping, and an idle reconnect timeout. The defaults keep current CLOB stream behavior.
  • Fixes the Gamma comment parser, which rejected integer-string positionSize values seen in live comment profiles. This affected GammaClient comment listings as well as RTDS.

The authenticated v2 price service and the RTDS activity topic are out of scope.

Verification

Commands run and their actual results:

  • scripts/ci_local.sh --title "feat(stream): add RTDS and Sports WebSocket streams": title, release, debug, sanitizers, fuzz and clang passed. Quality failed on two clang-tidy performance findings. After style(rtds): satisfy clang-tidy performance checks, --jobs quality passed.
  • New tests pass locally: test_websocket_heartbeat, test_sports_parsing, test_sports_stream, test_rtds_parsing, test_rtds_price_parsing and test_rtds_stream. test_environment and test_gamma_social were extended and pass.

Checks not run and the reason (or none):

  • Linux jobs ran with GCC 12, because GCC 11 is not installed locally.
  • macOS jobs cannot run locally.

Compatibility and evidence

Public API, binary compatibility, or release implications (or none):

Source compatible. New headers are sports_stream.hpp and rtds_stream.hpp. Binary layout changes:

  • WebSocketOptions has four new fields.
  • WebSocketStats has idle_timeouts.
  • Environment and Config have sports_ws_url.

Code compiled against an earlier release must be rebuilt.

For protocol changes: official docs links and the Python SDK commit or fixture source.

Frames, subscription rules, validation and models follow py-sdk commit 72297f05d6d8 and ts-sdk commit d2f5b9901a14. Fixtures are frames recorded on 2026-10-18. Comment bodies, names, wallets, addresses and connection IDs are replaced with synthetic values. Sports and price frames carry no personal data.

For live checks: distinguish observed outcomes from local fixture coverage.

Observed live with read-only connections:

  • Sports: 150 s connected, 108 results, 0 dropped, no idle reconnects.
  • RTDS comments: 2 min connected. A 3-minute capture parsed 12/12 frames after the positionSize fix; 2 had failed before it.
  • RTDS prices: 60 s connected, about 1,260 events, 0 dropped. A capture of 420 frames from the four crypto topics parsed 420/420.
  • RTDS sent no PONG and no subscribe acknowledgment.

Covered by fixtures only:

  • Equity prices: equity_prices was silent while markets were closed, so the update and history frames are synthetic, built from the py-sdk model.
  • comment_removed: none arrived live.
  • Sports finishedTimestamp: no game finished during the capture.
  • Sports heartbeat cadence during a quiet feed: not observed.

@yluoc

yluoc commented Oct 18, 2026

Copy link
Copy Markdown
Contributor Author

@SebastianBoehler

here's a quick summary of what's gone into the C++ SDK since v3.0.0.

Trading and setup (tier 1)

Data and discovery (tier 2)

Where we stop

With that, we cover everything the official Polymarket SDKs ship as stable. What's left there (builder program, gasless relayer, session keys, combos/RFQ, perps) is still beta or experimental in the official SDKs, so I'd suggest we stop here and pick those up once they stabilize.

Next version

I'd lean toward 4.0.0 over 3.1:

If we'd rather call it 3.1, we should double-check what #30 actually breaks first. What do you think?

@yluoc
yluoc marked this pull request as draft October 18, 2026 02:31
@yluoc
yluoc marked this pull request as ready for review October 18, 2026 02:58
@SebastianBoehler

Copy link
Copy Markdown
Owner

Thanks for adding these streams, and for documenting which cases you observed live versus covered with fixtures. I reviewed bc3c073 and ran the eight focused tests locally; all passed. I also checked two lifecycle cases with a local WebSocket server and found two things I think we should fix before merging:

  1. In RtdsStreamRuntime::handle_message, the subscriber callbacks are copied into targets and then called without checking whether the stream is still active. With two matching subscribers, I had the first callback call stream.stop(), and the second callback still ran after stop() returned. This can be a problem if the first callback releases application state during shutdown. Could you check session activity between deliveries and add a regression test for shutdown from a subscriber callback?

  2. Both stream parsers catch exceptions, increment dropped_events(), and return without reporting a gap or an error. Sending a malformed Sports update produced one dropped event, zero additional gap callbacks, and zero error callbacks. A consumer using the recovery callbacks to refresh its state would not know that it missed an update. Our protocol guidance requires gap reporting for invalid payloads. Could you report the parser error with its cause and trigger the gap/recovery path for malformed events on supported topics? A regression test for each stream would help cover this.

The subscription filtering and price parsing otherwise look consistent with the pinned SDK contract. These two cases are outside the current passing tests.

@SebastianBoehler

Copy link
Copy Markdown
Owner

Also after this pr is merged i will probably prepare the 4.0.0 release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants