@tuwaio/pulsar-evm 0.4.0 → 0.5.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 +8 -1
- package/dist/index.d.mts +151 -46
- package/dist/index.d.ts +151 -46
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +15 -14
package/README.md
CHANGED
|
@@ -88,7 +88,11 @@ import { config } from './wagmi'; // Your wagmi config
|
|
|
88
88
|
async function trackMyTransaction(txHash: string, chainId: number) {
|
|
89
89
|
await evmTracker({
|
|
90
90
|
config,
|
|
91
|
-
tx: {
|
|
91
|
+
tx: {
|
|
92
|
+
txKey: txHash,
|
|
93
|
+
chainId,
|
|
94
|
+
requiredConfirmations: 3,
|
|
95
|
+
},
|
|
92
96
|
onTxDetailsFetched: (txDetails) => {
|
|
93
97
|
console.log('Transaction details:', txDetails);
|
|
94
98
|
},
|
|
@@ -101,6 +105,9 @@ async function trackMyTransaction(txHash: string, chainId: number) {
|
|
|
101
105
|
onFailure: (error) => {
|
|
102
106
|
console.error('Tracking failed:', error);
|
|
103
107
|
},
|
|
108
|
+
onConfirmationsUpdate: (confirmations) => {
|
|
109
|
+
console.log(`Current confirmations: ${confirmations}/3`);
|
|
110
|
+
},
|
|
104
111
|
});
|
|
105
112
|
}
|
|
106
113
|
```
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Transaction, TxAdapter, ITxTrackingStore, TrackerCallbacks, PollingTrackerConfig,
|
|
1
|
+
import { Transaction, TxAdapter, ITxTrackingStore, TrackerCallbacks, PollingTrackerConfig, TransactionTracker, CheckTxTracker } from '@tuwaio/pulsar-core';
|
|
2
2
|
import { Config } from '@wagmi/core';
|
|
3
|
-
import { Chain, GetTransactionReturnType, TransactionReceipt, Client, ReplacementReturnType, WaitForTransactionReceiptParameters, Hex } from 'viem';
|
|
3
|
+
import { Chain, GetTransactionReturnType, TransactionReceipt, Client, ReplacementReturnType, WaitForTransactionReceiptParameters, Hex, Transport, HttpTransportConfig } from 'viem';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file This file contains the factory function for creating the EVM (Ethereum Virtual Machine) transaction adapter.
|
|
@@ -34,7 +34,7 @@ declare function pulsarEvmAdapter<T extends Transaction>(config: Config, appChai
|
|
|
34
34
|
* Defines the parameters for the low-level EVM transaction tracker.
|
|
35
35
|
*/
|
|
36
36
|
type EVMTrackerParams = {
|
|
37
|
-
tx: Pick<Transaction, 'chainId' | 'txKey'>;
|
|
37
|
+
tx: Pick<Transaction, 'chainId' | 'txKey' | 'requiredConfirmations'>;
|
|
38
38
|
config: Config;
|
|
39
39
|
onTxDetailsFetched: (txDetails: GetTransactionReturnType) => void;
|
|
40
40
|
onSuccess: (txDetails: GetTransactionReturnType, receipt: TransactionReceipt, client: Client) => Promise<void>;
|
|
@@ -43,6 +43,7 @@ type EVMTrackerParams = {
|
|
|
43
43
|
onInitialize?: () => void;
|
|
44
44
|
retryCount?: number;
|
|
45
45
|
retryTimeout?: number;
|
|
46
|
+
onConfirmationsUpdate?: (confirmations: number) => void;
|
|
46
47
|
waitForTransactionReceiptParams?: WaitForTransactionReceiptParameters;
|
|
47
48
|
};
|
|
48
49
|
/**
|
|
@@ -64,56 +65,97 @@ declare function evmTrackerForStore<T extends Transaction>(params: Pick<EVMTrack
|
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
67
|
* @file This file implements the transaction tracking logic for meta-transactions relayed via the Gelato Network.
|
|
67
|
-
* It uses a polling mechanism to check the status of a Gelato
|
|
68
|
+
* It uses a polling mechanism to check the status of a Gelato task via the authenticated Gelato RPC client.
|
|
69
|
+
*
|
|
70
|
+
* The fetcher calls `relayer_getStatus` on the Gelato RPC endpoint and interprets the numeric
|
|
71
|
+
* status codes to determine whether a task is still pending, succeeded, was rejected, or reverted.
|
|
68
72
|
*/
|
|
69
73
|
|
|
70
74
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* @
|
|
74
|
-
*/
|
|
75
|
-
declare
|
|
75
|
+
* Numeric status codes returned by the Gelato `relayer_getStatus` RPC method.
|
|
76
|
+
*
|
|
77
|
+
* @see https://docs.gelato.cloud/
|
|
78
|
+
*/
|
|
79
|
+
declare enum GelatoStatusCode {
|
|
80
|
+
/** The task has been received and is awaiting execution. */
|
|
81
|
+
Pending = 100,
|
|
82
|
+
/** The task has been submitted to the mempool and has a transaction hash. */
|
|
83
|
+
Submitted = 110,
|
|
84
|
+
/** The task was successfully executed and mined. */
|
|
85
|
+
Success = 200,
|
|
86
|
+
/** The task was rejected by the relayer before execution (e.g., validation failure). */
|
|
87
|
+
Rejected = 400,
|
|
88
|
+
/** The task was submitted but the transaction reverted on-chain. */
|
|
89
|
+
Reverted = 500
|
|
90
|
+
}
|
|
76
91
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @see https://docs.gelato.network/developer-services/relay/api/get-task-status
|
|
92
|
+
* Common fields shared by all Gelato task status responses.
|
|
79
93
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
94
|
+
type GelatoBaseStatus = {
|
|
95
|
+
/** The chain ID on which the task was submitted. */
|
|
96
|
+
chainId: number;
|
|
97
|
+
/** Unix timestamp (in seconds) when the task was created. */
|
|
98
|
+
createdAt: number;
|
|
99
|
+
/** The unique Gelato task identifier. */
|
|
100
|
+
id: string;
|
|
101
|
+
};
|
|
89
102
|
/**
|
|
90
|
-
*
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
* Discriminated union representing all possible Gelato task status responses.
|
|
104
|
+
* Each variant corresponds to a specific {@link GelatoStatusCode}.
|
|
105
|
+
*/
|
|
106
|
+
type GelatoTaskStatus = (GelatoBaseStatus & {
|
|
107
|
+
status: GelatoStatusCode.Pending;
|
|
108
|
+
}) | (GelatoBaseStatus & {
|
|
109
|
+
status: GelatoStatusCode.Submitted;
|
|
110
|
+
hash: Hex;
|
|
111
|
+
}) | (GelatoBaseStatus & {
|
|
112
|
+
status: GelatoStatusCode.Success;
|
|
113
|
+
receipt: {
|
|
114
|
+
transactionHash: Hex;
|
|
102
115
|
};
|
|
103
|
-
}
|
|
116
|
+
}) | (GelatoBaseStatus & {
|
|
117
|
+
status: GelatoStatusCode.Rejected;
|
|
118
|
+
message: string;
|
|
119
|
+
data?: unknown;
|
|
120
|
+
}) | (GelatoBaseStatus & {
|
|
121
|
+
status: GelatoStatusCode.Reverted;
|
|
122
|
+
message?: string;
|
|
123
|
+
data: string;
|
|
124
|
+
receipt: {
|
|
125
|
+
transactionHash: Hex;
|
|
126
|
+
};
|
|
127
|
+
});
|
|
104
128
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
129
|
+
* Creates a reusable fetcher function for `initializePollingTracker` that queries the
|
|
130
|
+
* Gelato RPC endpoint (`relayer_getStatus`) for a task's status using an authenticated client.
|
|
131
|
+
*
|
|
132
|
+
* The fetcher interprets the numeric status codes and calls the appropriate polling callbacks:
|
|
133
|
+
* - {@link GelatoStatusCode.Success} → `onSuccess`
|
|
134
|
+
* - {@link GelatoStatusCode.Rejected} / {@link GelatoStatusCode.Reverted} → `onFailure`
|
|
135
|
+
* - {@link GelatoStatusCode.Submitted} → `onIntervalTick` (to update the tx hash)
|
|
136
|
+
*
|
|
137
|
+
* @param {ReturnType<Transport>} client - A viem transport client configured for the Gelato API.
|
|
138
|
+
* @returns {PollingTrackerConfig<GelatoTaskStatus, Transaction>['fetcher']} The fetcher function.
|
|
107
139
|
*/
|
|
108
|
-
declare
|
|
140
|
+
declare function gelatoFetcher(client: ReturnType<Transport>): PollingTrackerConfig<GelatoTaskStatus, Transaction>['fetcher'];
|
|
109
141
|
/**
|
|
110
142
|
* A higher-level wrapper that integrates the Gelato polling logic with the Pulsar store.
|
|
111
|
-
* It
|
|
143
|
+
* It creates an authenticated Gelato RPC client and uses {@link gelatoFetcher} to
|
|
144
|
+
* build the fetcher, then delegates to `initializePollingTracker` with store-specific callbacks.
|
|
112
145
|
*
|
|
113
146
|
* @template T - The application-specific transaction type.
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
*
|
|
148
|
+
* @param params.tx - The transaction to track.
|
|
149
|
+
* @param params.gelatoApiKey - The Gelato API key for authenticating RPC requests.
|
|
150
|
+
* @param params.updateTxParams - Store action to update transaction fields.
|
|
151
|
+
* @param params.removeTxFromPool - Store action to remove a transaction from the pool.
|
|
152
|
+
* @param params.transactionsPool - The current pool of tracked transactions.
|
|
153
|
+
* @param params.onSuccess - Optional callback invoked when the transaction succeeds.
|
|
154
|
+
* @param params.onError - Optional callback invoked when the transaction fails.
|
|
155
|
+
*/
|
|
156
|
+
declare function gelatoTrackerForStore<T extends Transaction>({ tx, gelatoApiKey, updateTxParams, removeTxFromPool, transactionsPool, onSuccess, onError, }: Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'> & {
|
|
116
157
|
tx: T;
|
|
158
|
+
gelatoApiKey: string;
|
|
117
159
|
} & TrackerCallbacks<T>): void;
|
|
118
160
|
|
|
119
161
|
/**
|
|
@@ -206,6 +248,7 @@ type InitializeTrackerParams<T extends Transaction> = Pick<ITxTrackingStore<T>,
|
|
|
206
248
|
config: Config;
|
|
207
249
|
tx: T;
|
|
208
250
|
tracker: TransactionTracker;
|
|
251
|
+
gelatoApiKey?: string;
|
|
209
252
|
} & TrackerCallbacks<T>;
|
|
210
253
|
/**
|
|
211
254
|
* Initializes the appropriate tracker for a given transaction based on its `tracker` type.
|
|
@@ -216,21 +259,48 @@ type InitializeTrackerParams<T extends Transaction> = Pick<ITxTrackingStore<T>,
|
|
|
216
259
|
* @param {InitializeTrackerParams<T>} params - The parameters for initializing the tracker.
|
|
217
260
|
* @returns {Promise<void>} A promise that resolves once the tracking process has been successfully initiated.
|
|
218
261
|
*/
|
|
219
|
-
declare function checkAndInitializeTrackerInStore<T extends Transaction>({ tracker, tx, config, transactionsPool, onSuccess, onError, onReplaced, ...rest }: InitializeTrackerParams<T>): Promise<void>;
|
|
262
|
+
declare function checkAndInitializeTrackerInStore<T extends Transaction>({ tracker, tx, config, transactionsPool, onSuccess, onError, onReplaced, gelatoApiKey, ...rest }: InitializeTrackerParams<T>): Promise<void>;
|
|
220
263
|
|
|
221
264
|
/**
|
|
222
265
|
* @file This file contains a utility to check if the Gelato Relay service is available for a specific chain.
|
|
266
|
+
* It uses the authenticated Gelato RPC client to fetch relay capabilities and caches the result.
|
|
223
267
|
*/
|
|
268
|
+
/**
|
|
269
|
+
* Represents the per-chain capabilities returned by the Gelato `relayer_getCapabilities` RPC method.
|
|
270
|
+
*
|
|
271
|
+
* @property {string} feeCollector - The address of the fee collector contract on this chain.
|
|
272
|
+
* @property {GelatoToken[]} tokens - The list of ERC-20 tokens accepted for fee payment on this chain.
|
|
273
|
+
*/
|
|
274
|
+
type GelatoCapabilitiesByChain = {
|
|
275
|
+
feeCollector: string;
|
|
276
|
+
tokens: GelatoToken[];
|
|
277
|
+
};
|
|
278
|
+
/**
|
|
279
|
+
* Represents a token accepted for fee payment by the Gelato Relay on a given chain.
|
|
280
|
+
*
|
|
281
|
+
* @property {string} address - The ERC-20 token contract address.
|
|
282
|
+
* @property {number} decimals - The number of decimals for the token.
|
|
283
|
+
*/
|
|
284
|
+
type GelatoToken = {
|
|
285
|
+
address: string;
|
|
286
|
+
decimals: number;
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* A record of Gelato relay capabilities keyed by numeric chain ID.
|
|
290
|
+
*/
|
|
291
|
+
type GelatoCapabilities = Record<number, GelatoCapabilitiesByChain>;
|
|
224
292
|
/**
|
|
225
293
|
* Checks if the Gelato Relay service supports a given chain ID.
|
|
226
294
|
*
|
|
227
|
-
* This function fetches the
|
|
228
|
-
*
|
|
295
|
+
* This function fetches the relay capabilities via the authenticated Gelato RPC client
|
|
296
|
+
* (`relayer_getCapabilities`) and checks whether the specified chain is present in the response.
|
|
297
|
+
* Results are cached in memory per API key for the lifetime of the application to minimize network requests.
|
|
229
298
|
*
|
|
230
299
|
* @param {number} chainId - The chain identifier to check.
|
|
300
|
+
* @param {string} gelatoApiKey - The Gelato API key used for authentication.
|
|
231
301
|
* @returns {Promise<boolean>} A promise that resolves to `true` if Gelato supports the chain, `false` otherwise.
|
|
232
302
|
*/
|
|
233
|
-
declare function checkIsGelatoAvailable(chainId: number): Promise<boolean>;
|
|
303
|
+
declare function checkIsGelatoAvailable(chainId: number, gelatoApiKey: string): Promise<boolean>;
|
|
234
304
|
|
|
235
305
|
/**
|
|
236
306
|
* @file This file contains a utility function to determine the correct tracker for a transaction
|
|
@@ -249,16 +319,51 @@ declare function checkIsGelatoAvailable(chainId: number): Promise<boolean>;
|
|
|
249
319
|
*
|
|
250
320
|
* @param {ActionTxKey} actionTxKey - The key returned from the transaction submission function (e.g., a hash or a Gelato task object).
|
|
251
321
|
* @param {string} connectorType - The type of the connector that initiated the action (e.g., 'safe', 'injected').
|
|
252
|
-
*
|
|
322
|
+
* @param {TransactionTracker} tracker - The type of transaction tracker to use.
|
|
323
|
+
* @param {string} gelatoApiKey - Gelato API key for Gelato relayer integration.
|
|
253
324
|
* @returns {{ tracker: TransactionTracker; txKey: string }} An object containing the determined tracker type and the final string-based transaction key.
|
|
254
325
|
*
|
|
255
326
|
* @throws {Error} Throws an error if the `actionTxKey` is not a valid Hex string after failing the Gelato check.
|
|
256
327
|
*/
|
|
257
|
-
declare function checkTransactionsTracker(actionTxKey
|
|
328
|
+
declare function checkTransactionsTracker({ actionTxKey, connectorType, tracker, gelatoApiKey }: CheckTxTracker): {
|
|
258
329
|
tracker: TransactionTracker;
|
|
259
330
|
txKey: string;
|
|
260
331
|
};
|
|
261
332
|
|
|
333
|
+
/**
|
|
334
|
+
* @file This file contains a utility function for creating a cached viem HTTP transport
|
|
335
|
+
* client configured for the Gelato Relay API.
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Configuration options for creating a Gelato API client.
|
|
340
|
+
*
|
|
341
|
+
* @property {string} apiKey - The Gelato API key used for authentication.
|
|
342
|
+
* @property {number} [timeout] - Optional custom HTTP timeout in milliseconds. Defaults to 15000ms.
|
|
343
|
+
* @property {string} [baseUrl] - Optional custom base URL for the Gelato API. Defaults to `https://api.gelato.cloud/rpc`.
|
|
344
|
+
* @property {HttpTransportConfig} [httpTransportConfig] - Optional additional viem HTTP transport configuration overrides.
|
|
345
|
+
*/
|
|
346
|
+
type GelatoClientConfig = {
|
|
347
|
+
apiKey: string;
|
|
348
|
+
timeout?: number;
|
|
349
|
+
baseUrl?: string;
|
|
350
|
+
httpTransportConfig?: HttpTransportConfig;
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Creates or retrieves a cached viem HTTP transport client configured for the Gelato Relay API.
|
|
354
|
+
*
|
|
355
|
+
* The client is cached by a composite key of `apiKey` and `baseUrl` to avoid
|
|
356
|
+
* creating redundant transport instances for identical configurations.
|
|
357
|
+
*
|
|
358
|
+
* The default HTTP timeout is set to 15 seconds (instead of viem's default) because
|
|
359
|
+
* Gelato's synchronous relay methods may take up to 10 seconds on the server side,
|
|
360
|
+
* and the client should not time out before the server does.
|
|
361
|
+
*
|
|
362
|
+
* @param {GelatoClientConfig} parameters - The configuration for the Gelato client.
|
|
363
|
+
* @returns {ReturnType<Transport>} A viem transport instance configured for the Gelato API.
|
|
364
|
+
*/
|
|
365
|
+
declare const createGelatoClient: (parameters: GelatoClientConfig) => ReturnType<Transport>;
|
|
366
|
+
|
|
262
367
|
/**
|
|
263
368
|
* @file This file contains constants related to Safe (formerly Gnosis Safe) configuration,
|
|
264
369
|
* including SDK options, web app URLs, and transaction service API endpoints for various chains.
|
|
@@ -353,4 +458,4 @@ declare function speedUpTxAction<T extends Transaction>({ config, tx }: {
|
|
|
353
458
|
tx: T;
|
|
354
459
|
}): Promise<Hex>;
|
|
355
460
|
|
|
356
|
-
export { type EVMTrackerParams,
|
|
461
|
+
export { type EVMTrackerParams, type GelatoCapabilities, type GelatoCapabilitiesByChain, type GelatoClientConfig, GelatoStatusCode, type GelatoTaskStatus, type GelatoToken, SafeTransactionServiceUrls, type SafeTxStatusResponse, cancelTxAction, checkAndInitializeTrackerInStore, checkIsGelatoAvailable, checkTransactionsTracker, createGelatoClient, evmTracker, evmTrackerForStore, gelatoFetcher, gelatoTrackerForStore, gnosisSafeLinksHelper, pulsarEvmAdapter, safeFetcher, safeSdkOptions, safeTrackerForStore, selectEvmTxExplorerLink, speedUpTxAction };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Transaction, TxAdapter, ITxTrackingStore, TrackerCallbacks, PollingTrackerConfig,
|
|
1
|
+
import { Transaction, TxAdapter, ITxTrackingStore, TrackerCallbacks, PollingTrackerConfig, TransactionTracker, CheckTxTracker } from '@tuwaio/pulsar-core';
|
|
2
2
|
import { Config } from '@wagmi/core';
|
|
3
|
-
import { Chain, GetTransactionReturnType, TransactionReceipt, Client, ReplacementReturnType, WaitForTransactionReceiptParameters, Hex } from 'viem';
|
|
3
|
+
import { Chain, GetTransactionReturnType, TransactionReceipt, Client, ReplacementReturnType, WaitForTransactionReceiptParameters, Hex, Transport, HttpTransportConfig } from 'viem';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file This file contains the factory function for creating the EVM (Ethereum Virtual Machine) transaction adapter.
|
|
@@ -34,7 +34,7 @@ declare function pulsarEvmAdapter<T extends Transaction>(config: Config, appChai
|
|
|
34
34
|
* Defines the parameters for the low-level EVM transaction tracker.
|
|
35
35
|
*/
|
|
36
36
|
type EVMTrackerParams = {
|
|
37
|
-
tx: Pick<Transaction, 'chainId' | 'txKey'>;
|
|
37
|
+
tx: Pick<Transaction, 'chainId' | 'txKey' | 'requiredConfirmations'>;
|
|
38
38
|
config: Config;
|
|
39
39
|
onTxDetailsFetched: (txDetails: GetTransactionReturnType) => void;
|
|
40
40
|
onSuccess: (txDetails: GetTransactionReturnType, receipt: TransactionReceipt, client: Client) => Promise<void>;
|
|
@@ -43,6 +43,7 @@ type EVMTrackerParams = {
|
|
|
43
43
|
onInitialize?: () => void;
|
|
44
44
|
retryCount?: number;
|
|
45
45
|
retryTimeout?: number;
|
|
46
|
+
onConfirmationsUpdate?: (confirmations: number) => void;
|
|
46
47
|
waitForTransactionReceiptParams?: WaitForTransactionReceiptParameters;
|
|
47
48
|
};
|
|
48
49
|
/**
|
|
@@ -64,56 +65,97 @@ declare function evmTrackerForStore<T extends Transaction>(params: Pick<EVMTrack
|
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
67
|
* @file This file implements the transaction tracking logic for meta-transactions relayed via the Gelato Network.
|
|
67
|
-
* It uses a polling mechanism to check the status of a Gelato
|
|
68
|
+
* It uses a polling mechanism to check the status of a Gelato task via the authenticated Gelato RPC client.
|
|
69
|
+
*
|
|
70
|
+
* The fetcher calls `relayer_getStatus` on the Gelato RPC endpoint and interprets the numeric
|
|
71
|
+
* status codes to determine whether a task is still pending, succeeded, was rejected, or reverted.
|
|
68
72
|
*/
|
|
69
73
|
|
|
70
74
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* @
|
|
74
|
-
*/
|
|
75
|
-
declare
|
|
75
|
+
* Numeric status codes returned by the Gelato `relayer_getStatus` RPC method.
|
|
76
|
+
*
|
|
77
|
+
* @see https://docs.gelato.cloud/
|
|
78
|
+
*/
|
|
79
|
+
declare enum GelatoStatusCode {
|
|
80
|
+
/** The task has been received and is awaiting execution. */
|
|
81
|
+
Pending = 100,
|
|
82
|
+
/** The task has been submitted to the mempool and has a transaction hash. */
|
|
83
|
+
Submitted = 110,
|
|
84
|
+
/** The task was successfully executed and mined. */
|
|
85
|
+
Success = 200,
|
|
86
|
+
/** The task was rejected by the relayer before execution (e.g., validation failure). */
|
|
87
|
+
Rejected = 400,
|
|
88
|
+
/** The task was submitted but the transaction reverted on-chain. */
|
|
89
|
+
Reverted = 500
|
|
90
|
+
}
|
|
76
91
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @see https://docs.gelato.network/developer-services/relay/api/get-task-status
|
|
92
|
+
* Common fields shared by all Gelato task status responses.
|
|
79
93
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
94
|
+
type GelatoBaseStatus = {
|
|
95
|
+
/** The chain ID on which the task was submitted. */
|
|
96
|
+
chainId: number;
|
|
97
|
+
/** Unix timestamp (in seconds) when the task was created. */
|
|
98
|
+
createdAt: number;
|
|
99
|
+
/** The unique Gelato task identifier. */
|
|
100
|
+
id: string;
|
|
101
|
+
};
|
|
89
102
|
/**
|
|
90
|
-
*
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
* Discriminated union representing all possible Gelato task status responses.
|
|
104
|
+
* Each variant corresponds to a specific {@link GelatoStatusCode}.
|
|
105
|
+
*/
|
|
106
|
+
type GelatoTaskStatus = (GelatoBaseStatus & {
|
|
107
|
+
status: GelatoStatusCode.Pending;
|
|
108
|
+
}) | (GelatoBaseStatus & {
|
|
109
|
+
status: GelatoStatusCode.Submitted;
|
|
110
|
+
hash: Hex;
|
|
111
|
+
}) | (GelatoBaseStatus & {
|
|
112
|
+
status: GelatoStatusCode.Success;
|
|
113
|
+
receipt: {
|
|
114
|
+
transactionHash: Hex;
|
|
102
115
|
};
|
|
103
|
-
}
|
|
116
|
+
}) | (GelatoBaseStatus & {
|
|
117
|
+
status: GelatoStatusCode.Rejected;
|
|
118
|
+
message: string;
|
|
119
|
+
data?: unknown;
|
|
120
|
+
}) | (GelatoBaseStatus & {
|
|
121
|
+
status: GelatoStatusCode.Reverted;
|
|
122
|
+
message?: string;
|
|
123
|
+
data: string;
|
|
124
|
+
receipt: {
|
|
125
|
+
transactionHash: Hex;
|
|
126
|
+
};
|
|
127
|
+
});
|
|
104
128
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
129
|
+
* Creates a reusable fetcher function for `initializePollingTracker` that queries the
|
|
130
|
+
* Gelato RPC endpoint (`relayer_getStatus`) for a task's status using an authenticated client.
|
|
131
|
+
*
|
|
132
|
+
* The fetcher interprets the numeric status codes and calls the appropriate polling callbacks:
|
|
133
|
+
* - {@link GelatoStatusCode.Success} → `onSuccess`
|
|
134
|
+
* - {@link GelatoStatusCode.Rejected} / {@link GelatoStatusCode.Reverted} → `onFailure`
|
|
135
|
+
* - {@link GelatoStatusCode.Submitted} → `onIntervalTick` (to update the tx hash)
|
|
136
|
+
*
|
|
137
|
+
* @param {ReturnType<Transport>} client - A viem transport client configured for the Gelato API.
|
|
138
|
+
* @returns {PollingTrackerConfig<GelatoTaskStatus, Transaction>['fetcher']} The fetcher function.
|
|
107
139
|
*/
|
|
108
|
-
declare
|
|
140
|
+
declare function gelatoFetcher(client: ReturnType<Transport>): PollingTrackerConfig<GelatoTaskStatus, Transaction>['fetcher'];
|
|
109
141
|
/**
|
|
110
142
|
* A higher-level wrapper that integrates the Gelato polling logic with the Pulsar store.
|
|
111
|
-
* It
|
|
143
|
+
* It creates an authenticated Gelato RPC client and uses {@link gelatoFetcher} to
|
|
144
|
+
* build the fetcher, then delegates to `initializePollingTracker` with store-specific callbacks.
|
|
112
145
|
*
|
|
113
146
|
* @template T - The application-specific transaction type.
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
*
|
|
148
|
+
* @param params.tx - The transaction to track.
|
|
149
|
+
* @param params.gelatoApiKey - The Gelato API key for authenticating RPC requests.
|
|
150
|
+
* @param params.updateTxParams - Store action to update transaction fields.
|
|
151
|
+
* @param params.removeTxFromPool - Store action to remove a transaction from the pool.
|
|
152
|
+
* @param params.transactionsPool - The current pool of tracked transactions.
|
|
153
|
+
* @param params.onSuccess - Optional callback invoked when the transaction succeeds.
|
|
154
|
+
* @param params.onError - Optional callback invoked when the transaction fails.
|
|
155
|
+
*/
|
|
156
|
+
declare function gelatoTrackerForStore<T extends Transaction>({ tx, gelatoApiKey, updateTxParams, removeTxFromPool, transactionsPool, onSuccess, onError, }: Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'> & {
|
|
116
157
|
tx: T;
|
|
158
|
+
gelatoApiKey: string;
|
|
117
159
|
} & TrackerCallbacks<T>): void;
|
|
118
160
|
|
|
119
161
|
/**
|
|
@@ -206,6 +248,7 @@ type InitializeTrackerParams<T extends Transaction> = Pick<ITxTrackingStore<T>,
|
|
|
206
248
|
config: Config;
|
|
207
249
|
tx: T;
|
|
208
250
|
tracker: TransactionTracker;
|
|
251
|
+
gelatoApiKey?: string;
|
|
209
252
|
} & TrackerCallbacks<T>;
|
|
210
253
|
/**
|
|
211
254
|
* Initializes the appropriate tracker for a given transaction based on its `tracker` type.
|
|
@@ -216,21 +259,48 @@ type InitializeTrackerParams<T extends Transaction> = Pick<ITxTrackingStore<T>,
|
|
|
216
259
|
* @param {InitializeTrackerParams<T>} params - The parameters for initializing the tracker.
|
|
217
260
|
* @returns {Promise<void>} A promise that resolves once the tracking process has been successfully initiated.
|
|
218
261
|
*/
|
|
219
|
-
declare function checkAndInitializeTrackerInStore<T extends Transaction>({ tracker, tx, config, transactionsPool, onSuccess, onError, onReplaced, ...rest }: InitializeTrackerParams<T>): Promise<void>;
|
|
262
|
+
declare function checkAndInitializeTrackerInStore<T extends Transaction>({ tracker, tx, config, transactionsPool, onSuccess, onError, onReplaced, gelatoApiKey, ...rest }: InitializeTrackerParams<T>): Promise<void>;
|
|
220
263
|
|
|
221
264
|
/**
|
|
222
265
|
* @file This file contains a utility to check if the Gelato Relay service is available for a specific chain.
|
|
266
|
+
* It uses the authenticated Gelato RPC client to fetch relay capabilities and caches the result.
|
|
223
267
|
*/
|
|
268
|
+
/**
|
|
269
|
+
* Represents the per-chain capabilities returned by the Gelato `relayer_getCapabilities` RPC method.
|
|
270
|
+
*
|
|
271
|
+
* @property {string} feeCollector - The address of the fee collector contract on this chain.
|
|
272
|
+
* @property {GelatoToken[]} tokens - The list of ERC-20 tokens accepted for fee payment on this chain.
|
|
273
|
+
*/
|
|
274
|
+
type GelatoCapabilitiesByChain = {
|
|
275
|
+
feeCollector: string;
|
|
276
|
+
tokens: GelatoToken[];
|
|
277
|
+
};
|
|
278
|
+
/**
|
|
279
|
+
* Represents a token accepted for fee payment by the Gelato Relay on a given chain.
|
|
280
|
+
*
|
|
281
|
+
* @property {string} address - The ERC-20 token contract address.
|
|
282
|
+
* @property {number} decimals - The number of decimals for the token.
|
|
283
|
+
*/
|
|
284
|
+
type GelatoToken = {
|
|
285
|
+
address: string;
|
|
286
|
+
decimals: number;
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* A record of Gelato relay capabilities keyed by numeric chain ID.
|
|
290
|
+
*/
|
|
291
|
+
type GelatoCapabilities = Record<number, GelatoCapabilitiesByChain>;
|
|
224
292
|
/**
|
|
225
293
|
* Checks if the Gelato Relay service supports a given chain ID.
|
|
226
294
|
*
|
|
227
|
-
* This function fetches the
|
|
228
|
-
*
|
|
295
|
+
* This function fetches the relay capabilities via the authenticated Gelato RPC client
|
|
296
|
+
* (`relayer_getCapabilities`) and checks whether the specified chain is present in the response.
|
|
297
|
+
* Results are cached in memory per API key for the lifetime of the application to minimize network requests.
|
|
229
298
|
*
|
|
230
299
|
* @param {number} chainId - The chain identifier to check.
|
|
300
|
+
* @param {string} gelatoApiKey - The Gelato API key used for authentication.
|
|
231
301
|
* @returns {Promise<boolean>} A promise that resolves to `true` if Gelato supports the chain, `false` otherwise.
|
|
232
302
|
*/
|
|
233
|
-
declare function checkIsGelatoAvailable(chainId: number): Promise<boolean>;
|
|
303
|
+
declare function checkIsGelatoAvailable(chainId: number, gelatoApiKey: string): Promise<boolean>;
|
|
234
304
|
|
|
235
305
|
/**
|
|
236
306
|
* @file This file contains a utility function to determine the correct tracker for a transaction
|
|
@@ -249,16 +319,51 @@ declare function checkIsGelatoAvailable(chainId: number): Promise<boolean>;
|
|
|
249
319
|
*
|
|
250
320
|
* @param {ActionTxKey} actionTxKey - The key returned from the transaction submission function (e.g., a hash or a Gelato task object).
|
|
251
321
|
* @param {string} connectorType - The type of the connector that initiated the action (e.g., 'safe', 'injected').
|
|
252
|
-
*
|
|
322
|
+
* @param {TransactionTracker} tracker - The type of transaction tracker to use.
|
|
323
|
+
* @param {string} gelatoApiKey - Gelato API key for Gelato relayer integration.
|
|
253
324
|
* @returns {{ tracker: TransactionTracker; txKey: string }} An object containing the determined tracker type and the final string-based transaction key.
|
|
254
325
|
*
|
|
255
326
|
* @throws {Error} Throws an error if the `actionTxKey` is not a valid Hex string after failing the Gelato check.
|
|
256
327
|
*/
|
|
257
|
-
declare function checkTransactionsTracker(actionTxKey
|
|
328
|
+
declare function checkTransactionsTracker({ actionTxKey, connectorType, tracker, gelatoApiKey }: CheckTxTracker): {
|
|
258
329
|
tracker: TransactionTracker;
|
|
259
330
|
txKey: string;
|
|
260
331
|
};
|
|
261
332
|
|
|
333
|
+
/**
|
|
334
|
+
* @file This file contains a utility function for creating a cached viem HTTP transport
|
|
335
|
+
* client configured for the Gelato Relay API.
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Configuration options for creating a Gelato API client.
|
|
340
|
+
*
|
|
341
|
+
* @property {string} apiKey - The Gelato API key used for authentication.
|
|
342
|
+
* @property {number} [timeout] - Optional custom HTTP timeout in milliseconds. Defaults to 15000ms.
|
|
343
|
+
* @property {string} [baseUrl] - Optional custom base URL for the Gelato API. Defaults to `https://api.gelato.cloud/rpc`.
|
|
344
|
+
* @property {HttpTransportConfig} [httpTransportConfig] - Optional additional viem HTTP transport configuration overrides.
|
|
345
|
+
*/
|
|
346
|
+
type GelatoClientConfig = {
|
|
347
|
+
apiKey: string;
|
|
348
|
+
timeout?: number;
|
|
349
|
+
baseUrl?: string;
|
|
350
|
+
httpTransportConfig?: HttpTransportConfig;
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Creates or retrieves a cached viem HTTP transport client configured for the Gelato Relay API.
|
|
354
|
+
*
|
|
355
|
+
* The client is cached by a composite key of `apiKey` and `baseUrl` to avoid
|
|
356
|
+
* creating redundant transport instances for identical configurations.
|
|
357
|
+
*
|
|
358
|
+
* The default HTTP timeout is set to 15 seconds (instead of viem's default) because
|
|
359
|
+
* Gelato's synchronous relay methods may take up to 10 seconds on the server side,
|
|
360
|
+
* and the client should not time out before the server does.
|
|
361
|
+
*
|
|
362
|
+
* @param {GelatoClientConfig} parameters - The configuration for the Gelato client.
|
|
363
|
+
* @returns {ReturnType<Transport>} A viem transport instance configured for the Gelato API.
|
|
364
|
+
*/
|
|
365
|
+
declare const createGelatoClient: (parameters: GelatoClientConfig) => ReturnType<Transport>;
|
|
366
|
+
|
|
262
367
|
/**
|
|
263
368
|
* @file This file contains constants related to Safe (formerly Gnosis Safe) configuration,
|
|
264
369
|
* including SDK options, web app URLs, and transaction service API endpoints for various chains.
|
|
@@ -353,4 +458,4 @@ declare function speedUpTxAction<T extends Transaction>({ config, tx }: {
|
|
|
353
458
|
tx: T;
|
|
354
459
|
}): Promise<Hex>;
|
|
355
460
|
|
|
356
|
-
export { type EVMTrackerParams,
|
|
461
|
+
export { type EVMTrackerParams, type GelatoCapabilities, type GelatoCapabilitiesByChain, type GelatoClientConfig, GelatoStatusCode, type GelatoTaskStatus, type GelatoToken, SafeTransactionServiceUrls, type SafeTxStatusResponse, cancelTxAction, checkAndInitializeTrackerInStore, checkIsGelatoAvailable, checkTransactionsTracker, createGelatoClient, evmTracker, evmTrackerForStore, gelatoFetcher, gelatoTrackerForStore, gnosisSafeLinksHelper, pulsarEvmAdapter, safeFetcher, safeSdkOptions, safeTrackerForStore, selectEvmTxExplorerLink, speedUpTxAction };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitEvm=require('@tuwaio/orbit-evm'),pulsarCore=require('@tuwaio/pulsar-core'),core=require('@wagmi/core'),viem=require('viem'),actions=require('viem/actions'),T=require('dayjs'),chains=require('viem/chains');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var T__default=/*#__PURE__*/_interopDefault(T);var C=1.15;async function v({config:t,tx:e}){if(e.adapter!==orbitCore.OrbitAdapter.EVM)throw new Error(`Cancellation is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,maxFeePerGas:o,maxPriorityFeePerGas:s,chainId:c}=e;if(a===void 0||!o||!s)throw new Error("Transaction is missing required fields for cancellation (nonce, maxFeePerGas, maxPriorityFeePerGas).");try{if(!t)throw new Error("Wagmi config is not provided.");let n=core.getAccount(t);if(!n.address)throw new Error("No connected account found.");let r=BigInt(Math.ceil(Number(s)*C)),i=BigInt(Math.ceil(Number(o)*C));return await core.sendTransaction(t,{to:n.address,value:0n,chainId:c,nonce:a,maxFeePerGas:i,maxPriorityFeePerGas:r})}catch(n){let r=n instanceof Error?n.message:String(n);throw new Error(`Failed to cancel transaction: ${r}`)}}var ue=10,me=3e3;async function Te(t){let{tx:e,config:a,onInitialize:o,onTxDetailsFetched:s,onSuccess:c,onFailure:n,onReplaced:r,retryCount:i=ue,retryTimeout:l=me,waitForTransactionReceiptParams:u}=t;if(o?.(),e.txKey===viem.zeroHash)return n(new Error("Transaction hash cannot be the zero hash."));let p=core.getClient(a,{chainId:e.chainId});if(!p)return n(new Error(`Could not create a viem client for chainId: ${e.chainId}`));let d=null;for(let f=0;f<i;f++)try{d=await actions.getTransaction(p,{hash:e.txKey}),s(d);break}catch(m){if(f===i-1)return console.error(`EVM tracker failed to fetch tx ${e.txKey} after ${i} retries:`,m),n(m);await new Promise(b=>setTimeout(b,l));}if(!d)return n(new Error("Transaction details could not be fetched."));try{let f=!1,m=await actions.waitForTransactionReceipt(p,{hash:d.hash,onReplaced:b=>{f=!0,r(b);},...u});if(f)return;await c(d,m,p);}catch(f){console.error(`Error waiting for receipt for tx ${e.txKey}:`,f),n(f);}}async function y(t){let{tx:e,config:a,updateTxParams:o,transactionsPool:s,onSuccess:c,onError:n,onReplaced:r}=t;return Te({tx:e,config:a,onInitialize:()=>{o(e.txKey,{hash:e.txKey});},onTxDetailsFetched:i=>{o(e.txKey,{to:i.to??void 0,input:i.input,value:i.value?.toString(),nonce:i.nonce,maxFeePerGas:i.maxFeePerGas?.toString(),maxPriorityFeePerGas:i.maxPriorityFeePerGas?.toString()});},onSuccess:async(i,l,u)=>{let p=await actions.getBlock(u,{blockNumber:l.blockNumber}),d=Number(p.timestamp),f=l.status==="success";o(e.txKey,{status:f?pulsarCore.TransactionStatus.Success:pulsarCore.TransactionStatus.Failed,isError:!f,pending:false,finishedTimestamp:d});let m=s[e.txKey];f&&c&&m&&c(m),!f&&n&&m&&n(new Error("Transaction reverted"),m);},onReplaced:i=>{o(e.txKey,{status:pulsarCore.TransactionStatus.Replaced,replacedTxHash:i.transaction.hash,pending:false});let l=s[e.txKey];r&&l&&r(l,e);},onFailure:i=>{o(e.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,error:orbitCore.normalizeError(i)});let l=s[e.txKey];n&&l&&n(i,l);}})}function F(t){return typeof t=="object"&&t!==null&&"taskId"in t}var ge=(r=>(r.CheckPending="CheckPending",r.ExecPending="ExecPending",r.WaitingForConfirmation="WaitingForConfirmation",r.ExecSuccess="ExecSuccess",r.ExecReverted="ExecReverted",r.Cancelled="Cancelled",r.NotFound="NotFound",r))(ge||{}),ke="https://api.gelato.digital/tasks/status/",I=new Set(["ExecReverted","Cancelled","NotFound"]);function be(t){return t!=="ExecSuccess"&&!I.has(t)}var ye=async({tx:t,stopPolling:e,onSuccess:a,onFailure:o,onIntervalTick:s})=>{let c=await fetch(`${ke}${t.txKey}`);if(!c.ok){if(c.status===404){o(),e();return}throw new Error(`Gelato API responded with status: ${c.status}`)}let n=await c.json(),{taskState:r,creationDate:i}=n.task;if(s?.(n),i&&T__default.default().diff(T__default.default(i),"hour")>=1&&be(r)){e();return}r==="ExecSuccess"?(a(n),e({withoutRemoving:true})):I.has(r)&&(o(n),e({withoutRemoving:true}));};function P({tx:t,updateTxParams:e,removeTxFromPool:a,transactionsPool:o,onSuccess:s,onError:c}){return pulsarCore.initializePollingTracker({tx:t,fetcher:ye,removeTxFromPool:a,onSuccess:n=>{e(t.txKey,{status:pulsarCore.TransactionStatus.Success,pending:false,isError:false,hash:n.task.transactionHash,finishedTimestamp:n.task.executionDate?T__default.default(n.task.executionDate).unix():void 0});let r=o[t.txKey];s&&r&&s(r);},onIntervalTick:n=>{e(t.txKey,{hash:n.task.transactionHash});},onFailure:n=>{let r=n?.task.lastCheckMessage?new Error(n.task.lastCheckMessage):new Error("Transaction failed or was not found.");e(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,hash:n?.task.transactionHash,error:orbitCore.normalizeError(r),finishedTimestamp:n?.task.executionDate?T__default.default(n.task.executionDate).unix():void 0});let i=o[t.txKey];c&&i&&c(r,i);}})}var Tt={allowedDomains:[/gnosis-safe.io$/,/app.safe.global$/,/metissafe.tech$/],debug:false},B={[chains.mainnet.id]:"https://app.safe.global/eth:",[chains.goerli.id]:"https://app.safe.global/gor:",[chains.sepolia.id]:"https://app.safe.global/sep:",[chains.polygon.id]:"https://app.safe.global/matic:",[chains.arbitrum.id]:"https://app.safe.global/arb1:",[chains.aurora.id]:"https://app.safe.global/aurora:",[chains.avalanche.id]:"https://app.safe.global/avax:",[chains.base.id]:"https://app.safe.global/base:",[chains.boba.id]:"https://app.safe.global/boba:",[chains.bsc.id]:"https://app.safe.global/bnb:",[chains.celo.id]:"https://app.safe.global/celo:",[chains.gnosis.id]:"https://app.safe.global/gno:",[chains.optimism.id]:"https://app.safe.global/oeth:",[chains.polygonZkEvm.id]:"https://app.safe.global/zkevm:",[chains.zksync.id]:"https://app.safe.global/zksync:"},W={[chains.mainnet.id]:"https://safe-transaction-mainnet.safe.global/api/v1",[chains.goerli.id]:"https://safe-transaction-goerli.safe.global/api/v1",[chains.sepolia.id]:"https://safe-transaction-sepolia.safe.global/api/v1",[chains.polygon.id]:"https://safe-transaction-polygon.safe.global/api/v1",[chains.arbitrum.id]:"https://safe-transaction-arbitrum.safe.global/api/v1",[chains.aurora.id]:"https://safe-transaction-aurora.safe.global/api/v1",[chains.avalanche.id]:"https://safe-transaction-avalanche.safe.global/api/v1",[chains.base.id]:"https://safe-transaction-base.safe.global/api/v1",[chains.boba.id]:"https://safe-transaction-boba.safe.global/api/v1",[chains.bsc.id]:"https://safe-transaction-bsc.safe.global/api/v1",[chains.celo.id]:"https://safe-transaction-celo.safe.global/api/v1",[chains.gnosis.id]:"https://safe-transaction-gnosis-chain.safe.global/api/v1",[chains.optimism.id]:"https://safe-transaction-optimism.safe.global/api/v1",[chains.polygonZkEvm.id]:"https://safe-transaction-zkevm.safe.global/api/v1",[chains.zksync.id]:"https://safe-transaction-zksync.safe.global/api/v1"};var Ce=async({tx:t,stopPolling:e,onSuccess:a,onFailure:o,onReplaced:s,onIntervalTick:c})=>{let n=W[t.chainId];if(!n)throw new Error(`Safe Transaction Service URL not found for chainId: ${t.chainId}`);let r=await fetch(`${n}/multisig-transactions/${t.txKey}/`);if(!r.ok)throw r.status===404&&(o(),e()),new Error(`Safe API responded with status: ${r.status}`);let i=await r.json();if(c?.(i),i.isExecuted){i.isSuccessful?a(i):o(i),e({withoutRemoving:true});return}let l=await fetch(`${n}/safes/${t.from}/multisig-transactions/?nonce=${i.nonce}`);if(!l.ok)throw new Error(`Safe API (nonce check) responded with status: ${l.status}`);let p=(await l.json()).results.find(d=>d.isExecuted);if(p){s?.(p),e({withoutRemoving:true});return}T__default.default().diff(T__default.default(i.submissionDate),"day")>=1&&e();};function Y({tx:t,updateTxParams:e,removeTxFromPool:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n}){return pulsarCore.initializePollingTracker({tx:t,fetcher:Ce,removeTxFromPool:a,onSuccess:r=>{e(t.txKey,{status:pulsarCore.TransactionStatus.Success,pending:false,isError:false,hash:r.transactionHash??void 0,finishedTimestamp:r.executionDate?T__default.default(r.executionDate).unix():void 0});let i=o[t.txKey];s&&i&&s(i);},onIntervalTick:r=>{e(t.txKey,{hash:r.transactionHash??void 0});},onFailure:r=>{let i=r?new Error("Safe transaction failed or was rejected."):new Error("Transaction not found.");e(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,hash:r?.transactionHash??void 0,error:orbitCore.normalizeError(i),finishedTimestamp:r?.executionDate?T__default.default(r.executionDate).unix():void 0});let l=o[t.txKey];c&&l&&c(i,l);},onReplaced:r=>{e(t.txKey,{status:pulsarCore.TransactionStatus.Replaced,pending:false,hash:t.adapter===orbitCore.OrbitAdapter.EVM?t.hash:viem.zeroHash,replacedTxHash:r.safeTxHash??viem.zeroHash,finishedTimestamp:r.executionDate?T__default.default(r.executionDate).unix():void 0});let i=o[t.txKey];n&&i&&n(i,t);}})}async function J({tracker:t,tx:e,config:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r}){switch(t){case pulsarCore.TransactionTracker.Ethereum:return y({tx:e,config:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r});case pulsarCore.TransactionTracker.Gelato:return P({tx:e,transactionsPool:o,onSuccess:s,onError:c,...r});case pulsarCore.TransactionTracker.Safe:return Y({tx:e,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r});default:return console.warn(`Unknown tracker type: '${t}'. Falling back to default EVM tracker.`),y({tx:e,config:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r})}}function Z(t,e){if(F(t))return {tracker:pulsarCore.TransactionTracker.Gelato,txKey:t.taskId};if(!viem.isHex(t))throw new Error(`Invalid transaction key format. Expected a Hex string or a GelatoTxKey object, but received: ${JSON.stringify(t)}`);let a=e.split(":");return (a.length>1?a[a.length-1]==="safe"||a[a.length-1]==="safewallet":e?.toLowerCase()==="safe")?{tracker:pulsarCore.TransactionTracker.Safe,txKey:t}:{tracker:pulsarCore.TransactionTracker.Ethereum,txKey:t}}var X=({chains:t,tx:e})=>{if(e.tracker===pulsarCore.TransactionTracker.Safe){let c=B[e.chainId];return c?`${c}${e.from}/transactions/tx?id=multisig_${e.from}_${e.txKey}`:""}let o=t.find(c=>c.id===e.chainId)?.blockExplorers?.default.url;if(!o)return "";let s=(e.adapter===orbitCore.OrbitAdapter.EVM?e.replacedTxHash:e.txKey)||(e.adapter===orbitCore.OrbitAdapter.EVM?e.hash:e.txKey);return s?`${o}/tx/${s}`:""};var ee=1.15;async function te({config:t,tx:e}){if(e.adapter!==orbitCore.OrbitAdapter.EVM)throw new Error(`Speed up is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,from:o,to:s,value:c,input:n,maxFeePerGas:r,maxPriorityFeePerGas:i,chainId:l}=e;if(a===void 0||!o||!s||!c||!r||!i)throw new Error("Transaction is missing required fields for speed-up.");try{if(!t)throw new Error("Wagmi config is not provided.");if(!core.getAccount(t).address)throw new Error("No connected account found.");let p=BigInt(Math.ceil(Number(i)*ee)),d=BigInt(Math.ceil(Number(r)*ee));return await core.sendTransaction(t,{to:s,value:BigInt(c),data:n||"0x",chainId:l,nonce:a,maxFeePerGas:d,maxPriorityFeePerGas:p})}catch(u){let p=u instanceof Error?u.message:String(u);throw new Error(`Failed to speed up transaction: ${p}`)}}function fa(t,e){if(!t)throw new Error("EVM adapter requires a wagmi config object.");return {key:orbitCore.OrbitAdapter.EVM,getConnectorInfo:()=>{let a=core.getConnection(t),o=orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector();return {walletAddress:a.address??o?.address??viem.zeroAddress,connectorType:orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.EVM,a.connector?.name?.toLowerCase()??"unknown")}},checkChainForTx:a=>orbitEvm.checkAndSwitchChain(a,t),checkTransactionsTracker:(a,o)=>Z(a,o),checkAndInitializeTrackerInStore:({tx:a,...o})=>J({tracker:a.tracker,tx:a,config:t,...o}),getExplorerUrl:a=>{let{chain:o}=core.getConnection(t),s=o?.blockExplorers?.default.url;return a?`${s}/${a}`:s},getExplorerTxUrl:a=>X({chains:e,tx:a}),cancelTxAction:a=>v({config:t,tx:a}),speedUpTxAction:a=>te({config:t,tx:a}),retryTxAction:async({onClose:a,txKey:o,executeTxAction:s,tx:c})=>{if(a(o),!s){console.error("Retry failed: executeTxAction function is not provided.");return}await s({actionFunction:()=>c.actionFunction({config:t,...c.payload}),params:c,defaultTracker:pulsarCore.TransactionTracker.Ethereum});}}}var g=null,k=null,Me=300*1e3,Ne="https://relay.gelato.digital/relays/v2/supported-chains";async function da(t){let e=Date.now();if(g&&k&&e-k<Me)return g.includes(t);try{let a=await fetch(Ne);if(!a.ok)throw new Error(`Gelato API responded with status: ${a.status}`);let s=(await a.json()).chains.map(Number);return g=s,k=e,s.includes(t)}catch(a){return console.error("Failed to fetch Gelato supported chains:",a),g=null,k=null,false}}
|
|
2
|
-
exports.
|
|
1
|
+
'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitEvm=require('@tuwaio/orbit-evm'),pulsarCore=require('@tuwaio/pulsar-core'),core=require('@wagmi/core'),viem=require('viem'),actions=require('viem/actions'),b=require('dayjs'),chains=require('viem/chains');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var b__default=/*#__PURE__*/_interopDefault(b);var F=1.15;async function A({config:t,tx:e}){if(e.adapter!==orbitCore.OrbitAdapter.EVM)throw new Error(`Cancellation is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,maxFeePerGas:n,maxPriorityFeePerGas:i,chainId:o}=e;if(a===void 0||!n||!i)throw new Error("Transaction is missing required fields for cancellation (nonce, maxFeePerGas, maxPriorityFeePerGas).");try{if(!t)throw new Error("Wagmi config is not provided.");let s=core.getAccount(t);if(!s.address)throw new Error("No connected account found.");let c=BigInt(Math.ceil(Number(i)*F)),r=BigInt(Math.ceil(Number(n)*F));return await core.sendTransaction(t,{to:s.address,value:0n,chainId:o,nonce:a,maxFeePerGas:r,maxPriorityFeePerGas:c})}catch(s){let c=s instanceof Error?s.message:String(s);throw new Error(`Failed to cancel transaction: ${c}`,{cause:s})}}var be=10,ke=3e3,v=3,ye=1e4,Ce=5e3;async function Se(t){let{tx:e,config:a,onInitialize:n,onTxDetailsFetched:i,onSuccess:o,onFailure:s,onReplaced:c,retryCount:r=be,retryTimeout:l=ke,onConfirmationsUpdate:p,waitForTransactionReceiptParams:f}=t,{requiredConfirmations:d}=e;if(n?.(),e.txKey===viem.zeroHash)return s(new Error("Transaction hash cannot be the zero hash."));let u=core.getClient(a,{chainId:e.chainId});if(!u)return s(new Error(`Could not create a viem client for chainId: ${e.chainId}`));let m=null;for(let T=0;T<r;T++)try{m=await actions.getTransaction(u,{hash:e.txKey}),i(m);break}catch(h){if(T===r-1)return console.error(`[evmTracker] Fatal error fetching transaction ${e.txKey} on chain ${e.chainId}:`,h),s(h);console.warn(`[evmTracker] Error fetching transaction ${e.txKey} on chain ${e.chainId} (attempt ${T+1}/${r}):`,h),await new Promise(g=>setTimeout(g,l));}if(!m)return s(new Error("Transaction details could not be fetched."));let E=false;for(let T=0;T<=v;T++)try{let h=await actions.waitForTransactionReceipt(u,{hash:m.hash,onReplaced:g=>{E=!0,c(g);},...f});if(!E){let g=d??1;if(g>1)for(;;){try{let x=await actions.getTransactionConfirmations(u,{transactionReceipt:h}),I=Number(x);if(p?.(I),I>=g)break}catch(x){console.warn(`[evmTracker] Error fetching confirmations for ${e.txKey} on chain ${e.chainId}:`,x);}await new Promise(x=>setTimeout(x,Ce));}await o(m,h,u);}return}catch(h){if(h instanceof Error&&h.name==="TransactionReceiptNotFoundError"&&!E&&T<v){console.warn(`[evmTracker] Receipt not found for ${e.txKey}, retry ${T+1}/${v}...`),await new Promise(x=>setTimeout(x,ye*(T+1)));continue}s(h);return}}async function y(t){let{tx:e,config:a,updateTxParams:n,transactionsPool:i,onSuccess:o,onError:s,onReplaced:c}=t;return Se({tx:e,config:a,onInitialize:()=>{n(e.txKey,{hash:e.txKey});},onTxDetailsFetched:r=>{n(e.txKey,{to:r.to??void 0,input:r.input,value:r.value?.toString(),nonce:r.nonce,maxFeePerGas:r.maxFeePerGas?.toString(),maxPriorityFeePerGas:r.maxPriorityFeePerGas?.toString()});},onConfirmationsUpdate:r=>{n(e.txKey,{confirmations:r});},onSuccess:async(r,l,p)=>{let f=await actions.getBlock(p,{blockNumber:l.blockNumber}),d=Number(f.timestamp),u=l.status==="success";n(e.txKey,{status:u?pulsarCore.TransactionStatus.Success:pulsarCore.TransactionStatus.Failed,isError:!u,pending:false,finishedTimestamp:d});let m=i[e.txKey];u&&o&&m&&o(m),!u&&s&&m&&s(new Error("Transaction reverted"),m);},onReplaced:r=>{n(e.txKey,{status:pulsarCore.TransactionStatus.Replaced,replacedTxHash:r.transaction.hash,pending:false});let l=i[e.txKey];c&&l&&c(l,e);},onFailure:r=>{n(e.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,error:orbitCore.normalizeError(r)});let l=i[e.txKey];s&&l&&s(r,l);}})}var $=new Map,C=t=>{let{apiKey:e,baseUrl:a,timeout:n}=t,i=a||"https://api.gelato.cloud",o=`${e}:${i}`,s=$.get(o);if(s)return s;let c={timeout:n??15e3,...t.httpTransportConfig,fetchOptions:{headers:{Authorization:`Bearer ${e}`,...t.httpTransportConfig?.fetchOptions?.headers},...t.httpTransportConfig?.fetchOptions}},r=viem.http(`${i}/rpc`,c)({});return $.set(o,r),r};var Re=(o=>(o[o.Pending=100]="Pending",o[o.Submitted=110]="Submitted",o[o.Success=200]="Success",o[o.Rejected=400]="Rejected",o[o.Reverted=500]="Reverted",o))(Re||{}),Ge=new Set([200,400,500]);function Pe(t){return !Ge.has(t)}function Ie(t){return async({tx:e,stopPolling:a,onSuccess:n,onFailure:i,onIntervalTick:o})=>{let s=await t.request({method:"relayer_getStatus",params:{id:e.txKey,logs:false}});o?.(s);let{status:c,createdAt:r}=s;if(r&&b__default.default().diff(b__default.default.unix(r),"hour")>=1&&Pe(c)){a();return}c===200?(n(s),a({withoutRemoving:true})):(c===400||c===500)&&(i(s),a({withoutRemoving:true}));}}function K({tx:t,gelatoApiKey:e,updateTxParams:a,removeTxFromPool:n,transactionsPool:i,onSuccess:o,onError:s}){let c=C({apiKey:e}),r=Ie(c);return pulsarCore.initializePollingTracker({tx:t,fetcher:r,removeTxFromPool:n,onSuccess:l=>{let p=l.status===200?l.receipt.transactionHash:void 0;a(t.txKey,{status:pulsarCore.TransactionStatus.Success,pending:false,isError:false,hash:p,finishedTimestamp:b__default.default().unix()});let f=i[t.txKey];o&&f&&o(f);},onIntervalTick:l=>{l.status===110&&a(t.txKey,{hash:l.hash});},onFailure:l=>{let p="Transaction failed or was not found.",f;l&&(l.status===400?p=l.message||"Transaction was rejected by Gelato Relay.":l.status===500&&(p=l.message||"Transaction reverted on-chain.",f=l.receipt.transactionHash));let d=new Error(p);a(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,hash:f,error:orbitCore.normalizeError(d),finishedTimestamp:b__default.default().unix()});let u=i[t.txKey];s&&u&&s(d,u);}})}var Rt={allowedDomains:[/gnosis-safe.io$/,/app.safe.global$/,/metissafe.tech$/],debug:false},X={[chains.mainnet.id]:"https://app.safe.global/eth:",[chains.goerli.id]:"https://app.safe.global/gor:",[chains.sepolia.id]:"https://app.safe.global/sep:",[chains.polygon.id]:"https://app.safe.global/matic:",[chains.arbitrum.id]:"https://app.safe.global/arb1:",[chains.aurora.id]:"https://app.safe.global/aurora:",[chains.avalanche.id]:"https://app.safe.global/avax:",[chains.base.id]:"https://app.safe.global/base:",[chains.boba.id]:"https://app.safe.global/boba:",[chains.bsc.id]:"https://app.safe.global/bnb:",[chains.celo.id]:"https://app.safe.global/celo:",[chains.gnosis.id]:"https://app.safe.global/gno:",[chains.optimism.id]:"https://app.safe.global/oeth:",[chains.polygonZkEvm.id]:"https://app.safe.global/zkevm:",[chains.zksync.id]:"https://app.safe.global/zksync:"},Z={[chains.mainnet.id]:"https://safe-transaction-mainnet.safe.global/api/v1",[chains.goerli.id]:"https://safe-transaction-goerli.safe.global/api/v1",[chains.sepolia.id]:"https://safe-transaction-sepolia.safe.global/api/v1",[chains.polygon.id]:"https://safe-transaction-polygon.safe.global/api/v1",[chains.arbitrum.id]:"https://safe-transaction-arbitrum.safe.global/api/v1",[chains.aurora.id]:"https://safe-transaction-aurora.safe.global/api/v1",[chains.avalanche.id]:"https://safe-transaction-avalanche.safe.global/api/v1",[chains.base.id]:"https://safe-transaction-base.safe.global/api/v1",[chains.boba.id]:"https://safe-transaction-boba.safe.global/api/v1",[chains.bsc.id]:"https://safe-transaction-bsc.safe.global/api/v1",[chains.celo.id]:"https://safe-transaction-celo.safe.global/api/v1",[chains.gnosis.id]:"https://safe-transaction-gnosis-chain.safe.global/api/v1",[chains.optimism.id]:"https://safe-transaction-optimism.safe.global/api/v1",[chains.polygonZkEvm.id]:"https://safe-transaction-zkevm.safe.global/api/v1",[chains.zksync.id]:"https://safe-transaction-zksync.safe.global/api/v1"};var He=async({tx:t,stopPolling:e,onSuccess:a,onFailure:n,onReplaced:i,onIntervalTick:o})=>{let s=Z[t.chainId];if(!s)throw new Error(`Safe Transaction Service URL not found for chainId: ${t.chainId}`);let c=await fetch(`${s}/multisig-transactions/${t.txKey}/`);if(!c.ok)throw c.status===404&&(n(),e()),new Error(`Safe API responded with status: ${c.status}`);let r=await c.json();if(o?.(r),r.isExecuted){r.isSuccessful?a(r):n(r),e({withoutRemoving:true});return}let l=await fetch(`${s}/safes/${t.from}/multisig-transactions/?nonce=${r.nonce}`);if(!l.ok)throw new Error(`Safe API (nonce check) responded with status: ${l.status}`);let f=(await l.json()).results.find(d=>d.isExecuted);if(f){i?.(f),e({withoutRemoving:true});return}b__default.default().diff(b__default.default(r.submissionDate),"day")>=1&&e();};function ee({tx:t,updateTxParams:e,removeTxFromPool:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s}){return pulsarCore.initializePollingTracker({tx:t,fetcher:He,removeTxFromPool:a,onSuccess:c=>{e(t.txKey,{status:pulsarCore.TransactionStatus.Success,pending:false,isError:false,hash:c.transactionHash??void 0,finishedTimestamp:c.executionDate?b__default.default(c.executionDate).unix():void 0});let r=n[t.txKey];i&&r&&i(r);},onIntervalTick:c=>{e(t.txKey,{hash:c.transactionHash??void 0});},onFailure:c=>{let r=c?new Error("Safe transaction failed or was rejected."):new Error("Transaction not found.");e(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,hash:c?.transactionHash??void 0,error:orbitCore.normalizeError(r),finishedTimestamp:c?.executionDate?b__default.default(c.executionDate).unix():void 0});let l=n[t.txKey];o&&l&&o(r,l);},onReplaced:c=>{e(t.txKey,{status:pulsarCore.TransactionStatus.Replaced,pending:false,hash:t.adapter===orbitCore.OrbitAdapter.EVM?t.hash:viem.zeroHash,replacedTxHash:c.safeTxHash??viem.zeroHash,finishedTimestamp:c.executionDate?b__default.default(c.executionDate).unix():void 0});let r=n[t.txKey];s&&r&&s(r,t);}})}async function te({tracker:t,tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,gelatoApiKey:c,...r}){switch(t){case pulsarCore.TransactionTracker.Ethereum:return y({tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r});case pulsarCore.TransactionTracker.Gelato:return c?K({tx:e,transactionsPool:n,onSuccess:i,onError:o,gelatoApiKey:c,...r}):(console.warn(`Gelato tracker requested for tx '${e.txKey}', but no 'gelatoApiKey' was provided. Falling back to default EVM tracker.`),y({tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r}));case pulsarCore.TransactionTracker.Safe:return ee({tx:e,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r});default:return console.warn(`Unknown tracker type: '${t}'. Falling back to default EVM tracker.`),y({tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r})}}function ae({actionTxKey:t,connectorType:e,tracker:a,gelatoApiKey:n}){if(a&&a===pulsarCore.TransactionTracker.Gelato&&n)return {tracker:pulsarCore.TransactionTracker.Gelato,txKey:t};if(!viem.isHex(t))throw new Error(`Invalid transaction key format. Expected a Hex string or a GelatoTxKey object, but received: ${JSON.stringify(t)}`);let i=e.split(":");return (i.length>1?i[i.length-1]==="safe"||i[i.length-1]==="safewallet":e?.toLowerCase()==="safe")?{tracker:pulsarCore.TransactionTracker.Safe,txKey:t}:{tracker:pulsarCore.TransactionTracker.Ethereum,txKey:t}}var ne=({chains:t,tx:e})=>{if(e.tracker===pulsarCore.TransactionTracker.Safe){let o=X[e.chainId];return o?`${o}${e.from}/transactions/tx?id=multisig_${e.from}_${e.txKey}`:""}let n=t.find(o=>o.id===e.chainId)?.blockExplorers?.default.url;if(!n)return "";let i=(e.adapter===orbitCore.OrbitAdapter.EVM?e.replacedTxHash:e.txKey)||(e.adapter===orbitCore.OrbitAdapter.EVM?e.hash:e.txKey);return i?`${n}/tx/${i}`:""};var oe=1.15;async function ie({config:t,tx:e}){if(e.adapter!==orbitCore.OrbitAdapter.EVM)throw new Error(`Speed up is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,from:n,to:i,value:o,input:s,maxFeePerGas:c,maxPriorityFeePerGas:r,chainId:l}=e;if(a===void 0||!n||!i||!o||!c||!r)throw new Error("Transaction is missing required fields for speed-up.");try{if(!t)throw new Error("Wagmi config is not provided.");if(!core.getAccount(t).address)throw new Error("No connected account found.");let f=BigInt(Math.ceil(Number(r)*oe)),d=BigInt(Math.ceil(Number(c)*oe));return await core.sendTransaction(t,{to:i,value:BigInt(o),data:s||"0x",chainId:l,nonce:a,maxFeePerGas:d,maxPriorityFeePerGas:f})}catch(p){let f=p instanceof Error?p.message:String(p);throw new Error(`Failed to speed up transaction: ${f}`,{cause:p})}}function ya(t,e){if(!t)throw new Error("EVM adapter requires a wagmi config object.");return {key:orbitCore.OrbitAdapter.EVM,getConnectorInfo:()=>{let a=core.getConnection(t),n=orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector();return {walletAddress:a.address??n?.address??viem.zeroAddress,connectorType:orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.EVM,a.connector?.name?.toLowerCase()??"unknown")}},checkChainForTx:a=>orbitEvm.checkAndSwitchChain(a,t),checkTransactionsTracker:a=>ae(a),checkAndInitializeTrackerInStore:({tx:a,...n})=>te({tracker:a.tracker,tx:a,config:t,...n}),getExplorerUrl:a=>{let{chain:n}=core.getConnection(t),i=n?.blockExplorers?.default.url;return a?`${i}/${a}`:i},getExplorerTxUrl:a=>ne({chains:e,tx:a}),cancelTxAction:a=>A({config:t,tx:a}),speedUpTxAction:a=>ie({config:t,tx:a}),retryTxAction:async({onClose:a,txKey:n,executeTxAction:i,tx:o})=>{if(a(n),!i){console.error("Retry failed: executeTxAction function is not provided.");return}await i({actionFunction:()=>o.actionFunction({config:t,...o.payload}),params:o,defaultTracker:pulsarCore.TransactionTracker.Ethereum});}}}var P=new Map;async function De(t){let e=await t.request({method:"relayer_getCapabilities",params:[]}),a={};for(let[n,i]of Object.entries(e))a[Number(n)]=i;return a}async function je(t){let e=P.get(t);if(e)return e;let a=C({apiKey:t}),n=await De(a);return P.set(t,n),n}async function wa(t,e){try{let a=await je(e);return t in a}catch(a){return console.error("Failed to fetch Gelato relay capabilities:",a),P.delete(e),false}}
|
|
2
|
+
exports.GelatoStatusCode=Re;exports.SafeTransactionServiceUrls=Z;exports.cancelTxAction=A;exports.checkAndInitializeTrackerInStore=te;exports.checkIsGelatoAvailable=wa;exports.checkTransactionsTracker=ae;exports.createGelatoClient=C;exports.evmTracker=Se;exports.evmTrackerForStore=y;exports.gelatoFetcher=Ie;exports.gelatoTrackerForStore=K;exports.gnosisSafeLinksHelper=X;exports.pulsarEvmAdapter=ya;exports.safeFetcher=He;exports.safeSdkOptions=Rt;exports.safeTrackerForStore=ee;exports.selectEvmTxExplorerLink=ne;exports.speedUpTxAction=ie;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {OrbitAdapter,normalizeError,lastConnectedConnectorHelpers,getConnectorTypeFromName}from'@tuwaio/orbit-core';import {checkAndSwitchChain}from'@tuwaio/orbit-evm';import {TransactionStatus,initializePollingTracker,TransactionTracker}from'@tuwaio/pulsar-core';import {getAccount,sendTransaction,getClient,getConnection}from'@wagmi/core';import {zeroHash,isHex,zeroAddress}from'viem';import {getTransaction,waitForTransactionReceipt,getBlock}from'viem/actions';import T from'dayjs';import {zksync,polygonZkEvm,optimism,gnosis,celo,bsc,boba,base,avalanche,aurora,arbitrum,polygon,sepolia,goerli,mainnet}from'viem/chains';var C=1.15;async function v({config:t,tx:e}){if(e.adapter!==OrbitAdapter.EVM)throw new Error(`Cancellation is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,maxFeePerGas:o,maxPriorityFeePerGas:s,chainId:c}=e;if(a===void 0||!o||!s)throw new Error("Transaction is missing required fields for cancellation (nonce, maxFeePerGas, maxPriorityFeePerGas).");try{if(!t)throw new Error("Wagmi config is not provided.");let n=getAccount(t);if(!n.address)throw new Error("No connected account found.");let r=BigInt(Math.ceil(Number(s)*C)),i=BigInt(Math.ceil(Number(o)*C));return await sendTransaction(t,{to:n.address,value:0n,chainId:c,nonce:a,maxFeePerGas:i,maxPriorityFeePerGas:r})}catch(n){let r=n instanceof Error?n.message:String(n);throw new Error(`Failed to cancel transaction: ${r}`)}}var ue=10,me=3e3;async function Te(t){let{tx:e,config:a,onInitialize:o,onTxDetailsFetched:s,onSuccess:c,onFailure:n,onReplaced:r,retryCount:i=ue,retryTimeout:l=me,waitForTransactionReceiptParams:u}=t;if(o?.(),e.txKey===zeroHash)return n(new Error("Transaction hash cannot be the zero hash."));let p=getClient(a,{chainId:e.chainId});if(!p)return n(new Error(`Could not create a viem client for chainId: ${e.chainId}`));let d=null;for(let f=0;f<i;f++)try{d=await getTransaction(p,{hash:e.txKey}),s(d);break}catch(m){if(f===i-1)return console.error(`EVM tracker failed to fetch tx ${e.txKey} after ${i} retries:`,m),n(m);await new Promise(b=>setTimeout(b,l));}if(!d)return n(new Error("Transaction details could not be fetched."));try{let f=!1,m=await waitForTransactionReceipt(p,{hash:d.hash,onReplaced:b=>{f=!0,r(b);},...u});if(f)return;await c(d,m,p);}catch(f){console.error(`Error waiting for receipt for tx ${e.txKey}:`,f),n(f);}}async function y(t){let{tx:e,config:a,updateTxParams:o,transactionsPool:s,onSuccess:c,onError:n,onReplaced:r}=t;return Te({tx:e,config:a,onInitialize:()=>{o(e.txKey,{hash:e.txKey});},onTxDetailsFetched:i=>{o(e.txKey,{to:i.to??void 0,input:i.input,value:i.value?.toString(),nonce:i.nonce,maxFeePerGas:i.maxFeePerGas?.toString(),maxPriorityFeePerGas:i.maxPriorityFeePerGas?.toString()});},onSuccess:async(i,l,u)=>{let p=await getBlock(u,{blockNumber:l.blockNumber}),d=Number(p.timestamp),f=l.status==="success";o(e.txKey,{status:f?TransactionStatus.Success:TransactionStatus.Failed,isError:!f,pending:false,finishedTimestamp:d});let m=s[e.txKey];f&&c&&m&&c(m),!f&&n&&m&&n(new Error("Transaction reverted"),m);},onReplaced:i=>{o(e.txKey,{status:TransactionStatus.Replaced,replacedTxHash:i.transaction.hash,pending:false});let l=s[e.txKey];r&&l&&r(l,e);},onFailure:i=>{o(e.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,error:normalizeError(i)});let l=s[e.txKey];n&&l&&n(i,l);}})}function F(t){return typeof t=="object"&&t!==null&&"taskId"in t}var ge=(r=>(r.CheckPending="CheckPending",r.ExecPending="ExecPending",r.WaitingForConfirmation="WaitingForConfirmation",r.ExecSuccess="ExecSuccess",r.ExecReverted="ExecReverted",r.Cancelled="Cancelled",r.NotFound="NotFound",r))(ge||{}),ke="https://api.gelato.digital/tasks/status/",I=new Set(["ExecReverted","Cancelled","NotFound"]);function be(t){return t!=="ExecSuccess"&&!I.has(t)}var ye=async({tx:t,stopPolling:e,onSuccess:a,onFailure:o,onIntervalTick:s})=>{let c=await fetch(`${ke}${t.txKey}`);if(!c.ok){if(c.status===404){o(),e();return}throw new Error(`Gelato API responded with status: ${c.status}`)}let n=await c.json(),{taskState:r,creationDate:i}=n.task;if(s?.(n),i&&T().diff(T(i),"hour")>=1&&be(r)){e();return}r==="ExecSuccess"?(a(n),e({withoutRemoving:true})):I.has(r)&&(o(n),e({withoutRemoving:true}));};function P({tx:t,updateTxParams:e,removeTxFromPool:a,transactionsPool:o,onSuccess:s,onError:c}){return initializePollingTracker({tx:t,fetcher:ye,removeTxFromPool:a,onSuccess:n=>{e(t.txKey,{status:TransactionStatus.Success,pending:false,isError:false,hash:n.task.transactionHash,finishedTimestamp:n.task.executionDate?T(n.task.executionDate).unix():void 0});let r=o[t.txKey];s&&r&&s(r);},onIntervalTick:n=>{e(t.txKey,{hash:n.task.transactionHash});},onFailure:n=>{let r=n?.task.lastCheckMessage?new Error(n.task.lastCheckMessage):new Error("Transaction failed or was not found.");e(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,hash:n?.task.transactionHash,error:normalizeError(r),finishedTimestamp:n?.task.executionDate?T(n.task.executionDate).unix():void 0});let i=o[t.txKey];c&&i&&c(r,i);}})}var Tt={allowedDomains:[/gnosis-safe.io$/,/app.safe.global$/,/metissafe.tech$/],debug:false},B={[mainnet.id]:"https://app.safe.global/eth:",[goerli.id]:"https://app.safe.global/gor:",[sepolia.id]:"https://app.safe.global/sep:",[polygon.id]:"https://app.safe.global/matic:",[arbitrum.id]:"https://app.safe.global/arb1:",[aurora.id]:"https://app.safe.global/aurora:",[avalanche.id]:"https://app.safe.global/avax:",[base.id]:"https://app.safe.global/base:",[boba.id]:"https://app.safe.global/boba:",[bsc.id]:"https://app.safe.global/bnb:",[celo.id]:"https://app.safe.global/celo:",[gnosis.id]:"https://app.safe.global/gno:",[optimism.id]:"https://app.safe.global/oeth:",[polygonZkEvm.id]:"https://app.safe.global/zkevm:",[zksync.id]:"https://app.safe.global/zksync:"},W={[mainnet.id]:"https://safe-transaction-mainnet.safe.global/api/v1",[goerli.id]:"https://safe-transaction-goerli.safe.global/api/v1",[sepolia.id]:"https://safe-transaction-sepolia.safe.global/api/v1",[polygon.id]:"https://safe-transaction-polygon.safe.global/api/v1",[arbitrum.id]:"https://safe-transaction-arbitrum.safe.global/api/v1",[aurora.id]:"https://safe-transaction-aurora.safe.global/api/v1",[avalanche.id]:"https://safe-transaction-avalanche.safe.global/api/v1",[base.id]:"https://safe-transaction-base.safe.global/api/v1",[boba.id]:"https://safe-transaction-boba.safe.global/api/v1",[bsc.id]:"https://safe-transaction-bsc.safe.global/api/v1",[celo.id]:"https://safe-transaction-celo.safe.global/api/v1",[gnosis.id]:"https://safe-transaction-gnosis-chain.safe.global/api/v1",[optimism.id]:"https://safe-transaction-optimism.safe.global/api/v1",[polygonZkEvm.id]:"https://safe-transaction-zkevm.safe.global/api/v1",[zksync.id]:"https://safe-transaction-zksync.safe.global/api/v1"};var Ce=async({tx:t,stopPolling:e,onSuccess:a,onFailure:o,onReplaced:s,onIntervalTick:c})=>{let n=W[t.chainId];if(!n)throw new Error(`Safe Transaction Service URL not found for chainId: ${t.chainId}`);let r=await fetch(`${n}/multisig-transactions/${t.txKey}/`);if(!r.ok)throw r.status===404&&(o(),e()),new Error(`Safe API responded with status: ${r.status}`);let i=await r.json();if(c?.(i),i.isExecuted){i.isSuccessful?a(i):o(i),e({withoutRemoving:true});return}let l=await fetch(`${n}/safes/${t.from}/multisig-transactions/?nonce=${i.nonce}`);if(!l.ok)throw new Error(`Safe API (nonce check) responded with status: ${l.status}`);let p=(await l.json()).results.find(d=>d.isExecuted);if(p){s?.(p),e({withoutRemoving:true});return}T().diff(T(i.submissionDate),"day")>=1&&e();};function Y({tx:t,updateTxParams:e,removeTxFromPool:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n}){return initializePollingTracker({tx:t,fetcher:Ce,removeTxFromPool:a,onSuccess:r=>{e(t.txKey,{status:TransactionStatus.Success,pending:false,isError:false,hash:r.transactionHash??void 0,finishedTimestamp:r.executionDate?T(r.executionDate).unix():void 0});let i=o[t.txKey];s&&i&&s(i);},onIntervalTick:r=>{e(t.txKey,{hash:r.transactionHash??void 0});},onFailure:r=>{let i=r?new Error("Safe transaction failed or was rejected."):new Error("Transaction not found.");e(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,hash:r?.transactionHash??void 0,error:normalizeError(i),finishedTimestamp:r?.executionDate?T(r.executionDate).unix():void 0});let l=o[t.txKey];c&&l&&c(i,l);},onReplaced:r=>{e(t.txKey,{status:TransactionStatus.Replaced,pending:false,hash:t.adapter===OrbitAdapter.EVM?t.hash:zeroHash,replacedTxHash:r.safeTxHash??zeroHash,finishedTimestamp:r.executionDate?T(r.executionDate).unix():void 0});let i=o[t.txKey];n&&i&&n(i,t);}})}async function J({tracker:t,tx:e,config:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r}){switch(t){case TransactionTracker.Ethereum:return y({tx:e,config:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r});case TransactionTracker.Gelato:return P({tx:e,transactionsPool:o,onSuccess:s,onError:c,...r});case TransactionTracker.Safe:return Y({tx:e,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r});default:return console.warn(`Unknown tracker type: '${t}'. Falling back to default EVM tracker.`),y({tx:e,config:a,transactionsPool:o,onSuccess:s,onError:c,onReplaced:n,...r})}}function Z(t,e){if(F(t))return {tracker:TransactionTracker.Gelato,txKey:t.taskId};if(!isHex(t))throw new Error(`Invalid transaction key format. Expected a Hex string or a GelatoTxKey object, but received: ${JSON.stringify(t)}`);let a=e.split(":");return (a.length>1?a[a.length-1]==="safe"||a[a.length-1]==="safewallet":e?.toLowerCase()==="safe")?{tracker:TransactionTracker.Safe,txKey:t}:{tracker:TransactionTracker.Ethereum,txKey:t}}var X=({chains:t,tx:e})=>{if(e.tracker===TransactionTracker.Safe){let c=B[e.chainId];return c?`${c}${e.from}/transactions/tx?id=multisig_${e.from}_${e.txKey}`:""}let o=t.find(c=>c.id===e.chainId)?.blockExplorers?.default.url;if(!o)return "";let s=(e.adapter===OrbitAdapter.EVM?e.replacedTxHash:e.txKey)||(e.adapter===OrbitAdapter.EVM?e.hash:e.txKey);return s?`${o}/tx/${s}`:""};var ee=1.15;async function te({config:t,tx:e}){if(e.adapter!==OrbitAdapter.EVM)throw new Error(`Speed up is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,from:o,to:s,value:c,input:n,maxFeePerGas:r,maxPriorityFeePerGas:i,chainId:l}=e;if(a===void 0||!o||!s||!c||!r||!i)throw new Error("Transaction is missing required fields for speed-up.");try{if(!t)throw new Error("Wagmi config is not provided.");if(!getAccount(t).address)throw new Error("No connected account found.");let p=BigInt(Math.ceil(Number(i)*ee)),d=BigInt(Math.ceil(Number(r)*ee));return await sendTransaction(t,{to:s,value:BigInt(c),data:n||"0x",chainId:l,nonce:a,maxFeePerGas:d,maxPriorityFeePerGas:p})}catch(u){let p=u instanceof Error?u.message:String(u);throw new Error(`Failed to speed up transaction: ${p}`)}}function fa(t,e){if(!t)throw new Error("EVM adapter requires a wagmi config object.");return {key:OrbitAdapter.EVM,getConnectorInfo:()=>{let a=getConnection(t),o=lastConnectedConnectorHelpers.getLastConnectedConnector();return {walletAddress:a.address??o?.address??zeroAddress,connectorType:getConnectorTypeFromName(OrbitAdapter.EVM,a.connector?.name?.toLowerCase()??"unknown")}},checkChainForTx:a=>checkAndSwitchChain(a,t),checkTransactionsTracker:(a,o)=>Z(a,o),checkAndInitializeTrackerInStore:({tx:a,...o})=>J({tracker:a.tracker,tx:a,config:t,...o}),getExplorerUrl:a=>{let{chain:o}=getConnection(t),s=o?.blockExplorers?.default.url;return a?`${s}/${a}`:s},getExplorerTxUrl:a=>X({chains:e,tx:a}),cancelTxAction:a=>v({config:t,tx:a}),speedUpTxAction:a=>te({config:t,tx:a}),retryTxAction:async({onClose:a,txKey:o,executeTxAction:s,tx:c})=>{if(a(o),!s){console.error("Retry failed: executeTxAction function is not provided.");return}await s({actionFunction:()=>c.actionFunction({config:t,...c.payload}),params:c,defaultTracker:TransactionTracker.Ethereum});}}}var g=null,k=null,Me=300*1e3,Ne="https://relay.gelato.digital/relays/v2/supported-chains";async function da(t){let e=Date.now();if(g&&k&&e-k<Me)return g.includes(t);try{let a=await fetch(Ne);if(!a.ok)throw new Error(`Gelato API responded with status: ${a.status}`);let s=(await a.json()).chains.map(Number);return g=s,k=e,s.includes(t)}catch(a){return console.error("Failed to fetch Gelato supported chains:",a),g=null,k=null,false}}
|
|
2
|
-
export{
|
|
1
|
+
import {OrbitAdapter,normalizeError,lastConnectedConnectorHelpers,getConnectorTypeFromName}from'@tuwaio/orbit-core';import {checkAndSwitchChain}from'@tuwaio/orbit-evm';import {TransactionStatus,initializePollingTracker,TransactionTracker}from'@tuwaio/pulsar-core';import {getAccount,sendTransaction,getClient,getConnection}from'@wagmi/core';import {zeroHash,http,isHex,zeroAddress}from'viem';import {getTransaction,waitForTransactionReceipt,getTransactionConfirmations,getBlock}from'viem/actions';import b from'dayjs';import {zksync,polygonZkEvm,optimism,gnosis,celo,bsc,boba,base,avalanche,aurora,arbitrum,polygon,sepolia,goerli,mainnet}from'viem/chains';var F=1.15;async function A({config:t,tx:e}){if(e.adapter!==OrbitAdapter.EVM)throw new Error(`Cancellation is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,maxFeePerGas:n,maxPriorityFeePerGas:i,chainId:o}=e;if(a===void 0||!n||!i)throw new Error("Transaction is missing required fields for cancellation (nonce, maxFeePerGas, maxPriorityFeePerGas).");try{if(!t)throw new Error("Wagmi config is not provided.");let s=getAccount(t);if(!s.address)throw new Error("No connected account found.");let c=BigInt(Math.ceil(Number(i)*F)),r=BigInt(Math.ceil(Number(n)*F));return await sendTransaction(t,{to:s.address,value:0n,chainId:o,nonce:a,maxFeePerGas:r,maxPriorityFeePerGas:c})}catch(s){let c=s instanceof Error?s.message:String(s);throw new Error(`Failed to cancel transaction: ${c}`,{cause:s})}}var be=10,ke=3e3,v=3,ye=1e4,Ce=5e3;async function Se(t){let{tx:e,config:a,onInitialize:n,onTxDetailsFetched:i,onSuccess:o,onFailure:s,onReplaced:c,retryCount:r=be,retryTimeout:l=ke,onConfirmationsUpdate:p,waitForTransactionReceiptParams:f}=t,{requiredConfirmations:d}=e;if(n?.(),e.txKey===zeroHash)return s(new Error("Transaction hash cannot be the zero hash."));let u=getClient(a,{chainId:e.chainId});if(!u)return s(new Error(`Could not create a viem client for chainId: ${e.chainId}`));let m=null;for(let T=0;T<r;T++)try{m=await getTransaction(u,{hash:e.txKey}),i(m);break}catch(h){if(T===r-1)return console.error(`[evmTracker] Fatal error fetching transaction ${e.txKey} on chain ${e.chainId}:`,h),s(h);console.warn(`[evmTracker] Error fetching transaction ${e.txKey} on chain ${e.chainId} (attempt ${T+1}/${r}):`,h),await new Promise(g=>setTimeout(g,l));}if(!m)return s(new Error("Transaction details could not be fetched."));let E=false;for(let T=0;T<=v;T++)try{let h=await waitForTransactionReceipt(u,{hash:m.hash,onReplaced:g=>{E=!0,c(g);},...f});if(!E){let g=d??1;if(g>1)for(;;){try{let x=await getTransactionConfirmations(u,{transactionReceipt:h}),I=Number(x);if(p?.(I),I>=g)break}catch(x){console.warn(`[evmTracker] Error fetching confirmations for ${e.txKey} on chain ${e.chainId}:`,x);}await new Promise(x=>setTimeout(x,Ce));}await o(m,h,u);}return}catch(h){if(h instanceof Error&&h.name==="TransactionReceiptNotFoundError"&&!E&&T<v){console.warn(`[evmTracker] Receipt not found for ${e.txKey}, retry ${T+1}/${v}...`),await new Promise(x=>setTimeout(x,ye*(T+1)));continue}s(h);return}}async function y(t){let{tx:e,config:a,updateTxParams:n,transactionsPool:i,onSuccess:o,onError:s,onReplaced:c}=t;return Se({tx:e,config:a,onInitialize:()=>{n(e.txKey,{hash:e.txKey});},onTxDetailsFetched:r=>{n(e.txKey,{to:r.to??void 0,input:r.input,value:r.value?.toString(),nonce:r.nonce,maxFeePerGas:r.maxFeePerGas?.toString(),maxPriorityFeePerGas:r.maxPriorityFeePerGas?.toString()});},onConfirmationsUpdate:r=>{n(e.txKey,{confirmations:r});},onSuccess:async(r,l,p)=>{let f=await getBlock(p,{blockNumber:l.blockNumber}),d=Number(f.timestamp),u=l.status==="success";n(e.txKey,{status:u?TransactionStatus.Success:TransactionStatus.Failed,isError:!u,pending:false,finishedTimestamp:d});let m=i[e.txKey];u&&o&&m&&o(m),!u&&s&&m&&s(new Error("Transaction reverted"),m);},onReplaced:r=>{n(e.txKey,{status:TransactionStatus.Replaced,replacedTxHash:r.transaction.hash,pending:false});let l=i[e.txKey];c&&l&&c(l,e);},onFailure:r=>{n(e.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,error:normalizeError(r)});let l=i[e.txKey];s&&l&&s(r,l);}})}var $=new Map,C=t=>{let{apiKey:e,baseUrl:a,timeout:n}=t,i=a||"https://api.gelato.cloud",o=`${e}:${i}`,s=$.get(o);if(s)return s;let c={timeout:n??15e3,...t.httpTransportConfig,fetchOptions:{headers:{Authorization:`Bearer ${e}`,...t.httpTransportConfig?.fetchOptions?.headers},...t.httpTransportConfig?.fetchOptions}},r=http(`${i}/rpc`,c)({});return $.set(o,r),r};var Re=(o=>(o[o.Pending=100]="Pending",o[o.Submitted=110]="Submitted",o[o.Success=200]="Success",o[o.Rejected=400]="Rejected",o[o.Reverted=500]="Reverted",o))(Re||{}),Ge=new Set([200,400,500]);function Pe(t){return !Ge.has(t)}function Ie(t){return async({tx:e,stopPolling:a,onSuccess:n,onFailure:i,onIntervalTick:o})=>{let s=await t.request({method:"relayer_getStatus",params:{id:e.txKey,logs:false}});o?.(s);let{status:c,createdAt:r}=s;if(r&&b().diff(b.unix(r),"hour")>=1&&Pe(c)){a();return}c===200?(n(s),a({withoutRemoving:true})):(c===400||c===500)&&(i(s),a({withoutRemoving:true}));}}function K({tx:t,gelatoApiKey:e,updateTxParams:a,removeTxFromPool:n,transactionsPool:i,onSuccess:o,onError:s}){let c=C({apiKey:e}),r=Ie(c);return initializePollingTracker({tx:t,fetcher:r,removeTxFromPool:n,onSuccess:l=>{let p=l.status===200?l.receipt.transactionHash:void 0;a(t.txKey,{status:TransactionStatus.Success,pending:false,isError:false,hash:p,finishedTimestamp:b().unix()});let f=i[t.txKey];o&&f&&o(f);},onIntervalTick:l=>{l.status===110&&a(t.txKey,{hash:l.hash});},onFailure:l=>{let p="Transaction failed or was not found.",f;l&&(l.status===400?p=l.message||"Transaction was rejected by Gelato Relay.":l.status===500&&(p=l.message||"Transaction reverted on-chain.",f=l.receipt.transactionHash));let d=new Error(p);a(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,hash:f,error:normalizeError(d),finishedTimestamp:b().unix()});let u=i[t.txKey];s&&u&&s(d,u);}})}var Rt={allowedDomains:[/gnosis-safe.io$/,/app.safe.global$/,/metissafe.tech$/],debug:false},X={[mainnet.id]:"https://app.safe.global/eth:",[goerli.id]:"https://app.safe.global/gor:",[sepolia.id]:"https://app.safe.global/sep:",[polygon.id]:"https://app.safe.global/matic:",[arbitrum.id]:"https://app.safe.global/arb1:",[aurora.id]:"https://app.safe.global/aurora:",[avalanche.id]:"https://app.safe.global/avax:",[base.id]:"https://app.safe.global/base:",[boba.id]:"https://app.safe.global/boba:",[bsc.id]:"https://app.safe.global/bnb:",[celo.id]:"https://app.safe.global/celo:",[gnosis.id]:"https://app.safe.global/gno:",[optimism.id]:"https://app.safe.global/oeth:",[polygonZkEvm.id]:"https://app.safe.global/zkevm:",[zksync.id]:"https://app.safe.global/zksync:"},Z={[mainnet.id]:"https://safe-transaction-mainnet.safe.global/api/v1",[goerli.id]:"https://safe-transaction-goerli.safe.global/api/v1",[sepolia.id]:"https://safe-transaction-sepolia.safe.global/api/v1",[polygon.id]:"https://safe-transaction-polygon.safe.global/api/v1",[arbitrum.id]:"https://safe-transaction-arbitrum.safe.global/api/v1",[aurora.id]:"https://safe-transaction-aurora.safe.global/api/v1",[avalanche.id]:"https://safe-transaction-avalanche.safe.global/api/v1",[base.id]:"https://safe-transaction-base.safe.global/api/v1",[boba.id]:"https://safe-transaction-boba.safe.global/api/v1",[bsc.id]:"https://safe-transaction-bsc.safe.global/api/v1",[celo.id]:"https://safe-transaction-celo.safe.global/api/v1",[gnosis.id]:"https://safe-transaction-gnosis-chain.safe.global/api/v1",[optimism.id]:"https://safe-transaction-optimism.safe.global/api/v1",[polygonZkEvm.id]:"https://safe-transaction-zkevm.safe.global/api/v1",[zksync.id]:"https://safe-transaction-zksync.safe.global/api/v1"};var He=async({tx:t,stopPolling:e,onSuccess:a,onFailure:n,onReplaced:i,onIntervalTick:o})=>{let s=Z[t.chainId];if(!s)throw new Error(`Safe Transaction Service URL not found for chainId: ${t.chainId}`);let c=await fetch(`${s}/multisig-transactions/${t.txKey}/`);if(!c.ok)throw c.status===404&&(n(),e()),new Error(`Safe API responded with status: ${c.status}`);let r=await c.json();if(o?.(r),r.isExecuted){r.isSuccessful?a(r):n(r),e({withoutRemoving:true});return}let l=await fetch(`${s}/safes/${t.from}/multisig-transactions/?nonce=${r.nonce}`);if(!l.ok)throw new Error(`Safe API (nonce check) responded with status: ${l.status}`);let f=(await l.json()).results.find(d=>d.isExecuted);if(f){i?.(f),e({withoutRemoving:true});return}b().diff(b(r.submissionDate),"day")>=1&&e();};function ee({tx:t,updateTxParams:e,removeTxFromPool:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s}){return initializePollingTracker({tx:t,fetcher:He,removeTxFromPool:a,onSuccess:c=>{e(t.txKey,{status:TransactionStatus.Success,pending:false,isError:false,hash:c.transactionHash??void 0,finishedTimestamp:c.executionDate?b(c.executionDate).unix():void 0});let r=n[t.txKey];i&&r&&i(r);},onIntervalTick:c=>{e(t.txKey,{hash:c.transactionHash??void 0});},onFailure:c=>{let r=c?new Error("Safe transaction failed or was rejected."):new Error("Transaction not found.");e(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,hash:c?.transactionHash??void 0,error:normalizeError(r),finishedTimestamp:c?.executionDate?b(c.executionDate).unix():void 0});let l=n[t.txKey];o&&l&&o(r,l);},onReplaced:c=>{e(t.txKey,{status:TransactionStatus.Replaced,pending:false,hash:t.adapter===OrbitAdapter.EVM?t.hash:zeroHash,replacedTxHash:c.safeTxHash??zeroHash,finishedTimestamp:c.executionDate?b(c.executionDate).unix():void 0});let r=n[t.txKey];s&&r&&s(r,t);}})}async function te({tracker:t,tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,gelatoApiKey:c,...r}){switch(t){case TransactionTracker.Ethereum:return y({tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r});case TransactionTracker.Gelato:return c?K({tx:e,transactionsPool:n,onSuccess:i,onError:o,gelatoApiKey:c,...r}):(console.warn(`Gelato tracker requested for tx '${e.txKey}', but no 'gelatoApiKey' was provided. Falling back to default EVM tracker.`),y({tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r}));case TransactionTracker.Safe:return ee({tx:e,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r});default:return console.warn(`Unknown tracker type: '${t}'. Falling back to default EVM tracker.`),y({tx:e,config:a,transactionsPool:n,onSuccess:i,onError:o,onReplaced:s,...r})}}function ae({actionTxKey:t,connectorType:e,tracker:a,gelatoApiKey:n}){if(a&&a===TransactionTracker.Gelato&&n)return {tracker:TransactionTracker.Gelato,txKey:t};if(!isHex(t))throw new Error(`Invalid transaction key format. Expected a Hex string or a GelatoTxKey object, but received: ${JSON.stringify(t)}`);let i=e.split(":");return (i.length>1?i[i.length-1]==="safe"||i[i.length-1]==="safewallet":e?.toLowerCase()==="safe")?{tracker:TransactionTracker.Safe,txKey:t}:{tracker:TransactionTracker.Ethereum,txKey:t}}var ne=({chains:t,tx:e})=>{if(e.tracker===TransactionTracker.Safe){let o=X[e.chainId];return o?`${o}${e.from}/transactions/tx?id=multisig_${e.from}_${e.txKey}`:""}let n=t.find(o=>o.id===e.chainId)?.blockExplorers?.default.url;if(!n)return "";let i=(e.adapter===OrbitAdapter.EVM?e.replacedTxHash:e.txKey)||(e.adapter===OrbitAdapter.EVM?e.hash:e.txKey);return i?`${n}/tx/${i}`:""};var oe=1.15;async function ie({config:t,tx:e}){if(e.adapter!==OrbitAdapter.EVM)throw new Error(`Speed up is only available for EVM transactions. Received adapter type: '${e.adapter}'.`);let{nonce:a,from:n,to:i,value:o,input:s,maxFeePerGas:c,maxPriorityFeePerGas:r,chainId:l}=e;if(a===void 0||!n||!i||!o||!c||!r)throw new Error("Transaction is missing required fields for speed-up.");try{if(!t)throw new Error("Wagmi config is not provided.");if(!getAccount(t).address)throw new Error("No connected account found.");let f=BigInt(Math.ceil(Number(r)*oe)),d=BigInt(Math.ceil(Number(c)*oe));return await sendTransaction(t,{to:i,value:BigInt(o),data:s||"0x",chainId:l,nonce:a,maxFeePerGas:d,maxPriorityFeePerGas:f})}catch(p){let f=p instanceof Error?p.message:String(p);throw new Error(`Failed to speed up transaction: ${f}`,{cause:p})}}function ya(t,e){if(!t)throw new Error("EVM adapter requires a wagmi config object.");return {key:OrbitAdapter.EVM,getConnectorInfo:()=>{let a=getConnection(t),n=lastConnectedConnectorHelpers.getLastConnectedConnector();return {walletAddress:a.address??n?.address??zeroAddress,connectorType:getConnectorTypeFromName(OrbitAdapter.EVM,a.connector?.name?.toLowerCase()??"unknown")}},checkChainForTx:a=>checkAndSwitchChain(a,t),checkTransactionsTracker:a=>ae(a),checkAndInitializeTrackerInStore:({tx:a,...n})=>te({tracker:a.tracker,tx:a,config:t,...n}),getExplorerUrl:a=>{let{chain:n}=getConnection(t),i=n?.blockExplorers?.default.url;return a?`${i}/${a}`:i},getExplorerTxUrl:a=>ne({chains:e,tx:a}),cancelTxAction:a=>A({config:t,tx:a}),speedUpTxAction:a=>ie({config:t,tx:a}),retryTxAction:async({onClose:a,txKey:n,executeTxAction:i,tx:o})=>{if(a(n),!i){console.error("Retry failed: executeTxAction function is not provided.");return}await i({actionFunction:()=>o.actionFunction({config:t,...o.payload}),params:o,defaultTracker:TransactionTracker.Ethereum});}}}var P=new Map;async function De(t){let e=await t.request({method:"relayer_getCapabilities",params:[]}),a={};for(let[n,i]of Object.entries(e))a[Number(n)]=i;return a}async function je(t){let e=P.get(t);if(e)return e;let a=C({apiKey:t}),n=await De(a);return P.set(t,n),n}async function wa(t,e){try{let a=await je(e);return t in a}catch(a){return console.error("Failed to fetch Gelato relay capabilities:",a),P.delete(e),false}}
|
|
2
|
+
export{Re as GelatoStatusCode,Z as SafeTransactionServiceUrls,A as cancelTxAction,te as checkAndInitializeTrackerInStore,wa as checkIsGelatoAvailable,ae as checkTransactionsTracker,C as createGelatoClient,Se as evmTracker,y as evmTrackerForStore,Ie as gelatoFetcher,K as gelatoTrackerForStore,X as gnosisSafeLinksHelper,ya as pulsarEvmAdapter,He as safeFetcher,Rt as safeSdkOptions,ee as safeTrackerForStore,ne as selectEvmTxExplorerLink,ie as speedUpTxAction};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuwaio/pulsar-evm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Oleksandr Tkach",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
],
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@tuwaio/pulsar-core": ">=0.5",
|
|
43
|
-
"@tuwaio/orbit-core": ">=0.2.
|
|
44
|
-
"@tuwaio/orbit-evm": ">=0.2.
|
|
43
|
+
"@tuwaio/orbit-core": ">=0.2.8",
|
|
44
|
+
"@tuwaio/orbit-evm": ">=0.2.11",
|
|
45
45
|
"@wagmi/core": "3.x.x",
|
|
46
46
|
"dayjs": "1.x.x",
|
|
47
47
|
"immer": "11.x.x",
|
|
@@ -49,18 +49,19 @@
|
|
|
49
49
|
"zustand": "5.x.x"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@tuwaio/orbit-core": "^0.2.
|
|
53
|
-
"@tuwaio/orbit-evm": "^0.2.
|
|
54
|
-
"@wagmi/core": "^3.
|
|
55
|
-
"dayjs": "^1.11.
|
|
56
|
-
"immer": "^11.1.
|
|
57
|
-
"jsdom": "^
|
|
52
|
+
"@tuwaio/orbit-core": "^0.2.8",
|
|
53
|
+
"@tuwaio/orbit-evm": "^0.2.11",
|
|
54
|
+
"@wagmi/core": "^3.4.6",
|
|
55
|
+
"dayjs": "^1.11.20",
|
|
56
|
+
"immer": "^11.1.4",
|
|
57
|
+
"jsdom": "^29.1.0",
|
|
58
58
|
"tsup": "^8.5.1",
|
|
59
|
-
"typescript": "^
|
|
60
|
-
"viem": "^2.
|
|
61
|
-
"vitest": "^4.
|
|
62
|
-
"zustand": "^5.0.
|
|
63
|
-
"
|
|
59
|
+
"typescript": "^6.0.3",
|
|
60
|
+
"viem": "^2.48.4",
|
|
61
|
+
"vitest": "^4.1.5",
|
|
62
|
+
"zustand": "^5.0.12",
|
|
63
|
+
"dotenv": "^17.4.2",
|
|
64
|
+
"@tuwaio/pulsar-core": "^0.6.0"
|
|
64
65
|
},
|
|
65
66
|
"scripts": {
|
|
66
67
|
"start": "tsup src/index.ts --watch",
|