@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
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TxEvent` — the discriminated union of every observation the
|
|
3
|
+
* tracker emits, plus payload builders that guarantee every event
|
|
4
|
+
* carries a complete envelope.
|
|
5
|
+
*
|
|
6
|
+
* Per `docs/tx-tracker-spec.md` §6, this taxonomy is the contract
|
|
7
|
+
* between the tracker and every consumer. Naming is **strictly
|
|
8
|
+
* neutral** (§2.1): `seen-in-mempool` not `pending`, `seen-in-block`
|
|
9
|
+
* not `mined`, `vanished-from-block` not `reorged`. The tracker
|
|
10
|
+
* publishes facts; the consumer writes the policy on top.
|
|
11
|
+
*
|
|
12
|
+
* Every event variant extends a common `Envelope` carrying the
|
|
13
|
+
* tracked `hash`, the `chainId`, the `source` discriminator (per
|
|
14
|
+
* §2.2 — never silently downgrade) and the `at` block coordinate
|
|
15
|
+
* the observation was made at. Builders here produce that envelope
|
|
16
|
+
* once so the state machine in `tracker.ts` cannot accidentally
|
|
17
|
+
* publish a partial event.
|
|
18
|
+
*
|
|
19
|
+
* No I/O, no wall-clock, no mutation — pure data shape + pure
|
|
20
|
+
* builders. Browser/mobile safe (§2.4).
|
|
21
|
+
*/
|
|
22
|
+
import type { Capabilities, EventSource, RawTx, TransactionReceipt } from '@valve-tech/chain-source';
|
|
23
|
+
/**
|
|
24
|
+
* Hash type carried on every event. The chain-source layer keeps
|
|
25
|
+
* hashes as plain `string` rather than viem's `Hash` brand to stay
|
|
26
|
+
* permissive at the JSON boundary; tx-tracker mirrors that posture
|
|
27
|
+
* — every consumer can `as Hash` at the seam if they need the
|
|
28
|
+
* branded form.
|
|
29
|
+
*/
|
|
30
|
+
export type Hash = string;
|
|
31
|
+
/**
|
|
32
|
+
* EVM address. Same posture as `Hash` — plain `string` so consumers
|
|
33
|
+
* who normalize to lowercase or to checksum form don't trip a brand
|
|
34
|
+
* check at the boundary.
|
|
35
|
+
*/
|
|
36
|
+
export type Address = string;
|
|
37
|
+
/**
|
|
38
|
+
* Block coordinate the observation was made at. `blockNumber` is the
|
|
39
|
+
* canonical-tip number when the observation landed; `timestamp` is
|
|
40
|
+
* the tip block's timestamp (seconds since epoch, same units the
|
|
41
|
+
* EVM exposes). Both `bigint` per the toolkit's wire-format rule
|
|
42
|
+
* (§2.5).
|
|
43
|
+
*/
|
|
44
|
+
export interface At {
|
|
45
|
+
blockNumber: bigint;
|
|
46
|
+
timestamp: bigint;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Common envelope on every event. The state machine builds this once
|
|
50
|
+
* per emit and merges it into the variant-specific payload below.
|
|
51
|
+
*/
|
|
52
|
+
export interface Envelope {
|
|
53
|
+
hash: Hash;
|
|
54
|
+
chainId: number;
|
|
55
|
+
source: EventSource;
|
|
56
|
+
at: At;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Per-variant payload shapes. Consumers narrow on `event.kind` to
|
|
60
|
+
* access variant-specific fields. The eslint config disallows TS
|
|
61
|
+
* namespaces, so each variant is a top-level interface and the
|
|
62
|
+
* `TxEvent` union below sums them.
|
|
63
|
+
*/
|
|
64
|
+
/**
|
|
65
|
+
* Synthetic first event of a subscription when `emitInitial: true`
|
|
66
|
+
* (the default). Carries the capability snapshot at subscribe time
|
|
67
|
+
* so consumers can decide their fallback posture without a separate
|
|
68
|
+
* call.
|
|
69
|
+
*/
|
|
70
|
+
export interface TxEventStarted extends Envelope {
|
|
71
|
+
kind: 'started';
|
|
72
|
+
capabilities: Capabilities;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Tracked hash was observed in the upstream's mempool snapshot or
|
|
76
|
+
* pushed via `eth_subscribe('newPendingTransactions')`. `bucket`
|
|
77
|
+
* disambiguates `txpool_content`'s pending-vs-queued split.
|
|
78
|
+
*/
|
|
79
|
+
export interface TxEventSeenInMempool extends Envelope {
|
|
80
|
+
kind: 'seen-in-mempool';
|
|
81
|
+
bucket: 'pending' | 'queued';
|
|
82
|
+
tx: RawTx;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Tracked hash is no longer in the mempool snapshot. The tx may
|
|
86
|
+
* have been mined, replaced, or evicted by the upstream node;
|
|
87
|
+
* subsequent `seen-in-block` / `replaced-by` / `unseen-for-N-blocks`
|
|
88
|
+
* disambiguates which of those happened.
|
|
89
|
+
*/
|
|
90
|
+
export interface TxEventLeftMempool extends Envelope {
|
|
91
|
+
kind: 'left-mempool';
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Tracked hash was found in the canonical block at
|
|
95
|
+
* `blockNumber` / `blockHash`, at index `transactionIndex`.
|
|
96
|
+
* `confirmations` counts blocks observed since this inclusion
|
|
97
|
+
* inclusive of the inclusion block itself (so the first
|
|
98
|
+
* inclusion event has `confirmations: 1`).
|
|
99
|
+
*
|
|
100
|
+
* `receipt` is present iff the subscription set `withReceipts: true`.
|
|
101
|
+
* Adds one RPC per inclusion (spec §18.2, v0.8.0 design F2).
|
|
102
|
+
*/
|
|
103
|
+
export interface TxEventSeenInBlock extends Envelope {
|
|
104
|
+
kind: 'seen-in-block';
|
|
105
|
+
blockHash: Hash;
|
|
106
|
+
blockNumber: bigint;
|
|
107
|
+
transactionIndex: number;
|
|
108
|
+
confirmations: number;
|
|
109
|
+
/**
|
|
110
|
+
* Transaction receipt — present iff the subscription set
|
|
111
|
+
* `withReceipts: true`. Adds one RPC per inclusion (spec §18.2,
|
|
112
|
+
* v0.8.0 design F2).
|
|
113
|
+
*/
|
|
114
|
+
receipt?: TransactionReceipt;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Tx was previously seen at block `blockNumber` with hash
|
|
118
|
+
* `previousBlockHash`, but the canonical block at the same height
|
|
119
|
+
* now has `canonicalBlockHash` and the tracked tx is not in its
|
|
120
|
+
* `transactions`. Reorg.
|
|
121
|
+
*
|
|
122
|
+
* Per spec §12.3, this event never carries
|
|
123
|
+
* `source: 'receipt-poll'` — receipt-poll cannot detect a reorg
|
|
124
|
+
* because most providers happily return a receipt for a tx in a
|
|
125
|
+
* no-longer-canonical block.
|
|
126
|
+
*/
|
|
127
|
+
export interface TxEventVanishedFromBlock extends Envelope {
|
|
128
|
+
kind: 'vanished-from-block';
|
|
129
|
+
previousBlockHash: Hash;
|
|
130
|
+
canonicalBlockHash: Hash;
|
|
131
|
+
blockNumber: bigint;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A different hash with the same `(from, nonce)` pair was either
|
|
135
|
+
* seen in the mempool or mined. `replacementBlockNumber` is `null`
|
|
136
|
+
* when the replacement was only observed in the mempool; it
|
|
137
|
+
* carries the mined block's number when the replacement reached
|
|
138
|
+
* inclusion before the original.
|
|
139
|
+
*/
|
|
140
|
+
export interface TxEventReplacedBy extends Envelope {
|
|
141
|
+
kind: 'replaced-by';
|
|
142
|
+
replacementHash: Hash;
|
|
143
|
+
replacementBlockNumber: bigint | null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Tracked hash has not been in the mempool nor in any polled
|
|
147
|
+
* block for `blocks` consecutive observations. Threshold is
|
|
148
|
+
* configurable per subscription (`unseenThresholdBlocks`,
|
|
149
|
+
* default 30 — see `tracker.ts`). Consumer interprets as
|
|
150
|
+
* "likely dropped" / "stuck" / "rejected" in their own UX.
|
|
151
|
+
*/
|
|
152
|
+
export interface TxEventUnseenForNBlocks extends Envelope {
|
|
153
|
+
kind: 'unseen-for-N-blocks';
|
|
154
|
+
blocks: number;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A capability the tracker had been relying on for this hash is
|
|
158
|
+
* no longer authoritative — typically because the WS subscription
|
|
159
|
+
* dropped or `txpool_content` was newly gated. Tracking continues
|
|
160
|
+
* via `fallbackSource`; the consumer's interpretation of subsequent
|
|
161
|
+
* events should weigh that lower authority.
|
|
162
|
+
*/
|
|
163
|
+
export interface TxEventSignalDegraded extends Envelope {
|
|
164
|
+
kind: 'signal-degraded';
|
|
165
|
+
capabilityLost: keyof Capabilities;
|
|
166
|
+
fallbackSource: EventSource;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* A previously-degraded capability is back. Fired after a
|
|
170
|
+
* matching `signal-degraded` only.
|
|
171
|
+
*/
|
|
172
|
+
export interface TxEventSignalRecovered extends Envelope {
|
|
173
|
+
kind: 'signal-recovered';
|
|
174
|
+
capabilityRestored: keyof Capabilities;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Subscription teardown — fires once per subscription. Always the
|
|
178
|
+
* final event in the stream for that subscription. `reason`
|
|
179
|
+
* disambiguates which lifecycle path closed the iterator:
|
|
180
|
+
*
|
|
181
|
+
* - `'unsubscribed'`: consumer called the returned unsubscribe
|
|
182
|
+
* handle (or `break`'d an async iterator).
|
|
183
|
+
* - `'retention-expired'`: store's retention window elapsed past
|
|
184
|
+
* the last terminal observation; the record was GC'd.
|
|
185
|
+
* - `'tracker-stopped'`: `tracker.stop()` was called.
|
|
186
|
+
*/
|
|
187
|
+
export interface TxEventStopped extends Envelope {
|
|
188
|
+
kind: 'stopped';
|
|
189
|
+
reason: 'unsubscribed' | 'retention-expired' | 'tracker-stopped';
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Discriminated union of every event variant. Narrow on `kind` to
|
|
193
|
+
* access variant-specific fields.
|
|
194
|
+
*/
|
|
195
|
+
export type TxEvent = TxEventStarted | TxEventSeenInMempool | TxEventLeftMempool | TxEventSeenInBlock | TxEventVanishedFromBlock | TxEventReplacedBy | TxEventUnseenForNBlocks | TxEventSignalDegraded | TxEventSignalRecovered | TxEventStopped;
|
|
196
|
+
/**
|
|
197
|
+
* `TxStatus` — cached snapshot the state machine maintains per
|
|
198
|
+
* tracked hash. `getTxStatus(hash)` returns this; the iterator and
|
|
199
|
+
* callback adapters read from the same backing store so all three
|
|
200
|
+
* consumption shapes see consistent state.
|
|
201
|
+
*
|
|
202
|
+
* Carries the **last observation** rather than a derived editorial
|
|
203
|
+
* verb. Consumers interpret the fields as policy.
|
|
204
|
+
*/
|
|
205
|
+
export interface TxStatus {
|
|
206
|
+
hash: Hash;
|
|
207
|
+
chainId: number;
|
|
208
|
+
/** Last observed inclusion (null if never observed in a block). */
|
|
209
|
+
lastSeenInBlock: {
|
|
210
|
+
blockHash: Hash;
|
|
211
|
+
blockNumber: bigint;
|
|
212
|
+
transactionIndex: number;
|
|
213
|
+
/** Most recent confirmations count emitted. */
|
|
214
|
+
confirmations: number;
|
|
215
|
+
source: EventSource;
|
|
216
|
+
} | null;
|
|
217
|
+
/** Last observed mempool placement (null if never observed). */
|
|
218
|
+
lastSeenInMempool: {
|
|
219
|
+
bucket: 'pending' | 'queued';
|
|
220
|
+
tx: RawTx;
|
|
221
|
+
at: At;
|
|
222
|
+
source: EventSource;
|
|
223
|
+
} | null;
|
|
224
|
+
/** Replacement hash if ever observed (null otherwise). */
|
|
225
|
+
replacedBy: {
|
|
226
|
+
hash: Hash;
|
|
227
|
+
blockNumber: bigint | null;
|
|
228
|
+
} | null;
|
|
229
|
+
/** Last vanished-from-block observation, when applicable. */
|
|
230
|
+
vanishedAt: {
|
|
231
|
+
previousBlockHash: Hash;
|
|
232
|
+
canonicalBlockHash: Hash;
|
|
233
|
+
blockNumber: bigint;
|
|
234
|
+
} | null;
|
|
235
|
+
/** Number of consecutive observed blocks the hash has been unseen. */
|
|
236
|
+
unseenStreak: number;
|
|
237
|
+
/** First observation block number — used by retention. */
|
|
238
|
+
firstObservedAtBlock: bigint | null;
|
|
239
|
+
/** Most recent observation block number — used by retention. */
|
|
240
|
+
lastObservedAtBlock: bigint | null;
|
|
241
|
+
/** Capabilities at the most recent emit. */
|
|
242
|
+
capabilities: Capabilities;
|
|
243
|
+
}
|
|
244
|
+
/** Build a `started` event. */
|
|
245
|
+
export declare const buildStarted: (input: Envelope & {
|
|
246
|
+
capabilities: Capabilities;
|
|
247
|
+
}) => TxEventStarted;
|
|
248
|
+
/** Build a `seen-in-mempool` event. */
|
|
249
|
+
export declare const buildSeenInMempool: (input: Envelope & {
|
|
250
|
+
bucket: "pending" | "queued";
|
|
251
|
+
tx: RawTx;
|
|
252
|
+
}) => TxEventSeenInMempool;
|
|
253
|
+
/** Build a `left-mempool` event. */
|
|
254
|
+
export declare const buildLeftMempool: (input: Envelope) => TxEventLeftMempool;
|
|
255
|
+
/** Build a `seen-in-block` event. */
|
|
256
|
+
export declare const buildSeenInBlock: (input: Envelope & {
|
|
257
|
+
blockHash: Hash;
|
|
258
|
+
blockNumber: bigint;
|
|
259
|
+
transactionIndex: number;
|
|
260
|
+
confirmations: number;
|
|
261
|
+
receipt?: TransactionReceipt;
|
|
262
|
+
}) => TxEventSeenInBlock;
|
|
263
|
+
/**
|
|
264
|
+
* Build a `vanished-from-block` event. Spec §12.3 forbids
|
|
265
|
+
* `source: 'receipt-poll'` for this kind — receipt-poll cannot
|
|
266
|
+
* detect a reorg authoritatively, so the builder rejects that
|
|
267
|
+
* combination at construction rather than letting a malformed
|
|
268
|
+
* event ship to consumers.
|
|
269
|
+
*/
|
|
270
|
+
export declare const buildVanishedFromBlock: (input: Envelope & {
|
|
271
|
+
previousBlockHash: Hash;
|
|
272
|
+
canonicalBlockHash: Hash;
|
|
273
|
+
blockNumber: bigint;
|
|
274
|
+
}) => TxEventVanishedFromBlock;
|
|
275
|
+
/** Build a `replaced-by` event. */
|
|
276
|
+
export declare const buildReplacedBy: (input: Envelope & {
|
|
277
|
+
replacementHash: Hash;
|
|
278
|
+
replacementBlockNumber: bigint | null;
|
|
279
|
+
}) => TxEventReplacedBy;
|
|
280
|
+
/** Build an `unseen-for-N-blocks` event. */
|
|
281
|
+
export declare const buildUnseenForNBlocks: (input: Envelope & {
|
|
282
|
+
blocks: number;
|
|
283
|
+
}) => TxEventUnseenForNBlocks;
|
|
284
|
+
/** Build a `signal-degraded` event. */
|
|
285
|
+
export declare const buildSignalDegraded: (input: Envelope & {
|
|
286
|
+
capabilityLost: keyof Capabilities;
|
|
287
|
+
fallbackSource: EventSource;
|
|
288
|
+
}) => TxEventSignalDegraded;
|
|
289
|
+
/** Build a `signal-recovered` event. */
|
|
290
|
+
export declare const buildSignalRecovered: (input: Envelope & {
|
|
291
|
+
capabilityRestored: keyof Capabilities;
|
|
292
|
+
}) => TxEventSignalRecovered;
|
|
293
|
+
/** Build a `stopped` event. */
|
|
294
|
+
export declare const buildStopped: (input: Envelope & {
|
|
295
|
+
reason: "unsubscribed" | "retention-expired" | "tracker-stopped";
|
|
296
|
+
}) => TxEventStopped;
|
|
297
|
+
/**
|
|
298
|
+
* Snapshot constructor for a freshly-tracked hash. Used by the
|
|
299
|
+
* tracker to seed its in-memory record before any observation has
|
|
300
|
+
* landed. All "last observed" fields start `null`; `unseenStreak`
|
|
301
|
+
* starts `0`. Capabilities are passed in (sourced from
|
|
302
|
+
* `source.capabilities()` at construction).
|
|
303
|
+
*/
|
|
304
|
+
export declare const buildInitialStatus: (input: {
|
|
305
|
+
hash: Hash;
|
|
306
|
+
chainId: number;
|
|
307
|
+
capabilities: Capabilities;
|
|
308
|
+
}) => TxStatus;
|
|
309
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TxEvent` — the discriminated union of every observation the
|
|
3
|
+
* tracker emits, plus payload builders that guarantee every event
|
|
4
|
+
* carries a complete envelope.
|
|
5
|
+
*
|
|
6
|
+
* Per `docs/tx-tracker-spec.md` §6, this taxonomy is the contract
|
|
7
|
+
* between the tracker and every consumer. Naming is **strictly
|
|
8
|
+
* neutral** (§2.1): `seen-in-mempool` not `pending`, `seen-in-block`
|
|
9
|
+
* not `mined`, `vanished-from-block` not `reorged`. The tracker
|
|
10
|
+
* publishes facts; the consumer writes the policy on top.
|
|
11
|
+
*
|
|
12
|
+
* Every event variant extends a common `Envelope` carrying the
|
|
13
|
+
* tracked `hash`, the `chainId`, the `source` discriminator (per
|
|
14
|
+
* §2.2 — never silently downgrade) and the `at` block coordinate
|
|
15
|
+
* the observation was made at. Builders here produce that envelope
|
|
16
|
+
* once so the state machine in `tracker.ts` cannot accidentally
|
|
17
|
+
* publish a partial event.
|
|
18
|
+
*
|
|
19
|
+
* No I/O, no wall-clock, no mutation — pure data shape + pure
|
|
20
|
+
* builders. Browser/mobile safe (§2.4).
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Build an event envelope from the per-tracker context plus the
|
|
24
|
+
* call-site overrides. Used by every builder below so the envelope
|
|
25
|
+
* shape is centralized.
|
|
26
|
+
*/
|
|
27
|
+
const makeEnvelope = (input) => ({
|
|
28
|
+
hash: input.hash,
|
|
29
|
+
chainId: input.chainId,
|
|
30
|
+
source: input.source,
|
|
31
|
+
at: { blockNumber: input.at.blockNumber, timestamp: input.at.timestamp },
|
|
32
|
+
});
|
|
33
|
+
/** Build a `started` event. */
|
|
34
|
+
export const buildStarted = (input) => ({
|
|
35
|
+
...makeEnvelope(input),
|
|
36
|
+
kind: 'started',
|
|
37
|
+
capabilities: input.capabilities,
|
|
38
|
+
});
|
|
39
|
+
/** Build a `seen-in-mempool` event. */
|
|
40
|
+
export const buildSeenInMempool = (input) => ({
|
|
41
|
+
...makeEnvelope(input),
|
|
42
|
+
kind: 'seen-in-mempool',
|
|
43
|
+
bucket: input.bucket,
|
|
44
|
+
tx: input.tx,
|
|
45
|
+
});
|
|
46
|
+
/** Build a `left-mempool` event. */
|
|
47
|
+
export const buildLeftMempool = (input) => ({
|
|
48
|
+
...makeEnvelope(input),
|
|
49
|
+
kind: 'left-mempool',
|
|
50
|
+
});
|
|
51
|
+
/** Build a `seen-in-block` event. */
|
|
52
|
+
export const buildSeenInBlock = (input) => ({
|
|
53
|
+
...makeEnvelope(input),
|
|
54
|
+
kind: 'seen-in-block',
|
|
55
|
+
blockHash: input.blockHash,
|
|
56
|
+
blockNumber: input.blockNumber,
|
|
57
|
+
transactionIndex: input.transactionIndex,
|
|
58
|
+
confirmations: input.confirmations,
|
|
59
|
+
...(input.receipt !== undefined ? { receipt: input.receipt } : {}),
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Build a `vanished-from-block` event. Spec §12.3 forbids
|
|
63
|
+
* `source: 'receipt-poll'` for this kind — receipt-poll cannot
|
|
64
|
+
* detect a reorg authoritatively, so the builder rejects that
|
|
65
|
+
* combination at construction rather than letting a malformed
|
|
66
|
+
* event ship to consumers.
|
|
67
|
+
*/
|
|
68
|
+
export const buildVanishedFromBlock = (input) => {
|
|
69
|
+
if (input.source === 'receipt-poll') {
|
|
70
|
+
throw new Error('buildVanishedFromBlock: receipt-poll cannot detect reorgs ' +
|
|
71
|
+
'(spec §12.3). Use block-poll or subscription source.');
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
...makeEnvelope(input),
|
|
75
|
+
kind: 'vanished-from-block',
|
|
76
|
+
previousBlockHash: input.previousBlockHash,
|
|
77
|
+
canonicalBlockHash: input.canonicalBlockHash,
|
|
78
|
+
blockNumber: input.blockNumber,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** Build a `replaced-by` event. */
|
|
82
|
+
export const buildReplacedBy = (input) => ({
|
|
83
|
+
...makeEnvelope(input),
|
|
84
|
+
kind: 'replaced-by',
|
|
85
|
+
replacementHash: input.replacementHash,
|
|
86
|
+
replacementBlockNumber: input.replacementBlockNumber,
|
|
87
|
+
});
|
|
88
|
+
/** Build an `unseen-for-N-blocks` event. */
|
|
89
|
+
export const buildUnseenForNBlocks = (input) => ({
|
|
90
|
+
...makeEnvelope(input),
|
|
91
|
+
kind: 'unseen-for-N-blocks',
|
|
92
|
+
blocks: input.blocks,
|
|
93
|
+
});
|
|
94
|
+
/** Build a `signal-degraded` event. */
|
|
95
|
+
export const buildSignalDegraded = (input) => ({
|
|
96
|
+
...makeEnvelope(input),
|
|
97
|
+
kind: 'signal-degraded',
|
|
98
|
+
capabilityLost: input.capabilityLost,
|
|
99
|
+
fallbackSource: input.fallbackSource,
|
|
100
|
+
});
|
|
101
|
+
/** Build a `signal-recovered` event. */
|
|
102
|
+
export const buildSignalRecovered = (input) => ({
|
|
103
|
+
...makeEnvelope(input),
|
|
104
|
+
kind: 'signal-recovered',
|
|
105
|
+
capabilityRestored: input.capabilityRestored,
|
|
106
|
+
});
|
|
107
|
+
/** Build a `stopped` event. */
|
|
108
|
+
export const buildStopped = (input) => ({
|
|
109
|
+
...makeEnvelope(input),
|
|
110
|
+
kind: 'stopped',
|
|
111
|
+
reason: input.reason,
|
|
112
|
+
});
|
|
113
|
+
/**
|
|
114
|
+
* Snapshot constructor for a freshly-tracked hash. Used by the
|
|
115
|
+
* tracker to seed its in-memory record before any observation has
|
|
116
|
+
* landed. All "last observed" fields start `null`; `unseenStreak`
|
|
117
|
+
* starts `0`. Capabilities are passed in (sourced from
|
|
118
|
+
* `source.capabilities()` at construction).
|
|
119
|
+
*/
|
|
120
|
+
export const buildInitialStatus = (input) => ({
|
|
121
|
+
hash: input.hash,
|
|
122
|
+
chainId: input.chainId,
|
|
123
|
+
lastSeenInBlock: null,
|
|
124
|
+
lastSeenInMempool: null,
|
|
125
|
+
replacedBy: null,
|
|
126
|
+
vanishedAt: null,
|
|
127
|
+
unseenStreak: 0,
|
|
128
|
+
firstObservedAtBlock: null,
|
|
129
|
+
lastObservedAtBlock: null,
|
|
130
|
+
capabilities: input.capabilities,
|
|
131
|
+
});
|
|
132
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TxGroupEvent` — composite event union for `tracker.group([...hashes])`
|
|
3
|
+
* cross-tx correlation (spec §18.1, v0.8.0 design F3).
|
|
4
|
+
*
|
|
5
|
+
* Group emits its own kinds (group-progress / group-complete /
|
|
6
|
+
* group-failed / group-stopped) derived from the per-member event
|
|
7
|
+
* streams. Per-member events still flow through the underlying
|
|
8
|
+
* tracker.subscribe path; the group is a synthesis layer on top.
|
|
9
|
+
*
|
|
10
|
+
* Pure data shapes + pure builders. No I/O, no mutation.
|
|
11
|
+
*/
|
|
12
|
+
import type { At, Hash } from './events.js';
|
|
13
|
+
/**
|
|
14
|
+
* Common envelope on every group event. Carries the group identifier
|
|
15
|
+
* and the block coordinate the observation was made at.
|
|
16
|
+
*/
|
|
17
|
+
export interface TxGroupEventEnvelope {
|
|
18
|
+
groupId: string;
|
|
19
|
+
at: At;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Emitted when one or more members of the tracked group have reached
|
|
23
|
+
* inclusion in the canonical chain. `confirmed` is the count of members
|
|
24
|
+
* observed in blocks; `total` is the group size; `lastHash` is the most
|
|
25
|
+
* recently-included member's hash.
|
|
26
|
+
*/
|
|
27
|
+
export interface TxGroupEventProgress extends TxGroupEventEnvelope {
|
|
28
|
+
kind: 'group-progress';
|
|
29
|
+
confirmed: number;
|
|
30
|
+
total: number;
|
|
31
|
+
lastHash: Hash;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* All members of the group have reached inclusion in the canonical
|
|
35
|
+
* chain and none have been replaced or reorged. Final progress event
|
|
36
|
+
* before group stream closes (unless a reorg or replacement occurs).
|
|
37
|
+
*/
|
|
38
|
+
export interface TxGroupEventComplete extends TxGroupEventEnvelope {
|
|
39
|
+
kind: 'group-complete';
|
|
40
|
+
total: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* One member of the group was dropped (unseen for the threshold),
|
|
44
|
+
* failed (reverted or invalid), or replaced by a different tx with
|
|
45
|
+
* the same (from, nonce) pair. `reason` disambiguates the failure mode.
|
|
46
|
+
*/
|
|
47
|
+
export interface TxGroupEventFailed extends TxGroupEventEnvelope {
|
|
48
|
+
kind: 'group-failed';
|
|
49
|
+
failedHash: Hash;
|
|
50
|
+
reason: 'dropped' | 'failed' | 'replaced';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Group subscription was stopped before all members reached inclusion.
|
|
54
|
+
* Fires once per group subscription. Always the final event in the
|
|
55
|
+
* stream for that group.
|
|
56
|
+
*/
|
|
57
|
+
export interface TxGroupEventStopped extends TxGroupEventEnvelope {
|
|
58
|
+
kind: 'group-stopped';
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Discriminated union of every group event variant. Narrow on `kind`
|
|
62
|
+
* to access variant-specific fields.
|
|
63
|
+
*/
|
|
64
|
+
export type TxGroupEvent = TxGroupEventProgress | TxGroupEventComplete | TxGroupEventFailed | TxGroupEventStopped;
|
|
65
|
+
/** Build a `group-progress` event. */
|
|
66
|
+
export declare const buildGroupProgress: (input: TxGroupEventEnvelope & {
|
|
67
|
+
confirmed: number;
|
|
68
|
+
total: number;
|
|
69
|
+
lastHash: Hash;
|
|
70
|
+
}) => TxGroupEventProgress;
|
|
71
|
+
/** Build a `group-complete` event. */
|
|
72
|
+
export declare const buildGroupComplete: (input: TxGroupEventEnvelope & {
|
|
73
|
+
total: number;
|
|
74
|
+
}) => TxGroupEventComplete;
|
|
75
|
+
/** Build a `group-failed` event. */
|
|
76
|
+
export declare const buildGroupFailed: (input: TxGroupEventEnvelope & {
|
|
77
|
+
failedHash: Hash;
|
|
78
|
+
reason: "dropped" | "failed" | "replaced";
|
|
79
|
+
}) => TxGroupEventFailed;
|
|
80
|
+
/** Build a `group-stopped` event. */
|
|
81
|
+
export declare const buildGroupStopped: (input: TxGroupEventEnvelope) => TxGroupEventStopped;
|
|
82
|
+
//# sourceMappingURL=group-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-events.d.ts","sourceRoot":"","sources":["../src/group-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAE3C;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,EAAE,CAAA;CACP;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,IAAI,EAAE,gBAAgB,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,IAAI,CAAA;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,IAAI,EAAE,gBAAgB,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,IAAI,CAAA;IAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAA;CAC1C;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAC/D,IAAI,EAAE,eAAe,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GACpB,oBAAoB,GACpB,oBAAoB,GACpB,kBAAkB,GAClB,mBAAmB,CAAA;AAYvB,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,GAC7B,OAAO,oBAAoB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,KACjF,oBAMD,CAAA;AAEF,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,GAC7B,OAAO,oBAAoB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,KAC9C,oBAID,CAAA;AAEF,oCAAoC;AACpC,eAAO,MAAM,gBAAgB,GAC3B,OAAO,oBAAoB,GAAG;IAC5B,UAAU,EAAE,IAAI,CAAA;IAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAA;CAC1C,KACA,kBAKD,CAAA;AAEF,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,GAC5B,OAAO,oBAAoB,KAC1B,mBAGD,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `TxGroupEvent` — composite event union for `tracker.group([...hashes])`
|
|
3
|
+
* cross-tx correlation (spec §18.1, v0.8.0 design F3).
|
|
4
|
+
*
|
|
5
|
+
* Group emits its own kinds (group-progress / group-complete /
|
|
6
|
+
* group-failed / group-stopped) derived from the per-member event
|
|
7
|
+
* streams. Per-member events still flow through the underlying
|
|
8
|
+
* tracker.subscribe path; the group is a synthesis layer on top.
|
|
9
|
+
*
|
|
10
|
+
* Pure data shapes + pure builders. No I/O, no mutation.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Build an event envelope from the group context. Used by every builder
|
|
14
|
+
* below so the envelope shape is centralized and always produces a fresh
|
|
15
|
+
* copy (no aliasing).
|
|
16
|
+
*/
|
|
17
|
+
const makeEnvelope = (input) => ({
|
|
18
|
+
groupId: input.groupId,
|
|
19
|
+
at: { blockNumber: input.at.blockNumber, timestamp: input.at.timestamp },
|
|
20
|
+
});
|
|
21
|
+
/** Build a `group-progress` event. */
|
|
22
|
+
export const buildGroupProgress = (input) => ({
|
|
23
|
+
...makeEnvelope(input),
|
|
24
|
+
kind: 'group-progress',
|
|
25
|
+
confirmed: input.confirmed,
|
|
26
|
+
total: input.total,
|
|
27
|
+
lastHash: input.lastHash,
|
|
28
|
+
});
|
|
29
|
+
/** Build a `group-complete` event. */
|
|
30
|
+
export const buildGroupComplete = (input) => ({
|
|
31
|
+
...makeEnvelope(input),
|
|
32
|
+
kind: 'group-complete',
|
|
33
|
+
total: input.total,
|
|
34
|
+
});
|
|
35
|
+
/** Build a `group-failed` event. */
|
|
36
|
+
export const buildGroupFailed = (input) => ({
|
|
37
|
+
...makeEnvelope(input),
|
|
38
|
+
kind: 'group-failed',
|
|
39
|
+
failedHash: input.failedHash,
|
|
40
|
+
reason: input.reason,
|
|
41
|
+
});
|
|
42
|
+
/** Build a `group-stopped` event. */
|
|
43
|
+
export const buildGroupStopped = (input) => ({
|
|
44
|
+
...makeEnvelope(input),
|
|
45
|
+
kind: 'group-stopped',
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=group-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-events.js","sourceRoot":"","sources":["../src/group-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkEH;;;;GAIG;AACH,MAAM,YAAY,GAAG,CAAC,KAA2B,EAAwB,EAAE,CAAC,CAAC;IAC3E,OAAO,EAAE,KAAK,CAAC,OAAO;IACtB,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE;CACzE,CAAC,CAAA;AAEF,sCAAsC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,KAAkF,EAC5D,EAAE,CAAC,CAAC;IAC1B,GAAG,YAAY,CAAC,KAAK,CAAC;IACtB,IAAI,EAAE,gBAAgB;IACtB,SAAS,EAAE,KAAK,CAAC,SAAS;IAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;IAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;CACzB,CAAC,CAAA;AAEF,sCAAsC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,KAA+C,EACzB,EAAE,CAAC,CAAC;IAC1B,GAAG,YAAY,CAAC,KAAK,CAAC;IACtB,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,KAAK,CAAC,KAAK;CACnB,CAAC,CAAA;AAEF,oCAAoC;AACpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAGC,EACmB,EAAE,CAAC,CAAC;IACxB,GAAG,YAAY,CAAC,KAAK,CAAC;IACtB,IAAI,EAAE,cAAc;IACpB,UAAU,EAAE,KAAK,CAAC,UAAU;IAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;CACrB,CAAC,CAAA;AAEF,qCAAqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,KAA2B,EACN,EAAE,CAAC,CAAC;IACzB,GAAG,YAAY,CAAC,KAAK,CAAC;IACtB,IAAI,EAAE,eAAe;CACtB,CAAC,CAAA"}
|
package/dist/group.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createTxGroup` — synthesis layer on top of per-hash tracker
|
|
3
|
+
* subscriptions. Spec §18.1, v0.8.0 design F3.
|
|
4
|
+
*
|
|
5
|
+
* Listens to each member hash via the tracker's existing subscribe API,
|
|
6
|
+
* tracks confirmed/failed counters, and emits group-progress /
|
|
7
|
+
* group-complete / group-failed once per terminal transition. Member
|
|
8
|
+
* unsubscribes are torn down on stop().
|
|
9
|
+
*
|
|
10
|
+
* Replacement does NOT auto-promote — if a member is replaced via
|
|
11
|
+
* same-nonce bump, the group emits group-failed with reason
|
|
12
|
+
* 'replaced'. The consumer constructs a new group with the new hash
|
|
13
|
+
* if they want the replacement to count.
|
|
14
|
+
*
|
|
15
|
+
* Edge case: an empty hashes array immediately emits group-complete
|
|
16
|
+
* with total=0 (vacuously all confirmed) and marks the group terminal.
|
|
17
|
+
* This is a safe, predictable default and matches the mathematical
|
|
18
|
+
* sense of "all zero members confirmed."
|
|
19
|
+
*/
|
|
20
|
+
import type { Hash } from './events.js';
|
|
21
|
+
import type { GroupOptions, TxGroupSubscription, TxTracker } from './tracker.js';
|
|
22
|
+
/**
|
|
23
|
+
* Construct a group subscription that synthesises per-member `TxEvent`
|
|
24
|
+
* streams into group-level events.
|
|
25
|
+
*
|
|
26
|
+
* @param tracker - The tracker instance to call `subscribe` on.
|
|
27
|
+
* @param hashes - Member transaction hashes. Order is not significant.
|
|
28
|
+
* @param options - Optional group-level and member-level overrides.
|
|
29
|
+
*/
|
|
30
|
+
export declare const createTxGroup: (tracker: TxTracker, hashes: Hash[], options?: GroupOptions) => TxGroupSubscription;
|
|
31
|
+
//# sourceMappingURL=group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,aAAa,CAAA;AAQ1D,OAAO,KAAK,EACV,YAAY,EAEZ,mBAAmB,EACnB,SAAS,EACV,MAAM,cAAc,CAAA;AAErB;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS,SAAS,EAClB,QAAQ,IAAI,EAAE,EACd,UAAS,YAAiB,KACzB,mBAyLF,CAAA"}
|