fix(rtds): serialize crypto_prices filters as comma-separated string (closes #270)#341
Open
HxrmxStudio wants to merge 1 commit intoPolymarket:mainfrom
Open
Conversation
The RTDS server expects `crypto_prices` subscription filters as a comma-separated plain string per the published schema: https://docs.polymarket.com/market-data/websocket/rtds "filters": "solusdt,btcusdt,ethusdt" `Subscription::crypto_prices` was serializing the filter list via `serde_json::to_string`, which produced a JSON array on the wire: "filters": ["btcusdt","ethusdt"] The server silently rejects that shape with `{"message":"Invalid request body"}` while leaving the WebSocket connection open and healthy at the transport layer. Consumers see a stream that never forwards any ticks — no visible error anywhere in the SDK path, but the `crypto_prices` topic is effectively dead for the lifetime of the subscription. Originally reported in Polymarket#270 with the exact wire-format diagnosis; closed by the reporter without a fix merged. This patch adopts the reporter's recommended one-liner (`symbols.join(",")`) and updates the two unit tests that encoded the incorrect expected shape (`serialize_subscription_request` and `serialize_mixed_subscriptions`). `crypto_prices_chainlink` is unaffected — its filter shape (`"{\"symbol\":\"btc/usd\"}"`) is correct per Polymarket#136 and already serialized as an escaped JSON string. All 36 library tests pass.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #341 +/- ##
==========================================
- Coverage 85.54% 85.52% -0.02%
==========================================
Files 32 32
Lines 5167 5168 +1
==========================================
Hits 4420 4420
- Misses 747 748 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Subscription::crypto_pricesserializes itsfiltersfield as a JSON array (["btcusdt","ethusdt"]), but the Polymarket RTDS server expects a comma-separated plain string ("btcusdt,ethusdt") per the published schema. The server silently rejects the JSON-array body with{\"message\":\"Invalid request body\"}while leaving the WebSocket connection open — consumers see a live stream that never forwards any ticks, with no visible error anywhere in the SDK path.This matches the bug described in #270. The reporter closed that issue without a fix merged, so v0.4.4 still ships the broken serialization. This PR adopts the reporter's one-liner recommendation.
Repro (observed in production)
Downstream consumer of
polymarket-client-sdk = \"0.4.4\", subscribed via:```rust
client.subscribe_crypto_prices(Some(vec!["btcusdt".into(), "ethusdt".into(), "solusdt".into(), "xrpusdt".into(), "dogeusdt".into()]))
```
Outcome:
binance_ticks_forwardedcounter stayed at 0 across ≥6 hours whilechainlink_ticks_forwarded(on the sameClient) accumulated at a healthy ~4.95 tps. NoRTDS stream errorwarnings, nostream ENDEDlog line — the stream simply never yielded any items.Passing
Noneinstead (no server-side filter) resumes tick flow immediately, confirming the filter shape is the root cause.Fix
Replace the JSON array encoding with a
join(\",\"):```rust
```
The existing custom
Serializeimpl already handles plain-string filters correctly via the fallback branch (the JSON re-parse fails for a comma-separated string and falls through tomap.serialize_entry(\"filters\", filters)?, which emits the string value as-is). No changes needed there.The two unit tests that encoded the old (broken) expected shape are updated to match the documented wire format:
serialize_subscription_request— asserts\"filters\":\"btcusdt,ethusdt\"serialize_mixed_subscriptions— same assertion in the multi-topic caseChainlink
crypto_prices_chainlinkis unaffected. Its filter shape (\"{\\\"symbol\\\":\\\"btc/usd\\\"}\") is correct per #136 and remains serialized as an escaped JSON string by the existing Chainlink branch in theSerializeimpl.Test plan
crypto_prices_chainlinkserialization unchanged (verified byserialize_chainlink_subscriptionpassing)Closes #270.
Note
Low Risk
Low risk wire-format fix limited to RTDS Binance
crypto_pricessubscription serialization; main risk is behavior change for any consumers relying on the previous (incorrect) JSON-array encoding.Overview
Fixes RTDS Binance
crypto_pricessubscriptions to serializefiltersas a comma-separated string (e.g."btcusdt,ethusdt") instead of a JSON array, matching the published RTDS schema and preventing silent server rejection/no-tick streams.Updates unit tests to assert the new on-the-wire format (including mixed Chainlink+Binance requests) while keeping Chainlink filter serialization unchanged.
Reviewed by Cursor Bugbot for commit 223716d. Bugbot is set up for automated code reviews on this repo. Configure here.