fix: document watchOrderBook limit and params#406
Conversation
realfishsam
left a comment
There was a problem hiding this comment.
PR Review: PASS (NOT VERIFIED)
What This Does
Adds a CCXT-compatible third argument (params: Record<string, any>) to watchOrderBook and watchOrderBooks across the base class, all 9 exchange overrides, both SDK wrappers, server method metadata, and public docs. Before this PR, callers could not express exchange-specific WebSocket parameters through the public interface; the signatures only exposed (outcomeId, limit?). This makes the interface consistent with how CCXT signatures are shaped.
Blast Radius
core/src/BaseExchange.ts— base class signatures forwatchOrderBook+watchOrderBooks;watchOrderBooksdefault implementation now forwardsparamsto each individualwatchOrderBookcall- 9 exchange overrides — baozi, gemini-titan, kalshi, limitless, myriad, opinion, polymarket, polymarket_us, probable (all updated for signature consistency; all accept but do not use
_params) core/src/server/method-verbs.json— server GET-dispatch arg spec;paramsnow registered so GET calls can include itcore/api-doc-config.generated.json— JSDoc-derived doc config- Both SDK wrappers —
sdks/typescript/pmxt/client.ts,sdks/python/pmxt/client.py - Docs —
watch-order-book.mdx,watch-order-books.mdx,websocket.mdx,llms-full.txt,sdks/python/API_REFERENCE.md,sdks/typescript/API_REFERENCE.md
Consumer Verification
Before (main branch):
BaseExchange.ts:1253 declared watchOrderBook(outcomeId: string, limit?: number) — no params. TypeScript SDK client.ts:1465 likewise had (outcomeId, limit?). Python SDK had watch_order_book(outcome_id, limit=None, **_compat_kwargs) — only reachable via **kwargs, not a typed parameter. Consumer calling watchOrderBook("id", 10, { foo: "bar" }) in TypeScript would get a compile error; in Python, params would silently route into _compat_kwargs and not reach the args array sent to the sidecar.
After (PR branch):
BaseExchange.ts:1251 declares watchOrderBook(outcomeId: string, limit?: number, params: Record<string, any> = {}). Both SDK wrappers expose the parameter explicitly. Consumer code compiles cleanly:
await exchange.watchOrderBook("OUTCOME_ID", 50, { someVenueParam: true });TypeScript compile check: clean (npx tsc --noEmit). Python syntax check: clean (python3 -m py_compile).
Live WebSocket end-to-end verification was not possible in this environment — watchOrderBook requires an open WebSocket connection to the exchange, and outbound exchange network connections are not available here. Static analysis and unit tests were used instead.
Test Results
- Build (
npm run build --workspace=pmxt-core): PASS - New test (
test/pipeline/watch-order-book-api.test.ts): PASS (2/2) - Full suite (
npm test -- --runInBand): PASS (507/507) — the MyriadresolutionDateyear failure noted in the PR description did not reproduce; it appears to be a date-sensitive flap that has since self-resolved - Server starts: PASS
- E2E smoke (authenticated call to sidecar): confirmed auth middleware reached; exchange network calls timed out as expected in this environment
Findings
-
docs/llms-full.txtis inconsistent forwatchOrderBooks(docs/llms-full.txt:4234). The file was hand-edited to add thelimitandparamsrows for the singularwatchOrderBooksection but not for thewatchOrderBooks(plural) section, even thoughwatch-order-books.mdxwas correctly updated with both rows. Sincellms-full.txtis generated byscripts/generate-llms.jsfrom the.mdxsources, runningnpm run docs:llmswould fix this. The publish workflow does runnpm run docs:llms, so the inconsistency is self-healing at publish time — but the committed state ofllms-full.txtis currently inconsistent. The new regression test only checkswatch-order-book.mdxandllms-full.txtfor the singular case; it does not catch this gap. -
Three generated files are hand-edited.
core/api-doc-config.generated.jsoncarries an explicit"Do not edit manually"header (generated byextract-jsdoc.js).core/src/server/method-verbs.jsonis produced bygenerate-openapi.jsfrom theBaseExchange.tsAST (noted inapp.ts:13).docs/llms-full.txtis produced bygenerate-llms.js. The PR author explains the build could not run on a Windows checkout due torm -rf distin thecleanscript. The hand-edits forapi-doc-config.generated.jsonandmethod-verbs.jsonare correct — they match what the respective generators would produce from the updatedBaseExchange.ts(the generator readsparams: Record<string, any> = {}→kind: 'object', optional: true). The publish workflow regenerates all three, so they self-heal. No blocking issue, but the process deviation is worth noting. -
paramsis accepted by every venue but forwarded to none. All 9 exchange overrides name the argument_params(intentionally unused). This is appropriate for a CCXT-compatibility stub, but it means any caller who passes venue-specific params will receive no error and no effect — silent no-op. This is not documented in the public-facing parameter description ("Optional exchange-specific parameters" does not indicate it is currently a no-op on all venues). Not a blocking issue, but a transparency gap worth a doc note on the page. -
nullarrives aslimitwhenparamsis passed withoutlimit. Both SDKs insertundefined/Noneas a positional placeholder (e.g.args = [id, undefined, params]in TypeScript) to preserve the positional ordering before JSON-serializing to the sidecar.JSON.stringify([undefined])→"[null]", so the server receiveslimit = nullrather thanlimit = undefined. Since no currently active exchange implementation uses thelimitvalue in its WebSocket subscription logic (Kalshiindex.ts:354callsthis.ws.watchOrderBook(marketTicker)ignoring it; others are similar), there is no practical impact. Minor semantic inaccuracy only. -
Incidental pre-existing bug fixed in
sdks/typescript/API_REFERENCE.md. The example previously showedwatchOrderBook("12345", { limit: 10 })— passing an object literal as thelimit(number) parameter. Now corrected towatchOrderBook("12345", 10). Good catch.
PMXT Pipeline Check
- Field propagation (3-layer): N/A — this is a WebSocket method; no OpenAPI field propagation path
- OpenAPI sync: N/A —
watchOrderBookis a WS method and does not appear inopenapi.yaml;method-verbs.json(the relevant server config) is updated - Financial precision: N/A — no price/amount arithmetic
- Type safety: OK —
Record<string, any>is intentional here (CCXT convention);_paramson all overrides prevents accidental use; no new!assertions; TS compiles cleanly - Auth safety: OK — no credential handling touched
Semver Impact
minor — new optional parameters with defaults added to existing public methods; no existing call site breaks.
Risk
params is a stub with no current implementation on any venue. If a future PR implements actual venue-specific param routing, callers who already pass params objects will get previously-silent values forwarded to exchange WebSockets. That is the intended design, but it is worth flagging for whoever implements venue-side support: test existing callers that may inadvertently be passing params today.
The llms-full.txt inconsistency (Finding 1) is the only committed artifact that is factually wrong right now; it is resolved automatically at publish time but is observable between merge and tag.
Generated by Claude Code
Fixes #163
Summary
params = {}support to the corewatchOrderBook/watchOrderBookssignatures and method metadatalimitandparamsin the public watch order book docs, SDK API refs, andllms-full.txtBug verification
paramscore signature and missinglimitdocumentation.Validation
npm --workspace=pmxt-core test -- --runTestsByPath test/pipeline/watch-order-book-api.test.tsnpx tsc -p core/tsconfig.json --noEmitpython -m py_compile sdks/python/pmxt/client.pyNotes
npm --workspace=pmxt-core run builddoes not run on this Windows checkout because the existingcleanscript callsrm -rf dist.npm --workspace=pmxt-core test -- --runInBandhas one unrelated existing failure intest/normalizers/exchange-normalizers-2.test.ts: expected year2025, received2026for a MyriadresolutionDateassertion.