@valve-tech/tx-tracker 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/AGENTS.md +237 -0
  2. package/CHANGELOG.md +140 -0
  3. package/README.md +13 -6
  4. package/dist/events.d.ts +309 -0
  5. package/dist/events.d.ts.map +1 -0
  6. package/dist/events.js +132 -0
  7. package/dist/events.js.map +1 -0
  8. package/dist/group-events.d.ts +82 -0
  9. package/dist/group-events.d.ts.map +1 -0
  10. package/dist/group-events.js +47 -0
  11. package/dist/group-events.js.map +1 -0
  12. package/dist/group.d.ts +31 -0
  13. package/dist/group.d.ts.map +1 -0
  14. package/dist/group.js +196 -0
  15. package/dist/group.js.map +1 -0
  16. package/dist/index.d.ts +57 -10
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +52 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/observations.d.ts +169 -0
  21. package/dist/observations.d.ts.map +1 -0
  22. package/dist/observations.js +287 -0
  23. package/dist/observations.js.map +1 -0
  24. package/dist/reorg.d.ts +108 -0
  25. package/dist/reorg.d.ts.map +1 -0
  26. package/dist/reorg.js +125 -0
  27. package/dist/reorg.js.map +1 -0
  28. package/dist/replace-transaction.d.ts +46 -0
  29. package/dist/replace-transaction.d.ts.map +1 -0
  30. package/dist/replace-transaction.js +47 -0
  31. package/dist/replace-transaction.js.map +1 -0
  32. package/dist/selectors.d.ts +78 -0
  33. package/dist/selectors.d.ts.map +1 -0
  34. package/dist/selectors.js +119 -0
  35. package/dist/selectors.js.map +1 -0
  36. package/dist/store.d.ts +166 -0
  37. package/dist/store.d.ts.map +1 -0
  38. package/dist/store.js +110 -0
  39. package/dist/store.js.map +1 -0
  40. package/dist/tracker.d.ts +211 -0
  41. package/dist/tracker.d.ts.map +1 -0
  42. package/dist/tracker.js +1004 -0
  43. package/dist/tracker.js.map +1 -0
  44. package/dist/wait-for-pending.d.ts +41 -0
  45. package/dist/wait-for-pending.d.ts.map +1 -0
  46. package/dist/wait-for-pending.js +71 -0
  47. package/dist/wait-for-pending.js.map +1 -0
  48. package/dist/wait-for-transaction.d.ts +55 -0
  49. package/dist/wait-for-transaction.d.ts.map +1 -0
  50. package/dist/wait-for-transaction.js +72 -0
  51. package/dist/wait-for-transaction.js.map +1 -0
  52. package/dist/watch-transaction.d.ts +57 -0
  53. package/dist/watch-transaction.d.ts.map +1 -0
  54. package/dist/watch-transaction.js +76 -0
  55. package/dist/watch-transaction.js.map +1 -0
  56. package/package.json +6 -1
  57. package/skills/tx-tracker-integration/SKILL.md +198 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * `createTxTracker` — the per-tx state machine that turns a
3
+ * `ChainSource`'s block + mempool stream into a stream of neutral
4
+ * observations per tracked hash.
5
+ *
6
+ * Per `docs/tx-tracker-spec.md` §5.2 + §6 + §11 + §12. This file is
7
+ * the load-bearing piece of `@valve-tech/tx-tracker`; everything
8
+ * else is supporting infrastructure (events, store, reorg detector,
9
+ * selectors).
10
+ *
11
+ * Design rules carried in from the spec and the contributing skill:
12
+ *
13
+ * - **Three consumption shapes, one underlying stream** (§5.3).
14
+ * `getTxStatus(hash)` reads the cached snapshot; `subscribe(hash, cb)`
15
+ * attaches a callback; `track(hash)` returns an async iterator.
16
+ * All three see consistent state because they read from one
17
+ * internal `Subscriptions<TxEvent>` per hash.
18
+ *
19
+ * - **Neutral observations only** (§2.1). The tracker emits
20
+ * `seen-in-mempool` / `seen-in-block` / `vanished-from-block` /
21
+ * `replaced-by` / `unseen-for-N-blocks` and lets the consumer
22
+ * write the policy that says "confirmed" or "stuck" in their
23
+ * UX voice.
24
+ *
25
+ * - **No silent downgrade** (§2.2). Every emitted event carries a
26
+ * `source` discriminator. When the source's `capabilities()`
27
+ * change between ticks, the tracker emits `signal-degraded` /
28
+ * `signal-recovered` per affected capability.
29
+ *
30
+ * - **No own poll cycle** (§3.1, contributing-skill rule 3). The
31
+ * tracker hangs off `source.subscribeBlocks` and
32
+ * `source.subscribeMempool`; every per-tick computation runs
33
+ * inside those callbacks.
34
+ *
35
+ * - **Browser/mobile safe** (§2.4). No Node-only deps; the
36
+ * pub/sub primitive is `chain-source`'s `Subscriptions<E>`.
37
+ */
38
+ import type { ChainSource, Capabilities, RawTx } from '@valve-tech/chain-source';
39
+ import type { TxGroupEvent } from './group-events.js';
40
+ import { type Address, type At, type Hash, type TxEvent, type TxStatus } from './events.js';
41
+ import { type BulkSelector, type TxTrackerStore } from './store.js';
42
+ /**
43
+ * Lost-signal policy (spec §8). `'emit-uncertain'` is the default
44
+ * — every transition to a degraded source emits `signal-degraded`.
45
+ * `'silent'` keeps the events to itself; `'receipt-poll-fallback'`
46
+ * fetches `eth_getTransactionReceipt` every `pollEveryBlocks` block
47
+ * ticks and emits `seen-in-block` with `source: 'receipt-poll'` on a
48
+ * hit. Requires `capabilities().receiptByHash === 'available'`;
49
+ * when unavailable, downgrades to emit-uncertain semantics with a
50
+ * one-shot warning via `onError`.
51
+ */
52
+ export type LostSignalPolicy = 'emit-uncertain' | 'silent' | {
53
+ strategy: 'receipt-poll-fallback';
54
+ pollEveryBlocks: number;
55
+ };
56
+ /**
57
+ * Per-subscription overrides on top of the tracker defaults. See
58
+ * spec §5.4.
59
+ */
60
+ export interface TrackOptions {
61
+ /**
62
+ * Emit a synthetic `started` event on subscribe even if no real
63
+ * observation has fired yet. Default true. Wallets use this to
64
+ * render an "awaiting first observation" state without polling.
65
+ */
66
+ emitInitial?: boolean;
67
+ /**
68
+ * Persist this subscription via the store. Default false — the
69
+ * subscription survives only the current process. Indexer / relay
70
+ * consumers set this true.
71
+ */
72
+ durable?: boolean;
73
+ /** Per-subscription override of the tracker's `lostSignalPolicy`. */
74
+ lostSignalPolicy?: LostSignalPolicy;
75
+ /**
76
+ * How many consecutive blocks the hash must be unseen (not in
77
+ * mempool, not in the canonical block) before
78
+ * `unseen-for-N-blocks` fires. Default 30 (spec §6.1).
79
+ */
80
+ unseenThresholdBlocks?: number;
81
+ /**
82
+ * Eager receipt enrichment. When true, fetch the transaction
83
+ * receipt at seen-in-block time and attach it to the event via
84
+ * the `receipt` field. Adds one RPC per inclusion. Default false.
85
+ * Capability gate: requires source.capabilities().receiptByHash ===
86
+ * 'available'; when unavailable, events still flow but `receipt`
87
+ * is absent and a one-shot warning surfaces via onError.
88
+ */
89
+ withReceipts?: boolean;
90
+ }
91
+ /** Bulk subscription options — extends per-hash `TrackOptions`. */
92
+ export interface BulkTrackOptions extends TrackOptions {
93
+ /**
94
+ * Auto-track every tx the selector matches by starting an
95
+ * implicit per-hash subscription for it. Default true — an
96
+ * indexer wiring `trackFromAddress(treasury)` typically wants
97
+ * the per-hash event stream too. Set false to receive only the
98
+ * raw `matched` stream without per-hash detail.
99
+ */
100
+ autoTrackMatched?: boolean;
101
+ }
102
+ /** One emit from a bulk subscription — see spec §11.1. */
103
+ export interface TxMatchEvent {
104
+ kind: 'matched';
105
+ hash: Hash;
106
+ matchedBy: 'from' | 'to' | 'predicate';
107
+ selector: BulkSelector;
108
+ tx: RawTx;
109
+ source: 'mempool-snapshot' | 'block-poll';
110
+ at: At;
111
+ }
112
+ /** Handle returned by every bulk-track method. */
113
+ export interface TxSubscription {
114
+ /**
115
+ * Async iterator over the raw `matched` stream. Iteration ends
116
+ * when `stop()` is called or the tracker stops.
117
+ */
118
+ events(): AsyncIterable<TxMatchEvent>;
119
+ /**
120
+ * Imperative subscription to per-hash events on every matched tx.
121
+ * Returns an unsubscribe handle.
122
+ */
123
+ subscribe(cb: (event: TxEvent) => void): () => void;
124
+ /**
125
+ * Stop the bulk subscription. Per-hash subscriptions auto-tracked
126
+ * via this bulk subscription continue under their own retention
127
+ * rules (spec §11.1).
128
+ */
129
+ stop(): void;
130
+ }
131
+ /** Factory options. */
132
+ export interface CreateTxTrackerOptions {
133
+ source: ChainSource;
134
+ chainId: number;
135
+ store?: TxTrackerStore;
136
+ lostSignalPolicy?: LostSignalPolicy;
137
+ reorgDepthBlocks?: number;
138
+ /** Default `unseenThresholdBlocks` for new subscriptions. */
139
+ unseenThresholdBlocks?: number;
140
+ /** Cap on simultaneous bulk subscriptions (spec §11.3). */
141
+ maxBulkSubscriptions?: number;
142
+ onError?: (method: string, err: unknown) => void;
143
+ lifecycle?: 'eager' | 'lazy';
144
+ }
145
+ /**
146
+ * Options for a group subscription. All fields are optional — the group
147
+ * works with defaults. See `createTxGroup` in `group.ts`.
148
+ */
149
+ export interface GroupOptions {
150
+ /** Optional human-readable group ID echoed in events. Default: random. */
151
+ groupId?: string;
152
+ /** Per-member TrackOptions applied to each hash. */
153
+ memberOptions?: TrackOptions;
154
+ }
155
+ /**
156
+ * Handle returned by `tracker.group(hashes, options?)`. Exposes three
157
+ * consumption shapes (async iterator, callback, snapshot) over the same
158
+ * group-event stream, plus a `stop()` to tear down all member
159
+ * subscriptions.
160
+ */
161
+ export interface TxGroupSubscription {
162
+ /** Async-iterable surface over the group event stream. */
163
+ events(): AsyncIterable<TxGroupEvent>;
164
+ /**
165
+ * Imperative callback subscription. Returns an unsubscribe handle.
166
+ */
167
+ subscribe(cb: (event: TxGroupEvent) => void): () => void;
168
+ /** Snapshot of each member's current `TxStatus` (null if not yet observed). */
169
+ snapshot(): Record<Hash, TxStatus | null>;
170
+ /** Tear down all member subscriptions and emit `group-stopped`. */
171
+ stop(): void;
172
+ }
173
+ /** Public surface returned by `createTxTracker`. */
174
+ export interface TxTracker {
175
+ start(): void;
176
+ stop(): void;
177
+ getTxStatus(hash: Hash): TxStatus | null;
178
+ track(hash: Hash, options?: TrackOptions): AsyncIterable<TxEvent>;
179
+ subscribe(hash: Hash, cb: (event: TxEvent) => void, options?: TrackOptions): () => void;
180
+ trackFromAddress(address: Address, options?: BulkTrackOptions): TxSubscription;
181
+ trackToAddress(address: Address, options?: BulkTrackOptions): TxSubscription;
182
+ trackPredicate(match: (tx: RawTx) => boolean, options?: BulkTrackOptions): TxSubscription;
183
+ capabilities(): Capabilities;
184
+ subscribeAll(cb: (event: TxEvent) => void): () => void;
185
+ /**
186
+ * Cross-tx correlation — track a logical group of related hashes
187
+ * (e.g., a wallet's "claim + swap" pair). Emits group-level
188
+ * synthesis events derived from the per-member event streams.
189
+ * See spec §18.1, v0.8.0 design F3.
190
+ */
191
+ group(hashes: Hash[], options?: GroupOptions): TxGroupSubscription;
192
+ }
193
+ /**
194
+ * Build a configured tracker.
195
+ *
196
+ * @example
197
+ * import { createChainSource } from '@valve-tech/chain-source'
198
+ * import { createTxTracker } from '@valve-tech/tx-tracker'
199
+ *
200
+ * const source = createChainSource({ client })
201
+ * const tracker = createTxTracker({ source, chainId: 1 })
202
+ *
203
+ * source.start()
204
+ * tracker.start()
205
+ *
206
+ * for await (const event of tracker.track('0xabc...')) {
207
+ * if (event.kind === 'seen-in-block' && event.confirmations >= 3) break
208
+ * }
209
+ */
210
+ export declare const createTxTracker: (options: CreateTxTrackerOptions) => TxTracker;
211
+ //# sourceMappingURL=tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,YAAY,EAGZ,KAAK,EAEN,MAAM,0BAA0B,CAAA;AAIjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAQL,KAAK,OAAO,EACZ,KAAK,EAAE,EACP,KAAK,IAAI,EACT,KAAK,OAAO,EACZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAA;AAkBpB,OAAO,EAIL,KAAK,YAAY,EAGjB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAA;AAMnB;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GACxB,gBAAgB,GAChB,QAAQ,GACR;IAAE,QAAQ,EAAE,uBAAuB,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAA;AAElE;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAEnC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAE9B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CAAA;IACtC,QAAQ,EAAE,YAAY,CAAA;IACtB,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAAA;IACzC,EAAE,EAAE,EAAE,CAAA;CACP;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,IAAI,aAAa,CAAC,YAAY,CAAC,CAAA;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IACnD;;;;OAIG;IACH,IAAI,IAAI,IAAI,CAAA;CACb;AAED,uBAAuB;AACvB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,cAAc,CAAA;IACtB,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,6DAA6D;IAC7D,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,2DAA2D;IAC3D,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IAChD,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oDAAoD;IACpD,aAAa,CAAC,EAAE,YAAY,CAAA;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,MAAM,IAAI,aAAa,CAAC,YAAY,CAAC,CAAA;IACrC;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IACxD,+EAA+E;IAC/E,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC,CAAA;IACzC,mEAAmE;IACnE,IAAI,IAAI,IAAI,CAAA;CACb;AAED,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAA;IACxC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IACjE,SAAS,CACP,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAC5B,OAAO,CAAC,EAAE,YAAY,GACrB,MAAM,IAAI,CAAA;IACb,gBAAgB,CACd,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACzB,cAAc,CAAA;IACjB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,cAAc,CAAA;IAC5E,cAAc,CACZ,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,KAAK,OAAO,EAC7B,OAAO,CAAC,EAAE,gBAAgB,GACzB,cAAc,CAAA;IACjB,YAAY,IAAI,YAAY,CAAA;IAC5B,YAAY,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IACtD;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,mBAAmB,CAAA;CACnE;AAmID;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,sBAAsB,KAAG,SAw/BjE,CAAA"}