Skip to content

feat(ts-sdk): account activity resource - #310

Open
majesticwizardcat wants to merge 5 commits into
mainfrom
giannis/activity-feed
Open

majesticwizardcat wants to merge 5 commits into
mainfrom
giannis/activity-feed

Conversation

@majesticwizardcat

@majesticwizardcat majesticwizardcat commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Client side of the account activity feed (node: pod PR #113, ADR 0057). That PR is merged; the wire shapes here are main's.

client.activity(account, query?) returns an ActivityHistory, a SeriesResource<ActivityEntry> with the same lifecycle as OrderHistory: seed from GET /clob/activity/{account}, subscribe pod_activity with the page's watermark as since, drop frames at or below the cursor, fast-resume on a resumable close, re-seed with backoff, loadOlder by cursor, onEvent for toasts.

  • ActivityEntry is tagged on activityType: order (the existing Order, fills included), backstop (the existing BackstopTransfer plus realizedPnl), bridge_transfer and transfer (signed amount, negative left the account). Sorted newest first, the node's ordinal breaks ties.
  • ActivityQuery { types?, from?, to?, limit? }, times in ms; the transport converts to µs and joins activity_types.
  • The subscribe/resume/re-seed machine is lifted out of OrderHistory into sync/stream.ts (ResumableStream) and OrderHistory uses it with no behaviour change; orders.test.ts is byte-unchanged. orders() itself is untouched: the orders stream is retired later, once everything is on activity.
  • applyOrdersFrame reads the entity's book when present and falls back to the frame's, so one fold serves both channels.
  • pod_activity joins the Channel union; SubParams is unchanged, the cursor is the batch alone.

Tests: codec/activity-v2.test.ts (entry decode, frame fold, unknown kinds ignored) and sync/activity.test.ts (seed, subscribe from the watermark, query passthrough, frame apply and emit, cursor rule, resume then re-seed, type filter, loadOlder dedupe, ordinal tiebreak, onEvent ref-counting). 210 tests, typecheck and build green.

Review fixes. Window applied to live frames; a known order is never retimed by a re-seed (the seed times orders by signed deadline, the stream by inclusion batch, accepted while clients sign a tick or two ahead); the shared stream resets its retry budget on a successful retry, cancels a pending retry once a seed lands, stops on a 4xx, seeds single-flight and keeps pagination across reconnects; one query normaliser for memo key and constructor; unknown seed kinds skipped; stable sort tiebreak; money events folded in wire order through a small hook on the orders codec; the stream's one-value options removed. New tests for the two-part cursor path and the REST wire query. Version 0.11.0.

🤖 Generated with Claude Code

client.activity(account, query) seeds one account's history from
GET /clob/activity/{account} and streams pod_activity_v2, mirroring
OrderHistory: the subscribe, resume and re-seed machine is lifted out
of OrderHistory into a shared ResumableStream with no behaviour change,
the order events fold through applyOrdersFrame with the book now read
from the entity, and the backstop, bridge_transfer and transfer events
land as signed money entries. Entries carry a tagged activityType and
sort newest first with the node's ordinal as the tiebreak.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@majesticwizardcat
majesticwizardcat marked this pull request as ready for review September 30, 2026 14:28
@poszu
poszu added this pull request to stack #312 October 2, 2026 06:16
@poszu
poszu requested a balanced review from Copilot October 2, 2026 06:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Activity timestamps and paginated rows can be lost or reordered, and transient initial seed failures can leave resources permanently idle.

Review effort: Balanced
Findings: 4 Medium severity · 3 Low severity

Open (7)
What changed in this PR

Adds account activity history combining orders and money movements through REST and WebSocket synchronization.

Changes:

  • Adds activity wire/public types, codecs, REST endpoint, and client resource.
  • Extracts reusable resumable-stream lifecycle logic from order history.
  • Adds activity decoding and synchronization tests.
File Description
ts-sdk/​src/​types/​wire.ts Defines activity wire payloads.
ts-sdk/​src/​types/​public.ts Adds public activity types.
ts-sdk/​src/​transport/​ws.ts Registers the activity channel.
ts-sdk/​src/​transport/​rest.ts Adds activity REST transport.
ts-sdk/​src/​sync/​stream.ts Extracts resumable streaming logic.
ts-sdk/​src/​sync/​orders.ts Migrates orders to the shared stream.
ts-sdk/​src/​sync/​activity.ts Implements activity history synchronization.
ts-sdk/​src/​sync/​activity.test.ts Tests activity history behavior.
ts-sdk/​src/​index.ts Exports activity APIs.
ts-sdk/​src/​codec/​orders-v2.ts Supports entity-level books.
ts-sdk/​src/​codec/​decode.ts Decodes activity entries.
ts-sdk/​src/​codec/​activity-v2.ts Folds activity stream frames.
ts-sdk/​src/​codec/​activity-v2.test.ts Tests activity codecs.
ts-sdk/​src/​client.ts Exposes client.activity().

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ts-sdk/src/sync/activity.ts Outdated
Comment thread ts-sdk/src/sync/activity.ts Outdated
Comment thread ts-sdk/src/sync/activity.ts
Comment thread ts-sdk/src/sync/stream.ts Outdated
Comment thread ts-sdk/src/client.ts Outdated
Comment thread ts-sdk/src/types/public.ts Outdated
Comment thread ts-sdk/src/types/wire.ts Outdated
majesticwizardcat and others added 3 commits October 2, 2026 11:13
Money entries are keyed by what identifies the row, the transfer id,
the bridge tx hash and its idx, or the tick and book of a backstop,
so a page boundary inside a same-tick run loses nothing. An order
keeps the node's time when seeded and takes the batch only when a
frame is first to report it. An empty types filter means no filter on
the stream as it does on REST. A failed initial seed retries through
the re-seed backoff instead of leaving the resource idle, which also
fixes OrderHistory through the shared stream.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was never a v1 to version against.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
One decoder serves a money entry on the seed and its event on the
stream, since the node now sends both with the same short keys.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A windowed history drops frames outside its window. A known order is
never retimed by a re-seed. The shared stream resets its retry budget
when a retried seed subscribes, cancels a pending retry once a seed
lands, stops on a 4xx, and both resources seed single-flight and keep
their pagination across reconnects. One normaliser serves the memo key
and the constructor, unknown seed kinds are skipped like unknown frame
events, the sort has a stable tiebreak, and a frame's money events are
folded in wire order through a hook on the orders codec. The stream's
one-value options are gone. Tests for the two-part cursor path, the
REST wire query and each fix.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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