@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.
- package/AGENTS.md +237 -0
- package/CHANGELOG.md +140 -0
- package/README.md +13 -6
- package/dist/events.d.ts +309 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +132 -0
- package/dist/events.js.map +1 -0
- package/dist/group-events.d.ts +82 -0
- package/dist/group-events.d.ts.map +1 -0
- package/dist/group-events.js +47 -0
- package/dist/group-events.js.map +1 -0
- package/dist/group.d.ts +31 -0
- package/dist/group.d.ts.map +1 -0
- package/dist/group.js +196 -0
- package/dist/group.js.map +1 -0
- package/dist/index.d.ts +57 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -1
- package/dist/index.js.map +1 -1
- package/dist/observations.d.ts +169 -0
- package/dist/observations.d.ts.map +1 -0
- package/dist/observations.js +287 -0
- package/dist/observations.js.map +1 -0
- package/dist/reorg.d.ts +108 -0
- package/dist/reorg.d.ts.map +1 -0
- package/dist/reorg.js +125 -0
- package/dist/reorg.js.map +1 -0
- package/dist/replace-transaction.d.ts +46 -0
- package/dist/replace-transaction.d.ts.map +1 -0
- package/dist/replace-transaction.js +47 -0
- package/dist/replace-transaction.js.map +1 -0
- package/dist/selectors.d.ts +78 -0
- package/dist/selectors.d.ts.map +1 -0
- package/dist/selectors.js +119 -0
- package/dist/selectors.js.map +1 -0
- package/dist/store.d.ts +166 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +110 -0
- package/dist/store.js.map +1 -0
- package/dist/tracker.d.ts +211 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +1004 -0
- package/dist/tracker.js.map +1 -0
- package/dist/wait-for-pending.d.ts +41 -0
- package/dist/wait-for-pending.d.ts.map +1 -0
- package/dist/wait-for-pending.js +71 -0
- package/dist/wait-for-pending.js.map +1 -0
- package/dist/wait-for-transaction.d.ts +55 -0
- package/dist/wait-for-transaction.d.ts.map +1 -0
- package/dist/wait-for-transaction.js +72 -0
- package/dist/wait-for-transaction.js.map +1 -0
- package/dist/watch-transaction.d.ts +57 -0
- package/dist/watch-transaction.d.ts.map +1 -0
- package/dist/watch-transaction.js +76 -0
- package/dist/watch-transaction.js.map +1 -0
- package/package.json +6 -1
- 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":"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"}
|