@tuwaio/pulsar-core 0.6.12 → 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 +621 -321
- package/dist/index.d.ts +621 -321
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +17 -13
package/dist/index.d.mts
CHANGED
|
@@ -4,308 +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
|
+
/**
|
|
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.
|
|
30
|
+
*/
|
|
22
31
|
Gelato = "gelato",
|
|
23
|
-
/**
|
|
24
|
-
Solana = "solana"
|
|
32
|
+
/** A Solana transaction, tracked by its signature through RPC (`@tuwaio/pulsar-solana`). */
|
|
33
|
+
Solana = "solana",
|
|
34
|
+
/** An ERC-4337 UserOperation, tracked by its `userOpHash` through a bundler RPC and then on-chain. */
|
|
35
|
+
ERC4337 = "erc4337"
|
|
25
36
|
}
|
|
26
37
|
/**
|
|
27
|
-
*
|
|
38
|
+
* Terminal status of a transaction. Trackers set it together with `pending: false`.
|
|
28
39
|
*/
|
|
29
40
|
declare enum TransactionStatus {
|
|
30
|
-
/** The transaction failed
|
|
41
|
+
/** The transaction reverted, was rejected, or tracking failed (for example, it was not found in time). */
|
|
31
42
|
Failed = "Failed",
|
|
32
|
-
/** The transaction was
|
|
43
|
+
/** The transaction was included on-chain and executed successfully. */
|
|
33
44
|
Success = "Success",
|
|
34
|
-
/**
|
|
45
|
+
/** Another transaction with the same nonce was mined instead (a wallet speed-up or cancel). */
|
|
35
46
|
Replaced = "Replaced"
|
|
36
47
|
}
|
|
37
48
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* This key is crucial for the adapter to determine which tracker should
|
|
42
|
-
* monitor the transaction.
|
|
43
|
-
*
|
|
44
|
-
* It can be one of the following:
|
|
45
|
-
* - A standard `0x...` transaction hash (`Hex`).
|
|
46
|
-
* - 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.
|
|
47
52
|
*/
|
|
48
53
|
type ActionTxKey = `0x${string}` | string;
|
|
49
54
|
/**
|
|
50
|
-
*
|
|
51
|
-
* 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.
|
|
52
56
|
*/
|
|
53
57
|
type BaseTransaction = {
|
|
54
|
-
/**
|
|
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
|
+
*/
|
|
55
62
|
chainId: number | string;
|
|
56
63
|
/**
|
|
57
|
-
* User-facing description
|
|
58
|
-
* Each string
|
|
59
|
-
*
|
|
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.
|
|
60
68
|
* @example
|
|
61
|
-
*
|
|
62
|
-
* description: 'Swap 1 ETH for 1,500 USDC'
|
|
63
|
-
*
|
|
64
|
-
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* description: 'Swap 1 ETH for 1,500 USDC';
|
|
71
|
+
* description: ['Swapping...', 'Swapped successfully', 'Swap failed', 'Swap replaced'];
|
|
72
|
+
* ```
|
|
65
73
|
*/
|
|
66
74
|
description?: string | [string, string, string, string];
|
|
67
|
-
/** The error
|
|
75
|
+
/** The normalized error of a failed transaction (`normalizeError` from `@tuwaio/orbit-core`). */
|
|
68
76
|
error?: TuwaErrorState;
|
|
69
|
-
/**
|
|
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
|
+
*/
|
|
70
81
|
finishedTimestamp?: number;
|
|
71
|
-
/** The
|
|
82
|
+
/** The address of the wallet that sent the transaction, as reported by the adapter's `getConnectorInfo`. */
|
|
72
83
|
from: string;
|
|
73
|
-
/**
|
|
84
|
+
/** `true` when the transaction failed; set by trackers together with `status: Failed`. */
|
|
74
85
|
isError?: boolean;
|
|
75
|
-
/**
|
|
86
|
+
/** UI flag for a detailed tracking modal. Set from `withTrackedModal`; `closeTxTrackedModal` sets it to `false`. */
|
|
76
87
|
isTrackedModalOpen?: boolean;
|
|
77
|
-
/**
|
|
88
|
+
/** Unix timestamp (seconds) when `executeTxAction` started. The pool is ordered and evicted by this value. */
|
|
78
89
|
localTimestamp: number;
|
|
79
90
|
/**
|
|
80
|
-
* Custom JSON
|
|
81
|
-
*
|
|
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.
|
|
82
93
|
*/
|
|
83
94
|
payload?: Record<string, string | number>;
|
|
84
|
-
/**
|
|
95
|
+
/** `true` while the transaction is tracked; trackers set it to `false` when it reaches a terminal status. */
|
|
85
96
|
pending: boolean;
|
|
86
|
-
/** The
|
|
97
|
+
/** The terminal status, set together with `pending: false`. */
|
|
87
98
|
status?: TransactionStatus;
|
|
88
99
|
/**
|
|
89
|
-
* User-facing title
|
|
90
|
-
* Each string
|
|
91
|
-
*
|
|
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:`.
|
|
92
103
|
* @example
|
|
93
|
-
*
|
|
94
|
-
* title: 'ETH/USDC
|
|
95
|
-
*
|
|
96
|
-
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* title: 'ETH/USDC swap';
|
|
106
|
+
* title: ['Processing swap', 'Swap complete', 'Swap error', 'Swap replaced'];
|
|
107
|
+
* ```
|
|
97
108
|
*/
|
|
98
109
|
title?: string | [string, string, string, string];
|
|
99
|
-
/** The
|
|
110
|
+
/** The tracker that monitors the transaction. */
|
|
100
111
|
tracker: TransactionTracker;
|
|
101
|
-
/**
|
|
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
|
+
*/
|
|
102
116
|
txKey: string;
|
|
103
|
-
/**
|
|
117
|
+
/** Application-specific type of the transaction, for example `'SWAP'` or `'APPROVE'`. */
|
|
104
118
|
type: string;
|
|
105
|
-
/** The
|
|
119
|
+
/** The connector that signed the transaction, for example `evm:metamask` or `solana:phantom`. */
|
|
106
120
|
connectorType: string;
|
|
107
|
-
/**
|
|
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
|
+
*/
|
|
108
125
|
requiredConfirmations?: number;
|
|
109
|
-
/**
|
|
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
|
+
*/
|
|
110
130
|
confirmations?: number | string | null;
|
|
111
|
-
/**
|
|
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
|
+
*/
|
|
112
135
|
rpcUrl?: string;
|
|
113
|
-
/**
|
|
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
|
+
*/
|
|
114
141
|
syncStatus?: 'synced' | 'pending-sync';
|
|
115
142
|
};
|
|
116
143
|
/**
|
|
117
|
-
*
|
|
144
|
+
* An EVM transaction. Trackers fill the on-chain fields (`hash`, `nonce`, fees, `to`, `value`, `input`) once the
|
|
145
|
+
* transaction details are available.
|
|
118
146
|
*/
|
|
119
147
|
type EvmTransaction = BaseTransaction & {
|
|
120
|
-
/**
|
|
148
|
+
/** Always `OrbitAdapter.EVM`. */
|
|
121
149
|
adapter: OrbitAdapter.EVM;
|
|
122
|
-
/**
|
|
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
|
+
*/
|
|
123
154
|
hash?: `0x${string}`;
|
|
124
|
-
/** The
|
|
155
|
+
/** The calldata of the transaction. */
|
|
125
156
|
input?: `0x${string}`;
|
|
126
|
-
/**
|
|
157
|
+
/** EIP-1559 max fee per gas, in wei, as a decimal string. */
|
|
127
158
|
maxFeePerGas?: string;
|
|
128
|
-
/**
|
|
159
|
+
/** EIP-1559 max priority fee per gas, in wei, as a decimal string. */
|
|
129
160
|
maxPriorityFeePerGas?: string;
|
|
130
|
-
/** The
|
|
161
|
+
/** The nonce of the sender account. */
|
|
131
162
|
nonce?: number;
|
|
132
|
-
/**
|
|
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
|
+
*/
|
|
133
167
|
replacedTxHash?: `0x${string}`;
|
|
134
|
-
/** The recipient
|
|
168
|
+
/** The recipient or contract address. */
|
|
135
169
|
to?: `0x${string}`;
|
|
136
|
-
/** The
|
|
170
|
+
/** The native value sent, in wei, as a decimal string. */
|
|
137
171
|
value?: string;
|
|
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
|
+
*/
|
|
177
|
+
bundlerUrl?: string;
|
|
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
|
+
*/
|
|
182
|
+
pimlicoApiKey?: string;
|
|
138
183
|
};
|
|
139
184
|
/**
|
|
140
|
-
*
|
|
185
|
+
* A Solana transaction. The Solana tracker fills the on-chain fields once the transaction is found.
|
|
141
186
|
*/
|
|
142
187
|
type SolanaTransaction = BaseTransaction & {
|
|
143
|
-
/**
|
|
188
|
+
/** Always `OrbitAdapter.SOLANA`. */
|
|
144
189
|
adapter: OrbitAdapter.SOLANA;
|
|
145
|
-
/** The transaction fee in lamports. */
|
|
190
|
+
/** The transaction fee, in lamports. */
|
|
146
191
|
fee?: number;
|
|
147
|
-
/** The instructions
|
|
192
|
+
/** The instructions of the transaction, as returned by the `getTransaction` RPC method. */
|
|
148
193
|
instructions?: unknown[];
|
|
149
|
-
/** The
|
|
194
|
+
/** The blockhash the transaction was signed with. */
|
|
150
195
|
recentBlockhash?: string;
|
|
151
196
|
/** The slot in which the transaction was processed. */
|
|
152
197
|
slot?: number;
|
|
153
198
|
};
|
|
154
199
|
/**
|
|
155
|
-
*
|
|
200
|
+
* A Starknet transaction. Reserved for a Starknet adapter; Pulsar does not ship one.
|
|
156
201
|
*/
|
|
157
202
|
type StarknetTransaction = BaseTransaction & {
|
|
158
|
-
/**
|
|
203
|
+
/** Always `OrbitAdapter.Starknet`. */
|
|
159
204
|
adapter: OrbitAdapter.Starknet;
|
|
160
205
|
/** The actual fee paid for the transaction. */
|
|
161
206
|
actualFee?: {
|
|
207
|
+
/** The fee amount. */
|
|
162
208
|
amount: string;
|
|
209
|
+
/** The fee unit. */
|
|
163
210
|
unit: string;
|
|
164
211
|
};
|
|
165
212
|
/** The address of the contract being interacted with. */
|
|
166
213
|
contractAddress?: string;
|
|
167
214
|
};
|
|
168
|
-
/**
|
|
215
|
+
/** Any transaction Pulsar can track. Application transaction types extend one of its members. */
|
|
169
216
|
type Transaction = EvmTransaction | SolanaTransaction | StarknetTransaction;
|
|
170
217
|
/**
|
|
171
|
-
*
|
|
218
|
+
* The metadata of a transaction passed to `executeTxAction` (as `params`, without `actionFunction`) and kept in
|
|
219
|
+
* `initialTx`.
|
|
172
220
|
*/
|
|
173
|
-
type InitialTransactionParams = Pick<BaseTransaction, 'description' | 'title' | 'type' | 'requiredConfirmations' | 'rpcUrl' | 'payload'> & {
|
|
174
|
-
/** The
|
|
221
|
+
type InitialTransactionParams = Pick<BaseTransaction, 'description' | 'title' | 'type' | 'requiredConfirmations' | 'rpcUrl' | 'payload'> & Pick<EvmTransaction, 'bundlerUrl' | 'pimlicoApiKey'> & {
|
|
222
|
+
/** The adapter that handles the transaction. When no configured adapter has this key, the first one is used. */
|
|
175
223
|
adapter: OrbitAdapter;
|
|
176
|
-
/**
|
|
177
|
-
|
|
178
|
-
|
|
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
|
+
*/
|
|
179
235
|
desiredChainID: number | string;
|
|
180
|
-
/**
|
|
236
|
+
/** When `true`, the transaction is created with `isTrackedModalOpen: true`. */
|
|
181
237
|
withTrackedModal?: boolean;
|
|
182
|
-
/**
|
|
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
|
+
*/
|
|
183
242
|
tracker?: TransactionTracker;
|
|
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
|
+
*/
|
|
247
|
+
gelatoApiKey?: string;
|
|
184
248
|
};
|
|
185
249
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
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).
|
|
188
252
|
*/
|
|
189
253
|
type InitialTransaction = InitialTransactionParams & {
|
|
190
|
-
/**
|
|
254
|
+
/** The normalized error when the flow failed before tracking started, for example a rejected signature. */
|
|
191
255
|
error?: TuwaErrorState;
|
|
192
|
-
/**
|
|
256
|
+
/** `true` from the start of `executeTxAction` until the transaction is added to the pool or the flow fails. */
|
|
193
257
|
isInitializing: boolean;
|
|
194
|
-
/** The `txKey` of the
|
|
258
|
+
/** The `txKey` of the transaction this action added to the pool. */
|
|
195
259
|
lastTxKey?: string;
|
|
196
|
-
/**
|
|
260
|
+
/** Unix timestamp (seconds) when `executeTxAction` started. */
|
|
197
261
|
localTimestamp: number;
|
|
198
262
|
};
|
|
199
263
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
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.
|
|
202
269
|
*/
|
|
203
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
|
+
*/
|
|
204
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
|
+
*/
|
|
205
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
|
+
*/
|
|
206
287
|
onReplaced?: (newTx: T, oldTx: T) => Promise<void> | void;
|
|
207
288
|
}
|
|
208
289
|
/**
|
|
209
|
-
* Callbacks
|
|
210
|
-
*
|
|
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.
|
|
211
294
|
*/
|
|
212
295
|
interface SyncCallbacks<T extends Transaction> {
|
|
213
296
|
/**
|
|
214
|
-
* Called
|
|
215
|
-
*
|
|
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`.
|
|
216
303
|
*/
|
|
217
304
|
onRemoteCreate?: (tx: T) => Promise<void>;
|
|
218
305
|
}
|
|
219
306
|
/**
|
|
220
|
-
*
|
|
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.
|
|
221
309
|
*
|
|
222
|
-
* Throw
|
|
223
|
-
*
|
|
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.
|
|
224
313
|
*/
|
|
225
314
|
type BeforeTxProcess = () => Promise<void> | void;
|
|
226
315
|
/**
|
|
227
|
-
* The configuration
|
|
228
|
-
*
|
|
316
|
+
* The configuration of `createPulsarStore`: one or more chain adapters and the store options.
|
|
317
|
+
*
|
|
318
|
+
* @template T - The application transaction type.
|
|
229
319
|
*/
|
|
230
320
|
type PulsarAdapter<T extends Transaction> = OrbitGenericAdapter<TxAdapter<T>> & {
|
|
231
|
-
/**
|
|
321
|
+
/** Global preflight callback run before every transaction. A `beforeTxProcess` passed to `executeTxAction` replaces it. */
|
|
232
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. */
|
|
233
324
|
maxTransactions?: number;
|
|
325
|
+
/** @deprecated Gelato relay is deprecated. Gelato API key used to track `TransactionTracker.Gelato` transactions. */
|
|
234
326
|
gelatoApiKey?: string;
|
|
235
|
-
/**
|
|
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
|
+
*/
|
|
236
331
|
abortOnTxError?: boolean;
|
|
237
332
|
} & SyncCallbacks<T>;
|
|
238
333
|
/**
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* @typedef {Object} CheckTxTracker
|
|
242
|
-
* @property {ActionTxKey} actionTxKey - The key identifying the specific action related to the transaction.
|
|
243
|
-
* @property {string} connectorType - The type of connector used for the transaction (e.g., wallet provider, blockchain interface).
|
|
244
|
-
* @property {TransactionTracker} [tracker] - An optional tracker object that monitors the status and progress of the transaction.
|
|
245
|
-
* @property {string} [gelatoApiKey] - An optional Gelato API key for Gelato relayer integration.
|
|
334
|
+
* The input of `TxAdapter.checkTransactionsTracker`: the key returned by the action and the context needed to pick a
|
|
335
|
+
* tracker.
|
|
246
336
|
*/
|
|
247
337
|
type CheckTxTracker = {
|
|
338
|
+
/** The key returned by `actionFunction`. */
|
|
248
339
|
actionTxKey: ActionTxKey;
|
|
340
|
+
/** The connector that signed the transaction, for example `evm:safe` for a Safe wallet. */
|
|
249
341
|
connectorType: string;
|
|
342
|
+
/** The tracker requested in `executeTxAction` params, if any. */
|
|
250
343
|
tracker?: TransactionTracker;
|
|
344
|
+
/** @deprecated Gelato relay is deprecated. Use `bundlerUrl` / `pimlicoApiKey` with ERC-4337 instead. */
|
|
251
345
|
gelatoApiKey?: string;
|
|
346
|
+
/** Custom bundler RPC URL for ERC-4337 UserOperation tracking. */
|
|
347
|
+
bundlerUrl?: string;
|
|
348
|
+
/** Pimlico API key for ERC-4337 UserOperation tracking. */
|
|
349
|
+
pimlicoApiKey?: string;
|
|
252
350
|
};
|
|
253
351
|
/**
|
|
254
|
-
*
|
|
255
|
-
*
|
|
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.
|
|
256
356
|
*/
|
|
257
357
|
type TxAdapter<T extends Transaction> = Pick<BaseAdapter, 'getExplorerUrl'> & {
|
|
258
|
-
/** The
|
|
358
|
+
/** The chain family handled by the adapter. */
|
|
259
359
|
key: OrbitAdapter;
|
|
260
|
-
/** Returns
|
|
360
|
+
/** Returns the connected wallet. Called by `executeTxAction` before the chain check. */
|
|
261
361
|
getConnectorInfo: () => {
|
|
262
|
-
/** The
|
|
362
|
+
/** The address of the connected wallet. */
|
|
263
363
|
walletAddress: string;
|
|
264
|
-
/** The type
|
|
364
|
+
/** The connector type, for example `evm:metamask`. */
|
|
265
365
|
connectorType: string;
|
|
266
366
|
};
|
|
267
367
|
/**
|
|
268
|
-
* Ensures the
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* @param chainId The desired chain ID for the transaction.
|
|
272
|
-
* @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.
|
|
273
371
|
*/
|
|
274
372
|
checkChainForTx: (chainId: string | number) => Promise<void>;
|
|
275
373
|
/**
|
|
276
|
-
*
|
|
277
|
-
* @
|
|
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.
|
|
278
377
|
*/
|
|
279
|
-
checkTransactionsTracker: (
|
|
378
|
+
checkTransactionsTracker: (params: CheckTxTracker) => {
|
|
379
|
+
/** The key the transaction is stored under. */
|
|
280
380
|
txKey: string;
|
|
381
|
+
/** The tracker that monitors the transaction. */
|
|
281
382
|
tracker: TransactionTracker;
|
|
282
383
|
};
|
|
283
384
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
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.
|
|
286
388
|
*/
|
|
287
389
|
checkAndInitializeTrackerInStore: (params: {
|
|
288
390
|
tx: T;
|
|
289
391
|
gelatoApiKey?: string;
|
|
290
392
|
} & TrackerCallbacks<T> & Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'>) => Promise<void> | void;
|
|
291
393
|
/**
|
|
292
|
-
* Optional:
|
|
293
|
-
* @param tx The transaction to cancel.
|
|
294
|
-
* @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.
|
|
295
397
|
*/
|
|
296
398
|
cancelTxAction?: (tx: T) => Promise<string>;
|
|
297
399
|
/**
|
|
298
|
-
* Optional:
|
|
299
|
-
* @param tx The transaction to speed up.
|
|
300
|
-
* @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.
|
|
301
403
|
*/
|
|
302
404
|
speedUpTxAction?: (tx: T) => Promise<string>;
|
|
303
405
|
/**
|
|
304
|
-
* Optional:
|
|
305
|
-
* @param params The parameters
|
|
306
|
-
* @param params.txKey The
|
|
307
|
-
* @param params.tx The
|
|
308
|
-
* @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`.
|
|
309
412
|
*/
|
|
310
413
|
retryTxAction?: (params: {
|
|
311
414
|
txKey: string;
|
|
@@ -313,92 +416,118 @@ type TxAdapter<T extends Transaction> = Pick<BaseAdapter, 'getExplorerUrl'> & {
|
|
|
313
416
|
onClose: (txKey?: string) => void;
|
|
314
417
|
} & Partial<Pick<ITxTrackingStore<T>, 'executeTxAction'>>) => Promise<void>;
|
|
315
418
|
/**
|
|
316
|
-
* Optional:
|
|
317
|
-
*
|
|
318
|
-
* @
|
|
319
|
-
* @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.
|
|
320
422
|
*/
|
|
321
423
|
getExplorerTxUrl?: (tx: T) => string;
|
|
322
424
|
};
|
|
323
425
|
/**
|
|
324
|
-
*
|
|
325
|
-
*
|
|
426
|
+
* The transaction pool: transactions indexed by `txKey`.
|
|
427
|
+
*
|
|
428
|
+
* @template T - The application transaction type.
|
|
326
429
|
*/
|
|
327
430
|
type TransactionPool<T extends Transaction> = Record<string, T>;
|
|
328
431
|
/**
|
|
329
|
-
*
|
|
330
|
-
* on a transaction object via the `updateTxParams` action. This ensures type safety
|
|
331
|
-
* and prevents accidental modification of immutable properties.
|
|
432
|
+
* The fields `updateTxParams` accepts: the fields trackers change while a transaction is tracked.
|
|
332
433
|
*/
|
|
333
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'>>;
|
|
334
435
|
/**
|
|
335
|
-
* The
|
|
336
|
-
*
|
|
337
|
-
* @template T The
|
|
436
|
+
* The state and actions of the core store slice created by `initializeTxTrackingStore`.
|
|
437
|
+
*
|
|
438
|
+
* @template T - The application transaction type.
|
|
338
439
|
*/
|
|
339
440
|
interface IInitializeTxTrackingStore<T extends Transaction> {
|
|
340
|
-
/**
|
|
441
|
+
/** Every tracked transaction, indexed by `txKey`. Persisted to `localStorage` by `createPulsarStore`. */
|
|
341
442
|
transactionsPool: TransactionPool<T>;
|
|
342
|
-
/** The `txKey` of the
|
|
443
|
+
/** The `txKey` of the transaction added last. */
|
|
343
444
|
lastAddedTxKey?: string;
|
|
344
|
-
/**
|
|
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
|
+
*/
|
|
345
449
|
initialTx?: InitialTransaction;
|
|
346
450
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
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.
|
|
349
459
|
*/
|
|
350
460
|
addTxToPool: (tx: T) => Promise<void>;
|
|
351
461
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* @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.
|
|
355
466
|
*/
|
|
356
467
|
updateTxParams: (txKey: string, fields: UpdatableTransactionFields) => void;
|
|
357
468
|
/**
|
|
358
|
-
* Removes a transaction from the
|
|
359
|
-
* @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.
|
|
360
471
|
*/
|
|
361
472
|
removeTxFromPool: (txKey: string) => void;
|
|
362
473
|
/**
|
|
363
|
-
*
|
|
364
|
-
* @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.
|
|
365
476
|
*/
|
|
366
477
|
closeTxTrackedModal: (txKey?: string) => void;
|
|
367
478
|
/**
|
|
368
|
-
*
|
|
369
|
-
* @returns The key of the
|
|
479
|
+
* Returns `lastAddedTxKey`.
|
|
480
|
+
* @returns The key of the transaction added last, or `undefined`.
|
|
370
481
|
*/
|
|
371
482
|
getLastTxKey: () => string | undefined;
|
|
372
483
|
/**
|
|
373
|
-
*
|
|
374
|
-
*
|
|
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`.
|
|
375
486
|
*/
|
|
376
487
|
unsyncedTxKeys?: Record<string, boolean>;
|
|
377
488
|
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
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.
|
|
380
495
|
*/
|
|
381
496
|
reconcileUnsyncedTransactions: () => Promise<void>;
|
|
382
497
|
}
|
|
383
498
|
/**
|
|
384
|
-
* The
|
|
385
|
-
*
|
|
499
|
+
* The state and actions of the store created by `createPulsarStore`.
|
|
500
|
+
*
|
|
501
|
+
* @template T - The application transaction type.
|
|
386
502
|
*/
|
|
387
503
|
type ITxTrackingStore<T extends Transaction> = IInitializeTxTrackingStore<T> & {
|
|
388
|
-
/**
|
|
504
|
+
/**
|
|
505
|
+
* Returns the adapter configuration passed to `createPulsarStore`.
|
|
506
|
+
* @returns The adapter, or the array of adapters.
|
|
507
|
+
*/
|
|
389
508
|
getAdapter: () => TxAdapter<T> | TxAdapter<T>[];
|
|
390
509
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
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.
|
|
393
514
|
*
|
|
394
|
-
* @param params The
|
|
395
|
-
* @param params.actionFunction
|
|
396
|
-
* @param params.params The metadata
|
|
397
|
-
*
|
|
398
|
-
* @param params.
|
|
399
|
-
* @param params.
|
|
400
|
-
* @param params.
|
|
401
|
-
* @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.
|
|
402
531
|
*/
|
|
403
532
|
executeTxAction: (params: {
|
|
404
533
|
actionFunction: () => Promise<ActionTxKey | undefined>;
|
|
@@ -408,64 +537,83 @@ type ITxTrackingStore<T extends Transaction> = IInitializeTxTrackingStore<T> & {
|
|
|
408
537
|
abortOnTxError?: boolean;
|
|
409
538
|
} & TrackerCallbacks<T>) => Promise<void>;
|
|
410
539
|
/**
|
|
411
|
-
*
|
|
412
|
-
*
|
|
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.
|
|
413
544
|
*/
|
|
414
545
|
initializeTransactionsPool: () => Promise<void>;
|
|
415
546
|
/**
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
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.
|
|
419
553
|
*/
|
|
420
554
|
injectExternalPendingTxs: (remoteTxs: T[]) => Promise<void>;
|
|
421
555
|
};
|
|
422
556
|
/**
|
|
423
|
-
*
|
|
424
|
-
* for managing transaction history.
|
|
557
|
+
* The pagination state and action of the in-memory history store, as consumed by UI components.
|
|
425
558
|
*/
|
|
426
559
|
type TxInMemoryPagination = {
|
|
427
|
-
/**
|
|
560
|
+
/** `true` while a history page is loading. */
|
|
428
561
|
isLoading: boolean;
|
|
429
|
-
/**
|
|
562
|
+
/** `true` when the last history request failed. */
|
|
430
563
|
isError: boolean;
|
|
431
|
-
/**
|
|
564
|
+
/** `true` when the last loaded page reported a next page. */
|
|
432
565
|
hasMore: boolean;
|
|
433
|
-
/** The
|
|
566
|
+
/** The last loaded page number. */
|
|
434
567
|
currentPage: number;
|
|
435
|
-
/**
|
|
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
|
+
*/
|
|
436
573
|
fetchNextPage: (walletAddress: string) => Promise<void>;
|
|
437
574
|
};
|
|
438
575
|
/**
|
|
439
|
-
* The
|
|
440
|
-
*
|
|
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.
|
|
441
578
|
*
|
|
442
|
-
* @template T The transaction type.
|
|
579
|
+
* @template T - The application transaction type.
|
|
443
580
|
*/
|
|
444
581
|
type ITxInMemoryStore<T extends Transaction> = {
|
|
445
|
-
/**
|
|
582
|
+
/** The local and remote transactions, indexed by `txKey`. */
|
|
446
583
|
transactionsPool: TransactionPool<T>;
|
|
447
|
-
/**
|
|
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
|
+
*/
|
|
448
589
|
fetchInitial: (walletAddress: string) => Promise<void>;
|
|
449
|
-
/**
|
|
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
|
+
*/
|
|
450
595
|
syncWithLocalPool: (localPool: TransactionPool<T>) => void;
|
|
451
596
|
} & TxInMemoryPagination;
|
|
452
597
|
/**
|
|
453
|
-
*
|
|
598
|
+
* The configuration of `createTxInMemoryStore`.
|
|
454
599
|
*
|
|
455
|
-
* @template T The transaction type.
|
|
600
|
+
* @template T - The application transaction type.
|
|
456
601
|
*/
|
|
457
602
|
type ITxInMemoryStoreParameters<T extends Transaction> = {
|
|
458
|
-
/**
|
|
603
|
+
/** The initial pool, usually `transactionsPool` of the persistent store. */
|
|
459
604
|
localTransactionsPool: TransactionPool<T>;
|
|
460
|
-
/**
|
|
461
|
-
* Attempts to synchronize any transactions in `unsyncedTxKeys` that have reached a terminal
|
|
462
|
-
* status but failed their initial `onRemoteCreate` call.
|
|
463
|
-
*/
|
|
605
|
+
/** Called by `fetchInitial` before the first page is loaded, usually the store's `reconcileUnsyncedTransactions`. */
|
|
464
606
|
reconcileUnsyncedTransactions?: () => Promise<void>;
|
|
465
|
-
/**
|
|
466
|
-
*
|
|
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.
|
|
467
611
|
*/
|
|
468
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
|
+
*/
|
|
469
617
|
getHistory?: ({ page, walletAddress, }: {
|
|
470
618
|
/**
|
|
471
619
|
* Page number for pagination.
|
|
@@ -473,6 +621,7 @@ type ITxInMemoryStoreParameters<T extends Transaction> = {
|
|
|
473
621
|
* @defaultValue `1`
|
|
474
622
|
*/
|
|
475
623
|
page?: number;
|
|
624
|
+
/** The wallet whose history is requested. */
|
|
476
625
|
walletAddress: string;
|
|
477
626
|
}) => Promise<{
|
|
478
627
|
/** Array of transactions for the current page. */
|
|
@@ -491,95 +640,135 @@ type ITxInMemoryStoreParameters<T extends Transaction> = {
|
|
|
491
640
|
};
|
|
492
641
|
|
|
493
642
|
/**
|
|
494
|
-
* @file
|
|
495
|
-
*
|
|
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.
|
|
496
645
|
*/
|
|
497
646
|
|
|
498
647
|
/**
|
|
499
|
-
* Creates
|
|
500
|
-
*
|
|
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.
|
|
501
650
|
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
* @
|
|
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`.
|
|
505
660
|
*/
|
|
506
661
|
declare function initializeTxTrackingStore<T extends Transaction>({ maxTransactions, onRemoteCreate, }: Pick<PulsarAdapter<T>, 'onRemoteCreate'> & {
|
|
507
662
|
maxTransactions: number;
|
|
508
663
|
}): StoreSlice<IInitializeTxTrackingStore<T>>;
|
|
509
664
|
|
|
510
665
|
/**
|
|
511
|
-
* @file
|
|
512
|
-
*
|
|
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.
|
|
513
668
|
*/
|
|
514
669
|
|
|
515
670
|
/**
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
* @
|
|
519
|
-
* @
|
|
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.
|
|
520
676
|
*/
|
|
521
677
|
declare const selectAllTransactions: <T extends Transaction>(transactionsPool: TransactionPool<T>) => T[];
|
|
522
678
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* @
|
|
526
|
-
* @
|
|
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.
|
|
527
684
|
*/
|
|
528
685
|
declare const selectPendingTransactions: <T extends Transaction>(transactionsPool: TransactionPool<T>) => T[];
|
|
529
686
|
/**
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
* @
|
|
533
|
-
* @param
|
|
534
|
-
* @
|
|
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.
|
|
535
693
|
*/
|
|
536
694
|
declare const selectTxByKey: <T extends Transaction>(transactionsPool: TransactionPool<T>, key: string) => T | undefined;
|
|
537
695
|
/**
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
* @
|
|
541
|
-
* @param
|
|
542
|
-
* @
|
|
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.
|
|
543
702
|
*/
|
|
544
703
|
declare const selectAllTransactionsByActiveWallet: <T extends Transaction>(transactionsPool: TransactionPool<T>, from: string) => T[];
|
|
545
704
|
/**
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
* @
|
|
549
|
-
* @param
|
|
550
|
-
* @
|
|
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.
|
|
551
711
|
*/
|
|
552
712
|
declare const selectPendingTransactionsByActiveWallet: <T extends Transaction>(transactionsPool: TransactionPool<T>, from: string) => T[];
|
|
553
713
|
|
|
554
714
|
/**
|
|
555
|
-
* 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.
|
|
718
|
+
*
|
|
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.
|
|
721
|
+
*
|
|
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`.
|
|
556
724
|
*
|
|
557
|
-
* The store
|
|
558
|
-
*
|
|
559
|
-
* - preserve terminal transaction states
|
|
560
|
-
* - support paginated history loading
|
|
561
|
-
* - avoid duplicated merge logic across store actions
|
|
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.
|
|
562
727
|
*
|
|
563
|
-
* @template T The transaction type.
|
|
564
|
-
* @param params
|
|
565
|
-
* @param params.
|
|
566
|
-
* @
|
|
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`.
|
|
567
736
|
*/
|
|
568
737
|
declare function createTxInMemoryStore<T extends Transaction>({ localTransactionsPool, reconcileUnsyncedTransactions, getHistory, onHistoryFetched, }: ITxInMemoryStoreParameters<T>): zustand.StoreApi<ITxInMemoryStore<T>>;
|
|
569
738
|
|
|
570
739
|
/**
|
|
571
|
-
* 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.
|
|
572
742
|
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
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.
|
|
576
749
|
*
|
|
577
|
-
* @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()`).
|
|
578
761
|
*
|
|
579
|
-
* @
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
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
|
+
* ```
|
|
583
772
|
*/
|
|
584
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"> & {
|
|
585
774
|
setState(partial: ITxTrackingStore<T> | Partial<ITxTrackingStore<T>> | ((state: ITxTrackingStore<T>) => ITxTrackingStore<T> | Partial<ITxTrackingStore<T>>), replace?: false | undefined): unknown;
|
|
@@ -596,36 +785,36 @@ declare function createPulsarStore<T extends Transaction>({ adapter, maxTransact
|
|
|
596
785
|
};
|
|
597
786
|
|
|
598
787
|
/**
|
|
599
|
-
* @file
|
|
600
|
-
* This pattern is recommended by the official Zustand documentation to ensure full type
|
|
601
|
-
* 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.
|
|
602
789
|
*
|
|
603
|
-
* @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}
|
|
604
791
|
*/
|
|
605
792
|
|
|
606
793
|
/**
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
* @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.
|
|
610
797
|
*/
|
|
611
798
|
type ExtractState<S> = S extends {
|
|
612
799
|
getState: () => infer T;
|
|
613
800
|
} ? T : never;
|
|
614
801
|
/**
|
|
615
|
-
* Creates a
|
|
802
|
+
* Creates a React hook bound to a vanilla Zustand store, so components do not pass the store on every call.
|
|
616
803
|
*
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
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.
|
|
621
808
|
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
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.
|
|
625
812
|
*
|
|
626
|
-
* @
|
|
627
|
-
*
|
|
628
|
-
*
|
|
813
|
+
* @example
|
|
814
|
+
* ```ts
|
|
815
|
+
* const usePulsarStore = createBoundedUseStore(pulsarStore);
|
|
816
|
+
* const executeTxAction = usePulsarStore((state) => state.executeTxAction);
|
|
817
|
+
* ```
|
|
629
818
|
*/
|
|
630
819
|
declare const createBoundedUseStore: <S extends StoreApi<unknown>>(store: S) => {
|
|
631
820
|
(): ExtractState<S>;
|
|
@@ -633,95 +822,206 @@ declare const createBoundedUseStore: <S extends StoreApi<unknown>>(store: S) =>
|
|
|
633
822
|
};
|
|
634
823
|
|
|
635
824
|
/**
|
|
636
|
-
* @file
|
|
637
|
-
|
|
825
|
+
* @file Helper for store-connected trackers that keeps their copy of a transaction in sync with the fields they write.
|
|
826
|
+
*/
|
|
827
|
+
|
|
828
|
+
/**
|
|
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).
|
|
638
859
|
*/
|
|
639
860
|
|
|
640
861
|
/**
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
* @template
|
|
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.
|
|
645
867
|
*/
|
|
646
868
|
type PollingFetcherParams<R, T> = {
|
|
647
|
-
/** The transaction
|
|
869
|
+
/** The tracked transaction, as passed to `initializePollingTracker`. */
|
|
648
870
|
tx: T;
|
|
649
|
-
/**
|
|
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
|
+
*/
|
|
650
876
|
stopPolling: (options?: {
|
|
877
|
+
/** Keep the transaction in the pool. Defaults to `false`. */
|
|
651
878
|
withoutRemoving?: boolean;
|
|
652
879
|
}) => void;
|
|
653
|
-
/**
|
|
880
|
+
/**
|
|
881
|
+
* The `onSuccess` callback of the tracker configuration.
|
|
882
|
+
* @param response - The result of the check.
|
|
883
|
+
*/
|
|
654
884
|
onSuccess: (response: R) => void;
|
|
655
|
-
/**
|
|
885
|
+
/**
|
|
886
|
+
* The `onFailure` callback of the tracker configuration.
|
|
887
|
+
* @param response - The result of the check, if any.
|
|
888
|
+
*/
|
|
656
889
|
onFailure: (response?: R) => void;
|
|
657
|
-
/**
|
|
890
|
+
/**
|
|
891
|
+
* The `onIntervalTick` callback of the tracker configuration, if any.
|
|
892
|
+
* @param response - The intermediate result.
|
|
893
|
+
*/
|
|
658
894
|
onIntervalTick?: (response: R) => void;
|
|
659
|
-
/**
|
|
895
|
+
/**
|
|
896
|
+
* The `onReplaced` callback of the tracker configuration, if any.
|
|
897
|
+
* @param response - The result describing the replacement.
|
|
898
|
+
*/
|
|
660
899
|
onReplaced?: (response: R) => void;
|
|
661
900
|
};
|
|
662
901
|
/**
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
* @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.
|
|
666
906
|
*/
|
|
667
|
-
type PollingTrackerConfig<R, T extends Transaction
|
|
668
|
-
/** The transaction
|
|
669
|
-
tx: T
|
|
670
|
-
/**
|
|
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
|
+
*/
|
|
671
915
|
fetcher: (params: PollingFetcherParams<R, T>) => Promise<void>;
|
|
672
|
-
/**
|
|
916
|
+
/**
|
|
917
|
+
* Called by the fetcher when the transaction succeeded.
|
|
918
|
+
* @param response - The result reported by the fetcher.
|
|
919
|
+
*/
|
|
673
920
|
onSuccess: (response: R) => void;
|
|
674
|
-
/**
|
|
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
|
+
*/
|
|
675
926
|
onFailure: (response?: R) => void;
|
|
676
|
-
/**
|
|
927
|
+
/** Called once, synchronously, when polling starts. */
|
|
677
928
|
onInitialize?: () => void;
|
|
678
|
-
/**
|
|
929
|
+
/**
|
|
930
|
+
* Called by the fetcher with intermediate results.
|
|
931
|
+
* @param response - The intermediate result.
|
|
932
|
+
*/
|
|
679
933
|
onIntervalTick?: (response: R) => void;
|
|
680
|
-
/**
|
|
934
|
+
/**
|
|
935
|
+
* Called by the fetcher when the transaction was replaced.
|
|
936
|
+
* @param response - The result describing the replacement.
|
|
937
|
+
*/
|
|
681
938
|
onReplaced?: (response: R) => void;
|
|
682
|
-
/**
|
|
939
|
+
/**
|
|
940
|
+
* Called when polling stops, unless it was stopped with `withoutRemoving: true`.
|
|
941
|
+
* @param txKey - The `txKey` of the tracked transaction.
|
|
942
|
+
*/
|
|
683
943
|
removeTxFromPool?: (txKey: string) => void;
|
|
684
|
-
/** The
|
|
944
|
+
/** The delay before each attempt, in milliseconds. Defaults to 5000. */
|
|
685
945
|
pollingInterval?: number;
|
|
686
|
-
/** The number of consecutive failed
|
|
946
|
+
/** The number of consecutive failed attempts (thrown errors) after which polling stops. Defaults to 10. */
|
|
687
947
|
maxRetries?: number;
|
|
688
948
|
};
|
|
689
949
|
/**
|
|
690
|
-
*
|
|
691
|
-
*
|
|
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.
|
|
692
956
|
*
|
|
693
|
-
*
|
|
694
|
-
* 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.
|
|
695
958
|
*
|
|
696
|
-
* @template R The
|
|
697
|
-
* @template T The
|
|
698
|
-
* @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
|
+
* ```
|
|
699
977
|
*/
|
|
700
|
-
declare function initializePollingTracker<R, T extends Transaction
|
|
978
|
+
declare function initializePollingTracker<R, T extends Pick<Transaction, 'txKey' | 'pending'>>(config: PollingTrackerConfig<R, T>): void;
|
|
701
979
|
|
|
702
|
-
/**
|
|
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. */
|
|
703
986
|
declare const MAX_TRANSACTION_TITLE_LENGTH = 100;
|
|
704
|
-
/** Maximum
|
|
987
|
+
/** Maximum length, in characters, of each `description` string. */
|
|
705
988
|
declare const MAX_TRANSACTION_DESCRIPTION_LENGTH = 300;
|
|
706
|
-
/** Maximum
|
|
989
|
+
/** Maximum size, in bytes, of the UTF-8 JSON of `payload`. */
|
|
707
990
|
declare const MAX_TRANSACTION_PAYLOAD_BYTES: number;
|
|
708
991
|
/**
|
|
709
|
-
*
|
|
992
|
+
* Thrown when the title, description or payload of a transaction breaks Pulsar's safety limits.
|
|
710
993
|
*/
|
|
711
994
|
declare class PulsarTransactionValidationError extends Error {
|
|
712
|
-
/** The
|
|
995
|
+
/** The field that failed, for example `title`, `description[1]` or `payload.amount`. */
|
|
713
996
|
readonly field: string;
|
|
997
|
+
/**
|
|
998
|
+
* @param field - The field that failed.
|
|
999
|
+
* @param message - The error message.
|
|
1000
|
+
*/
|
|
714
1001
|
constructor(field: string, message: string);
|
|
715
1002
|
}
|
|
716
1003
|
/**
|
|
717
|
-
* Validates metadata
|
|
718
|
-
*
|
|
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.
|
|
719
1014
|
*/
|
|
720
1015
|
declare function validateInitialTransactionParams(params: Omit<InitialTransactionParams, 'actionFunction'>): void;
|
|
721
1016
|
/**
|
|
722
|
-
* Validates a complete transaction
|
|
723
|
-
*
|
|
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.
|
|
724
1024
|
*/
|
|
725
1025
|
declare function validateTransaction<T extends Transaction>(tx: T): void;
|
|
726
1026
|
|
|
727
|
-
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 };
|