@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/group.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
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 { Subscriptions } from '@valve-tech/chain-source';
|
|
21
|
+
import { buildGroupComplete, buildGroupFailed, buildGroupProgress, buildGroupStopped, } from './group-events.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 const createTxGroup = (tracker, hashes, options = {}) => {
|
|
31
|
+
const groupId = options.groupId ??
|
|
32
|
+
`grp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
33
|
+
const memberOptions = options.memberOptions ?? {};
|
|
34
|
+
const subs = new Subscriptions();
|
|
35
|
+
const total = hashes.length;
|
|
36
|
+
const confirmedSet = new Set();
|
|
37
|
+
let terminal = false;
|
|
38
|
+
const memberUnsubs = [];
|
|
39
|
+
const emit = (event) => subs.emit(event);
|
|
40
|
+
// Empty group — vacuously all confirmed. Emit complete immediately
|
|
41
|
+
// (synchronously; no member subscriptions to set up).
|
|
42
|
+
if (total === 0) {
|
|
43
|
+
terminal = true;
|
|
44
|
+
const zeroAt = { blockNumber: 0n, timestamp: 0n };
|
|
45
|
+
emit(buildGroupComplete({ groupId, at: zeroAt, total: 0 }));
|
|
46
|
+
}
|
|
47
|
+
const handleMemberEvent = (memberHash, event) => {
|
|
48
|
+
if (terminal)
|
|
49
|
+
return;
|
|
50
|
+
const at = event.at;
|
|
51
|
+
if (event.kind === 'seen-in-block' && event.confirmations >= 1) {
|
|
52
|
+
// Idempotency guard: same hash can emit multiple seen-in-block
|
|
53
|
+
// events (confirmations 1, 2, 3 …) — only count it once.
|
|
54
|
+
if (confirmedSet.has(memberHash))
|
|
55
|
+
return;
|
|
56
|
+
confirmedSet.add(memberHash);
|
|
57
|
+
if (confirmedSet.size < total) {
|
|
58
|
+
emit(buildGroupProgress({
|
|
59
|
+
groupId,
|
|
60
|
+
at,
|
|
61
|
+
confirmed: confirmedSet.size,
|
|
62
|
+
total,
|
|
63
|
+
lastHash: memberHash,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
terminal = true;
|
|
68
|
+
emit(buildGroupComplete({ groupId, at, total }));
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (event.kind === 'unseen-for-N-blocks') {
|
|
73
|
+
terminal = true;
|
|
74
|
+
emit(buildGroupFailed({
|
|
75
|
+
groupId,
|
|
76
|
+
at,
|
|
77
|
+
failedHash: memberHash,
|
|
78
|
+
reason: 'dropped',
|
|
79
|
+
}));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (event.kind === 'replaced-by') {
|
|
83
|
+
terminal = true;
|
|
84
|
+
emit(buildGroupFailed({
|
|
85
|
+
groupId,
|
|
86
|
+
at,
|
|
87
|
+
failedHash: memberHash,
|
|
88
|
+
reason: 'replaced',
|
|
89
|
+
}));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
for (const hash of hashes) {
|
|
94
|
+
const unsub = tracker.subscribe(hash, (event) => handleMemberEvent(hash, event), { ...memberOptions, emitInitial: false });
|
|
95
|
+
memberUnsubs.push(unsub);
|
|
96
|
+
}
|
|
97
|
+
let stopped = false;
|
|
98
|
+
const stop = () => {
|
|
99
|
+
if (stopped)
|
|
100
|
+
return;
|
|
101
|
+
stopped = true;
|
|
102
|
+
for (const unsub of memberUnsubs) {
|
|
103
|
+
try {
|
|
104
|
+
unsub();
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Swallow per-sub teardown errors — we always emit group-stopped.
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
emit(buildGroupStopped({ groupId, at: { blockNumber: 0n, timestamp: 0n } }));
|
|
111
|
+
};
|
|
112
|
+
const snapshot = () => {
|
|
113
|
+
const out = {};
|
|
114
|
+
for (const hash of hashes)
|
|
115
|
+
out[hash] = tracker.getTxStatus(hash);
|
|
116
|
+
return out;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Async-iterable surface over the group event stream. Resolves each
|
|
120
|
+
* `next()` call with the next queued event, or parks the caller in a
|
|
121
|
+
* waiter array until one arrives. Terminal events (group-complete /
|
|
122
|
+
* group-failed / group-stopped) flip `done` so subsequent `next()`
|
|
123
|
+
* calls resolve immediately with `done: true`.
|
|
124
|
+
*/
|
|
125
|
+
const events = () => ({
|
|
126
|
+
[Symbol.asyncIterator]: () => {
|
|
127
|
+
const queue = [];
|
|
128
|
+
const waiters = [];
|
|
129
|
+
let done = false;
|
|
130
|
+
const unsub = subs.subscribe((event) => {
|
|
131
|
+
if (event.kind === 'group-stopped' ||
|
|
132
|
+
event.kind === 'group-complete' ||
|
|
133
|
+
event.kind === 'group-failed') {
|
|
134
|
+
done = true;
|
|
135
|
+
}
|
|
136
|
+
const waiter = waiters.shift();
|
|
137
|
+
if (waiter) {
|
|
138
|
+
waiter({ value: event, done: false });
|
|
139
|
+
if (done) {
|
|
140
|
+
// Drain remaining waiters with done after a terminal event.
|
|
141
|
+
// Reachable when a consumer parks multiple `next()` calls
|
|
142
|
+
// concurrently before any event arrives — first waiter gets
|
|
143
|
+
// the terminal event, the rest resolve with done:true here.
|
|
144
|
+
while (waiters.length > 0) {
|
|
145
|
+
waiters.shift()({
|
|
146
|
+
value: undefined,
|
|
147
|
+
done: true,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
queue.push(event);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return {
|
|
157
|
+
next: () => {
|
|
158
|
+
if (queue.length > 0) {
|
|
159
|
+
const value = queue.shift();
|
|
160
|
+
return Promise.resolve({ value, done: false });
|
|
161
|
+
}
|
|
162
|
+
if (done) {
|
|
163
|
+
return Promise.resolve({
|
|
164
|
+
value: undefined,
|
|
165
|
+
done: true,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return new Promise((resolve) => {
|
|
169
|
+
waiters.push(resolve);
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
return: () => {
|
|
173
|
+
unsub();
|
|
174
|
+
done = true;
|
|
175
|
+
while (waiters.length > 0) {
|
|
176
|
+
waiters.shift()({
|
|
177
|
+
value: undefined,
|
|
178
|
+
done: true,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return Promise.resolve({
|
|
182
|
+
value: undefined,
|
|
183
|
+
done: true,
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
return {
|
|
190
|
+
events,
|
|
191
|
+
subscribe: (cb) => subs.subscribe(cb),
|
|
192
|
+
snapshot,
|
|
193
|
+
stop,
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group.js","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* `@valve-tech/tx-tracker` — per-tx state machine for EVM chains.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Emits **neutral observations** (`seen-in-mempool`, `seen-in-block`,
|
|
5
|
+
* `replaced-by`, `vanished-from-block`, `unseen-for-N-blocks`,
|
|
6
|
+
* `signal-degraded`, `signal-recovered`, `stopped`) so wallet UIs,
|
|
7
|
+
* indexers, and relays can write their own interpretations on top.
|
|
8
|
+
* The tracker itself never says "confirmed" or "stuck"; it gives
|
|
9
|
+
* you the data to decide.
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* Three consumption shapes (callback, async iterator, snapshot)
|
|
12
|
+
* over one push-based core. Per-method capability detection keeps
|
|
13
|
+
* the "no silent downgrade" invariant — every emitted event carries
|
|
14
|
+
* a `source` discriminator (`'subscription' | 'block-poll' |
|
|
15
|
+
* 'mempool-snapshot' | 'receipt-poll'`).
|
|
12
16
|
*
|
|
13
|
-
*
|
|
17
|
+
* Consumes `@valve-tech/chain-source` for upstream signals; sibling
|
|
18
|
+
* to `@valve-tech/gas-oracle` (both consume the same source, neither
|
|
19
|
+
* depends on the other).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* import { createPublicClient, http } from 'viem'
|
|
23
|
+
* import { mainnet } from 'viem/chains'
|
|
24
|
+
* import { createChainSource } from '@valve-tech/chain-source'
|
|
25
|
+
* import { createTxTracker } from '@valve-tech/tx-tracker'
|
|
26
|
+
*
|
|
27
|
+
* const client = createPublicClient({ chain: mainnet, transport: http() })
|
|
28
|
+
* const source = createChainSource({ client })
|
|
29
|
+
* const tracker = createTxTracker({ source, chainId: 1 })
|
|
30
|
+
*
|
|
31
|
+
* source.start()
|
|
32
|
+
* tracker.start()
|
|
33
|
+
*
|
|
34
|
+
* for await (const event of tracker.track('0xabc...')) {
|
|
35
|
+
* console.log(event.kind, event.source, event.at.blockNumber)
|
|
36
|
+
* if (event.kind === 'seen-in-block' && event.confirmations >= 6) break
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* tracker.stop()
|
|
40
|
+
* source.stop()
|
|
14
41
|
*/
|
|
15
|
-
export {};
|
|
42
|
+
export { createTxTracker } from './tracker.js';
|
|
43
|
+
export type { CreateTxTrackerOptions, TxTracker, TrackOptions, BulkTrackOptions, TxMatchEvent, TxSubscription, LostSignalPolicy, GroupOptions, TxGroupSubscription, } from './tracker.js';
|
|
44
|
+
export { buildStarted, buildSeenInMempool, buildLeftMempool, buildSeenInBlock, buildVanishedFromBlock, buildReplacedBy, buildUnseenForNBlocks, buildSignalDegraded, buildSignalRecovered, buildStopped, buildInitialStatus, } from './events.js';
|
|
45
|
+
export type { Address, At, Envelope, Hash, TxEvent, TxEventStarted, TxEventSeenInMempool, TxEventLeftMempool, TxEventSeenInBlock, TxEventVanishedFromBlock, TxEventReplacedBy, TxEventUnseenForNBlocks, TxEventSignalDegraded, TxEventSignalRecovered, TxEventStopped, TxStatus, } from './events.js';
|
|
46
|
+
export { createInMemoryStore, computeRetentionExpiry, defaultRetentionBlocks, } from './store.js';
|
|
47
|
+
export type { BulkSelector, HashSelector, InMemoryStoreOptions, PersistedSubscription, TrackedTxRecord, TxTrackerStore, } from './store.js';
|
|
48
|
+
export { appendBlock, defaultReorgDepthBlocks, detectDivergences, } from './reorg.js';
|
|
49
|
+
export type { BlockDivergence, BlockSample } from './reorg.js';
|
|
50
|
+
export { compileSelector, defaultMaxBulkSubscriptions, matchAll, } from './selectors.js';
|
|
51
|
+
export type { BulkMatchPayload, CompiledSelector } from './selectors.js';
|
|
52
|
+
export { createTxGroup } from './group.js';
|
|
53
|
+
export { watchTransaction } from './watch-transaction.js';
|
|
54
|
+
export type { WatchTransactionOptions } from './watch-transaction.js';
|
|
55
|
+
export { waitForTransaction } from './wait-for-transaction.js';
|
|
56
|
+
export type { WaitForTransactionOptions, WaitForTransactionOutcome, } from './wait-for-transaction.js';
|
|
57
|
+
export { waitForPending, WaitForPendingTimeoutError, } from './wait-for-pending.js';
|
|
58
|
+
export type { WaitForPendingOptions } from './wait-for-pending.js';
|
|
59
|
+
export { buildGroupComplete, buildGroupFailed, buildGroupProgress, buildGroupStopped, } from './group-events.js';
|
|
60
|
+
export type { TxGroupEvent, TxGroupEventComplete, TxGroupEventEnvelope, TxGroupEventFailed, TxGroupEventProgress, TxGroupEventStopped, } from './group-events.js';
|
|
61
|
+
export { replaceTransaction } from './replace-transaction.js';
|
|
62
|
+
export type { ReplaceTransactionNewGas, ReplaceTransactionOptions, ReplaceTransactionOriginal, } from './replace-transaction.js';
|
|
16
63
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EACV,sBAAsB,EACtB,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,GACpB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,OAAO,EACP,EAAE,EACF,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,cAAc,EACd,QAAQ,GACT,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE9D,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,QAAQ,GACT,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAExE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAErE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,YAAY,EACV,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAA;AAElC,OAAO,EACL,cAAc,EACd,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAElE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAC7D,YAAY,EACV,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,0BAA0B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* `@valve-tech/tx-tracker` — per-tx state machine for EVM chains.
|
|
3
|
+
*
|
|
4
|
+
* Emits **neutral observations** (`seen-in-mempool`, `seen-in-block`,
|
|
5
|
+
* `replaced-by`, `vanished-from-block`, `unseen-for-N-blocks`,
|
|
6
|
+
* `signal-degraded`, `signal-recovered`, `stopped`) so wallet UIs,
|
|
7
|
+
* indexers, and relays can write their own interpretations on top.
|
|
8
|
+
* The tracker itself never says "confirmed" or "stuck"; it gives
|
|
9
|
+
* you the data to decide.
|
|
10
|
+
*
|
|
11
|
+
* Three consumption shapes (callback, async iterator, snapshot)
|
|
12
|
+
* over one push-based core. Per-method capability detection keeps
|
|
13
|
+
* the "no silent downgrade" invariant — every emitted event carries
|
|
14
|
+
* a `source` discriminator (`'subscription' | 'block-poll' |
|
|
15
|
+
* 'mempool-snapshot' | 'receipt-poll'`).
|
|
16
|
+
*
|
|
17
|
+
* Consumes `@valve-tech/chain-source` for upstream signals; sibling
|
|
18
|
+
* to `@valve-tech/gas-oracle` (both consume the same source, neither
|
|
19
|
+
* depends on the other).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* import { createPublicClient, http } from 'viem'
|
|
23
|
+
* import { mainnet } from 'viem/chains'
|
|
24
|
+
* import { createChainSource } from '@valve-tech/chain-source'
|
|
25
|
+
* import { createTxTracker } from '@valve-tech/tx-tracker'
|
|
26
|
+
*
|
|
27
|
+
* const client = createPublicClient({ chain: mainnet, transport: http() })
|
|
28
|
+
* const source = createChainSource({ client })
|
|
29
|
+
* const tracker = createTxTracker({ source, chainId: 1 })
|
|
30
|
+
*
|
|
31
|
+
* source.start()
|
|
32
|
+
* tracker.start()
|
|
33
|
+
*
|
|
34
|
+
* for await (const event of tracker.track('0xabc...')) {
|
|
35
|
+
* console.log(event.kind, event.source, event.at.blockNumber)
|
|
36
|
+
* if (event.kind === 'seen-in-block' && event.confirmations >= 6) break
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* tracker.stop()
|
|
40
|
+
* source.stop()
|
|
41
|
+
*/
|
|
42
|
+
export { createTxTracker } from './tracker.js';
|
|
43
|
+
export { buildStarted, buildSeenInMempool, buildLeftMempool, buildSeenInBlock, buildVanishedFromBlock, buildReplacedBy, buildUnseenForNBlocks, buildSignalDegraded, buildSignalRecovered, buildStopped, buildInitialStatus, } from './events.js';
|
|
44
|
+
export { createInMemoryStore, computeRetentionExpiry, defaultRetentionBlocks, } from './store.js';
|
|
45
|
+
export { appendBlock, defaultReorgDepthBlocks, detectDivergences, } from './reorg.js';
|
|
46
|
+
export { compileSelector, defaultMaxBulkSubscriptions, matchAll, } from './selectors.js';
|
|
47
|
+
export { createTxGroup } from './group.js';
|
|
48
|
+
export { watchTransaction } from './watch-transaction.js';
|
|
49
|
+
export { waitForTransaction } from './wait-for-transaction.js';
|
|
50
|
+
export { waitForPending, WaitForPendingTimeoutError, } from './wait-for-pending.js';
|
|
51
|
+
export { buildGroupComplete, buildGroupFailed, buildGroupProgress, buildGroupStopped, } from './group-events.js';
|
|
52
|
+
export { replaceTransaction } from './replace-transaction.js';
|
|
2
53
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAa9C,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,GACnB,MAAM,aAAa,CAAA;AAoBpB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAA;AAUnB,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,QAAQ,GACT,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAGzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAM9D,OAAO,EACL,cAAc,EACd,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAU1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-record decision functions — the **pure** logic that turns one
|
|
3
|
+
* upstream observation (a block or a mempool snapshot) plus one
|
|
4
|
+
* tracked record's current state into the events that should be
|
|
5
|
+
* emitted and the state patch the orchestrator should apply.
|
|
6
|
+
*
|
|
7
|
+
* These functions are extracted from `tracker.ts`'s `onBlock` /
|
|
8
|
+
* `onMempool` so each branch of the per-record state machine is
|
|
9
|
+
* testable with literal fixture inputs — no stub source, no async
|
|
10
|
+
* orchestration, no shared mutable closure. This is the same
|
|
11
|
+
* primitive-vs-orchestrator split that `oracle.ts` (`reducePollInputs`
|
|
12
|
+
* pure / poll loop stateful) and `chain-source` (math pure / source
|
|
13
|
+
* stateful) already follow.
|
|
14
|
+
*
|
|
15
|
+
* Inputs are immutable; outputs are immutable. The caller in
|
|
16
|
+
* `tracker.ts` applies the returned `statusPatch` and `identityPatch`
|
|
17
|
+
* to its mutable `TrackedRecord`, then emits the returned `events`
|
|
18
|
+
* via its event-bus + store-audit-log machinery.
|
|
19
|
+
*/
|
|
20
|
+
import type { EventSource, RawTx, TransactionReceipt } from '@valve-tech/chain-source';
|
|
21
|
+
import { type At, type Hash, type TxEvent, type TxStatus } from './events.js';
|
|
22
|
+
/**
|
|
23
|
+
* Read-only projection of `TrackedRecord` that the decision functions
|
|
24
|
+
* consume. The orchestrator passes its mutable record through this
|
|
25
|
+
* shape so the pure layer cannot accidentally mutate state.
|
|
26
|
+
*/
|
|
27
|
+
export interface ReadonlyTrackedRecord {
|
|
28
|
+
hash: Hash;
|
|
29
|
+
status: TxStatus;
|
|
30
|
+
identity: {
|
|
31
|
+
from: string;
|
|
32
|
+
nonce: string;
|
|
33
|
+
} | null;
|
|
34
|
+
inLastMempoolSnapshot: boolean;
|
|
35
|
+
unseenThresholdBlocks: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Cached `(from, nonce)` identity of the tracked tx. Used for
|
|
39
|
+
* replacement detection.
|
|
40
|
+
*/
|
|
41
|
+
export interface IdentityPatch {
|
|
42
|
+
from: string;
|
|
43
|
+
nonce: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Result of a decision function: events to emit and patches to apply
|
|
47
|
+
* to the tracked record. The patch shapes are deliberately narrow —
|
|
48
|
+
* only the fields the function decided to change. The orchestrator
|
|
49
|
+
* merges them into its mutable record.
|
|
50
|
+
*/
|
|
51
|
+
export interface ObservationResult {
|
|
52
|
+
events: TxEvent[];
|
|
53
|
+
statusPatch: Partial<TxStatus>;
|
|
54
|
+
identityPatch: IdentityPatch | null;
|
|
55
|
+
/** Set when the per-mempool-tick "in-snapshot?" flag should change. */
|
|
56
|
+
inMempoolPatch: boolean | null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Inputs to `decideBlockObservation`. The orchestrator builds a
|
|
60
|
+
* `txHashSet` once per block and passes it for O(1) "did this hash
|
|
61
|
+
* appear?" lookups across every tracked record.
|
|
62
|
+
*/
|
|
63
|
+
export interface BlockObservationInput {
|
|
64
|
+
record: ReadonlyTrackedRecord;
|
|
65
|
+
blockHash: Hash;
|
|
66
|
+
blockNumber: bigint;
|
|
67
|
+
txHashSet: ReadonlySet<Hash>;
|
|
68
|
+
txs: ReadonlyArray<RawTx>;
|
|
69
|
+
chainId: number;
|
|
70
|
+
eventSource: EventSource;
|
|
71
|
+
envelope: At;
|
|
72
|
+
/**
|
|
73
|
+
* The previous canonical tip's block number, or `null` if this is
|
|
74
|
+
* the first block the tracker has seen. Used to gate the
|
|
75
|
+
* "confirmation bump" path — we don't bump confirmations on the
|
|
76
|
+
* very first block we observe.
|
|
77
|
+
*/
|
|
78
|
+
previousTipNumber: bigint | null;
|
|
79
|
+
/**
|
|
80
|
+
* Pre-fetched receipts for hashes whose `withReceipts` flag is set.
|
|
81
|
+
* When a hash appears in this map, the receipt is attached to the
|
|
82
|
+
* `seen-in-block` event. Omitted or empty means no enrichment. This
|
|
83
|
+
* is the sole path for F2 eager receipt attachment (spec §18.2) —
|
|
84
|
+
* the orchestrator fetches and populates this map before calling
|
|
85
|
+
* `decideBlockObservation`, so the first emitted event carries the
|
|
86
|
+
* receipt without a follow-up re-emit.
|
|
87
|
+
*/
|
|
88
|
+
prefetchedReceipts?: ReadonlyMap<Hash, TransactionReceipt>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Per-record decision for one new canonical block. Returns the events
|
|
92
|
+
* to emit and the state patch to apply. Mutually-exclusive paths,
|
|
93
|
+
* evaluated in order:
|
|
94
|
+
*
|
|
95
|
+
* 1. Hash is in this block → fresh inclusion (emit `seen-in-block`
|
|
96
|
+
* with `confirmations: 1`) OR same-block re-observation (no
|
|
97
|
+
* emit; `lastSeenInBlock` is already current).
|
|
98
|
+
* 2. Hash NOT in this block but was previously included → bump
|
|
99
|
+
* `confirmations` on the cached observation, emit a fresh
|
|
100
|
+
* `seen-in-block` carrying the new count.
|
|
101
|
+
* 3. Hash NOT in this block, no prior inclusion, but identity is
|
|
102
|
+
* cached AND a different hash with the same `(from, nonce)` is
|
|
103
|
+
* in this block → emit `replaced-by` with the replacement's
|
|
104
|
+
* block number.
|
|
105
|
+
* 4. Truly unseen → bump the unseen-block streak; emit
|
|
106
|
+
* `unseen-for-N-blocks` when the streak crosses the
|
|
107
|
+
* subscription's threshold. Does NOT emit on the first block
|
|
108
|
+
* after subscription (no `firstObservedAtBlock` yet).
|
|
109
|
+
*/
|
|
110
|
+
export declare const decideBlockObservation: (input: BlockObservationInput) => ObservationResult;
|
|
111
|
+
/**
|
|
112
|
+
* Inputs to `decideMempoolObservation`. The orchestrator builds the
|
|
113
|
+
* hash-keyed snapshot index once per mempool tick.
|
|
114
|
+
*/
|
|
115
|
+
export interface MempoolObservationInput {
|
|
116
|
+
record: ReadonlyTrackedRecord;
|
|
117
|
+
presence: {
|
|
118
|
+
bucket: 'pending' | 'queued';
|
|
119
|
+
tx: RawTx;
|
|
120
|
+
} | null;
|
|
121
|
+
/**
|
|
122
|
+
* The replacement candidate found in the snapshot for this record's
|
|
123
|
+
* `(from, nonce)` identity, or `null` if none. Computed by the
|
|
124
|
+
* orchestrator once per record so this function stays pure on
|
|
125
|
+
* inputs (no closure over the snapshot).
|
|
126
|
+
*/
|
|
127
|
+
replacementInMempool: RawTx | null;
|
|
128
|
+
chainId: number;
|
|
129
|
+
eventSource: EventSource;
|
|
130
|
+
envelope: At;
|
|
131
|
+
/**
|
|
132
|
+
* The current canonical-tip block number the orchestrator is using
|
|
133
|
+
* for `firstObservedAtBlock` / `lastObservedAtBlock` book-keeping.
|
|
134
|
+
* Falls back to `0n` when no tip has been observed yet.
|
|
135
|
+
*/
|
|
136
|
+
tipBlockNumber: bigint;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Per-record decision for one mempool snapshot. Three independent
|
|
140
|
+
* outputs that may all fire on the same call:
|
|
141
|
+
*
|
|
142
|
+
* - **Presence transition** — emit `seen-in-mempool` on first
|
|
143
|
+
* observation or bucket change; emit `left-mempool` when a
|
|
144
|
+
* previously-seen hash is absent from this snapshot.
|
|
145
|
+
* - **Replacement** — emit `replaced-by` (with `null` block) when
|
|
146
|
+
* the orchestrator's pre-computed `replacementInMempool` is set
|
|
147
|
+
* AND the record hasn't already recorded a replacement.
|
|
148
|
+
*/
|
|
149
|
+
export declare const decideMempoolObservation: (input: MempoolObservationInput) => ObservationResult;
|
|
150
|
+
/**
|
|
151
|
+
* Find a tx in `txs` whose `(from, nonce)` matches `identity` but
|
|
152
|
+
* whose hash differs from `originalHash` — the replacement candidate
|
|
153
|
+
* for the original tracked tx. Compares senders case-insensitively
|
|
154
|
+
* since upstreams disagree on checksum form.
|
|
155
|
+
*/
|
|
156
|
+
export declare const findReplacementInBlock: (identity: {
|
|
157
|
+
from: string;
|
|
158
|
+
nonce: string;
|
|
159
|
+
}, originalHash: Hash, txs: ReadonlyArray<RawTx>) => RawTx | null;
|
|
160
|
+
/**
|
|
161
|
+
* Cache the tx's `(from, nonce)` as the record's identity if it's
|
|
162
|
+
* not already cached AND the tx carries both fields. Returns the
|
|
163
|
+
* patch to apply (or `null` when no change).
|
|
164
|
+
*/
|
|
165
|
+
export declare const cacheIdentity: (current: {
|
|
166
|
+
from: string;
|
|
167
|
+
nonce: string;
|
|
168
|
+
} | null, tx: RawTx) => IdentityPatch | null;
|
|
169
|
+
//# sourceMappingURL=observations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../src/observations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAEtF,OAAO,EAML,KAAK,EAAE,EACP,KAAK,IAAI,EACT,KAAK,OAAO,EACZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAA;AAEpB;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,QAAQ,CAAA;IAChB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAChD,qBAAqB,EAAE,OAAO,CAAA;IAC9B,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,EAAE,CAAA;IACjB,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9B,aAAa,EAAE,aAAa,GAAG,IAAI,CAAA;IACnC,uEAAuE;IACvE,cAAc,EAAE,OAAO,GAAG,IAAI,CAAA;CAC/B;AAaD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,qBAAqB,CAAA;IAC7B,SAAS,EAAE,IAAI,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;IAC5B,GAAG,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,WAAW,CAAA;IACxB,QAAQ,EAAE,EAAE,CAAA;IACZ;;;;;OAKG;IACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;CAC3D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO,qBAAqB,KAC3B,iBAkJF,CAAA;AAMD;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,qBAAqB,CAAA;IAC7B,QAAQ,EAAE;QAAE,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;QAAC,EAAE,EAAE,KAAK,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5D;;;;;OAKG;IACH,oBAAoB,EAAE,KAAK,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,WAAW,CAAA;IACxB,QAAQ,EAAE,EAAE,CAAA;IACZ;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,uBAAuB,KAC7B,iBAqFF,CAAA;AAMD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAU;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACzC,cAAc,IAAI,EAClB,KAAK,aAAa,CAAC,KAAK,CAAC,KACxB,KAAK,GAAG,IAUV,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC/C,IAAI,KAAK,KACR,aAAa,GAAG,IAIlB,CAAA"}
|