@valve-tech/tx-tracker 0.5.0 → 0.7.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 +138 -0
- package/README.md +13 -6
- package/dist/events.d.ts +299 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +131 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +46 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -1
- package/dist/index.js.map +1 -1
- package/dist/observations.d.ts +159 -0
- package/dist/observations.d.ts.map +1 -0
- package/dist/observations.js +283 -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/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 +165 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +823 -0
- package/dist/tracker.js.map +1 -0
- package/package.json +6 -1
- package/skills/tx-tracker-integration/SKILL.md +168 -0
|
@@ -0,0 +1,165 @@
|
|
|
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 Address, type At, type Hash, type TxEvent, type TxStatus } from './events.js';
|
|
40
|
+
import { type BulkSelector, type TxTrackerStore } from './store.js';
|
|
41
|
+
/**
|
|
42
|
+
* Lost-signal policy (spec §8). `'emit-uncertain'` is the default
|
|
43
|
+
* — every transition to a degraded source emits `signal-degraded`.
|
|
44
|
+
* `'silent'` keeps the events to itself; `'receipt-poll-fallback'`
|
|
45
|
+
* is reserved for relay/settlement consumers and is not yet
|
|
46
|
+
* implemented (the type is accepted but the runtime falls back to
|
|
47
|
+
* `'emit-uncertain'`; a follow-up PR adds the per-block receipt
|
|
48
|
+
* fetch path).
|
|
49
|
+
*/
|
|
50
|
+
export type LostSignalPolicy = 'emit-uncertain' | 'silent' | {
|
|
51
|
+
strategy: 'receipt-poll-fallback';
|
|
52
|
+
pollEveryBlocks: number;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Per-subscription overrides on top of the tracker defaults. See
|
|
56
|
+
* spec §5.4.
|
|
57
|
+
*/
|
|
58
|
+
export interface TrackOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Emit a synthetic `started` event on subscribe even if no real
|
|
61
|
+
* observation has fired yet. Default true. Wallets use this to
|
|
62
|
+
* render an "awaiting first observation" state without polling.
|
|
63
|
+
*/
|
|
64
|
+
emitInitial?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Persist this subscription via the store. Default false — the
|
|
67
|
+
* subscription survives only the current process. Indexer / relay
|
|
68
|
+
* consumers set this true.
|
|
69
|
+
*/
|
|
70
|
+
durable?: boolean;
|
|
71
|
+
/** Per-subscription override of the tracker's `lostSignalPolicy`. */
|
|
72
|
+
lostSignalPolicy?: LostSignalPolicy;
|
|
73
|
+
/**
|
|
74
|
+
* How many consecutive blocks the hash must be unseen (not in
|
|
75
|
+
* mempool, not in the canonical block) before
|
|
76
|
+
* `unseen-for-N-blocks` fires. Default 30 (spec §6.1).
|
|
77
|
+
*/
|
|
78
|
+
unseenThresholdBlocks?: number;
|
|
79
|
+
}
|
|
80
|
+
/** Bulk subscription options — extends per-hash `TrackOptions`. */
|
|
81
|
+
export interface BulkTrackOptions extends TrackOptions {
|
|
82
|
+
/**
|
|
83
|
+
* Auto-track every tx the selector matches by starting an
|
|
84
|
+
* implicit per-hash subscription for it. Default true — an
|
|
85
|
+
* indexer wiring `trackFromAddress(treasury)` typically wants
|
|
86
|
+
* the per-hash event stream too. Set false to receive only the
|
|
87
|
+
* raw `matched` stream without per-hash detail.
|
|
88
|
+
*/
|
|
89
|
+
autoTrackMatched?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/** One emit from a bulk subscription — see spec §11.1. */
|
|
92
|
+
export interface TxMatchEvent {
|
|
93
|
+
kind: 'matched';
|
|
94
|
+
hash: Hash;
|
|
95
|
+
matchedBy: 'from' | 'to' | 'predicate';
|
|
96
|
+
selector: BulkSelector;
|
|
97
|
+
tx: RawTx;
|
|
98
|
+
source: 'mempool-snapshot' | 'block-poll';
|
|
99
|
+
at: At;
|
|
100
|
+
}
|
|
101
|
+
/** Handle returned by every bulk-track method. */
|
|
102
|
+
export interface TxSubscription {
|
|
103
|
+
/**
|
|
104
|
+
* Async iterator over the raw `matched` stream. Iteration ends
|
|
105
|
+
* when `stop()` is called or the tracker stops.
|
|
106
|
+
*/
|
|
107
|
+
events(): AsyncIterable<TxMatchEvent>;
|
|
108
|
+
/**
|
|
109
|
+
* Imperative subscription to per-hash events on every matched tx.
|
|
110
|
+
* Returns an unsubscribe handle.
|
|
111
|
+
*/
|
|
112
|
+
subscribe(cb: (event: TxEvent) => void): () => void;
|
|
113
|
+
/**
|
|
114
|
+
* Stop the bulk subscription. Per-hash subscriptions auto-tracked
|
|
115
|
+
* via this bulk subscription continue under their own retention
|
|
116
|
+
* rules (spec §11.1).
|
|
117
|
+
*/
|
|
118
|
+
stop(): void;
|
|
119
|
+
}
|
|
120
|
+
/** Factory options. */
|
|
121
|
+
export interface CreateTxTrackerOptions {
|
|
122
|
+
source: ChainSource;
|
|
123
|
+
chainId: number;
|
|
124
|
+
store?: TxTrackerStore;
|
|
125
|
+
lostSignalPolicy?: LostSignalPolicy;
|
|
126
|
+
reorgDepthBlocks?: number;
|
|
127
|
+
/** Default `unseenThresholdBlocks` for new subscriptions. */
|
|
128
|
+
unseenThresholdBlocks?: number;
|
|
129
|
+
/** Cap on simultaneous bulk subscriptions (spec §11.3). */
|
|
130
|
+
maxBulkSubscriptions?: number;
|
|
131
|
+
onError?: (method: string, err: unknown) => void;
|
|
132
|
+
lifecycle?: 'eager' | 'lazy';
|
|
133
|
+
}
|
|
134
|
+
/** Public surface returned by `createTxTracker`. */
|
|
135
|
+
export interface TxTracker {
|
|
136
|
+
start(): void;
|
|
137
|
+
stop(): void;
|
|
138
|
+
getTxStatus(hash: Hash): TxStatus | null;
|
|
139
|
+
track(hash: Hash, options?: TrackOptions): AsyncIterable<TxEvent>;
|
|
140
|
+
subscribe(hash: Hash, cb: (event: TxEvent) => void, options?: TrackOptions): () => void;
|
|
141
|
+
trackFromAddress(address: Address, options?: BulkTrackOptions): TxSubscription;
|
|
142
|
+
trackToAddress(address: Address, options?: BulkTrackOptions): TxSubscription;
|
|
143
|
+
trackPredicate(match: (tx: RawTx) => boolean, options?: BulkTrackOptions): TxSubscription;
|
|
144
|
+
capabilities(): Capabilities;
|
|
145
|
+
subscribeAll(cb: (event: TxEvent) => void): () => void;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Build a configured tracker.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* import { createChainSource } from '@valve-tech/chain-source'
|
|
152
|
+
* import { createTxTracker } from '@valve-tech/tx-tracker'
|
|
153
|
+
*
|
|
154
|
+
* const source = createChainSource({ client })
|
|
155
|
+
* const tracker = createTxTracker({ source, chainId: 1 })
|
|
156
|
+
*
|
|
157
|
+
* source.start()
|
|
158
|
+
* tracker.start()
|
|
159
|
+
*
|
|
160
|
+
* for await (const event of tracker.track('0xabc...')) {
|
|
161
|
+
* if (event.kind === 'seen-in-block' && event.confirmations >= 3) break
|
|
162
|
+
* }
|
|
163
|
+
*/
|
|
164
|
+
export declare const createTxTracker: (options: CreateTxTrackerOptions) => TxTracker;
|
|
165
|
+
//# 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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"}
|