@tuwaio/pulsar-core 0.7.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/README.md +91 -319
- package/dist/index.d.mts +611 -329
- package/dist/index.d.ts +611 -329
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +11 -7
package/dist/index.d.ts
CHANGED
|
@@ -4,326 +4,411 @@ import { StoreApi } from 'zustand';
|
|
|
4
4
|
import { PersistOptions } from 'zustand/middleware';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
7
|
+
* @file Core types of Pulsar: transaction shapes, the adapter contract that chain packages implement, and the state
|
|
8
|
+
* and actions of the transaction stores.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A Zustand slice creator: receives the store's `set` and `get` and returns the slice state and actions.
|
|
13
|
+
*
|
|
14
|
+
* @template T - The state slice being defined.
|
|
15
|
+
* @template S - The full store state that includes the slice `T`.
|
|
10
16
|
*/
|
|
11
17
|
type StoreSlice<T extends object, S extends object = T> = (set: StoreApi<S extends T ? S : S & T>['setState'], get: StoreApi<S extends T ? S : S & T>['getState']) => T;
|
|
12
18
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
19
|
+
* Tracking strategy of a transaction. The chain adapter picks it after the action returns (see
|
|
20
|
+
* `TxAdapter.checkTransactionsTracker`) and routes the transaction to the matching tracker.
|
|
15
21
|
*/
|
|
16
22
|
declare enum TransactionTracker {
|
|
17
|
-
/**
|
|
23
|
+
/** A standard EVM transaction, tracked by its hash through RPC (`@tuwaio/pulsar-evm`). */
|
|
18
24
|
Ethereum = "ethereum",
|
|
19
|
-
/**
|
|
25
|
+
/** A Safe multisig transaction, tracked by its `safeTxHash` through the Safe Transaction Service API. */
|
|
20
26
|
Safe = "safe",
|
|
21
27
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @deprecated Gelato
|
|
28
|
+
* A meta-transaction relayed by Gelato, tracked by its task ID through the Gelato API.
|
|
29
|
+
* @deprecated Gelato relay is deprecated. Use `TransactionTracker.ERC4337` instead.
|
|
24
30
|
*/
|
|
25
31
|
Gelato = "gelato",
|
|
26
|
-
/**
|
|
32
|
+
/** A Solana transaction, tracked by its signature through RPC (`@tuwaio/pulsar-solana`). */
|
|
27
33
|
Solana = "solana",
|
|
28
|
-
/**
|
|
34
|
+
/** An ERC-4337 UserOperation, tracked by its `userOpHash` through a bundler RPC and then on-chain. */
|
|
29
35
|
ERC4337 = "erc4337"
|
|
30
36
|
}
|
|
31
37
|
/**
|
|
32
|
-
*
|
|
38
|
+
* Terminal status of a transaction. Trackers set it together with `pending: false`.
|
|
33
39
|
*/
|
|
34
40
|
declare enum TransactionStatus {
|
|
35
|
-
/** The transaction failed
|
|
41
|
+
/** The transaction reverted, was rejected, or tracking failed (for example, it was not found in time). */
|
|
36
42
|
Failed = "Failed",
|
|
37
|
-
/** The transaction was
|
|
43
|
+
/** The transaction was included on-chain and executed successfully. */
|
|
38
44
|
Success = "Success",
|
|
39
|
-
/**
|
|
45
|
+
/** Another transaction with the same nonce was mined instead (a wallet speed-up or cancel). */
|
|
40
46
|
Replaced = "Replaced"
|
|
41
47
|
}
|
|
42
48
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* This key is crucial for the adapter to determine which tracker should
|
|
47
|
-
* monitor the transaction.
|
|
48
|
-
*
|
|
49
|
-
* It can be one of the following:
|
|
50
|
-
* - A standard `0x...` transaction hash (`Hex`).
|
|
51
|
-
* - A Solana transaction signature (string).
|
|
49
|
+
* The identifier returned by an `actionFunction` once the transaction is submitted: an EVM transaction hash, an
|
|
50
|
+
* ERC-4337 `userOpHash`, a Safe `safeTxHash`, a Gelato task ID or a Solana signature. The adapter uses it to pick the
|
|
51
|
+
* tracker and the `txKey` of the transaction.
|
|
52
52
|
*/
|
|
53
53
|
type ActionTxKey = `0x${string}` | string;
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
56
|
-
* This serves as the base upon which chain-specific transaction types are built.
|
|
55
|
+
* Fields shared by every tracked transaction. Chain-specific transaction types extend it.
|
|
57
56
|
*/
|
|
58
57
|
type BaseTransaction = {
|
|
59
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* The chain of the transaction: the numeric chain ID for EVM (for example `1`), or `solana:<cluster>` for Solana
|
|
60
|
+
* (for example `solana:devnet`). `executeTxAction` derives it from `desiredChainID`.
|
|
61
|
+
*/
|
|
60
62
|
chainId: number | string;
|
|
61
63
|
/**
|
|
62
|
-
* User-facing description
|
|
63
|
-
* Each string
|
|
64
|
-
*
|
|
64
|
+
* User-facing description: one string for every state, or a tuple for the `[pending, success, error, replaced]`
|
|
65
|
+
* states. Each string must be 300 characters or less and must not contain executable-like patterns such as `eval(`
|
|
66
|
+
* or `javascript:`; `executeTxAction`, `addTxToPool` and the pool restore functions reject or drop transactions that
|
|
67
|
+
* break these rules.
|
|
65
68
|
* @example
|
|
66
|
-
*
|
|
67
|
-
* description: 'Swap 1 ETH for 1,500 USDC'
|
|
68
|
-
*
|
|
69
|
-
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* description: 'Swap 1 ETH for 1,500 USDC';
|
|
71
|
+
* description: ['Swapping...', 'Swapped successfully', 'Swap failed', 'Swap replaced'];
|
|
72
|
+
* ```
|
|
70
73
|
*/
|
|
71
74
|
description?: string | [string, string, string, string];
|
|
72
|
-
/** The error
|
|
75
|
+
/** The normalized error of a failed transaction (`normalizeError` from `@tuwaio/orbit-core`). */
|
|
73
76
|
error?: TuwaErrorState;
|
|
74
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Unix timestamp (seconds) of the terminal state: the block timestamp for EVM and ERC-4337 transactions confirmed
|
|
79
|
+
* on-chain, the execution date for Safe, and the local time otherwise.
|
|
80
|
+
*/
|
|
75
81
|
finishedTimestamp?: number;
|
|
76
|
-
/** The
|
|
82
|
+
/** The address of the wallet that sent the transaction, as reported by the adapter's `getConnectorInfo`. */
|
|
77
83
|
from: string;
|
|
78
|
-
/**
|
|
84
|
+
/** `true` when the transaction failed; set by trackers together with `status: Failed`. */
|
|
79
85
|
isError?: boolean;
|
|
80
|
-
/**
|
|
86
|
+
/** UI flag for a detailed tracking modal. Set from `withTrackedModal`; `closeTxTrackedModal` sets it to `false`. */
|
|
81
87
|
isTrackedModalOpen?: boolean;
|
|
82
|
-
/**
|
|
88
|
+
/** Unix timestamp (seconds) when `executeTxAction` started. The pool is ordered and evicted by this value. */
|
|
83
89
|
localTimestamp: number;
|
|
84
90
|
/**
|
|
85
|
-
* Custom JSON
|
|
86
|
-
*
|
|
91
|
+
* Custom JSON data of the application. The UTF-8 JSON must be 10 KB or less, and string keys and values must not
|
|
92
|
+
* contain executable-like patterns.
|
|
87
93
|
*/
|
|
88
94
|
payload?: Record<string, string | number>;
|
|
89
|
-
/**
|
|
95
|
+
/** `true` while the transaction is tracked; trackers set it to `false` when it reaches a terminal status. */
|
|
90
96
|
pending: boolean;
|
|
91
|
-
/** The
|
|
97
|
+
/** The terminal status, set together with `pending: false`. */
|
|
92
98
|
status?: TransactionStatus;
|
|
93
99
|
/**
|
|
94
|
-
* User-facing title
|
|
95
|
-
* Each string
|
|
96
|
-
*
|
|
100
|
+
* User-facing title: one string for every state, or a tuple for the `[pending, success, error, replaced]` states.
|
|
101
|
+
* Each string must be 100 characters or less and must not contain executable-like patterns such as `eval(` or
|
|
102
|
+
* `javascript:`.
|
|
97
103
|
* @example
|
|
98
|
-
*
|
|
99
|
-
* title: 'ETH/USDC
|
|
100
|
-
*
|
|
101
|
-
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* title: 'ETH/USDC swap';
|
|
106
|
+
* title: ['Processing swap', 'Swap complete', 'Swap error', 'Swap replaced'];
|
|
107
|
+
* ```
|
|
102
108
|
*/
|
|
103
109
|
title?: string | [string, string, string, string];
|
|
104
|
-
/** The
|
|
110
|
+
/** The tracker that monitors the transaction. */
|
|
105
111
|
tracker: TransactionTracker;
|
|
106
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* The key of the transaction in the pool: the transaction hash, `userOpHash` (ERC-4337), `safeTxHash` (Safe), Gelato
|
|
114
|
+
* task ID or Solana signature.
|
|
115
|
+
*/
|
|
107
116
|
txKey: string;
|
|
108
|
-
/**
|
|
117
|
+
/** Application-specific type of the transaction, for example `'SWAP'` or `'APPROVE'`. */
|
|
109
118
|
type: string;
|
|
110
|
-
/** The
|
|
119
|
+
/** The connector that signed the transaction, for example `evm:metamask` or `solana:phantom`. */
|
|
111
120
|
connectorType: string;
|
|
112
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* Number of block confirmations the EVM trackers wait for before marking the transaction successful. Defaults to 1.
|
|
123
|
+
* The Solana tracker always waits for the `finalized` commitment instead.
|
|
124
|
+
*/
|
|
113
125
|
requiredConfirmations?: number;
|
|
114
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* Confirmations reported by the tracker while the transaction is pending. The Solana tracker sets it to `'MAX'` when
|
|
128
|
+
* the transaction is finalized.
|
|
129
|
+
*/
|
|
115
130
|
confirmations?: number | string | null;
|
|
116
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* RPC endpoint used by the Solana tracker, also after a page reload. Without it, the tracker uses the public
|
|
133
|
+
* endpoint of the cluster in `chainId`.
|
|
134
|
+
*/
|
|
117
135
|
rpcUrl?: string;
|
|
118
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* Remote sync state, set only when the store has an `onRemoteCreate` callback: `'pending-sync'` from the moment the
|
|
138
|
+
* transaction is added until `onRemoteCreate` resolves (the key is listed in `unsyncedTxKeys` meanwhile and retried
|
|
139
|
+
* if the call fails), then `'synced'`.
|
|
140
|
+
*/
|
|
119
141
|
syncStatus?: 'synced' | 'pending-sync';
|
|
120
142
|
};
|
|
121
143
|
/**
|
|
122
|
-
*
|
|
144
|
+
* An EVM transaction. Trackers fill the on-chain fields (`hash`, `nonce`, fees, `to`, `value`, `input`) once the
|
|
145
|
+
* transaction details are available.
|
|
123
146
|
*/
|
|
124
147
|
type EvmTransaction = BaseTransaction & {
|
|
125
|
-
/**
|
|
148
|
+
/** Always `OrbitAdapter.EVM`. */
|
|
126
149
|
adapter: OrbitAdapter.EVM;
|
|
127
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* The on-chain transaction hash: the `txKey` for standard transactions, and the hash of the mined transaction for
|
|
152
|
+
* ERC-4337, Safe and Gelato once it is known.
|
|
153
|
+
*/
|
|
128
154
|
hash?: `0x${string}`;
|
|
129
|
-
/** The
|
|
155
|
+
/** The calldata of the transaction. */
|
|
130
156
|
input?: `0x${string}`;
|
|
131
|
-
/**
|
|
157
|
+
/** EIP-1559 max fee per gas, in wei, as a decimal string. */
|
|
132
158
|
maxFeePerGas?: string;
|
|
133
|
-
/**
|
|
159
|
+
/** EIP-1559 max priority fee per gas, in wei, as a decimal string. */
|
|
134
160
|
maxPriorityFeePerGas?: string;
|
|
135
|
-
/** The
|
|
161
|
+
/** The nonce of the sender account. */
|
|
136
162
|
nonce?: number;
|
|
137
|
-
/**
|
|
163
|
+
/**
|
|
164
|
+
* The hash of the transaction that replaced this one (set with `status: Replaced`). For Safe transactions it is the
|
|
165
|
+
* `safeTxHash` of the transaction executed instead.
|
|
166
|
+
*/
|
|
138
167
|
replacedTxHash?: `0x${string}`;
|
|
139
|
-
/** The recipient
|
|
168
|
+
/** The recipient or contract address. */
|
|
140
169
|
to?: `0x${string}`;
|
|
141
|
-
/** The
|
|
170
|
+
/** The native value sent, in wei, as a decimal string. */
|
|
142
171
|
value?: string;
|
|
143
|
-
/**
|
|
172
|
+
/**
|
|
173
|
+
* Custom bundler RPC URL used to track an ERC-4337 UserOperation. Stored with the transaction, so it is persisted to
|
|
174
|
+
* `localStorage` and passed to `onRemoteCreate` (a backend can track through the same bundler). Keep API keys out of
|
|
175
|
+
* this URL; pass them as `pimlicoApiKey`.
|
|
176
|
+
*/
|
|
144
177
|
bundlerUrl?: string;
|
|
145
|
-
/**
|
|
178
|
+
/**
|
|
179
|
+
* Pimlico API key used to track an ERC-4337 UserOperation when no `bundlerUrl` is set. Persisted to `localStorage`
|
|
180
|
+
* with the transaction, so tracking can resume after a reload, but never passed to `onRemoteCreate`.
|
|
181
|
+
*/
|
|
146
182
|
pimlicoApiKey?: string;
|
|
147
183
|
};
|
|
148
184
|
/**
|
|
149
|
-
*
|
|
185
|
+
* A Solana transaction. The Solana tracker fills the on-chain fields once the transaction is found.
|
|
150
186
|
*/
|
|
151
187
|
type SolanaTransaction = BaseTransaction & {
|
|
152
|
-
/**
|
|
188
|
+
/** Always `OrbitAdapter.SOLANA`. */
|
|
153
189
|
adapter: OrbitAdapter.SOLANA;
|
|
154
|
-
/** The transaction fee in lamports. */
|
|
190
|
+
/** The transaction fee, in lamports. */
|
|
155
191
|
fee?: number;
|
|
156
|
-
/** The instructions
|
|
192
|
+
/** The instructions of the transaction, as returned by the `getTransaction` RPC method. */
|
|
157
193
|
instructions?: unknown[];
|
|
158
|
-
/** The
|
|
194
|
+
/** The blockhash the transaction was signed with. */
|
|
159
195
|
recentBlockhash?: string;
|
|
160
196
|
/** The slot in which the transaction was processed. */
|
|
161
197
|
slot?: number;
|
|
162
198
|
};
|
|
163
199
|
/**
|
|
164
|
-
*
|
|
200
|
+
* A Starknet transaction. Reserved for a Starknet adapter; Pulsar does not ship one.
|
|
165
201
|
*/
|
|
166
202
|
type StarknetTransaction = BaseTransaction & {
|
|
167
|
-
/**
|
|
203
|
+
/** Always `OrbitAdapter.Starknet`. */
|
|
168
204
|
adapter: OrbitAdapter.Starknet;
|
|
169
205
|
/** The actual fee paid for the transaction. */
|
|
170
206
|
actualFee?: {
|
|
207
|
+
/** The fee amount. */
|
|
171
208
|
amount: string;
|
|
209
|
+
/** The fee unit. */
|
|
172
210
|
unit: string;
|
|
173
211
|
};
|
|
174
212
|
/** The address of the contract being interacted with. */
|
|
175
213
|
contractAddress?: string;
|
|
176
214
|
};
|
|
177
|
-
/**
|
|
215
|
+
/** Any transaction Pulsar can track. Application transaction types extend one of its members. */
|
|
178
216
|
type Transaction = EvmTransaction | SolanaTransaction | StarknetTransaction;
|
|
179
217
|
/**
|
|
180
|
-
*
|
|
218
|
+
* The metadata of a transaction passed to `executeTxAction` (as `params`, without `actionFunction`) and kept in
|
|
219
|
+
* `initialTx`.
|
|
181
220
|
*/
|
|
182
221
|
type InitialTransactionParams = Pick<BaseTransaction, 'description' | 'title' | 'type' | 'requiredConfirmations' | 'rpcUrl' | 'payload'> & Pick<EvmTransaction, 'bundlerUrl' | 'pimlicoApiKey'> & {
|
|
183
|
-
/** The
|
|
222
|
+
/** The adapter that handles the transaction. When no configured adapter has this key, the first one is used. */
|
|
184
223
|
adapter: OrbitAdapter;
|
|
185
|
-
/**
|
|
186
|
-
|
|
187
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Signs and submits the transaction and returns its `ActionTxKey`, or `undefined` when the user cancelled.
|
|
226
|
+
* `executeTxAction` calls it without arguments. The adapters' `retryTxAction` call it with
|
|
227
|
+
* `{ config, ...payload }` (EVM) or `{ client, ...payload }` (Solana).
|
|
228
|
+
* @param args - No arguments from `executeTxAction`; one object from `retryTxAction`.
|
|
229
|
+
*/
|
|
230
|
+
actionFunction: (...args: unknown[]) => Promise<ActionTxKey | undefined>;
|
|
231
|
+
/**
|
|
232
|
+
* The chain the transaction must be sent on: a numeric chain ID for EVM (the wallet is asked to switch if needed),
|
|
233
|
+
* or a cluster moniker such as `'devnet'` for Solana (compared with the cluster of the connected wallet).
|
|
234
|
+
*/
|
|
188
235
|
desiredChainID: number | string;
|
|
189
|
-
/**
|
|
236
|
+
/** When `true`, the transaction is created with `isTrackedModalOpen: true`. */
|
|
190
237
|
withTrackedModal?: boolean;
|
|
191
|
-
/**
|
|
238
|
+
/**
|
|
239
|
+
* Forces a tracker. Required for ERC-4337 (`TransactionTracker.ERC4337`) and Gelato; otherwise the adapter picks
|
|
240
|
+
* one from the returned key and the connector.
|
|
241
|
+
*/
|
|
192
242
|
tracker?: TransactionTracker;
|
|
193
|
-
/**
|
|
243
|
+
/**
|
|
244
|
+
* Stored with the transaction and persisted to `localStorage`, but never passed to `onRemoteCreate`.
|
|
245
|
+
* @deprecated Gelato relay is deprecated. Use ERC-4337 with `bundlerUrl` or `pimlicoApiKey` instead.
|
|
246
|
+
*/
|
|
194
247
|
gelatoApiKey?: string;
|
|
195
248
|
};
|
|
196
249
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
250
|
+
* The state of a transaction while `executeTxAction` runs, before it is added to the pool. UI layers use it for
|
|
251
|
+
* immediate feedback (signature prompts, preflight errors).
|
|
199
252
|
*/
|
|
200
253
|
type InitialTransaction = InitialTransactionParams & {
|
|
201
|
-
/**
|
|
254
|
+
/** The normalized error when the flow failed before tracking started, for example a rejected signature. */
|
|
202
255
|
error?: TuwaErrorState;
|
|
203
|
-
/**
|
|
256
|
+
/** `true` from the start of `executeTxAction` until the transaction is added to the pool or the flow fails. */
|
|
204
257
|
isInitializing: boolean;
|
|
205
|
-
/** The `txKey` of the
|
|
258
|
+
/** The `txKey` of the transaction this action added to the pool. */
|
|
206
259
|
lastTxKey?: string;
|
|
207
|
-
/**
|
|
260
|
+
/** Unix timestamp (seconds) when `executeTxAction` started. */
|
|
208
261
|
localTimestamp: number;
|
|
209
262
|
};
|
|
210
263
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
264
|
+
* Callbacks passed to `executeTxAction` and forwarded to the tracker of that transaction. They are not stored:
|
|
265
|
+
* trackers restarted by `initializeTransactionsPool` or `injectExternalPendingTxs` (for example after a page reload)
|
|
266
|
+
* run without them. Their return values are not awaited.
|
|
267
|
+
*
|
|
268
|
+
* @template T - The application transaction type.
|
|
213
269
|
*/
|
|
214
270
|
interface TrackerCallbacks<T extends Transaction> {
|
|
271
|
+
/**
|
|
272
|
+
* Called when the tracker marks the transaction `Success`.
|
|
273
|
+
* @param tx - The transaction after the update.
|
|
274
|
+
*/
|
|
215
275
|
onSuccess?: (tx: T) => Promise<void> | void;
|
|
276
|
+
/**
|
|
277
|
+
* Called when the transaction fails: it reverted, was rejected, or tracking gave up.
|
|
278
|
+
* @param error - The raw error, or a generated `Error`.
|
|
279
|
+
* @param tx - The transaction after the update.
|
|
280
|
+
*/
|
|
216
281
|
onError?: (error: unknown, tx?: T) => Promise<void> | void;
|
|
282
|
+
/**
|
|
283
|
+
* Called when the transaction is replaced by another one with the same nonce.
|
|
284
|
+
* @param newTx - The tracked transaction after the update (`status: Replaced`, `replacedTxHash` set).
|
|
285
|
+
* @param oldTx - The transaction as tracking started.
|
|
286
|
+
*/
|
|
217
287
|
onReplaced?: (newTx: T, oldTx: T) => Promise<void> | void;
|
|
218
288
|
}
|
|
219
289
|
/**
|
|
220
|
-
* Callbacks
|
|
221
|
-
*
|
|
290
|
+
* Callbacks that synchronize the local pool with a remote backend (for example Quasar). Passed to
|
|
291
|
+
* `createPulsarStore`.
|
|
292
|
+
*
|
|
293
|
+
* @template T - The application transaction type.
|
|
222
294
|
*/
|
|
223
295
|
interface SyncCallbacks<T extends Transaction> {
|
|
224
296
|
/**
|
|
225
|
-
* Called
|
|
226
|
-
*
|
|
297
|
+
* Called in the background with every new transaction, right after `addTxToPool` has written it to the pool with
|
|
298
|
+
* `syncStatus: 'pending-sync'` and listed its key in `unsyncedTxKeys`. It never delays or blocks tracking. Resolving
|
|
299
|
+
* marks the transaction `'synced'` and removes the key; rejecting logs a warning and leaves the key for
|
|
300
|
+
* `reconcileUnsyncedTransactions`, also across reloads. Reject (throw) on failure: a resolved promise counts as
|
|
301
|
+
* synced. A transaction is never sent twice at the same time.
|
|
302
|
+
* @param tx - A copy of the pooled transaction without `pimlicoApiKey` and `gelatoApiKey`.
|
|
227
303
|
*/
|
|
228
304
|
onRemoteCreate?: (tx: T) => Promise<void>;
|
|
229
305
|
}
|
|
230
306
|
/**
|
|
231
|
-
*
|
|
307
|
+
* Preflight callback run by `executeTxAction` after metadata validation and the chain check (which can ask the wallet
|
|
308
|
+
* to switch networks), before `actionFunction` asks the wallet to sign. It receives no transaction data.
|
|
232
309
|
*
|
|
233
|
-
* Throw
|
|
234
|
-
*
|
|
310
|
+
* Throw to block the transaction: with `abortOnTxError` (default `true`), `initialTx.error` is set and
|
|
311
|
+
* `executeTxAction` rejects with the thrown error. With `abortOnTxError: false`, the error is logged and the flow
|
|
312
|
+
* continues.
|
|
235
313
|
*/
|
|
236
314
|
type BeforeTxProcess = () => Promise<void> | void;
|
|
237
315
|
/**
|
|
238
|
-
* The configuration
|
|
239
|
-
*
|
|
316
|
+
* The configuration of `createPulsarStore`: one or more chain adapters and the store options.
|
|
317
|
+
*
|
|
318
|
+
* @template T - The application transaction type.
|
|
240
319
|
*/
|
|
241
320
|
type PulsarAdapter<T extends Transaction> = OrbitGenericAdapter<TxAdapter<T>> & {
|
|
242
|
-
/**
|
|
321
|
+
/** Global preflight callback run before every transaction. A `beforeTxProcess` passed to `executeTxAction` replaces it. */
|
|
243
322
|
beforeTxProcess?: BeforeTxProcess;
|
|
323
|
+
/** Maximum number of transactions in the pool. When it is full, the oldest one (by `localTimestamp`) is evicted. Defaults to 50. */
|
|
244
324
|
maxTransactions?: number;
|
|
325
|
+
/** @deprecated Gelato relay is deprecated. Gelato API key used to track `TransactionTracker.Gelato` transactions. */
|
|
245
326
|
gelatoApiKey?: string;
|
|
246
|
-
/**
|
|
327
|
+
/**
|
|
328
|
+
* Whether an error thrown by `beforeTxProcess` aborts the transaction. Defaults to `true`. It does not apply to
|
|
329
|
+
* `onRemoteCreate`, whose errors never abort the transaction.
|
|
330
|
+
*/
|
|
247
331
|
abortOnTxError?: boolean;
|
|
248
332
|
} & SyncCallbacks<T>;
|
|
249
333
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
* @typedef {Object} CheckTxTracker
|
|
253
|
-
* @property {ActionTxKey} actionTxKey - The key identifying the specific action related to the transaction.
|
|
254
|
-
* @property {string} connectorType - The type of connector used for the transaction (e.g., wallet provider, blockchain interface).
|
|
255
|
-
* @property {TransactionTracker} [tracker] - An optional tracker object that monitors the status and progress of the transaction.
|
|
256
|
-
* @property {string} [gelatoApiKey] - @deprecated Gelato API key for Gelato relayer integration.
|
|
257
|
-
* @property {string} [bundlerUrl] - Optional custom bundler RPC URL for ERC-4337 UserOperation tracking.
|
|
258
|
-
* @property {string} [pimlicoApiKey] - Optional Pimlico API key for ERC-4337 UserOperation tracking.
|
|
334
|
+
* The input of `TxAdapter.checkTransactionsTracker`: the key returned by the action and the context needed to pick a
|
|
335
|
+
* tracker.
|
|
259
336
|
*/
|
|
260
337
|
type CheckTxTracker = {
|
|
338
|
+
/** The key returned by `actionFunction`. */
|
|
261
339
|
actionTxKey: ActionTxKey;
|
|
340
|
+
/** The connector that signed the transaction, for example `evm:safe` for a Safe wallet. */
|
|
262
341
|
connectorType: string;
|
|
342
|
+
/** The tracker requested in `executeTxAction` params, if any. */
|
|
263
343
|
tracker?: TransactionTracker;
|
|
264
|
-
/** @deprecated Gelato relay is deprecated. Use bundlerUrl / pimlicoApiKey with ERC-4337 instead. */
|
|
344
|
+
/** @deprecated Gelato relay is deprecated. Use `bundlerUrl` / `pimlicoApiKey` with ERC-4337 instead. */
|
|
265
345
|
gelatoApiKey?: string;
|
|
266
|
-
/**
|
|
346
|
+
/** Custom bundler RPC URL for ERC-4337 UserOperation tracking. */
|
|
267
347
|
bundlerUrl?: string;
|
|
268
|
-
/**
|
|
348
|
+
/** Pimlico API key for ERC-4337 UserOperation tracking. */
|
|
269
349
|
pimlicoApiKey?: string;
|
|
270
350
|
};
|
|
271
351
|
/**
|
|
272
|
-
*
|
|
273
|
-
*
|
|
352
|
+
* The contract a chain adapter implements to plug into the Pulsar store. `@tuwaio/pulsar-evm` and
|
|
353
|
+
* `@tuwaio/pulsar-solana` provide implementations.
|
|
354
|
+
*
|
|
355
|
+
* @template T - The application transaction type.
|
|
274
356
|
*/
|
|
275
357
|
type TxAdapter<T extends Transaction> = Pick<BaseAdapter, 'getExplorerUrl'> & {
|
|
276
|
-
/** The
|
|
358
|
+
/** The chain family handled by the adapter. */
|
|
277
359
|
key: OrbitAdapter;
|
|
278
|
-
/** Returns
|
|
360
|
+
/** Returns the connected wallet. Called by `executeTxAction` before the chain check. */
|
|
279
361
|
getConnectorInfo: () => {
|
|
280
|
-
/** The
|
|
362
|
+
/** The address of the connected wallet. */
|
|
281
363
|
walletAddress: string;
|
|
282
|
-
/** The type
|
|
364
|
+
/** The connector type, for example `evm:metamask`. */
|
|
283
365
|
connectorType: string;
|
|
284
366
|
};
|
|
285
367
|
/**
|
|
286
|
-
* Ensures the
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* @param chainId The desired chain ID for the transaction.
|
|
290
|
-
* @param walletChainId The connected wallet chain ID.
|
|
368
|
+
* Ensures the wallet is on the chain of the transaction, switching it if the adapter can. Rejects when the chain
|
|
369
|
+
* does not match, which aborts `executeTxAction`.
|
|
370
|
+
* @param chainId - The `desiredChainID` of the transaction.
|
|
291
371
|
*/
|
|
292
372
|
checkChainForTx: (chainId: string | number) => Promise<void>;
|
|
293
373
|
/**
|
|
294
|
-
*
|
|
295
|
-
* @
|
|
374
|
+
* Picks the tracker and the final `txKey` for the key returned by `actionFunction`.
|
|
375
|
+
* @param params - The returned key, the connector type and the requested tracker.
|
|
376
|
+
* @returns The `txKey` to store the transaction under and the tracker to use.
|
|
296
377
|
*/
|
|
297
|
-
checkTransactionsTracker: (
|
|
378
|
+
checkTransactionsTracker: (params: CheckTxTracker) => {
|
|
379
|
+
/** The key the transaction is stored under. */
|
|
298
380
|
txKey: string;
|
|
381
|
+
/** The tracker that monitors the transaction. */
|
|
299
382
|
tracker: TransactionTracker;
|
|
300
383
|
};
|
|
301
384
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
385
|
+
* Starts the background tracker of a transaction. Trackers update the transaction through `updateTxParams`. The
|
|
386
|
+
* built-in trackers keep failed transactions in the pool; `removeTxFromPool` is available to custom trackers.
|
|
387
|
+
* @param params - The transaction, the Gelato API key, the callbacks and the store members used by trackers.
|
|
304
388
|
*/
|
|
305
389
|
checkAndInitializeTrackerInStore: (params: {
|
|
306
390
|
tx: T;
|
|
307
391
|
gelatoApiKey?: string;
|
|
308
392
|
} & TrackerCallbacks<T> & Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'>) => Promise<void> | void;
|
|
309
393
|
/**
|
|
310
|
-
* Optional:
|
|
311
|
-
* @param tx The transaction to cancel.
|
|
312
|
-
* @returns The
|
|
394
|
+
* Optional: cancels a pending transaction by sending a replacement with the same nonce.
|
|
395
|
+
* @param tx - The transaction to cancel.
|
|
396
|
+
* @returns The hash of the cancellation transaction.
|
|
313
397
|
*/
|
|
314
398
|
cancelTxAction?: (tx: T) => Promise<string>;
|
|
315
399
|
/**
|
|
316
|
-
* Optional:
|
|
317
|
-
* @param tx The transaction to speed up.
|
|
318
|
-
* @returns The
|
|
400
|
+
* Optional: speeds up a pending transaction by resending it with the same nonce and higher fees.
|
|
401
|
+
* @param tx - The transaction to speed up.
|
|
402
|
+
* @returns The hash of the replacement transaction.
|
|
319
403
|
*/
|
|
320
404
|
speedUpTxAction?: (tx: T) => Promise<string>;
|
|
321
405
|
/**
|
|
322
|
-
* Optional:
|
|
323
|
-
* @param params The parameters
|
|
324
|
-
* @param params.txKey The
|
|
325
|
-
* @param params.tx The
|
|
326
|
-
* @param params.onClose
|
|
406
|
+
* Optional: closes the tracking modal and runs a failed transaction again through `executeTxAction`.
|
|
407
|
+
* @param params - The retry parameters.
|
|
408
|
+
* @param params.txKey - The key of the failed transaction, passed to `onClose`.
|
|
409
|
+
* @param params.tx - The parameters of the transaction, including its `actionFunction`.
|
|
410
|
+
* @param params.onClose - Closes the tracking modal.
|
|
411
|
+
* @param params.executeTxAction - The store's `executeTxAction`.
|
|
327
412
|
*/
|
|
328
413
|
retryTxAction?: (params: {
|
|
329
414
|
txKey: string;
|
|
@@ -331,92 +416,118 @@ type TxAdapter<T extends Transaction> = Pick<BaseAdapter, 'getExplorerUrl'> & {
|
|
|
331
416
|
onClose: (txKey?: string) => void;
|
|
332
417
|
} & Partial<Pick<ITxTrackingStore<T>, 'executeTxAction'>>) => Promise<void>;
|
|
333
418
|
/**
|
|
334
|
-
* Optional:
|
|
335
|
-
*
|
|
336
|
-
* @
|
|
337
|
-
* @returns The full URL to the transaction on the explorer.
|
|
419
|
+
* Optional: builds the explorer URL of a transaction.
|
|
420
|
+
* @param tx - The transaction.
|
|
421
|
+
* @returns The URL, or an empty string when it cannot be built.
|
|
338
422
|
*/
|
|
339
423
|
getExplorerTxUrl?: (tx: T) => string;
|
|
340
424
|
};
|
|
341
425
|
/**
|
|
342
|
-
*
|
|
343
|
-
*
|
|
426
|
+
* The transaction pool: transactions indexed by `txKey`.
|
|
427
|
+
*
|
|
428
|
+
* @template T - The application transaction type.
|
|
344
429
|
*/
|
|
345
430
|
type TransactionPool<T extends Transaction> = Record<string, T>;
|
|
346
431
|
/**
|
|
347
|
-
*
|
|
348
|
-
* on a transaction object via the `updateTxParams` action. This ensures type safety
|
|
349
|
-
* and prevents accidental modification of immutable properties.
|
|
432
|
+
* The fields `updateTxParams` accepts: the fields trackers change while a transaction is tracked.
|
|
350
433
|
*/
|
|
351
434
|
type UpdatableTransactionFields = Partial<Pick<EvmTransaction, 'to' | 'nonce' | 'txKey' | 'pending' | 'hash' | 'status' | 'replacedTxHash' | 'error' | 'finishedTimestamp' | 'isTrackedModalOpen' | 'isError' | 'maxPriorityFeePerGas' | 'maxFeePerGas' | 'input' | 'value' | 'confirmations' | 'requiredConfirmations'>> & Partial<Pick<SolanaTransaction, 'slot' | 'confirmations' | 'fee' | 'instructions' | 'recentBlockhash' | 'rpcUrl'>>;
|
|
352
435
|
/**
|
|
353
|
-
* The
|
|
354
|
-
*
|
|
355
|
-
* @template T The
|
|
436
|
+
* The state and actions of the core store slice created by `initializeTxTrackingStore`.
|
|
437
|
+
*
|
|
438
|
+
* @template T - The application transaction type.
|
|
356
439
|
*/
|
|
357
440
|
interface IInitializeTxTrackingStore<T extends Transaction> {
|
|
358
|
-
/**
|
|
441
|
+
/** Every tracked transaction, indexed by `txKey`. Persisted to `localStorage` by `createPulsarStore`. */
|
|
359
442
|
transactionsPool: TransactionPool<T>;
|
|
360
|
-
/** The `txKey` of the
|
|
443
|
+
/** The `txKey` of the transaction added last. */
|
|
361
444
|
lastAddedTxKey?: string;
|
|
362
|
-
/**
|
|
445
|
+
/**
|
|
446
|
+
* The transaction `executeTxAction` is processing, before it is added to the pool. Not persisted by
|
|
447
|
+
* `createPulsarStore`: after a reload it is `undefined`.
|
|
448
|
+
*/
|
|
363
449
|
initialTx?: InitialTransaction;
|
|
364
450
|
/**
|
|
365
|
-
*
|
|
366
|
-
*
|
|
451
|
+
* Validates a transaction and adds it to the pool with `pending: true`. When the pool already holds
|
|
452
|
+
* `maxTransactions` transactions, the oldest one is evicted. If `onRemoteCreate` is configured, the transaction gets
|
|
453
|
+
* `syncStatus: 'pending-sync'`, its key is listed in `unsyncedTxKeys`, and `onRemoteCreate` runs in the background
|
|
454
|
+
* (see `SyncCallbacks`). Does not start a tracker.
|
|
455
|
+
* @param tx - The transaction to add.
|
|
456
|
+
* @returns A promise that resolves once the transaction is in the pool, without waiting for `onRemoteCreate`.
|
|
457
|
+
* @throws `PulsarTransactionValidationError` synchronously, before anything is written, when the title, description
|
|
458
|
+
* or payload is invalid.
|
|
367
459
|
*/
|
|
368
460
|
addTxToPool: (tx: T) => Promise<void>;
|
|
369
461
|
/**
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
* @param
|
|
462
|
+
* Merges fields into a transaction of the pool; does nothing if the key is unknown. When `fields.status` is terminal
|
|
463
|
+
* and the transaction is in `unsyncedTxKeys`, it starts `reconcileUnsyncedTransactions` in the background.
|
|
464
|
+
* @param txKey - The key of the transaction.
|
|
465
|
+
* @param fields - The fields to merge.
|
|
373
466
|
*/
|
|
374
467
|
updateTxParams: (txKey: string, fields: UpdatableTransactionFields) => void;
|
|
375
468
|
/**
|
|
376
|
-
* Removes a transaction from the
|
|
377
|
-
* @param txKey The key of the transaction
|
|
469
|
+
* Removes a transaction from the pool. Does not stop its tracker.
|
|
470
|
+
* @param txKey - The key of the transaction.
|
|
378
471
|
*/
|
|
379
472
|
removeTxFromPool: (txKey: string) => void;
|
|
380
473
|
/**
|
|
381
|
-
*
|
|
382
|
-
* @param txKey The
|
|
474
|
+
* Sets `isTrackedModalOpen: false` on a transaction and always clears `initialTx`.
|
|
475
|
+
* @param txKey - The key of the transaction whose modal is closed, if any.
|
|
383
476
|
*/
|
|
384
477
|
closeTxTrackedModal: (txKey?: string) => void;
|
|
385
478
|
/**
|
|
386
|
-
*
|
|
387
|
-
* @returns The key of the
|
|
479
|
+
* Returns `lastAddedTxKey`.
|
|
480
|
+
* @returns The key of the transaction added last, or `undefined`.
|
|
388
481
|
*/
|
|
389
482
|
getLastTxKey: () => string | undefined;
|
|
390
483
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
484
|
+
* Keys of transactions that `onRemoteCreate` has not confirmed yet: in flight, failed, or interrupted by a reload.
|
|
485
|
+
* `reconcileUnsyncedTransactions` retries them. Persisted to `localStorage`.
|
|
393
486
|
*/
|
|
394
487
|
unsyncedTxKeys?: Record<string, boolean>;
|
|
395
488
|
/**
|
|
396
|
-
*
|
|
397
|
-
*
|
|
489
|
+
* Calls `onRemoteCreate` again for every key in `unsyncedTxKeys`, one after another, skipping keys whose call is still
|
|
490
|
+
* in flight. Successful transactions are marked `'synced'` and removed from the list; failures are logged and stay
|
|
491
|
+
* listed; keys of transactions no longer in the pool are removed. Does nothing without `onRemoteCreate` or while a
|
|
492
|
+
* previous run is in progress. Runs at the start of every `executeTxAction`, when an
|
|
493
|
+
* unsynced transaction reaches a terminal status, and when `createTxInMemoryStore` loads the first history page.
|
|
494
|
+
* @returns A promise that resolves when the run is finished. It does not reject.
|
|
398
495
|
*/
|
|
399
496
|
reconcileUnsyncedTransactions: () => Promise<void>;
|
|
400
497
|
}
|
|
401
498
|
/**
|
|
402
|
-
* The
|
|
403
|
-
*
|
|
499
|
+
* The state and actions of the store created by `createPulsarStore`.
|
|
500
|
+
*
|
|
501
|
+
* @template T - The application transaction type.
|
|
404
502
|
*/
|
|
405
503
|
type ITxTrackingStore<T extends Transaction> = IInitializeTxTrackingStore<T> & {
|
|
406
|
-
/**
|
|
504
|
+
/**
|
|
505
|
+
* Returns the adapter configuration passed to `createPulsarStore`.
|
|
506
|
+
* @returns The adapter, or the array of adapters.
|
|
507
|
+
*/
|
|
407
508
|
getAdapter: () => TxAdapter<T> | TxAdapter<T>[];
|
|
408
509
|
/**
|
|
409
|
-
*
|
|
410
|
-
*
|
|
510
|
+
* Runs a transaction from start to tracking: validates `params`, sets `initialTx`, checks the chain (the EVM adapter
|
|
511
|
+
* may ask the wallet to switch), runs `beforeTxProcess`, calls `actionFunction`, adds the transaction to the pool
|
|
512
|
+
* (see `addTxToPool`) and starts its tracker. When `actionFunction` returns `undefined`, `initialTx` is cleared and
|
|
513
|
+
* nothing is tracked. Also starts `reconcileUnsyncedTransactions` in the background.
|
|
411
514
|
*
|
|
412
|
-
* @param params The
|
|
413
|
-
* @param params.actionFunction
|
|
414
|
-
* @param params.params The metadata
|
|
415
|
-
*
|
|
416
|
-
* @param params.
|
|
417
|
-
* @param params.
|
|
418
|
-
* @param params.
|
|
419
|
-
* @param params.
|
|
515
|
+
* @param params - The action, its metadata and the callbacks.
|
|
516
|
+
* @param params.actionFunction - Signs and submits the transaction; returns its key, or `undefined` if cancelled.
|
|
517
|
+
* @param params.params - The transaction metadata. `title`, `description` and `payload` are validated before
|
|
518
|
+
* anything else runs.
|
|
519
|
+
* @param params.defaultTracker - Tracker used when the adapter does not return one.
|
|
520
|
+
* @param params.beforeTxProcess - Preflight callback for this transaction; replaces the global one.
|
|
521
|
+
* @param params.abortOnTxError - Overrides the global `abortOnTxError` for this transaction.
|
|
522
|
+
* @param params.onSuccess - Called when the transaction succeeds (see `TrackerCallbacks`).
|
|
523
|
+
* @param params.onError - Called when the transaction fails after it was submitted (see `TrackerCallbacks`).
|
|
524
|
+
* @param params.onReplaced - Called when the transaction is replaced (see `TrackerCallbacks`).
|
|
525
|
+
* @returns A promise that resolves when the adapter's `checkAndInitializeTrackerInStore` resolves: once polling has
|
|
526
|
+
* started for polling trackers (Solana, Safe, ERC-4337, Gelato), but only when tracking has finished for standard
|
|
527
|
+
* EVM transactions (`TransactionTracker.Ethereum`). Read the state from the store instead of awaiting the result.
|
|
528
|
+
* @throws `PulsarTransactionValidationError` when the metadata is invalid (before `initialTx` is set). Rejects with
|
|
529
|
+
* the underlying error when no adapter is configured, or when the chain check, `beforeTxProcess` (with
|
|
530
|
+
* `abortOnTxError`), `actionFunction` or the tracker start fails; `initialTx.error` is set first.
|
|
420
531
|
*/
|
|
421
532
|
executeTxAction: (params: {
|
|
422
533
|
actionFunction: () => Promise<ActionTxKey | undefined>;
|
|
@@ -426,64 +537,83 @@ type ITxTrackingStore<T extends Transaction> = IInitializeTxTrackingStore<T> & {
|
|
|
426
537
|
abortOnTxError?: boolean;
|
|
427
538
|
} & TrackerCallbacks<T>) => Promise<void>;
|
|
428
539
|
/**
|
|
429
|
-
*
|
|
430
|
-
*
|
|
540
|
+
* Restarts the trackers of all pending transactions in the pool, for example after a page reload. Pending
|
|
541
|
+
* transactions that fail validation are removed from the pool. Call it once per page load: every call starts new
|
|
542
|
+
* trackers, and trackers started here have no `TrackerCallbacks`.
|
|
543
|
+
* @returns A promise that resolves when all trackers have started.
|
|
431
544
|
*/
|
|
432
545
|
initializeTransactionsPool: () => Promise<void>;
|
|
433
546
|
/**
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
547
|
+
* Merges transactions from a remote backend into the pool (cross-device sync). Invalid transactions are skipped
|
|
548
|
+
* with a warning. Pending remote transactions that are not in the pool are added and tracked. Local pending
|
|
549
|
+
* transactions that are terminal remotely take the remote `status`, `txKey` and `finishedTimestamp` and are marked
|
|
550
|
+
* not pending.
|
|
551
|
+
* @param remoteTxs - Transactions returned by the backend.
|
|
552
|
+
* @returns A promise that resolves when the trackers of the added transactions have started.
|
|
437
553
|
*/
|
|
438
554
|
injectExternalPendingTxs: (remoteTxs: T[]) => Promise<void>;
|
|
439
555
|
};
|
|
440
556
|
/**
|
|
441
|
-
*
|
|
442
|
-
* for managing transaction history.
|
|
557
|
+
* The pagination state and action of the in-memory history store, as consumed by UI components.
|
|
443
558
|
*/
|
|
444
559
|
type TxInMemoryPagination = {
|
|
445
|
-
/**
|
|
560
|
+
/** `true` while a history page is loading. */
|
|
446
561
|
isLoading: boolean;
|
|
447
|
-
/**
|
|
562
|
+
/** `true` when the last history request failed. */
|
|
448
563
|
isError: boolean;
|
|
449
|
-
/**
|
|
564
|
+
/** `true` when the last loaded page reported a next page. */
|
|
450
565
|
hasMore: boolean;
|
|
451
|
-
/** The
|
|
566
|
+
/** The last loaded page number. */
|
|
452
567
|
currentPage: number;
|
|
453
|
-
/**
|
|
568
|
+
/**
|
|
569
|
+
* Loads the page after `currentPage` and merges it into the pool. Does nothing while loading, when `hasMore` is
|
|
570
|
+
* `false`, or without `getHistory`.
|
|
571
|
+
* @param walletAddress - The wallet whose history is loaded.
|
|
572
|
+
*/
|
|
454
573
|
fetchNextPage: (walletAddress: string) => Promise<void>;
|
|
455
574
|
};
|
|
456
575
|
/**
|
|
457
|
-
* The
|
|
458
|
-
*
|
|
576
|
+
* The state and actions of the store created by `createTxInMemoryStore`: a paginated remote history merged with the
|
|
577
|
+
* local pool. Nothing in it is persisted.
|
|
459
578
|
*
|
|
460
|
-
* @template T The transaction type.
|
|
579
|
+
* @template T - The application transaction type.
|
|
461
580
|
*/
|
|
462
581
|
type ITxInMemoryStore<T extends Transaction> = {
|
|
463
|
-
/**
|
|
582
|
+
/** The local and remote transactions, indexed by `txKey`. */
|
|
464
583
|
transactionsPool: TransactionPool<T>;
|
|
465
|
-
/**
|
|
584
|
+
/**
|
|
585
|
+
* Runs `reconcileUnsyncedTransactions` (if provided), then loads the first history page and merges it into the
|
|
586
|
+
* pool. Does nothing without `getHistory` or an empty `walletAddress`.
|
|
587
|
+
* @param walletAddress - The wallet whose history is loaded.
|
|
588
|
+
*/
|
|
466
589
|
fetchInitial: (walletAddress: string) => Promise<void>;
|
|
467
|
-
/**
|
|
590
|
+
/**
|
|
591
|
+
* Merges a local pool into the in-memory pool. Transactions that are `Success` or `Replaced` in memory are kept;
|
|
592
|
+
* pending ones are overwritten only by a terminal transaction or one with more confirmations.
|
|
593
|
+
* @param localPool - The pool of the persistent store, usually from its `subscribe` listener.
|
|
594
|
+
*/
|
|
468
595
|
syncWithLocalPool: (localPool: TransactionPool<T>) => void;
|
|
469
596
|
} & TxInMemoryPagination;
|
|
470
597
|
/**
|
|
471
|
-
*
|
|
598
|
+
* The configuration of `createTxInMemoryStore`.
|
|
472
599
|
*
|
|
473
|
-
* @template T The transaction type.
|
|
600
|
+
* @template T - The application transaction type.
|
|
474
601
|
*/
|
|
475
602
|
type ITxInMemoryStoreParameters<T extends Transaction> = {
|
|
476
|
-
/**
|
|
603
|
+
/** The initial pool, usually `transactionsPool` of the persistent store. */
|
|
477
604
|
localTransactionsPool: TransactionPool<T>;
|
|
478
|
-
/**
|
|
479
|
-
* Attempts to synchronize any transactions in `unsyncedTxKeys` that have reached a terminal
|
|
480
|
-
* status but failed their initial `onRemoteCreate` call.
|
|
481
|
-
*/
|
|
605
|
+
/** Called by `fetchInitial` before the first page is loaded, usually the store's `reconcileUnsyncedTransactions`. */
|
|
482
606
|
reconcileUnsyncedTransactions?: () => Promise<void>;
|
|
483
|
-
/**
|
|
484
|
-
*
|
|
607
|
+
/**
|
|
608
|
+
* Called in a microtask with the valid transactions of every loaded page, usually to pass them to the store's
|
|
609
|
+
* `injectExternalPendingTxs`.
|
|
610
|
+
* @param remoteTxs - The transactions of the loaded page.
|
|
485
611
|
*/
|
|
486
612
|
onHistoryFetched?: (remoteTxs: T[]) => void;
|
|
613
|
+
/**
|
|
614
|
+
* Loads one page of the remote history of a wallet. Return `null` when there is no history to show (for example,
|
|
615
|
+
* the user is not signed in); throw on errors to set `isError`.
|
|
616
|
+
*/
|
|
487
617
|
getHistory?: ({ page, walletAddress, }: {
|
|
488
618
|
/**
|
|
489
619
|
* Page number for pagination.
|
|
@@ -491,6 +621,7 @@ type ITxInMemoryStoreParameters<T extends Transaction> = {
|
|
|
491
621
|
* @defaultValue `1`
|
|
492
622
|
*/
|
|
493
623
|
page?: number;
|
|
624
|
+
/** The wallet whose history is requested. */
|
|
494
625
|
walletAddress: string;
|
|
495
626
|
}) => Promise<{
|
|
496
627
|
/** Array of transactions for the current page. */
|
|
@@ -509,95 +640,135 @@ type ITxInMemoryStoreParameters<T extends Transaction> = {
|
|
|
509
640
|
};
|
|
510
641
|
|
|
511
642
|
/**
|
|
512
|
-
* @file
|
|
513
|
-
*
|
|
643
|
+
* @file The core Zustand slice of the transaction store: the transaction pool and the actions that add, update and
|
|
644
|
+
* remove transactions and synchronize them with a remote backend.
|
|
514
645
|
*/
|
|
515
646
|
|
|
516
647
|
/**
|
|
517
|
-
* Creates
|
|
518
|
-
*
|
|
648
|
+
* Creates the core slice of the transaction store: `transactionsPool`, `initialTx`, `unsyncedTxKeys` and the actions
|
|
649
|
+
* that change them. `createPulsarStore` uses it; call it directly only to compose a custom Zustand store.
|
|
519
650
|
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
* @
|
|
651
|
+
* The slice keeps its state in memory; persistence is added by the store that uses it.
|
|
652
|
+
*
|
|
653
|
+
* @template T - The application transaction type.
|
|
654
|
+
* @param params - The slice options.
|
|
655
|
+
* @param params.maxTransactions - Maximum number of transactions in the pool; `addTxToPool` evicts the oldest one
|
|
656
|
+
* (by `localTimestamp`) when the pool is full.
|
|
657
|
+
* @param params.onRemoteCreate - Optional remote sync callback, called in the background by `addTxToPool` (see
|
|
658
|
+
* `SyncCallbacks`).
|
|
659
|
+
* @returns A slice creator for Zustand's `create` / `createStore`.
|
|
523
660
|
*/
|
|
524
661
|
declare function initializeTxTrackingStore<T extends Transaction>({ maxTransactions, onRemoteCreate, }: Pick<PulsarAdapter<T>, 'onRemoteCreate'> & {
|
|
525
662
|
maxTransactions: number;
|
|
526
663
|
}): StoreSlice<IInitializeTxTrackingStore<T>>;
|
|
527
664
|
|
|
528
665
|
/**
|
|
529
|
-
* @file
|
|
530
|
-
*
|
|
666
|
+
* @file Selectors that derive lists of transactions from a transaction pool. They are plain functions: each call
|
|
667
|
+
* returns a new array, so memoize the result (or compare it shallowly) when using it in a React selector.
|
|
531
668
|
*/
|
|
532
669
|
|
|
533
670
|
/**
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
* @
|
|
537
|
-
* @
|
|
671
|
+
* Returns every transaction of the pool, oldest first (by `localTimestamp`).
|
|
672
|
+
*
|
|
673
|
+
* @template T - The application transaction type.
|
|
674
|
+
* @param transactionsPool - The transaction pool of the store.
|
|
675
|
+
* @returns A new array of all transactions, sorted chronologically.
|
|
538
676
|
*/
|
|
539
677
|
declare const selectAllTransactions: <T extends Transaction>(transactionsPool: TransactionPool<T>) => T[];
|
|
540
678
|
/**
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
* @
|
|
544
|
-
* @
|
|
679
|
+
* Returns the transactions with `pending: true`, oldest first.
|
|
680
|
+
*
|
|
681
|
+
* @template T - The application transaction type.
|
|
682
|
+
* @param transactionsPool - The transaction pool of the store.
|
|
683
|
+
* @returns A new array of pending transactions, sorted chronologically.
|
|
545
684
|
*/
|
|
546
685
|
declare const selectPendingTransactions: <T extends Transaction>(transactionsPool: TransactionPool<T>) => T[];
|
|
547
686
|
/**
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
* @
|
|
551
|
-
* @param
|
|
552
|
-
* @
|
|
687
|
+
* Returns the transaction stored under a `txKey`.
|
|
688
|
+
*
|
|
689
|
+
* @template T - The application transaction type.
|
|
690
|
+
* @param transactionsPool - The transaction pool of the store.
|
|
691
|
+
* @param key - The `txKey` of the transaction.
|
|
692
|
+
* @returns The transaction, or `undefined` if the pool has no such key.
|
|
553
693
|
*/
|
|
554
694
|
declare const selectTxByKey: <T extends Transaction>(transactionsPool: TransactionPool<T>, key: string) => T | undefined;
|
|
555
695
|
/**
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
* @
|
|
559
|
-
* @param
|
|
560
|
-
* @
|
|
696
|
+
* Returns the transactions sent by a wallet, oldest first. Addresses are compared case-insensitively.
|
|
697
|
+
*
|
|
698
|
+
* @template T - The application transaction type.
|
|
699
|
+
* @param transactionsPool - The transaction pool of the store.
|
|
700
|
+
* @param from - The wallet address to match against the `from` field.
|
|
701
|
+
* @returns A new array of the wallet's transactions, sorted chronologically.
|
|
561
702
|
*/
|
|
562
703
|
declare const selectAllTransactionsByActiveWallet: <T extends Transaction>(transactionsPool: TransactionPool<T>, from: string) => T[];
|
|
563
704
|
/**
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
* @
|
|
567
|
-
* @param
|
|
568
|
-
* @
|
|
705
|
+
* Returns the pending transactions sent by a wallet, oldest first. Addresses are compared case-insensitively.
|
|
706
|
+
*
|
|
707
|
+
* @template T - The application transaction type.
|
|
708
|
+
* @param transactionsPool - The transaction pool of the store.
|
|
709
|
+
* @param from - The wallet address to match against the `from` field.
|
|
710
|
+
* @returns A new array of the wallet's pending transactions, sorted chronologically.
|
|
569
711
|
*/
|
|
570
712
|
declare const selectPendingTransactionsByActiveWallet: <T extends Transaction>(transactionsPool: TransactionPool<T>, from: string) => T[];
|
|
571
713
|
|
|
572
714
|
/**
|
|
573
|
-
* Creates an in-memory transaction
|
|
715
|
+
* Creates an in-memory store that shows the remote transaction history of a wallet (for example from Quasar) together
|
|
716
|
+
* with the local pool of the persistent store. Nothing in it is persisted. Keep it in sync with the persistent store by
|
|
717
|
+
* calling `syncWithLocalPool` from that store's `subscribe` listener.
|
|
574
718
|
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
* - preserve terminal transaction states
|
|
578
|
-
* - support paginated history loading
|
|
579
|
-
* - avoid duplicated merge logic across store actions
|
|
719
|
+
* Merge rules: a transaction that is `Success` or `Replaced` in memory is never overwritten; a pending one is
|
|
720
|
+
* overwritten only by a terminal transaction or by one with more confirmations; any other one is overwritten.
|
|
580
721
|
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
722
|
+
* History pages are validated like `injectExternalPendingTxs` does: transactions whose title, description or payload
|
|
723
|
+
* break the safety limits are skipped with a warning and are not passed to `onHistoryFetched`.
|
|
724
|
+
*
|
|
725
|
+
* Side effects: `fetchInitial` and `fetchNextPage` call `getHistory`, usually a network request. The store uses its
|
|
726
|
+
* own Immer instance without auto-freeze and does not change the global Immer configuration.
|
|
727
|
+
*
|
|
728
|
+
* @template T - The application transaction type.
|
|
729
|
+
* @param params - The store configuration.
|
|
730
|
+
* @param params.localTransactionsPool - The initial pool.
|
|
731
|
+
* @param params.reconcileUnsyncedTransactions - Called by `fetchInitial` before the first page is loaded.
|
|
732
|
+
* @param params.getHistory - Loads one page of the remote history. A `null` result stops loading without changing the
|
|
733
|
+
* pool; a thrown error sets `isError`.
|
|
734
|
+
* @param params.onHistoryFetched - Called in a microtask with the valid transactions of every loaded page.
|
|
735
|
+
* @returns A vanilla Zustand store; bind it to React with `createBoundedUseStore`.
|
|
585
736
|
*/
|
|
586
737
|
declare function createTxInMemoryStore<T extends Transaction>({ localTransactionsPool, reconcileUnsyncedTransactions, getHistory, onHistoryFetched, }: ITxInMemoryStoreParameters<T>): zustand.StoreApi<ITxInMemoryStore<T>>;
|
|
587
738
|
|
|
588
739
|
/**
|
|
589
|
-
* Creates the
|
|
740
|
+
* Creates the Pulsar transaction store: a vanilla Zustand store (use it from any framework, or bind it to React with
|
|
741
|
+
* `createBoundedUseStore`) that runs transactions through chain adapters and tracks them in the background.
|
|
590
742
|
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
743
|
+
* Side effects: the state is saved with Zustand's `persist` middleware under the key `name`, by default in
|
|
744
|
+
* `localStorage`, on every change: `transactionsPool`, `lastAddedTxKey` and `unsyncedTxKeys`. `initialTx` is neither
|
|
745
|
+
* saved nor restored (pass your own `partialize` and `merge` to change that). In the browser the saved state is
|
|
746
|
+
* restored synchronously when the store is created. Where
|
|
747
|
+
* `localStorage` is not available (server rendering), nothing is read or written and Zustand logs a warning on
|
|
748
|
+
* updates. Creating the store does not start any tracker: call `initializeTransactionsPool` once on the client.
|
|
594
749
|
*
|
|
595
|
-
* @template T The
|
|
750
|
+
* @template T - The application transaction type.
|
|
751
|
+
* @param params - The adapters, the store options and the options of Zustand's `persist` middleware.
|
|
752
|
+
* @param params.adapter - A chain adapter, or an array of adapters, such as `pulsarEvmAdapter` from
|
|
753
|
+
* `@tuwaio/pulsar-evm` or `pulsarSolanaAdapter` from `@tuwaio/pulsar-solana`.
|
|
754
|
+
* @param params.maxTransactions - Maximum number of transactions in the pool. Defaults to 50.
|
|
755
|
+
* @param params.onRemoteCreate - Remote sync callback (see `SyncCallbacks`).
|
|
756
|
+
* @param params.gelatoApiKey - Deprecated Gelato API key, passed to the trackers.
|
|
757
|
+
* @param params.beforeTxProcess - Global preflight callback (see `BeforeTxProcess`).
|
|
758
|
+
* @param params.abortOnTxError - Whether a `beforeTxProcess` error aborts the transaction. Defaults to `true`.
|
|
759
|
+
* @param params.name - The storage key. Required by `persist`; use a different key for every store.
|
|
760
|
+
* @returns The vanilla Zustand store. `store.persist` exposes the `persist` API (for example `clearStorage()`).
|
|
596
761
|
*
|
|
597
|
-
* @
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
762
|
+
* @example
|
|
763
|
+
* ```ts
|
|
764
|
+
* import { createPulsarStore } from '@tuwaio/pulsar-core';
|
|
765
|
+
* import { pulsarEvmAdapter } from '@tuwaio/pulsar-evm';
|
|
766
|
+
*
|
|
767
|
+
* export const pulsarStore = createPulsarStore({
|
|
768
|
+
* name: 'transactions-tracking-storage',
|
|
769
|
+
* adapter: pulsarEvmAdapter(wagmiConfig, appChains),
|
|
770
|
+
* });
|
|
771
|
+
* ```
|
|
601
772
|
*/
|
|
602
773
|
declare function createPulsarStore<T extends Transaction>({ adapter, maxTransactions, onRemoteCreate, gelatoApiKey, beforeTxProcess, abortOnTxError, ...options }: PulsarAdapter<T> & PersistOptions<ITxTrackingStore<T>>): Omit<zustand.StoreApi<ITxTrackingStore<T>>, "setState" | "persist"> & {
|
|
603
774
|
setState(partial: ITxTrackingStore<T> | Partial<ITxTrackingStore<T>> | ((state: ITxTrackingStore<T>) => ITxTrackingStore<T> | Partial<ITxTrackingStore<T>>), replace?: false | undefined): unknown;
|
|
@@ -614,36 +785,36 @@ declare function createPulsarStore<T extends Transaction>({ adapter, maxTransact
|
|
|
614
785
|
};
|
|
615
786
|
|
|
616
787
|
/**
|
|
617
|
-
* @file
|
|
618
|
-
* This pattern is recommended by the official Zustand documentation to ensure full type
|
|
619
|
-
* safety when integrating vanilla stores with React.
|
|
788
|
+
* @file Binds a vanilla Zustand store (such as the Pulsar stores) to React with a typed hook.
|
|
620
789
|
*
|
|
621
|
-
* @see https://docs.pmnd.rs/
|
|
790
|
+
* @see {@link https://zustand.docs.pmnd.rs/guides/typescript#bounded-usestore-hook-for-vanilla-stores Zustand: bounded useStore hook}
|
|
622
791
|
*/
|
|
623
792
|
|
|
624
793
|
/**
|
|
625
|
-
*
|
|
626
|
-
*
|
|
627
|
-
* @template S - The
|
|
794
|
+
* The state type of a Zustand store: the return type of its `getState` method.
|
|
795
|
+
*
|
|
796
|
+
* @template S - The store type.
|
|
628
797
|
*/
|
|
629
798
|
type ExtractState<S> = S extends {
|
|
630
799
|
getState: () => infer T;
|
|
631
800
|
} ? T : never;
|
|
632
801
|
/**
|
|
633
|
-
* Creates a
|
|
802
|
+
* Creates a React hook bound to a vanilla Zustand store, so components do not pass the store on every call.
|
|
634
803
|
*
|
|
635
|
-
*
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
804
|
+
* The hook calls `useStore` from `zustand`, so it follows the rules of React hooks and needs `react` in the app. Call it
|
|
805
|
+
* without arguments to subscribe to the whole state, or with a selector to subscribe to a slice. A selector that
|
|
806
|
+
* returns a new object or array on every call (such as the transaction selectors) re-renders on every store update;
|
|
807
|
+
* select stable values or memoize.
|
|
639
808
|
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
809
|
+
* @template S - The store type.
|
|
810
|
+
* @param store - The vanilla Zustand store, for example the result of `createPulsarStore`.
|
|
811
|
+
* @returns A hook: `useBoundedStore()` returns the whole state, `useBoundedStore(selector)` returns the selected value.
|
|
643
812
|
*
|
|
644
|
-
* @
|
|
645
|
-
*
|
|
646
|
-
*
|
|
813
|
+
* @example
|
|
814
|
+
* ```ts
|
|
815
|
+
* const usePulsarStore = createBoundedUseStore(pulsarStore);
|
|
816
|
+
* const executeTxAction = usePulsarStore((state) => state.executeTxAction);
|
|
817
|
+
* ```
|
|
647
818
|
*/
|
|
648
819
|
declare const createBoundedUseStore: <S extends StoreApi<unknown>>(store: S) => {
|
|
649
820
|
(): ExtractState<S>;
|
|
@@ -651,95 +822,206 @@ declare const createBoundedUseStore: <S extends StoreApi<unknown>>(store: S) =>
|
|
|
651
822
|
};
|
|
652
823
|
|
|
653
824
|
/**
|
|
654
|
-
* @file
|
|
655
|
-
* asynchronous tasks, such as API-based transaction status checks (e.g., for Gelato or Safe).
|
|
825
|
+
* @file Helper for store-connected trackers that keeps their copy of a transaction in sync with the fields they write.
|
|
656
826
|
*/
|
|
657
827
|
|
|
658
828
|
/**
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
*
|
|
662
|
-
*
|
|
829
|
+
* Creates an updater for a store-connected tracker: it writes fields to the store with `updateTxParams` and returns the
|
|
830
|
+
* tracked transaction with every update applied so far.
|
|
831
|
+
*
|
|
832
|
+
* The `transactionsPool` a tracker receives is a snapshot taken when tracking starts, and Immer replaces the pool on
|
|
833
|
+
* every update, so reading the snapshot after `updateTxParams` returns stale data. Pass the object returned here to
|
|
834
|
+
* `TrackerCallbacks` instead. The built-in trackers of `@tuwaio/pulsar-evm` and `@tuwaio/pulsar-solana` use it; use it
|
|
835
|
+
* in custom trackers too.
|
|
836
|
+
*
|
|
837
|
+
* @template T - The application transaction type.
|
|
838
|
+
* @param params - The tracked transaction and the store members used by trackers.
|
|
839
|
+
* @param params.tx - The tracked transaction.
|
|
840
|
+
* @param params.transactionsPool - The pool snapshot; the tracked transaction is read from it once.
|
|
841
|
+
* @param params.updateTxParams - The store's `updateTxParams`.
|
|
842
|
+
* @returns A function that calls `updateTxParams(tx.txKey, fields)` and returns the updated transaction, or `undefined`
|
|
843
|
+
* when the transaction was not in the pool when tracking started. The snapshot is not mutated.
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```ts
|
|
847
|
+
* const updateTx = createTxUpdater({ tx, transactionsPool, updateTxParams });
|
|
848
|
+
* const updatedTx = updateTx({ status: TransactionStatus.Success, pending: false });
|
|
849
|
+
* if (updatedTx) onSuccess?.(updatedTx);
|
|
850
|
+
* ```
|
|
851
|
+
*/
|
|
852
|
+
declare function createTxUpdater<T extends Transaction>({ tx, transactionsPool, updateTxParams, }: Pick<ITxTrackingStore<T>, 'transactionsPool' | 'updateTxParams'> & {
|
|
853
|
+
tx: T;
|
|
854
|
+
}): (fields: UpdatableTransactionFields) => T | undefined;
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* @file A generic polling loop for trackers that check a transaction through an API or RPC method (Safe, Gelato,
|
|
858
|
+
* ERC-4337 bundlers, Solana).
|
|
859
|
+
*/
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* The argument passed to a polling fetcher on every tick. The fetcher checks the transaction once and reports the result
|
|
863
|
+
* through the callbacks.
|
|
864
|
+
*
|
|
865
|
+
* @template R - The response type the fetcher reports.
|
|
866
|
+
* @template T - The tracked transaction type.
|
|
663
867
|
*/
|
|
664
868
|
type PollingFetcherParams<R, T> = {
|
|
665
|
-
/** The transaction
|
|
869
|
+
/** The tracked transaction, as passed to `initializePollingTracker`. */
|
|
666
870
|
tx: T;
|
|
667
|
-
/**
|
|
871
|
+
/**
|
|
872
|
+
* Stops polling. Unless `withoutRemoving` is `true`, it also calls `removeTxFromPool` (if configured) with the
|
|
873
|
+
* transaction key.
|
|
874
|
+
* @param options - Stop options.
|
|
875
|
+
*/
|
|
668
876
|
stopPolling: (options?: {
|
|
877
|
+
/** Keep the transaction in the pool. Defaults to `false`. */
|
|
669
878
|
withoutRemoving?: boolean;
|
|
670
879
|
}) => void;
|
|
671
|
-
/**
|
|
880
|
+
/**
|
|
881
|
+
* The `onSuccess` callback of the tracker configuration.
|
|
882
|
+
* @param response - The result of the check.
|
|
883
|
+
*/
|
|
672
884
|
onSuccess: (response: R) => void;
|
|
673
|
-
/**
|
|
885
|
+
/**
|
|
886
|
+
* The `onFailure` callback of the tracker configuration.
|
|
887
|
+
* @param response - The result of the check, if any.
|
|
888
|
+
*/
|
|
674
889
|
onFailure: (response?: R) => void;
|
|
675
|
-
/**
|
|
890
|
+
/**
|
|
891
|
+
* The `onIntervalTick` callback of the tracker configuration, if any.
|
|
892
|
+
* @param response - The intermediate result.
|
|
893
|
+
*/
|
|
676
894
|
onIntervalTick?: (response: R) => void;
|
|
677
|
-
/**
|
|
895
|
+
/**
|
|
896
|
+
* The `onReplaced` callback of the tracker configuration, if any.
|
|
897
|
+
* @param response - The result describing the replacement.
|
|
898
|
+
*/
|
|
678
899
|
onReplaced?: (response: R) => void;
|
|
679
900
|
};
|
|
680
901
|
/**
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
* @template
|
|
902
|
+
* The configuration of `initializePollingTracker`.
|
|
903
|
+
*
|
|
904
|
+
* @template R - The response type the fetcher reports.
|
|
905
|
+
* @template T - The tracked transaction type; only `txKey` and `pending` are required.
|
|
684
906
|
*/
|
|
685
|
-
type PollingTrackerConfig<R, T extends Transaction
|
|
686
|
-
/** The transaction
|
|
687
|
-
tx: T
|
|
688
|
-
/**
|
|
907
|
+
type PollingTrackerConfig<R, T extends Pick<Transaction, 'txKey' | 'pending'>> = {
|
|
908
|
+
/** The transaction to track. Polling starts only if `pending` is `true`. */
|
|
909
|
+
tx: T;
|
|
910
|
+
/**
|
|
911
|
+
* Checks the transaction once per tick and reports through the callbacks it receives. It must call `stopPolling` on a
|
|
912
|
+
* terminal result. A thrown error counts as a failed attempt.
|
|
913
|
+
* @param params - The transaction, `stopPolling` and the callbacks.
|
|
914
|
+
*/
|
|
689
915
|
fetcher: (params: PollingFetcherParams<R, T>) => Promise<void>;
|
|
690
|
-
/**
|
|
916
|
+
/**
|
|
917
|
+
* Called by the fetcher when the transaction succeeded.
|
|
918
|
+
* @param response - The result reported by the fetcher.
|
|
919
|
+
*/
|
|
691
920
|
onSuccess: (response: R) => void;
|
|
692
|
-
/**
|
|
921
|
+
/**
|
|
922
|
+
* Called by the fetcher when the transaction failed, and without arguments by the tracker after `maxRetries`
|
|
923
|
+
* consecutive failed attempts.
|
|
924
|
+
* @param response - The result reported by the fetcher, if any.
|
|
925
|
+
*/
|
|
693
926
|
onFailure: (response?: R) => void;
|
|
694
|
-
/**
|
|
927
|
+
/** Called once, synchronously, when polling starts. */
|
|
695
928
|
onInitialize?: () => void;
|
|
696
|
-
/**
|
|
929
|
+
/**
|
|
930
|
+
* Called by the fetcher with intermediate results.
|
|
931
|
+
* @param response - The intermediate result.
|
|
932
|
+
*/
|
|
697
933
|
onIntervalTick?: (response: R) => void;
|
|
698
|
-
/**
|
|
934
|
+
/**
|
|
935
|
+
* Called by the fetcher when the transaction was replaced.
|
|
936
|
+
* @param response - The result describing the replacement.
|
|
937
|
+
*/
|
|
699
938
|
onReplaced?: (response: R) => void;
|
|
700
|
-
/**
|
|
939
|
+
/**
|
|
940
|
+
* Called when polling stops, unless it was stopped with `withoutRemoving: true`.
|
|
941
|
+
* @param txKey - The `txKey` of the tracked transaction.
|
|
942
|
+
*/
|
|
701
943
|
removeTxFromPool?: (txKey: string) => void;
|
|
702
|
-
/** The
|
|
944
|
+
/** The delay before each attempt, in milliseconds. Defaults to 5000. */
|
|
703
945
|
pollingInterval?: number;
|
|
704
|
-
/** The number of consecutive failed
|
|
946
|
+
/** The number of consecutive failed attempts (thrown errors) after which polling stops. Defaults to 10. */
|
|
705
947
|
maxRetries?: number;
|
|
706
948
|
};
|
|
707
949
|
/**
|
|
708
|
-
*
|
|
709
|
-
*
|
|
950
|
+
* Starts polling a transaction in the background and returns immediately. Does nothing if `tx.pending` is `false`.
|
|
951
|
+
*
|
|
952
|
+
* Every `pollingInterval` milliseconds (the first attempt also waits) it calls `fetcher`. Polling continues until the
|
|
953
|
+
* fetcher calls `stopPolling`. A fetcher that throws counts as a failed attempt; after `maxRetries` consecutive failed
|
|
954
|
+
* attempts the tracker calls `onFailure()` without arguments, logs a warning and stops (which calls
|
|
955
|
+
* `removeTxFromPool`, if configured). A successful attempt resets the count.
|
|
710
956
|
*
|
|
711
|
-
*
|
|
712
|
-
* and automatic termination after a certain number of failed attempts.
|
|
957
|
+
* Side effects: runs a timer loop until it is stopped; there is no way to cancel it from the outside.
|
|
713
958
|
*
|
|
714
|
-
* @template R The
|
|
715
|
-
* @template T The
|
|
716
|
-
* @param
|
|
959
|
+
* @template R - The response type the fetcher reports.
|
|
960
|
+
* @template T - The tracked transaction type.
|
|
961
|
+
* @param config - The transaction, the fetcher and the callbacks.
|
|
962
|
+
*
|
|
963
|
+
* @example
|
|
964
|
+
* ```ts
|
|
965
|
+
* initializePollingTracker<string, { txKey: string; pending: boolean }>({
|
|
966
|
+
* tx: { txKey: taskId, pending: true },
|
|
967
|
+
* fetcher: async ({ tx, stopPolling, onSuccess, onFailure }) => {
|
|
968
|
+
* const status = await getTaskStatus(tx.txKey); // your API call; throw on network errors
|
|
969
|
+
* if (status === 'done') onSuccess(status);
|
|
970
|
+
* if (status === 'failed') onFailure(status);
|
|
971
|
+
* if (status !== 'pending') stopPolling({ withoutRemoving: true });
|
|
972
|
+
* },
|
|
973
|
+
* onSuccess: () => console.log('Done'),
|
|
974
|
+
* onFailure: () => console.log('Failed'),
|
|
975
|
+
* });
|
|
976
|
+
* ```
|
|
717
977
|
*/
|
|
718
|
-
declare function initializePollingTracker<R, T extends Transaction
|
|
978
|
+
declare function initializePollingTracker<R, T extends Pick<Transaction, 'txKey' | 'pending'>>(config: PollingTrackerConfig<R, T>): void;
|
|
719
979
|
|
|
720
|
-
/**
|
|
980
|
+
/**
|
|
981
|
+
* @file Safety limits for the user-facing metadata of transactions (title, description, payload), checked before a
|
|
982
|
+
* transaction is executed, stored, restored or synchronized.
|
|
983
|
+
*/
|
|
984
|
+
|
|
985
|
+
/** Maximum length, in characters, of each `title` string. */
|
|
721
986
|
declare const MAX_TRANSACTION_TITLE_LENGTH = 100;
|
|
722
|
-
/** Maximum
|
|
987
|
+
/** Maximum length, in characters, of each `description` string. */
|
|
723
988
|
declare const MAX_TRANSACTION_DESCRIPTION_LENGTH = 300;
|
|
724
|
-
/** Maximum
|
|
989
|
+
/** Maximum size, in bytes, of the UTF-8 JSON of `payload`. */
|
|
725
990
|
declare const MAX_TRANSACTION_PAYLOAD_BYTES: number;
|
|
726
991
|
/**
|
|
727
|
-
*
|
|
992
|
+
* Thrown when the title, description or payload of a transaction breaks Pulsar's safety limits.
|
|
728
993
|
*/
|
|
729
994
|
declare class PulsarTransactionValidationError extends Error {
|
|
730
|
-
/** The
|
|
995
|
+
/** The field that failed, for example `title`, `description[1]` or `payload.amount`. */
|
|
731
996
|
readonly field: string;
|
|
997
|
+
/**
|
|
998
|
+
* @param field - The field that failed.
|
|
999
|
+
* @param message - The error message.
|
|
1000
|
+
*/
|
|
732
1001
|
constructor(field: string, message: string);
|
|
733
1002
|
}
|
|
734
1003
|
/**
|
|
735
|
-
* Validates metadata
|
|
736
|
-
*
|
|
1004
|
+
* Validates the metadata passed to `executeTxAction` before anything else runs.
|
|
1005
|
+
*
|
|
1006
|
+
* Each `title` string must be at most {@link MAX_TRANSACTION_TITLE_LENGTH} characters and each `description` string at
|
|
1007
|
+
* most {@link MAX_TRANSACTION_DESCRIPTION_LENGTH}. `payload` must be JSON-serializable and at most
|
|
1008
|
+
* {@link MAX_TRANSACTION_PAYLOAD_BYTES} bytes as UTF-8 JSON. Strings (including payload keys) must not match
|
|
1009
|
+
* executable-like patterns: `eval(`, `Function(`, `setTimeout`/`setInterval` with a string argument, and `javascript:`.
|
|
1010
|
+
* This is a defensive gate, not a replacement for escaping output in the UI.
|
|
1011
|
+
*
|
|
1012
|
+
* @param params - The transaction metadata.
|
|
1013
|
+
* @throws {@link PulsarTransactionValidationError} for the first field that breaks a rule.
|
|
737
1014
|
*/
|
|
738
1015
|
declare function validateInitialTransactionParams(params: Omit<InitialTransactionParams, 'actionFunction'>): void;
|
|
739
1016
|
/**
|
|
740
|
-
* Validates a complete transaction
|
|
741
|
-
*
|
|
1017
|
+
* Validates the title, description and payload of a complete transaction with the rules of
|
|
1018
|
+
* {@link validateInitialTransactionParams}. Used by `addTxToPool`, `initializeTransactionsPool` and
|
|
1019
|
+
* `injectExternalPendingTxs`.
|
|
1020
|
+
*
|
|
1021
|
+
* @template T - The application transaction type.
|
|
1022
|
+
* @param tx - The transaction.
|
|
1023
|
+
* @throws {@link PulsarTransactionValidationError} for the first field that breaks a rule.
|
|
742
1024
|
*/
|
|
743
1025
|
declare function validateTransaction<T extends Transaction>(tx: T): void;
|
|
744
1026
|
|
|
745
|
-
export { type ActionTxKey, type BaseTransaction, type BeforeTxProcess, type CheckTxTracker, type EvmTransaction, type IInitializeTxTrackingStore, type ITxInMemoryStore, type ITxInMemoryStoreParameters, type ITxTrackingStore, type InitialTransaction, type InitialTransactionParams, MAX_TRANSACTION_DESCRIPTION_LENGTH, MAX_TRANSACTION_PAYLOAD_BYTES, MAX_TRANSACTION_TITLE_LENGTH, type PollingFetcherParams, type PollingTrackerConfig, type PulsarAdapter, PulsarTransactionValidationError, type SolanaTransaction, type StarknetTransaction, type StoreSlice, type SyncCallbacks, type TrackerCallbacks, type Transaction, type TransactionPool, TransactionStatus, TransactionTracker, type TxAdapter, type TxInMemoryPagination, type UpdatableTransactionFields, createBoundedUseStore, createPulsarStore, createTxInMemoryStore, initializePollingTracker, initializeTxTrackingStore, selectAllTransactions, selectAllTransactionsByActiveWallet, selectPendingTransactions, selectPendingTransactionsByActiveWallet, selectTxByKey, validateInitialTransactionParams, validateTransaction };
|
|
1027
|
+
export { type ActionTxKey, type BaseTransaction, type BeforeTxProcess, type CheckTxTracker, type EvmTransaction, type ExtractState, type IInitializeTxTrackingStore, type ITxInMemoryStore, type ITxInMemoryStoreParameters, type ITxTrackingStore, type InitialTransaction, type InitialTransactionParams, MAX_TRANSACTION_DESCRIPTION_LENGTH, MAX_TRANSACTION_PAYLOAD_BYTES, MAX_TRANSACTION_TITLE_LENGTH, type PollingFetcherParams, type PollingTrackerConfig, type PulsarAdapter, PulsarTransactionValidationError, type SolanaTransaction, type StarknetTransaction, type StoreSlice, type SyncCallbacks, type TrackerCallbacks, type Transaction, type TransactionPool, TransactionStatus, TransactionTracker, type TxAdapter, type TxInMemoryPagination, type UpdatableTransactionFields, createBoundedUseStore, createPulsarStore, createTxInMemoryStore, createTxUpdater, initializePollingTracker, initializeTxTrackingStore, selectAllTransactions, selectAllTransactionsByActiveWallet, selectPendingTransactions, selectPendingTransactionsByActiveWallet, selectTxByKey, validateInitialTransactionParams, validateTransaction };
|