Add graph ql subscriptions for live prices#76
Conversation
Attach response schemas to every route in src/api/rest.ts (/status, /price/:a/:b, /price/:a/:b/route, /price/:a/:b/history, /pools) and add shared schema objects in src/api/schemas.ts. In dev/test a validating serializer checks each outgoing payload against its schema and throws on a mismatch, so accidental response-shape changes fail loudly instead of shipping silently. Production keeps Fastify default (fast) serialization for the same schemas, so there is no runtime impact. Adds src/__tests__/schemaValidation.test.ts asserting a known endpoint matches its schema and that extra/wrong-typed fields are rejected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Attach response schemas to every route in src/api/rest.ts (/status, /price/:a/:b, /price/:a/:b/route, /price/:a/:b/history, /pools) and add shared schema objects in src/api/schemas.ts. In dev/test a validating serializer checks each outgoing payload against its schema and throws on a mismatch, so accidental response-shape changes fail loudly instead of shipping silently. Production keeps Fastify default (fast) serialization for the same schemas, so there is no runtime impact. Adds src/__tests__/schemaValidation.test.ts asserting a known endpoint matches its schema and that extra/wrong-typed fields are rejected.
…ts' of https://github.com/mikkyvans0-source/Lens into Add-JSON-Schema-response-validation-to-all-REST-endpoints
|
@mikkyvans0-source Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Miracle656
left a comment
There was a problem hiding this comment.
The priceUpdated GraphQL subscription over the existing Mercurius endpoint is a clean approach (good call keeping the REST /ws channel untouched).
The blocker: this branch is stacked on your JSON-schema-validation work (#75), so it also re-includes schemas.ts / schemaValidation.test.ts / the rest.ts changes. #75 has now been merged to main, so please rebase on the latest main and drop the #75 files — leaving just the subscription work (events.ts, graphql.ts, the ingester publishPriceUpdate calls, and graphqlSubscription.test.ts). I'll merge once it's rebased.
|
Friendly nudge — the GraphQL subscriptions PR is mergeable but still has the earlier change requests outstanding. Please rebase on the latest |
Summary
Closes #56
Added a priceUpdated(pair: String!) GraphQL subscription that streams live prices over the existing Mercurius/Fastify /graphql endpoint — no separate WebSocket stack.
Changes
src/events.ts — Added a minimal PRICE_PUBLISHED event with a { pair, price, ts } payload and a publishPriceUpdate() helper. Kept the existing priceEmitter/PRICE_UPDATE intact so the REST /ws channel is untouched.
src/api/graphql.ts —
Added a PriceUpdate type and a Subscription.priceUpdated(pair) field.
Enabled Mercurius subscriptions with the graphql-transport-ws subprotocol (fullWsTransport: true) so standard graphql-ws clients connect.
Resolver uses withFilter to forward only the requested pair.
A single app-level bridge listener forwards priceEmitter events onto app.graphql.pubsub, detached on onClose so the listener doesn't leak.
src/ingesters/sdex.ts, amm.ts, soroswap.ts — Each ingester calls publishPriceUpdate({ pair, price, ts }) after recording a new price, alongside the existing webhook dispatch.
README.md — Documented the subscription with a graphql-ws client snippet showing subscribe and the unsubscribe (clean-close) call.
src/tests/graphqlSubscription.test.ts — Integration test over a real ws connection covering all three acceptance criteria: streaming for the subscribed pair, server-side filtering of other pairs, and clean unsubscribe via complete. Also asserts the bridge listener is detached on shutdown.
Verification
Tests: full suite passes — 85/85, including the 3 new subscription tests.
Typecheck: no new errors. The two webhookDispatcher.ts errors are pre-existing (Prisma client isn't generated locally) and unrelated — I confirmed they exist on the unmodified tree via git stash.