@valve-tech/tx-flight-react 0.0.1

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 (80) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +21 -0
  3. package/README.md +283 -0
  4. package/dist/components/actions.d.ts +32 -0
  5. package/dist/components/actions.d.ts.map +1 -0
  6. package/dist/components/actions.js +10 -0
  7. package/dist/components/actions.js.map +1 -0
  8. package/dist/components/age.d.ts +21 -0
  9. package/dist/components/age.d.ts.map +1 -0
  10. package/dist/components/age.js +29 -0
  11. package/dist/components/age.js.map +1 -0
  12. package/dist/components/hash-link.d.ts +26 -0
  13. package/dist/components/hash-link.d.ts.map +1 -0
  14. package/dist/components/hash-link.js +20 -0
  15. package/dist/components/hash-link.js.map +1 -0
  16. package/dist/components/item.d.ts +27 -0
  17. package/dist/components/item.d.ts.map +1 -0
  18. package/dist/components/item.js +18 -0
  19. package/dist/components/item.js.map +1 -0
  20. package/dist/components/list.d.ts +27 -0
  21. package/dist/components/list.d.ts.map +1 -0
  22. package/dist/components/list.js +14 -0
  23. package/dist/components/list.js.map +1 -0
  24. package/dist/components/status-icon.d.ts +20 -0
  25. package/dist/components/status-icon.d.ts.map +1 -0
  26. package/dist/components/status-icon.js +28 -0
  27. package/dist/components/status-icon.js.map +1 -0
  28. package/dist/index.d.ts +18 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +19 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/integrations/tx-tracker.d.ts +48 -0
  33. package/dist/integrations/tx-tracker.d.ts.map +1 -0
  34. package/dist/integrations/tx-tracker.js +169 -0
  35. package/dist/integrations/tx-tracker.js.map +1 -0
  36. package/dist/integrations/wallet-adapter.d.ts +34 -0
  37. package/dist/integrations/wallet-adapter.d.ts.map +1 -0
  38. package/dist/integrations/wallet-adapter.js +97 -0
  39. package/dist/integrations/wallet-adapter.js.map +1 -0
  40. package/dist/provider.d.ts +67 -0
  41. package/dist/provider.d.ts.map +1 -0
  42. package/dist/provider.js +182 -0
  43. package/dist/provider.js.map +1 -0
  44. package/dist/storage/index.d.ts +7 -0
  45. package/dist/storage/index.d.ts.map +1 -0
  46. package/dist/storage/index.js +7 -0
  47. package/dist/storage/index.js.map +1 -0
  48. package/dist/storage/indexed-db.d.ts +21 -0
  49. package/dist/storage/indexed-db.d.ts.map +1 -0
  50. package/dist/storage/indexed-db.js +58 -0
  51. package/dist/storage/indexed-db.js.map +1 -0
  52. package/dist/storage/local-storage.d.ts +18 -0
  53. package/dist/storage/local-storage.d.ts.map +1 -0
  54. package/dist/storage/local-storage.js +39 -0
  55. package/dist/storage/local-storage.js.map +1 -0
  56. package/dist/storage/memory.d.ts +7 -0
  57. package/dist/storage/memory.d.ts.map +1 -0
  58. package/dist/storage/memory.js +17 -0
  59. package/dist/storage/memory.js.map +1 -0
  60. package/dist/storage/serialize.d.ts +13 -0
  61. package/dist/storage/serialize.d.ts.map +1 -0
  62. package/dist/storage/serialize.js +29 -0
  63. package/dist/storage/serialize.js.map +1 -0
  64. package/dist/store/reducers.d.ts +53 -0
  65. package/dist/store/reducers.d.ts.map +1 -0
  66. package/dist/store/reducers.js +135 -0
  67. package/dist/store/reducers.js.map +1 -0
  68. package/dist/store/store.d.ts +56 -0
  69. package/dist/store/store.d.ts.map +1 -0
  70. package/dist/store/store.js +93 -0
  71. package/dist/store/store.js.map +1 -0
  72. package/dist/types.d.ts +96 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +21 -0
  75. package/dist/types.js.map +1 -0
  76. package/dist/use-tx-flight.d.ts +31 -0
  77. package/dist/use-tx-flight.d.ts.map +1 -0
  78. package/dist/use-tx-flight.js +47 -0
  79. package/dist/use-tx-flight.js.map +1 -0
  80. package/package.json +83 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * @fileoverview Pure reducers for the tx-flight store.
3
+ *
4
+ * Side effects (start watcher, save storage, call unsub) belong in the
5
+ * Provider. Reducers fold state changes only. The Provider invokes
6
+ * reducers with `now` parameters so timestamping is testable.
7
+ */
8
+ const TERMINAL_STATUSES = new Set([
9
+ 'confirmed',
10
+ 'failed',
11
+ 'dropped',
12
+ 'replaced',
13
+ ]);
14
+ const isTerminal = (tx) => TERMINAL_STATUSES.has(tx.status);
15
+ /**
16
+ * The "when did this tx settle / start" timestamp used for both
17
+ * eviction passes. For terminals: `confirmedAt` if set (the Provider
18
+ * stamps it on status flip via `updateReducer`), else `submittedAt`
19
+ * as a conservative fallback for terminals that were added directly
20
+ * (e.g., via `addManual`). For non-terminals: `submittedAt`.
21
+ */
22
+ const settledOrSubmittedAt = (tx) => isTerminal(tx) ? (tx.confirmedAt ?? tx.submittedAt) : tx.submittedAt;
23
+ /**
24
+ * Insert (or overwrite) a TrackedTx and an optional watcher unsub.
25
+ *
26
+ * When overwriting a tx that previously had a watcher, the caller MUST
27
+ * call the previous watcher's unsub BEFORE invoking this reducer —
28
+ * reducers are pure and don't perform side effects. The Provider owns
29
+ * watcher lifecycle.
30
+ */
31
+ export const addReducer = (state, tx, watcher) => {
32
+ const txs = new Map(state.txs);
33
+ txs.set(tx.id, tx);
34
+ const watchers = new Map(state.watchers);
35
+ if (watcher) {
36
+ watchers.set(tx.id, watcher);
37
+ }
38
+ else {
39
+ watchers.delete(tx.id);
40
+ }
41
+ return { txs, watchers };
42
+ };
43
+ /**
44
+ * Patch an existing tx's fields. No-op (returns the same state
45
+ * reference) on a missing id.
46
+ *
47
+ * If the patch flips status to a terminal value and `confirmedAt` is
48
+ * not yet set, stamps `confirmedAt` to `now`. This gives `evictReducer`
49
+ * a uniform "settled at" timestamp regardless of which terminal status
50
+ * the tx ended in.
51
+ */
52
+ export const updateReducer = (state, txId, patch, now) => {
53
+ const existing = state.txs.get(txId);
54
+ if (!existing)
55
+ return state;
56
+ const next = { ...existing, ...patch };
57
+ if (isTerminal(next) && next.confirmedAt === undefined) {
58
+ next.confirmedAt = now;
59
+ }
60
+ const txs = new Map(state.txs);
61
+ txs.set(txId, next);
62
+ return { txs, watchers: state.watchers };
63
+ };
64
+ /**
65
+ * Drop a tx and its watcher map entry. The Provider is responsible for
66
+ * calling the watcher's unsub BEFORE this reducer runs.
67
+ *
68
+ * No-op (returns the same state reference) on a missing id.
69
+ */
70
+ export const removeReducer = (state, txId) => {
71
+ if (!state.txs.has(txId) && !state.watchers.has(txId))
72
+ return state;
73
+ const txs = new Map(state.txs);
74
+ txs.delete(txId);
75
+ const watchers = new Map(state.watchers);
76
+ watchers.delete(txId);
77
+ return { txs, watchers };
78
+ };
79
+ /**
80
+ * Two-pass eviction. Returns the same state reference when nothing
81
+ * changed.
82
+ *
83
+ * Pass 1: drop terminal entries older than `terminalRetentionMs` —
84
+ * `now - (confirmedAt ?? submittedAt) > terminalRetentionMs`.
85
+ * Pass 2: if the surviving set is still larger than `maxItems`, drop
86
+ * in priority order: terminals first (oldest first by their settled
87
+ * timestamp), then non-terminals (oldest first by submittedAt).
88
+ * Non-terminals are preserved over terminals at the same age — an
89
+ * active in-flight tx is more valuable than a settled one.
90
+ */
91
+ export const evictReducer = (state, opts) => {
92
+ const { maxItems, terminalRetentionMs, now } = opts;
93
+ // Pass 1: collect terminals past their retention window.
94
+ const expired = new Set();
95
+ for (const [id, tx] of state.txs) {
96
+ if (!isTerminal(tx))
97
+ continue;
98
+ if (now - settledOrSubmittedAt(tx) > terminalRetentionMs)
99
+ expired.add(id);
100
+ }
101
+ // Pass 2: if still over cap, sort survivors by (terminal-first,
102
+ // then oldest-first) and slice off the head until under cap.
103
+ const survivorsAfterPass1 = state.txs.size - expired.size;
104
+ let extraEvictions = [];
105
+ if (survivorsAfterPass1 > maxItems) {
106
+ const survivors = [];
107
+ for (const [id, tx] of state.txs) {
108
+ if (!expired.has(id))
109
+ survivors.push(tx);
110
+ }
111
+ survivors.sort((a, b) => {
112
+ const aT = isTerminal(a) ? 0 : 1;
113
+ const bT = isTerminal(b) ? 0 : 1;
114
+ if (aT !== bT)
115
+ return aT - bT;
116
+ return settledOrSubmittedAt(a) - settledOrSubmittedAt(b);
117
+ });
118
+ const evictCount = survivorsAfterPass1 - maxItems;
119
+ extraEvictions = survivors.slice(0, evictCount).map((t) => t.id);
120
+ }
121
+ if (expired.size === 0 && extraEvictions.length === 0)
122
+ return state;
123
+ const txs = new Map(state.txs);
124
+ const watchers = new Map(state.watchers);
125
+ for (const id of expired) {
126
+ txs.delete(id);
127
+ watchers.delete(id);
128
+ }
129
+ for (const id of extraEvictions) {
130
+ txs.delete(id);
131
+ watchers.delete(id);
132
+ }
133
+ return { txs, watchers };
134
+ };
135
+ //# sourceMappingURL=reducers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reducers.js","sourceRoot":"","sources":["../../src/store/reducers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @fileoverview Subscribable store wrapping the pure reducers with the
3
+ * side effects the Provider needs:
4
+ *
5
+ * - notify subscribers on state change (so React's
6
+ * `useSyncExternalStore` re-renders consumers)
7
+ * - call watcher unsub on remove / clear / evict / overwrite (the
8
+ * reducers are forbidden from doing this — see AGENTS.md invariant 1)
9
+ * - cache the txs-as-array projection so `useSyncExternalStore` sees
10
+ * a stable reference between dispatches
11
+ *
12
+ * Storage IO and the eviction `setInterval` belong in the Provider,
13
+ * not here. The store exposes `dispatch.evict()` so the Provider can
14
+ * invoke it on its own schedule (testable + composable).
15
+ */
16
+ import type { TrackedTx } from '@valve-tech/wallet-adapter';
17
+ import type { InternalState } from '../types.js';
18
+ export interface TxFlightStoreOptions {
19
+ /** Cap on retained entries. Eviction tick prunes terminals first, then non-terminals if still over. */
20
+ maxItems: number;
21
+ /** How long terminals linger before eviction. */
22
+ terminalRetentionMs: number;
23
+ /**
24
+ * Routed for watcher-unsub failures. Storage errors come from the
25
+ * Provider, not the store. Optional — undefined silently swallows.
26
+ */
27
+ onError?: (method: string, err: unknown) => void;
28
+ }
29
+ export interface TxFlightStore {
30
+ getState(): InternalState;
31
+ /** Stable-reference array projection of txs. Recomputed only on state change. */
32
+ getTxs(): readonly TrackedTx[];
33
+ subscribe(listener: () => void): () => void;
34
+ dispatch: {
35
+ /**
36
+ * Insert (or overwrite) a TrackedTx with an optional watcher unsub.
37
+ * If a prior watcher was registered for the same `tx.id`, it is
38
+ * unsubscribed BEFORE the state changes — so its in-flight callbacks
39
+ * cannot pollute the new entry.
40
+ */
41
+ addWithTx: (tx: TrackedTx, watcher: (() => void) | null) => void;
42
+ update: (txId: string, patch: Partial<TrackedTx>) => void;
43
+ /** Remove a tx + its watcher. Calls the watcher's unsub before state changes. */
44
+ remove: (txId: string) => void;
45
+ /** Empty the store. Calls every watcher's unsub before state changes. */
46
+ clear: () => void;
47
+ /**
48
+ * Periodic eviction tick. Calls `evictReducer` with `Date.now()`;
49
+ * when the resulting state drops txs that had watchers, those
50
+ * watchers are unsubscribed.
51
+ */
52
+ evict: () => void;
53
+ };
54
+ }
55
+ export declare const createTxFlightStore: (options: TxFlightStoreOptions) => TxFlightStore;
56
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAQhD,MAAM,WAAW,oBAAoB;IACnC,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAA;IAChB,iDAAiD;IACjD,mBAAmB,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;CACjD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,IAAI,aAAa,CAAA;IACzB,iFAAiF;IACjF,MAAM,IAAI,SAAS,SAAS,EAAE,CAAA;IAC9B,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;IAC3C,QAAQ,EAAE;QACR;;;;;WAKG;QACH,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;QAChE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAA;QACzD,iFAAiF;QACjF,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;QAC9B,yEAAyE;QACzE,KAAK,EAAE,MAAM,IAAI,CAAA;QACjB;;;;WAIG;QACH,KAAK,EAAE,MAAM,IAAI,CAAA;KAClB,CAAA;CACF;AAOD,eAAO,MAAM,mBAAmB,YACrB,oBAAoB,KAC5B,aAiEF,CAAA"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @fileoverview Subscribable store wrapping the pure reducers with the
3
+ * side effects the Provider needs:
4
+ *
5
+ * - notify subscribers on state change (so React's
6
+ * `useSyncExternalStore` re-renders consumers)
7
+ * - call watcher unsub on remove / clear / evict / overwrite (the
8
+ * reducers are forbidden from doing this — see AGENTS.md invariant 1)
9
+ * - cache the txs-as-array projection so `useSyncExternalStore` sees
10
+ * a stable reference between dispatches
11
+ *
12
+ * Storage IO and the eviction `setInterval` belong in the Provider,
13
+ * not here. The store exposes `dispatch.evict()` so the Provider can
14
+ * invoke it on its own schedule (testable + composable).
15
+ */
16
+ import { addReducer, evictReducer, removeReducer, updateReducer, } from './reducers.js';
17
+ const emptyInternalState = () => ({
18
+ txs: new Map(),
19
+ watchers: new Map(),
20
+ });
21
+ export const createTxFlightStore = (options) => {
22
+ let state = emptyInternalState();
23
+ let cachedTxs = null;
24
+ const listeners = new Set();
25
+ const safeUnsub = (unsub) => {
26
+ try {
27
+ unsub();
28
+ }
29
+ catch (err) {
30
+ options.onError?.('watcher-unsub', err);
31
+ }
32
+ };
33
+ const setState = (next) => {
34
+ if (next === state)
35
+ return;
36
+ state = next;
37
+ cachedTxs = null;
38
+ for (const fn of listeners)
39
+ fn();
40
+ };
41
+ return {
42
+ getState: () => state,
43
+ getTxs: () => {
44
+ if (cachedTxs === null)
45
+ cachedTxs = Array.from(state.txs.values());
46
+ return cachedTxs;
47
+ },
48
+ subscribe: (listener) => {
49
+ listeners.add(listener);
50
+ return () => {
51
+ listeners.delete(listener);
52
+ };
53
+ },
54
+ dispatch: {
55
+ addWithTx: (tx, watcher) => {
56
+ const priorUnsub = state.watchers.get(tx.id);
57
+ if (priorUnsub)
58
+ safeUnsub(priorUnsub);
59
+ setState(addReducer(state, tx, watcher));
60
+ },
61
+ update: (txId, patch) => {
62
+ setState(updateReducer(state, txId, patch, Date.now()));
63
+ },
64
+ remove: (txId) => {
65
+ const unsub = state.watchers.get(txId);
66
+ if (unsub)
67
+ safeUnsub(unsub);
68
+ setState(removeReducer(state, txId));
69
+ },
70
+ clear: () => {
71
+ const unsubs = Array.from(state.watchers.values());
72
+ for (const unsub of unsubs)
73
+ safeUnsub(unsub);
74
+ setState(emptyInternalState());
75
+ },
76
+ evict: () => {
77
+ const next = evictReducer(state, {
78
+ maxItems: options.maxItems,
79
+ terminalRetentionMs: options.terminalRetentionMs,
80
+ now: Date.now(),
81
+ });
82
+ if (next === state)
83
+ return;
84
+ for (const [id, unsub] of state.watchers) {
85
+ if (!next.watchers.has(id))
86
+ safeUnsub(unsub);
87
+ }
88
+ setState(next);
89
+ },
90
+ },
91
+ };
92
+ };
93
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview Public + internal type surface for `@valve-tech/tx-flight-react`.
3
+ *
4
+ * Public types: the three add-input shapes (`AddWithWalletAdapterInput`,
5
+ * `AddByHashInput`, `AddManualInput`), the `TxFlightStorage` adapter
6
+ * contract, and provider/hook option bags.
7
+ *
8
+ * Internal types: `InternalState` (used by reducers + store) is exported
9
+ * for cross-module use within the package but is NOT re-exported from
10
+ * `index.ts` — consumers don't need it.
11
+ *
12
+ * wallet-adapter and viem types are imported as `type`-only so the
13
+ * optional-peer-dep posture (spec §6.1) holds: a wallet-adapter-only
14
+ * consumer doesn't pay any tx-tracker bundle cost, and a hash-only
15
+ * consumer doesn't pay any wallet-adapter cost.
16
+ */
17
+ import type { Hex, PublicClient } from 'viem';
18
+ import type { TrackedTx, TxFlow, WriteHookParams, WalletSendTransactionRequest } from '@valve-tech/wallet-adapter';
19
+ export type { TrackedTx, TxFlow };
20
+ /**
21
+ * Input for `addWithWalletAdapter(input)`. Use when the caller is
22
+ * submitting their tx via `sendTransactionWithHooks` from
23
+ * `@valve-tech/wallet-adapter`. The strip wraps `hooks` so each phase
24
+ * fans out to both the caller's original callbacks AND the strip's
25
+ * store dispatch.
26
+ */
27
+ export interface AddWithWalletAdapterInput {
28
+ /** The hooks bag the consumer is already passing to sendTransactionWithHooks. */
29
+ hooks: WriteHookParams;
30
+ /** Echoed onto TrackedTx.flow. Caller-defined string. */
31
+ flow: TxFlow;
32
+ /** Echoed onto TrackedTx.chainId. */
33
+ chainId: number;
34
+ /** Echoed onto TrackedTx.request — used for replay/replace flows. */
35
+ request: WalletSendTransactionRequest;
36
+ }
37
+ /**
38
+ * Input for `addByHash(input)`. Use when the caller already has a tx
39
+ * hash + chainId and a `PublicClient` to watch with. Internally builds
40
+ * a private `ChainSource` + `TxTracker` pair (dynamic-imports
41
+ * `@valve-tech/tx-tracker` + `@valve-tech/chain-source`).
42
+ */
43
+ export interface AddByHashInput {
44
+ hash: Hex;
45
+ chainId: number;
46
+ /** viem PublicClient pointed at the chain. */
47
+ client: PublicClient;
48
+ flow?: TxFlow;
49
+ /** Confirmations before TrackedTx.status flips to mined. Default 1. */
50
+ confirmations?: number;
51
+ /** Blocks of unseen observation before TrackedTx.status flips to dropped. Default 12. */
52
+ staleAfterBlocks?: number;
53
+ /**
54
+ * If true, fetches the receipt at inclusion. When the receipt's
55
+ * status is reverted, the strip surfaces `failed`. Adds one RPC.
56
+ */
57
+ withReceipts?: boolean;
58
+ }
59
+ /**
60
+ * Input for `addManual(input)`. Use when the caller already has a
61
+ * fully-formed `TrackedTx` (e.g., back-filling from a server push,
62
+ * surfacing a tx observed elsewhere). The strip stores the entry
63
+ * verbatim and does NOT auto-update — caller drives subsequent state
64
+ * by calling `addManual` again with the same `tx.id` (overwrites in
65
+ * place) or `remove(id)`.
66
+ */
67
+ export interface AddManualInput {
68
+ tx: TrackedTx;
69
+ }
70
+ /**
71
+ * Pluggable persistence contract for the tx-flight strip. The Provider
72
+ * loads on mount and saves on state change (debounced ~250ms).
73
+ *
74
+ * Built-in adapters live at `@valve-tech/tx-flight-react/storage`:
75
+ * `localStorageAdapter` (default), `indexedDBAdapter`, `memoryAdapter`.
76
+ * Custom adapters just satisfy this two-method interface.
77
+ */
78
+ export interface TxFlightStorage {
79
+ /** Returns null if no entry exists for the given id. */
80
+ load(id: string): Promise<TrackedTx[] | null>;
81
+ /** Replace stored value. Called debounced ~250ms by the Provider. */
82
+ save(id: string, txs: TrackedTx[]): Promise<void>;
83
+ }
84
+ export interface InternalState {
85
+ /** TrackedTx records keyed by their assigned id. */
86
+ txs: ReadonlyMap<string, TrackedTx>;
87
+ /**
88
+ * Per-tx unsubscribe handles for active watchers (addByHash spawns
89
+ * one; addWithWalletAdapter and addManual leave this empty for the
90
+ * tx). The reducers don't call these — the Provider does on remove
91
+ * or unmount, keeping reducers pure.
92
+ */
93
+ watchers: ReadonlyMap<string, () => void>;
94
+ }
95
+ export declare const emptyState: InternalState;
96
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAC7C,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EACN,eAAe,EACf,4BAA4B,EAC7B,MAAM,4BAA4B,CAAA;AASnC,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;AAIjC;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC,iFAAiF;IACjF,KAAK,EAAE,eAAe,CAAA;IACtB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,OAAO,EAAE,4BAA4B,CAAA;CACtC;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,GAAG,CAAA;IACT,OAAO,EAAE,MAAM,CAAA;IACf,8CAA8C;IAC9C,MAAM,EAAE,YAAY,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,SAAS,CAAA;CACd;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAAA;IAC7C,qEAAqE;IACrE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClD;AAQD,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,GAAG,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACnC;;;;;OAKG;IACH,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAA;CAC1C;AAED,eAAO,MAAM,UAAU,EAAE,aAGxB,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @fileoverview Public + internal type surface for `@valve-tech/tx-flight-react`.
3
+ *
4
+ * Public types: the three add-input shapes (`AddWithWalletAdapterInput`,
5
+ * `AddByHashInput`, `AddManualInput`), the `TxFlightStorage` adapter
6
+ * contract, and provider/hook option bags.
7
+ *
8
+ * Internal types: `InternalState` (used by reducers + store) is exported
9
+ * for cross-module use within the package but is NOT re-exported from
10
+ * `index.ts` — consumers don't need it.
11
+ *
12
+ * wallet-adapter and viem types are imported as `type`-only so the
13
+ * optional-peer-dep posture (spec §6.1) holds: a wallet-adapter-only
14
+ * consumer doesn't pay any tx-tracker bundle cost, and a hash-only
15
+ * consumer doesn't pay any wallet-adapter cost.
16
+ */
17
+ export const emptyState = {
18
+ txs: new Map(),
19
+ watchers: new Map(),
20
+ };
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA6GH,MAAM,CAAC,MAAM,UAAU,GAAkB;IACvC,GAAG,EAAE,IAAI,GAAG,EAAE;IACd,QAAQ,EAAE,IAAI,GAAG,EAAE;CACpB,CAAA"}
@@ -0,0 +1,31 @@
1
+ import type { TrackedTx, WriteHookParams } from '@valve-tech/wallet-adapter';
2
+ import { type AddWithWalletAdapterResult } from './integrations/wallet-adapter.js';
3
+ import type { AddByHashInput, AddManualInput, AddWithWalletAdapterInput } from './types.js';
4
+ export interface UseTxFlightReturn {
5
+ /** Reactive snapshot — re-renders when state changes. */
6
+ txs: readonly TrackedTx[];
7
+ /**
8
+ * Add a tx the consumer is submitting via @valve-tech/wallet-adapter.
9
+ * Returns the assigned id and a wrapped `WriteHookParams` to pass to
10
+ * `sendTransactionWithHooks`. Each phase fans out to the consumer's
11
+ * original callbacks AND a store dispatch reflecting the new state.
12
+ */
13
+ addWithWalletAdapter: (input: AddWithWalletAdapterInput) => AddWithWalletAdapterResult;
14
+ /**
15
+ * Add a tx by its hash + chainId. Internally builds a private
16
+ * ChainSource + TxTracker and watches the hash. Async because
17
+ * `@valve-tech/tx-tracker` is dynamic-imported (optional peer dep).
18
+ */
19
+ addByHash: (input: AddByHashInput) => Promise<string>;
20
+ /** Add a fully-formed TrackedTx. Returns the supplied id. */
21
+ addManual: (input: AddManualInput) => string;
22
+ /** Remove an entry by id. No-op if not found. */
23
+ remove: (id: string) => void;
24
+ /** Empty the strip (terminal + non-terminal). */
25
+ clear: () => void;
26
+ /** Imperative read; doesn't subscribe to re-renders. */
27
+ get: (id: string) => TrackedTx | null;
28
+ }
29
+ export type { WriteHookParams, AddWithWalletAdapterResult };
30
+ export declare const useTxFlight: (id?: string) => UseTxFlightReturn;
31
+ //# sourceMappingURL=use-tx-flight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tx-flight.d.ts","sourceRoot":"","sources":["../src/use-tx-flight.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAG5E,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,kCAAkC,CAAA;AAEzC,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,yBAAyB,EAC1B,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,GAAG,EAAE,SAAS,SAAS,EAAE,CAAA;IACzB;;;;;OAKG;IACH,oBAAoB,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,0BAA0B,CAAA;IACtF;;;;OAIG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACrD,6DAA6D;IAC7D,SAAS,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,MAAM,CAAA;IAC5C,iDAAiD;IACjD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,iDAAiD;IACjD,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,wDAAwD;IACxD,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,GAAG,IAAI,CAAA;CACtC;AAED,YAAY,EAAE,eAAe,EAAE,0BAA0B,EAAE,CAAA;AAE3D,eAAO,MAAM,WAAW,QAAS,MAAM,KAAG,iBA4BzC,CAAA"}
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ /**
3
+ * @fileoverview `useTxFlight(id?)` — the consumer's entry point to a
4
+ * Provider's store.
5
+ *
6
+ * Resolution order for the id:
7
+ * 1. Explicit argument — `useTxFlight('settings-page')`.
8
+ * 2. Ambient context from the nearest `<TxFlightProvider>`.
9
+ * 3. Fallback `'default'`.
10
+ *
11
+ * Throws if no Provider has registered a store for the resolved id.
12
+ *
13
+ * For Task 5 the hook surface is `txs` + `addManual` + `remove` +
14
+ * `clear` + `get`. The wallet-adapter (`addWithWalletAdapter`) and
15
+ * tx-tracker (`addByHash`) integrations land in Tasks 7 and 8 and
16
+ * extend this surface.
17
+ */
18
+ import { useSyncExternalStore } from 'react';
19
+ import { addByHashImpl } from './integrations/tx-tracker.js';
20
+ import { addWithWalletAdapterImpl, } from './integrations/wallet-adapter.js';
21
+ import { _getStoreForId, _useTxFlightContext } from './provider.js';
22
+ export const useTxFlight = (id) => {
23
+ const ambient = _useTxFlightContext();
24
+ const resolvedId = id ?? ambient?.id ?? 'default';
25
+ const store = _getStoreForId(resolvedId);
26
+ if (!store) {
27
+ throw new Error(`[@valve-tech/tx-flight-react] No <TxFlightProvider id="${resolvedId}"> found in tree`);
28
+ }
29
+ const txs = useSyncExternalStore(store.subscribe, store.getTxs, store.getTxs);
30
+ return {
31
+ txs,
32
+ addWithWalletAdapter: (input) => addWithWalletAdapterImpl(store, input),
33
+ addByHash: (input) => addByHashImpl(store, input),
34
+ addManual: (input) => {
35
+ store.dispatch.addWithTx(input.tx, null);
36
+ return input.tx.id;
37
+ },
38
+ remove: (txId) => {
39
+ store.dispatch.remove(txId);
40
+ },
41
+ clear: () => {
42
+ store.dispatch.clear();
43
+ },
44
+ get: (txId) => store.getState().txs.get(txId) ?? null,
45
+ };
46
+ };
47
+ //# sourceMappingURL=use-tx-flight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tx-flight.js","sourceRoot":"","sources":["../src/use-tx-flight.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EACL,wBAAwB,GAEzB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAmCnE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAW,EAAqB,EAAE;IAC5D,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAA;IACrC,MAAM,UAAU,GAAG,EAAE,IAAI,OAAO,EAAE,EAAE,IAAI,SAAS,CAAA;IACjD,MAAM,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAA;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,0DAA0D,UAAU,kBAAkB,CACvF,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAE7E,OAAO;QACL,GAAG;QACH,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,CAAC;QACvE,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC;QACjD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACnB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;YACxC,OAAO,KAAK,CAAC,EAAE,CAAC,EAAE,CAAA;QACpB,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACf,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACxB,CAAC;QACD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI;KACtD,CAAA;AACH,CAAC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@valve-tech/tx-flight-react",
3
+ "version": "0.0.1",
4
+ "description": "React UI primitives for rendering an in-flight transaction strip. Provider with multi-instance scoping (id + storage key), three add methods (addWithWalletAdapter for callers using @valve-tech/wallet-adapter, addByHash for raw hash + chain via @valve-tech/tx-tracker, addManual for back-fill), pluggable storage (localStorage default, IndexedDB and memory adapters included), atomic + layout components for headless composition, SSR-safe (the package's React-side hooks are client-only; storage adapters no-op on the server). Part of the valve-tech/evm-toolkit synchronized release line.",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/valve-tech/evm-toolkit/tree/main/packages/tx-flight-react#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/valve-tech/evm-toolkit.git",
10
+ "directory": "packages/tx-flight-react"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/valve-tech/evm-toolkit/issues"
14
+ },
15
+ "keywords": [
16
+ "ethereum",
17
+ "evm",
18
+ "viem",
19
+ "react",
20
+ "tx-flight",
21
+ "tx-status",
22
+ "transaction-tracker",
23
+ "wallet-adapter",
24
+ "ui-primitives"
25
+ ],
26
+ "type": "module",
27
+ "main": "dist/index.js",
28
+ "types": "dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ },
34
+ "./storage": {
35
+ "types": "./dist/storage/index.d.ts",
36
+ "import": "./dist/storage/index.js"
37
+ }
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "README.md",
42
+ "CHANGELOG.md",
43
+ "LICENSE"
44
+ ],
45
+ "sideEffects": false,
46
+ "scripts": {
47
+ "build": "tsc -p .",
48
+ "typecheck": "tsc -p . --noEmit",
49
+ "lint": "eslint src",
50
+ "test": "vitest run",
51
+ "test:coverage": "vitest run --coverage",
52
+ "prepare": "yarn build"
53
+ },
54
+ "peerDependencies": {
55
+ "@valve-tech/chain-source": "^0.8.1",
56
+ "@valve-tech/tx-tracker": "^0.8.1",
57
+ "@valve-tech/wallet-adapter": "^0.8.1",
58
+ "react": "^18.2.0 || ^19.0.0",
59
+ "react-dom": "^18.2.0 || ^19.0.0",
60
+ "viem": "^2.0.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@valve-tech/chain-source": {
64
+ "optional": true
65
+ },
66
+ "@valve-tech/tx-tracker": {
67
+ "optional": true
68
+ },
69
+ "@valve-tech/wallet-adapter": {
70
+ "optional": true
71
+ }
72
+ },
73
+ "devDependencies": {
74
+ "@testing-library/dom": "^10.4.0",
75
+ "@testing-library/react": "^16.1.0",
76
+ "@types/react": "^18.3.0",
77
+ "@types/react-dom": "^18.3.0",
78
+ "fake-indexeddb": "^6.0.0",
79
+ "happy-dom": "^15.0.0",
80
+ "react": "^18.3.1",
81
+ "react-dom": "^18.3.1"
82
+ }
83
+ }