@metamask-previews/transaction-controller 62.7.0-preview-42084fe4 → 62.7.0-preview-7bc2d97e
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/CHANGELOG.md +6 -0
- package/dist/TransactionController.cjs +23 -72
- package/dist/TransactionController.cjs.map +1 -1
- package/dist/TransactionController.d.cts +12 -13
- package/dist/TransactionController.d.cts.map +1 -1
- package/dist/TransactionController.d.mts +12 -13
- package/dist/TransactionController.d.mts.map +1 -1
- package/dist/TransactionController.mjs +23 -72
- package/dist/TransactionController.mjs.map +1 -1
- package/dist/helpers/PendingTransactionTracker.cjs +37 -25
- package/dist/helpers/PendingTransactionTracker.cjs.map +1 -1
- package/dist/helpers/PendingTransactionTracker.d.cts.map +1 -1
- package/dist/helpers/PendingTransactionTracker.d.mts.map +1 -1
- package/dist/helpers/PendingTransactionTracker.mjs +38 -26
- package/dist/helpers/PendingTransactionTracker.mjs.map +1 -1
- package/dist/index.cjs +1 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +5 -4
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +5 -4
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/feature-flags.cjs +4 -1
- package/dist/utils/feature-flags.cjs.map +1 -1
- package/dist/utils/feature-flags.d.cts +5 -0
- package/dist/utils/feature-flags.d.cts.map +1 -1
- package/dist/utils/feature-flags.d.mts +5 -0
- package/dist/utils/feature-flags.d.mts.map +1 -1
- package/dist/utils/feature-flags.mjs +4 -1
- package/dist/utils/feature-flags.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/utils/history.cjs +0 -164
- package/dist/utils/history.cjs.map +0 -1
- package/dist/utils/history.d.cts +0 -29
- package/dist/utils/history.d.cts.map +0 -1
- package/dist/utils/history.d.mts +0 -29
- package/dist/utils/history.d.mts.map +0 -1
- package/dist/utils/history.mjs +0 -164
- package/dist/utils/history.mjs.map +0 -1
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _PendingTransactionTracker_instances, _PendingTransactionTracker_beforeCheckPendingTransaction, _PendingTransactionTracker_droppedBlockCountByHash, _PendingTransactionTracker_isTimeoutEnabled, _PendingTransactionTracker_getChainId, _PendingTransactionTracker_getEthQuery, _PendingTransactionTracker_getGlobalLock, _PendingTransactionTracker_getNetworkClientId, _PendingTransactionTracker_getTransactions, _PendingTransactionTracker_isResubmitEnabled, _PendingTransactionTracker_listener, _PendingTransactionTracker_log, _PendingTransactionTracker_messenger, _PendingTransactionTracker_publishTransaction, _PendingTransactionTracker_running,
|
|
16
|
+
var _PendingTransactionTracker_instances, _PendingTransactionTracker_beforeCheckPendingTransaction, _PendingTransactionTracker_droppedBlockCountByHash, _PendingTransactionTracker_isTimeoutEnabled, _PendingTransactionTracker_getChainId, _PendingTransactionTracker_getEthQuery, _PendingTransactionTracker_getGlobalLock, _PendingTransactionTracker_getNetworkClientId, _PendingTransactionTracker_getTransactions, _PendingTransactionTracker_isResubmitEnabled, _PendingTransactionTracker_lastSeenTimestampByHash, _PendingTransactionTracker_listener, _PendingTransactionTracker_log, _PendingTransactionTracker_messenger, _PendingTransactionTracker_publishTransaction, _PendingTransactionTracker_running, _PendingTransactionTracker_transactionPoller, _PendingTransactionTracker_transactionToForcePoll, _PendingTransactionTracker_start, _PendingTransactionTracker_onLatestBlock, _PendingTransactionTracker_checkTransactions, _PendingTransactionTracker_resubmitTransactions, _PendingTransactionTracker_isKnownTransactionError, _PendingTransactionTracker_resubmitTransaction, _PendingTransactionTracker_isResubmitDue, _PendingTransactionTracker_cleanTransaction, _PendingTransactionTracker_checkTransaction, _PendingTransactionTracker_onTransactionConfirmed, _PendingTransactionTracker_isTransactionTimeout, _PendingTransactionTracker_isTransactionDropped, _PendingTransactionTracker_isNonceTaken, _PendingTransactionTracker_getPendingTransactions, _PendingTransactionTracker_warnTransaction, _PendingTransactionTracker_failTransaction, _PendingTransactionTracker_dropTransaction, _PendingTransactionTracker_updateTransaction, _PendingTransactionTracker_getTransactionReceipt, _PendingTransactionTracker_getTransactionByHash, _PendingTransactionTracker_getBlockByHash, _PendingTransactionTracker_getNetworkTransactionCount, _PendingTransactionTracker_getChainTransactions, _PendingTransactionTracker_getNetworkClientTransactions;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.PendingTransactionTracker = void 0;
|
|
19
19
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
@@ -54,6 +54,7 @@ class PendingTransactionTracker {
|
|
|
54
54
|
_PendingTransactionTracker_getNetworkClientId.set(this, void 0);
|
|
55
55
|
_PendingTransactionTracker_getTransactions.set(this, void 0);
|
|
56
56
|
_PendingTransactionTracker_isResubmitEnabled.set(this, void 0);
|
|
57
|
+
_PendingTransactionTracker_lastSeenTimestampByHash.set(this, void 0);
|
|
57
58
|
// TODO: Replace `any` with type
|
|
58
59
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
59
60
|
_PendingTransactionTracker_listener.set(this, void 0);
|
|
@@ -61,7 +62,6 @@ class PendingTransactionTracker {
|
|
|
61
62
|
_PendingTransactionTracker_messenger.set(this, void 0);
|
|
62
63
|
_PendingTransactionTracker_publishTransaction.set(this, void 0);
|
|
63
64
|
_PendingTransactionTracker_running.set(this, void 0);
|
|
64
|
-
_PendingTransactionTracker_timeoutCountByHash.set(this, void 0);
|
|
65
65
|
_PendingTransactionTracker_transactionPoller.set(this, void 0);
|
|
66
66
|
_PendingTransactionTracker_transactionToForcePoll.set(this, void 0);
|
|
67
67
|
this.startIfPendingTransactions = () => {
|
|
@@ -81,11 +81,11 @@ class PendingTransactionTracker {
|
|
|
81
81
|
__classPrivateFieldSet(this, _PendingTransactionTracker_getNetworkClientId, getNetworkClientId, "f");
|
|
82
82
|
__classPrivateFieldSet(this, _PendingTransactionTracker_getTransactions, getTransactions, "f");
|
|
83
83
|
__classPrivateFieldSet(this, _PendingTransactionTracker_isResubmitEnabled, isResubmitEnabled ?? (() => true), "f");
|
|
84
|
+
__classPrivateFieldSet(this, _PendingTransactionTracker_lastSeenTimestampByHash, new Map(), "f");
|
|
84
85
|
__classPrivateFieldSet(this, _PendingTransactionTracker_listener, __classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_onLatestBlock).bind(this), "f");
|
|
85
86
|
__classPrivateFieldSet(this, _PendingTransactionTracker_messenger, messenger, "f");
|
|
86
87
|
__classPrivateFieldSet(this, _PendingTransactionTracker_publishTransaction, publishTransaction, "f");
|
|
87
88
|
__classPrivateFieldSet(this, _PendingTransactionTracker_running, false, "f");
|
|
88
|
-
__classPrivateFieldSet(this, _PendingTransactionTracker_timeoutCountByHash, new Map(), "f");
|
|
89
89
|
__classPrivateFieldSet(this, _PendingTransactionTracker_transactionToForcePoll, undefined, "f");
|
|
90
90
|
__classPrivateFieldSet(this, _PendingTransactionTracker_transactionPoller, new TransactionPoller_1.TransactionPoller({
|
|
91
91
|
blockTracker,
|
|
@@ -141,7 +141,7 @@ class PendingTransactionTracker {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
exports.PendingTransactionTracker = PendingTransactionTracker;
|
|
144
|
-
_PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _PendingTransactionTracker_droppedBlockCountByHash = new WeakMap(), _PendingTransactionTracker_isTimeoutEnabled = new WeakMap(), _PendingTransactionTracker_getChainId = new WeakMap(), _PendingTransactionTracker_getEthQuery = new WeakMap(), _PendingTransactionTracker_getGlobalLock = new WeakMap(), _PendingTransactionTracker_getNetworkClientId = new WeakMap(), _PendingTransactionTracker_getTransactions = new WeakMap(), _PendingTransactionTracker_isResubmitEnabled = new WeakMap(),
|
|
144
|
+
_PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _PendingTransactionTracker_droppedBlockCountByHash = new WeakMap(), _PendingTransactionTracker_isTimeoutEnabled = new WeakMap(), _PendingTransactionTracker_getChainId = new WeakMap(), _PendingTransactionTracker_getEthQuery = new WeakMap(), _PendingTransactionTracker_getGlobalLock = new WeakMap(), _PendingTransactionTracker_getNetworkClientId = new WeakMap(), _PendingTransactionTracker_getTransactions = new WeakMap(), _PendingTransactionTracker_isResubmitEnabled = new WeakMap(), _PendingTransactionTracker_lastSeenTimestampByHash = new WeakMap(), _PendingTransactionTracker_listener = new WeakMap(), _PendingTransactionTracker_log = new WeakMap(), _PendingTransactionTracker_messenger = new WeakMap(), _PendingTransactionTracker_publishTransaction = new WeakMap(), _PendingTransactionTracker_running = new WeakMap(), _PendingTransactionTracker_transactionPoller = new WeakMap(), _PendingTransactionTracker_transactionToForcePoll = new WeakMap(), _PendingTransactionTracker_instances = new WeakSet(), _PendingTransactionTracker_start = function _PendingTransactionTracker_start(pendingTransactions) {
|
|
145
145
|
__classPrivateFieldGet(this, _PendingTransactionTracker_transactionPoller, "f").setPendingTransactions(pendingTransactions);
|
|
146
146
|
if (__classPrivateFieldGet(this, _PendingTransactionTracker_running, "f")) {
|
|
147
147
|
return;
|
|
@@ -242,10 +242,14 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
242
242
|
// Capped at ~15 minutes between retries
|
|
243
243
|
const requiredBlocksSinceFirstRetry = Math.min(MAX_RETRY_BLOCK_DISTANCE, Math.pow(2, retryCount));
|
|
244
244
|
return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;
|
|
245
|
-
},
|
|
246
|
-
|
|
245
|
+
}, _PendingTransactionTracker_cleanTransaction = function _PendingTransactionTracker_cleanTransaction(txMeta) {
|
|
246
|
+
const { hash, id } = txMeta;
|
|
247
|
+
if (__classPrivateFieldGet(this, _PendingTransactionTracker_transactionToForcePoll, "f")?.id === id) {
|
|
247
248
|
__classPrivateFieldSet(this, _PendingTransactionTracker_transactionToForcePoll, undefined, "f");
|
|
248
249
|
}
|
|
250
|
+
if (hash) {
|
|
251
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").delete(hash);
|
|
252
|
+
}
|
|
249
253
|
}, _PendingTransactionTracker_checkTransaction = async function _PendingTransactionTracker_checkTransaction(txMeta) {
|
|
250
254
|
const { hash, id, isIntentComplete, txParams: { from }, } = txMeta;
|
|
251
255
|
if (isIntentComplete) {
|
|
@@ -269,7 +273,7 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
269
273
|
const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;
|
|
270
274
|
if (isFailure) {
|
|
271
275
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction receipt has failed status');
|
|
272
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_failTransaction).call(this, txMeta, new Error('Transaction
|
|
276
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_failTransaction).call(this, txMeta, new Error('Transaction failed on-chain'));
|
|
273
277
|
return;
|
|
274
278
|
}
|
|
275
279
|
const { blockNumber, blockHash } = receipt ?? {};
|
|
@@ -300,8 +304,9 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
300
304
|
const { id } = txMeta;
|
|
301
305
|
const { blockHash } = receipt ?? {};
|
|
302
306
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction confirmed', id);
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
const isForcePollTransaction = __classPrivateFieldGet(this, _PendingTransactionTracker_transactionToForcePoll, "f")?.id === id;
|
|
308
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_cleanTransaction).call(this, txMeta);
|
|
309
|
+
if (isForcePollTransaction) {
|
|
305
310
|
this.hub.emit('transaction-confirmed', txMeta);
|
|
306
311
|
return;
|
|
307
312
|
}
|
|
@@ -321,7 +326,7 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
321
326
|
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_updateTransaction).call(this, updatedTxMeta, 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed');
|
|
322
327
|
this.hub.emit('transaction-confirmed', updatedTxMeta);
|
|
323
328
|
}, _PendingTransactionTracker_isTransactionTimeout = async function _PendingTransactionTracker_isTransactionTimeout(txMeta, nextNonce) {
|
|
324
|
-
const { chainId, hash, id: transactionId, txParams: { nonce }, } = txMeta;
|
|
329
|
+
const { chainId, hash, id: transactionId, submittedTime, txParams: { nonce }, } = txMeta;
|
|
325
330
|
if (!hash || !nonce) {
|
|
326
331
|
return false;
|
|
327
332
|
}
|
|
@@ -347,27 +352,34 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
347
352
|
try {
|
|
348
353
|
// Check if transaction exists on the network
|
|
349
354
|
const transaction = await __classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_getTransactionByHash).call(this, hash);
|
|
350
|
-
// If transaction exists,
|
|
355
|
+
// If transaction exists, record the timestamp
|
|
351
356
|
if (transaction !== null) {
|
|
352
|
-
|
|
353
|
-
__classPrivateFieldGet(this,
|
|
357
|
+
const currentTimestamp = Date.now();
|
|
358
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction found on network, recording timestamp', transactionId);
|
|
359
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").set(hash, currentTimestamp);
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
const lastSeenTimestamp = __classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").get(hash) ?? submittedTime;
|
|
363
|
+
if (lastSeenTimestamp === undefined) {
|
|
364
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction not yet seen on network and has no submitted time, skipping timeout check', transactionId);
|
|
354
365
|
return false;
|
|
355
366
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
__classPrivateFieldGet(this,
|
|
361
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Incrementing timeout counter', {
|
|
367
|
+
const { blockTime } = (0, feature_flags_1.getAcceleratedPollingParams)(chainId, __classPrivateFieldGet(this, _PendingTransactionTracker_messenger, "f"));
|
|
368
|
+
const currentTimestamp = Date.now();
|
|
369
|
+
const durationSinceLastSeen = currentTimestamp - lastSeenTimestamp;
|
|
370
|
+
const timeoutDuration = blockTime * threshold;
|
|
371
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Checking timeout duration', {
|
|
362
372
|
transactionId,
|
|
363
|
-
|
|
373
|
+
durationSinceLastSeen,
|
|
374
|
+
timeoutDuration,
|
|
364
375
|
threshold,
|
|
376
|
+
blockTime,
|
|
365
377
|
});
|
|
366
|
-
if (
|
|
378
|
+
if (durationSinceLastSeen < timeoutDuration) {
|
|
367
379
|
return false;
|
|
368
380
|
}
|
|
369
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Hit timeout threshold', transactionId);
|
|
370
|
-
__classPrivateFieldGet(this,
|
|
381
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Hit timeout duration threshold', transactionId);
|
|
382
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").delete(hash);
|
|
371
383
|
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_failTransaction).call(this, txMeta, new Error('Transaction not found on network after timeout'));
|
|
372
384
|
return true;
|
|
373
385
|
}
|
|
@@ -418,11 +430,11 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
418
430
|
}, 'PendingTransactionTracker:#warnTransaction - Warning added');
|
|
419
431
|
}, _PendingTransactionTracker_failTransaction = function _PendingTransactionTracker_failTransaction(txMeta, error) {
|
|
420
432
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction failed', txMeta.id, error);
|
|
421
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m",
|
|
433
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_cleanTransaction).call(this, txMeta);
|
|
422
434
|
this.hub.emit('transaction-failed', txMeta, error);
|
|
423
435
|
}, _PendingTransactionTracker_dropTransaction = function _PendingTransactionTracker_dropTransaction(txMeta) {
|
|
424
436
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction dropped', txMeta.id);
|
|
425
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m",
|
|
437
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_cleanTransaction).call(this, txMeta);
|
|
426
438
|
this.hub.emit('transaction-dropped', txMeta);
|
|
427
439
|
}, _PendingTransactionTracker_updateTransaction = function _PendingTransactionTracker_updateTransaction(txMeta, note) {
|
|
428
440
|
this.hub.emit('transaction-updated', txMeta, note);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingTransactionTracker.cjs","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type {\n BlockTracker,\n NetworkClientId,\n} from '@metamask/network-controller';\nimport type { Hex, Json } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { TransactionPoller } from './TransactionPoller';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport { getTimeoutAttempts } from '../utils/feature-flags';\n\n/**\n * We wait this many blocks before emitting a 'transaction-dropped' event\n * This is because we could be talking to a node that is out of sync\n */\nconst DROPPED_BLOCK_COUNT = 3;\n\nconst RECEIPT_STATUS_SUCCESS = '0x1';\nconst RECEIPT_STATUS_FAILURE = '0x0';\nconst MAX_RETRY_BLOCK_DISTANCE = 50;\n\nconst KNOWN_TRANSACTION_ERRORS = [\n 'replacement transaction underpriced',\n 'known transaction',\n 'gas price too low to replace',\n 'transaction with the same hash was already imported',\n 'gateway timeout',\n 'nonce too low',\n];\n\nconst log = createModuleLogger(projectLogger, 'pending-transactions');\n\ntype SuccessfulTransactionReceipt = TransactionReceipt & {\n blockNumber: string;\n blockHash: string;\n};\n\ntype Events = {\n 'transaction-confirmed': [txMeta: TransactionMeta];\n 'transaction-dropped': [txMeta: TransactionMeta];\n 'transaction-failed': [txMeta: TransactionMeta, error: Error];\n 'transaction-updated': [txMeta: TransactionMeta, note: string];\n};\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface PendingTransactionTrackerEventEmitter extends EventEmitter {\n on<EventName extends keyof Events>(\n eventName: EventName,\n listener: (...args: Events[EventName]) => void,\n ): this;\n\n emit<EventName extends keyof Events>(\n eventName: EventName,\n ...args: Events[EventName]\n ): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n readonly #beforeCheckPendingTransaction: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n\n readonly #droppedBlockCountByHash: Map<string, number>;\n\n readonly #isTimeoutEnabled: (transactionMeta: TransactionMeta) => boolean;\n\n readonly #getChainId: () => string;\n\n readonly #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n readonly #getGlobalLock: () => Promise<() => void>;\n\n readonly #getNetworkClientId: () => NetworkClientId;\n\n readonly #getTransactions: () => TransactionMeta[];\n\n readonly #isResubmitEnabled: () => boolean;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly #listener: any;\n\n readonly #log: debug.Debugger;\n\n readonly #messenger: TransactionControllerMessenger;\n\n readonly #publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => Promise<string>;\n\n #running: boolean;\n\n readonly #timeoutCountByHash: Map<string, number>;\n\n readonly #transactionPoller: TransactionPoller;\n\n #transactionToForcePoll: TransactionMeta | undefined;\n\n constructor({\n blockTracker,\n getChainId,\n getEthQuery,\n getGlobalLock,\n getNetworkClientId,\n getTransactions,\n isTimeoutEnabled,\n hooks,\n isResubmitEnabled,\n messenger,\n publishTransaction,\n }: {\n blockTracker: BlockTracker;\n getChainId: () => Hex;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getGlobalLock: () => Promise<() => void>;\n getNetworkClientId: () => string;\n getTransactions: () => TransactionMeta[];\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n };\n isResubmitEnabled?: () => boolean;\n isTimeoutEnabled: (transactionMeta: TransactionMeta) => boolean;\n messenger: TransactionControllerMessenger;\n publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => Promise<string>;\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getGlobalLock = getGlobalLock;\n this.#getNetworkClientId = getNetworkClientId;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? ((): boolean => true);\n this.#listener = this.#onLatestBlock.bind(this);\n this.#messenger = messenger;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#timeoutCountByHash = new Map();\n this.#transactionToForcePoll = undefined;\n\n this.#transactionPoller = new TransactionPoller({\n blockTracker,\n chainId: getChainId(),\n messenger,\n });\n\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ??\n /* istanbul ignore next */\n ((): Promise<boolean> => Promise.resolve(true));\n\n this.#isTimeoutEnabled = isTimeoutEnabled;\n\n this.#log = createModuleLogger(\n log,\n `${getChainId()}:${getNetworkClientId()}`,\n );\n }\n\n startIfPendingTransactions = (): void => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start(pendingTransactions);\n } else {\n this.stop();\n }\n };\n\n /**\n * Adds a transaction to the polling mechanism for monitoring its status.\n *\n * This method forcefully adds a single transaction to the list of transactions\n * being polled, ensuring that its status is checked, event emitted but no update is performed.\n * It overrides the default behavior by prioritizing the given transaction for polling.\n *\n * @param transactionMeta - The transaction metadata to be added for polling.\n *\n * The transaction will now be monitored for updates, such as confirmation or failure.\n */\n addTransactionToPoll(transactionMeta: TransactionMeta): void {\n this.#start([transactionMeta]);\n this.#transactionToForcePoll = transactionMeta;\n }\n\n /**\n * Force checks the network if the given transaction is confirmed and updates it's status.\n *\n * @param txMeta - The transaction to check\n */\n async forceCheckTransaction(txMeta: TransactionMeta): Promise<void> {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n this.#log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start(pendingTransactions: TransactionMeta[]): void {\n this.#transactionPoller.setPendingTransactions(pendingTransactions);\n\n if (this.#running) {\n return;\n }\n\n this.#transactionPoller.start(this.#listener);\n this.#running = true;\n\n this.#log('Started polling');\n }\n\n stop(): void {\n if (!this.#running) {\n return;\n }\n\n this.#transactionPoller.stop();\n this.#running = false;\n\n this.#log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string): Promise<void> {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n this.#log('Failed to check transactions', error);\n } finally {\n releaseLock();\n }\n\n try {\n await this.#resubmitTransactions(latestBlockNumber);\n } catch (error) {\n /* istanbul ignore next */\n this.#log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions(): Promise<void> {\n this.#log('Checking transactions');\n\n const pendingTransactions: TransactionMeta[] = [\n ...this.#getPendingTransactions(),\n ...(this.#transactionToForcePoll ? [this.#transactionToForcePoll] : []),\n ];\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to check');\n return;\n }\n\n this.#log('Found pending transactions to check', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n await Promise.all(\n pendingTransactions.map((tx) => this.#checkTransaction(tx)),\n );\n }\n\n async #resubmitTransactions(latestBlockNumber: string): Promise<void> {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n this.#log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to resubmit');\n return;\n }\n\n this.#log('Found pending transactions to resubmit', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n for (const txMeta of pendingTransactions) {\n try {\n await this.#resubmitTransaction(txMeta, latestBlockNumber);\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n /* istanbul ignore next */\n const errorMessage =\n error.value?.message?.toLowerCase() ??\n error.message?.toLowerCase() ??\n String(error);\n\n if (this.#isKnownTransactionError(errorMessage)) {\n this.#log('Ignoring known transaction error', errorMessage);\n continue;\n }\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was an error when resubmitting this transaction.',\n );\n }\n }\n }\n\n #isKnownTransactionError(errorMessage: string): boolean {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ): Promise<void> {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n if (!(await this.#beforeCheckPendingTransaction(txMeta))) {\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, txMeta);\n\n const retryCount = (txMeta.retryCount ?? 0) + 1;\n\n this.#updateTransaction(\n merge({}, txMeta, { retryCount }),\n 'PendingTransactionTracker:transaction-retry - Retry count increased',\n );\n }\n\n #isResubmitDue(txMeta: TransactionMeta, latestBlockNumber: string): boolean {\n const txMetaWithFirstRetryBlockNumber = cloneDeep(txMeta);\n\n if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {\n txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;\n\n this.#updateTransaction(\n txMetaWithFirstRetryBlockNumber,\n 'PendingTransactionTracker:#isResubmitDue - First retry block number set',\n );\n }\n\n const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;\n\n const blocksSinceFirstRetry =\n Number.parseInt(latestBlockNumber, 16) -\n Number.parseInt(firstRetryBlockNumber, 16);\n\n const retryCount = txMeta.retryCount ?? 0;\n\n // Exponential backoff to limit retries at publishing\n // Capped at ~15 minutes between retries\n const requiredBlocksSinceFirstRetry = Math.min(\n MAX_RETRY_BLOCK_DISTANCE,\n Math.pow(2, retryCount),\n );\n\n return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;\n }\n\n #cleanTransactionToForcePoll(transactionId: string): void {\n if (this.#transactionToForcePoll?.id === transactionId) {\n this.#transactionToForcePoll = undefined;\n }\n }\n\n async #checkTransaction(txMeta: TransactionMeta): Promise<void> {\n const {\n hash,\n id,\n isIntentComplete,\n txParams: { from },\n } = txMeta;\n\n if (isIntentComplete) {\n await this.#onTransactionConfirmed(txMeta);\n return;\n }\n\n if (!hash && (await this.#beforeCheckPendingTransaction(txMeta))) {\n const error = new Error(\n 'We had an error while submitting this transaction, please try again.',\n );\n\n error.name = 'NoTxHashError';\n\n this.#failTransaction(txMeta, error);\n\n return;\n }\n\n if (this.#isNonceTaken(txMeta)) {\n this.#log('Nonce already taken', id);\n this.#dropTransaction(txMeta);\n return;\n }\n\n try {\n const receipt = await this.#getTransactionReceipt(hash);\n const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;\n const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;\n\n if (isFailure) {\n this.#log('Transaction receipt has failed status');\n\n this.#failTransaction(\n txMeta,\n new Error('Transaction dropped or replaced'),\n );\n\n return;\n }\n\n const { blockNumber, blockHash } = receipt ?? {};\n\n if (isSuccess && blockNumber && blockHash) {\n await this.#onTransactionConfirmed(txMeta, {\n ...receipt,\n blockNumber,\n blockHash,\n });\n\n return;\n }\n\n this.#log('No receipt status', { hash, receipt });\n\n const nextNonceHex = await this.#getNetworkTransactionCount(from);\n const nextNonce = parseInt(nextNonceHex, 16);\n\n // Check if transaction should be failed due to no receipt\n if (!receipt && (await this.#isTransactionTimeout(txMeta, nextNonce))) {\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta, nextNonce)) {\n this.#dropTransaction(txMeta);\n }\n } catch (error) {\n this.#log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n (error as { message: string }).message,\n 'There was a problem loading this transaction.',\n );\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt?: SuccessfulTransactionReceipt,\n ): Promise<void> {\n const { id } = txMeta;\n const { blockHash } = receipt ?? {};\n\n this.#log('Transaction confirmed', id);\n\n if (this.#transactionToForcePoll) {\n this.#cleanTransactionToForcePoll(txMeta.id);\n this.hub.emit('transaction-confirmed', txMeta);\n return;\n }\n\n const updatedTxMeta = cloneDeep(txMeta);\n\n if (receipt && blockHash) {\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n }\n\n updatedTxMeta.status = TransactionStatus.confirmed;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionTimeout(\n txMeta: TransactionMeta,\n nextNonce: number,\n ): Promise<boolean> {\n const {\n chainId,\n hash,\n id: transactionId,\n txParams: { nonce },\n } = txMeta;\n\n if (!hash || !nonce) {\n return false;\n }\n\n if (!this.#isTimeoutEnabled(txMeta)) {\n this.#log('Timeout disabled for transaction', txMeta);\n return false;\n }\n\n const threshold = getTimeoutAttempts(chainId, this.#messenger);\n\n // Feature is disabled if threshold is undefined or zero\n if (threshold === undefined || threshold === 0) {\n this.#log('Timeout disabled due to threshold', { chainId, threshold });\n return false;\n }\n\n // Skip timeout if this transaction's nonce is a queued transaction with a future nonce\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber > nextNonce) {\n this.#log('Skipping timeout as queued transaction', {\n transactionNonce: nonceNumber,\n nextNonce,\n });\n return false;\n }\n\n try {\n // Check if transaction exists on the network\n const transaction = await this.#getTransactionByHash(hash);\n\n // If transaction exists, reset the counter\n if (transaction !== null) {\n this.#log(\n 'Transaction found on network, resetting timeout counter',\n transactionId,\n );\n\n this.#timeoutCountByHash.delete(hash);\n return false;\n }\n\n // Transaction doesn't exist, increment counter\n let attempts = this.#timeoutCountByHash.get(hash);\n\n attempts ??= 0;\n attempts += 1;\n this.#timeoutCountByHash.set(hash, attempts);\n\n this.#log('Incrementing timeout counter', {\n transactionId,\n attempts,\n threshold,\n });\n\n if (attempts < threshold) {\n return false;\n }\n\n this.#log('Hit timeout threshold', transactionId);\n this.#timeoutCountByHash.delete(hash);\n\n this.#failTransaction(\n txMeta,\n new Error('Transaction not found on network after timeout'),\n );\n\n return true;\n } catch (error) {\n this.#log('Failed to check transaction by hash', transactionId, error);\n return false;\n }\n }\n\n async #isTransactionDropped(\n txMeta: TransactionMeta,\n nextNonce: number,\n ): Promise<boolean> {\n const {\n hash,\n id,\n txParams: { nonce },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= nextNonce) {\n return false;\n }\n\n let droppedBlockCount = this.#droppedBlockCountByHash.get(hash);\n\n if (droppedBlockCount === undefined) {\n droppedBlockCount = 0;\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount);\n }\n\n if (droppedBlockCount < DROPPED_BLOCK_COUNT) {\n this.#log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n this.#log('Hit dropped block count', id);\n\n this.#droppedBlockCountByHash.delete(hash);\n return true;\n }\n\n #isNonceTaken(txMeta: TransactionMeta): boolean {\n const { id, txParams } = txMeta;\n\n return this.#getChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming &&\n tx.isTransfer === undefined,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getNetworkClientTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(\n txMeta: TransactionMeta,\n error: string,\n message: string,\n ): void {\n this.#updateTransaction(\n {\n ...txMeta,\n warning: { error, message },\n },\n 'PendingTransactionTracker:#warnTransaction - Warning added',\n );\n }\n\n #failTransaction(txMeta: TransactionMeta, error: Error): void {\n this.#log('Transaction failed', txMeta.id, error);\n this.#cleanTransactionToForcePoll(txMeta.id);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta): void {\n this.#log('Transaction dropped', txMeta.id);\n this.#cleanTransactionToForcePoll(txMeta.id);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string): void {\n this.hub.emit('transaction-updated', txMeta, note);\n }\n\n async #getTransactionReceipt(\n txHash?: string,\n ): Promise<TransactionReceipt | undefined> {\n return await query(this.#getEthQuery(), 'getTransactionReceipt', [txHash]);\n }\n\n async #getTransactionByHash(txHash?: string): Promise<Json> {\n return await query(this.#getEthQuery(), 'getTransactionByHash', [txHash]);\n }\n\n async #getBlockByHash(\n blockHash: string,\n includeTransactionDetails: boolean,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n return await query(this.#getEthQuery(), 'getBlockByHash', [\n blockHash,\n includeTransactionDetails,\n ]);\n }\n\n async #getNetworkTransactionCount(address: string): Promise<string> {\n return await query(this.#getEthQuery(), 'getTransactionCount', [address]);\n }\n\n #getChainTransactions(): TransactionMeta[] {\n const chainId = this.#getChainId();\n return this.#getTransactions().filter((tx) => tx.chainId === chainId);\n }\n\n #getNetworkClientTransactions(): TransactionMeta[] {\n const networkClientId = this.#getNetworkClientId();\n return this.#getTransactions().filter(\n (tx) => tx.networkClientId === networkClientId,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PendingTransactionTracker.cjs","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,iEAAmD;AAOnD,kEAAkE;AAClE,sDAAsD;AACtD,oDAAkC;AAClC,mCAA0C;AAE1C,+DAAwD;AACxD,0CAA8D;AAG9D,wCAA8D;AAC9D,8DAGgC;AAEhC;;;GAGG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,MAAM,sBAAsB,GAAG,KAAK,CAAC;AACrC,MAAM,sBAAsB,GAAG,KAAK,CAAC;AACrC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAEpC,MAAM,wBAAwB,GAAG;IAC/B,qCAAqC;IACrC,mBAAmB;IACnB,8BAA8B;IAC9B,qDAAqD;IACrD,iBAAiB;IACjB,eAAe;CAChB,CAAC;AAEF,MAAM,GAAG,GAAG,IAAA,2BAAkB,EAAC,sBAAa,EAAE,sBAAsB,CAAC,CAAC;AA6BtE,MAAa,yBAAyB;IA4CpC,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,KAAK,EACL,iBAAiB,EACjB,SAAS,EACT,kBAAkB,GAoBnB;;QAxEQ,2EAEa;QAEb,qEAA8C;QAE9C,8DAAiE;QAEjE,wDAA0B;QAE1B,yDAA8D;QAE9D,2DAA0C;QAE1C,gEAA2C;QAE3C,6DAA0C;QAE1C,+DAAkC;QAElC,qEAA8C;QAEvD,gCAAgC;QAChC,8DAA8D;QACrD,sDAAe;QAEf,iDAAqB;QAErB,uDAA2C;QAE3C,gEAGY;QAErB,qDAAkB;QAET,+DAAsC;QAE/C,oEAAqD;QAqErD,+BAA0B,GAAG,GAAS,EAAE;YACtC,MAAM,mBAAmB,GAAG,uBAAA,IAAI,+FAAwB,MAA5B,IAAI,CAA0B,CAAC;YAE3D,IAAI,mBAAmB,CAAC,MAAM,EAAE,CAAC;gBAC/B,uBAAA,IAAI,8EAAO,MAAX,IAAI,EAAQ,mBAAmB,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,CAAC;QACH,CAAC,CAAC;QA3CA,IAAI,CAAC,GAAG,GAAG,IAAI,gBAAY,EAA2C,CAAC;QAEvE,uBAAA,IAAI,sDAA4B,IAAI,GAAG,EAAE,MAAA,CAAC;QAC1C,uBAAA,IAAI,yCAAe,UAAU,MAAA,CAAC;QAC9B,uBAAA,IAAI,0CAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,4CAAkB,aAAa,MAAA,CAAC;QACpC,uBAAA,IAAI,iDAAuB,kBAAkB,MAAA,CAAC;QAC9C,uBAAA,IAAI,8CAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,gDAAsB,iBAAiB,IAAI,CAAC,GAAY,EAAE,CAAC,IAAI,CAAC,MAAA,CAAC;QACrE,uBAAA,IAAI,sDAA4B,IAAI,GAAG,EAAE,MAAA,CAAC;QAC1C,uBAAA,IAAI,uCAAa,uBAAA,IAAI,sFAAe,CAAC,IAAI,CAAC,IAAI,CAAC,MAAA,CAAC;QAChD,uBAAA,IAAI,wCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,iDAAuB,kBAAkB,MAAA,CAAC;QAC9C,uBAAA,IAAI,sCAAY,KAAK,MAAA,CAAC;QACtB,uBAAA,IAAI,qDAA2B,SAAS,MAAA,CAAC;QAEzC,uBAAA,IAAI,gDAAsB,IAAI,qCAAiB,CAAC;YAC9C,YAAY;YACZ,OAAO,EAAE,UAAU,EAAE;YACrB,SAAS;SACV,CAAC,MAAA,CAAC;QAEH,uBAAA,IAAI,4DACF,KAAK,EAAE,6BAA6B;YACpC,0BAA0B;YAC1B,CAAC,GAAqB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAA,CAAC;QAElD,uBAAA,IAAI,+CAAqB,gBAAgB,MAAA,CAAC;QAE1C,uBAAA,IAAI,kCAAQ,IAAA,2BAAkB,EAC5B,GAAG,EACH,GAAG,UAAU,EAAE,IAAI,kBAAkB,EAAE,EAAE,CAC1C,MAAA,CAAC;IACJ,CAAC;IAYD;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,eAAgC;QACnD,uBAAA,IAAI,8EAAO,MAAX,IAAI,EAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;QAC/B,uBAAA,IAAI,qDAA2B,eAAe,MAAA,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,qBAAqB,CAAC,MAAuB;QACjD,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,gDAAe,MAAnB,IAAI,CAAiB,CAAC;QAEhD,IAAI,CAAC;YACH,MAAM,uBAAA,IAAI,yFAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0BAA0B;YAC1B,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,6BAA6B,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,WAAW,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAeD,IAAI;QACF,IAAI,CAAC,uBAAA,IAAI,0CAAS,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,uBAAA,IAAI,oDAAmB,CAAC,IAAI,EAAE,CAAC;QAC/B,uBAAA,IAAI,sCAAY,KAAK,MAAA,CAAC;QAEtB,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,iBAAiB,CAAC,CAAC;IAC/B,CAAC;CAygBF;AA1rBD,8DA0rBC;moCA/hBQ,mBAAsC;IAC3C,uBAAA,IAAI,oDAAmB,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;IAEpE,IAAI,uBAAA,IAAI,0CAAS,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,uBAAA,IAAI,oDAAmB,CAAC,KAAK,CAAC,uBAAA,IAAI,2CAAU,CAAC,CAAC;IAC9C,uBAAA,IAAI,sCAAY,IAAI,MAAA,CAAC;IAErB,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,iBAAiB,CAAC,CAAC;AAC/B,CAAC,6CAaD,KAAK,mDAAgB,iBAAyB;IAC5C,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,gDAAe,MAAnB,IAAI,CAAiB,CAAC;IAEhD,IAAI,CAAC;QACH,MAAM,uBAAA,IAAI,0FAAmB,MAAvB,IAAI,CAAqB,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0BAA0B;QAC1B,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,8BAA8B,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;YAAS,CAAC;QACT,WAAW,EAAE,CAAC;IAChB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,uBAAA,IAAI,6FAAsB,MAA1B,IAAI,EAAuB,iBAAiB,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0BAA0B;QAC1B,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,iCAAiC,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;AACH,CAAC,iDAED,KAAK;IACH,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,uBAAuB,CAAC,CAAC;IAEnC,MAAM,mBAAmB,GAAsB;QAC7C,GAAG,uBAAA,IAAI,+FAAwB,MAA5B,IAAI,CAA0B;QACjC,GAAG,CAAC,uBAAA,IAAI,yDAAwB,CAAC,CAAC,CAAC,CAAC,uBAAA,IAAI,yDAAwB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACxE,CAAC;IAEF,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,CAAC;QAChC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,kCAAkC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,qCAAqC,EAAE;QAC/C,KAAK,EAAE,mBAAmB,CAAC,MAAM;QACjC,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KAC5C,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CACf,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,uBAAA,IAAI,yFAAkB,MAAtB,IAAI,EAAmB,EAAE,CAAC,CAAC,CAC5D,CAAC;AACJ,CAAC,oDAED,KAAK,0DAAuB,iBAAyB;IACnD,IAAI,CAAC,uBAAA,IAAI,oDAAmB,MAAvB,IAAI,CAAqB,IAAI,CAAC,uBAAA,IAAI,0CAAS,EAAE,CAAC;QACjD,OAAO;IACT,CAAC;IAED,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,2BAA2B,CAAC,CAAC;IAEvC,MAAM,mBAAmB,GAAG,uBAAA,IAAI,+FAAwB,MAA5B,IAAI,CAA0B,CAAC;IAE3D,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,CAAC;QAChC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,qCAAqC,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IAED,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,wCAAwC,EAAE;QAClD,KAAK,EAAE,mBAAmB,CAAC,MAAM;QACjC,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KAC5C,CAAC,CAAC;IAEH,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,uBAAA,IAAI,4FAAqB,MAAzB,IAAI,EAAsB,MAAM,EAAE,iBAAiB,CAAC,CAAC;YAC3D,gCAAgC;YAChC,8DAA8D;QAChE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,0BAA0B;YAC1B,MAAM,YAAY,GAChB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE;gBACnC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE;gBAC5B,MAAM,CAAC,KAAK,CAAC,CAAC;YAEhB,IAAI,uBAAA,IAAI,gGAAyB,MAA7B,IAAI,EAA0B,YAAY,CAAC,EAAE,CAAC;gBAChD,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,kCAAkC,EAAE,YAAY,CAAC,CAAC;gBAC5D,SAAS;YACX,CAAC;YAED,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EACF,MAAM,EACN,KAAK,CAAC,OAAO,EACb,wDAAwD,CACzD,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC,mHAEwB,YAAoB;IAC3C,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAClD,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,CAClC,CAAC;AACJ,CAAC,mDAED,KAAK,yDACH,MAAuB,EACvB,iBAAyB;IAEzB,IAAI,CAAC,uBAAA,IAAI,sFAAe,MAAnB,IAAI,EAAgB,MAAM,EAAE,iBAAiB,CAAC,EAAE,CAAC;QACpD,OAAO;IACT,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,uBAAA,IAAI,gEAA+B,MAAnC,IAAI,EAAgC,MAAM,CAAC,CAAC,EAAE,CAAC;QACzD,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,uBAAA,IAAI,8CAAa,MAAjB,IAAI,EAAc,MAAM,CAAC,eAAe,CAAC,CAAC;IAC3D,MAAM,uBAAA,IAAI,qDAAoB,MAAxB,IAAI,EAAqB,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEjD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAEhD,uBAAA,IAAI,0FAAmB,MAAvB,IAAI,EACF,IAAA,cAAK,EAAC,EAAE,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,EACjC,qEAAqE,CACtE,CAAC;AACJ,CAAC,+FAEc,MAAuB,EAAE,iBAAyB;IAC/D,MAAM,+BAA+B,GAAG,IAAA,kBAAS,EAAC,MAAM,CAAC,CAAC;IAE1D,IAAI,CAAC,+BAA+B,CAAC,qBAAqB,EAAE,CAAC;QAC3D,+BAA+B,CAAC,qBAAqB,GAAG,iBAAiB,CAAC;QAE1E,uBAAA,IAAI,0FAAmB,MAAvB,IAAI,EACF,+BAA+B,EAC/B,yEAAyE,CAC1E,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,qBAAqB,EAAE,GAAG,+BAA+B,CAAC;IAElE,MAAM,qBAAqB,GACzB,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IAE7C,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;IAE1C,qDAAqD;IACrD,wCAAwC;IACxC,MAAM,6BAA6B,GAAG,IAAI,CAAC,GAAG,CAC5C,wBAAwB,EACxB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CACxB,CAAC;IAEF,OAAO,qBAAqB,IAAI,6BAA6B,CAAC;AAChE,CAAC,qGAEiB,MAAuB;IACvC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC;IAE5B,IAAI,uBAAA,IAAI,yDAAwB,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5C,uBAAA,IAAI,qDAA2B,SAAS,MAAA,CAAC;IAC3C,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,uBAAA,IAAI,0DAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC,gDAED,KAAK,sDAAmB,MAAuB;IAC7C,MAAM,EACJ,IAAI,EACJ,EAAE,EACF,gBAAgB,EAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,GACnB,GAAG,MAAM,CAAC;IAEX,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,uBAAA,IAAI,+FAAwB,MAA5B,IAAI,EAAyB,MAAM,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,uBAAA,IAAI,gEAA+B,MAAnC,IAAI,EAAgC,MAAM,CAAC,CAAC,EAAE,CAAC;QACjE,MAAM,KAAK,GAAG,IAAI,KAAK,CACrB,sEAAsE,CACvE,CAAC;QAEF,KAAK,CAAC,IAAI,GAAG,eAAe,CAAC;QAE7B,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EAAkB,MAAM,EAAE,KAAK,CAAC,CAAC;QAErC,OAAO;IACT,CAAC;IAED,IAAI,uBAAA,IAAI,qFAAc,MAAlB,IAAI,EAAe,MAAM,CAAC,EAAE,CAAC;QAC/B,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACrC,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,uBAAA,IAAI,8FAAuB,MAA3B,IAAI,EAAwB,IAAI,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,OAAO,EAAE,MAAM,KAAK,sBAAsB,CAAC;QAC7D,MAAM,SAAS,GAAG,OAAO,EAAE,MAAM,KAAK,sBAAsB,CAAC;QAE7D,IAAI,SAAS,EAAE,CAAC;YACd,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,uCAAuC,CAAC,CAAC;YAEnD,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EAAkB,MAAM,EAAE,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;YAExE,OAAO;QACT,CAAC;QAED,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAEjD,IAAI,SAAS,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;YAC1C,MAAM,uBAAA,IAAI,+FAAwB,MAA5B,IAAI,EAAyB,MAAM,EAAE;gBACzC,GAAG,OAAO;gBACV,WAAW;gBACX,SAAS;aACV,CAAC,CAAC;YAEH,OAAO;QACT,CAAC;QAED,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,mBAAmB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAElD,MAAM,YAAY,GAAG,MAAM,uBAAA,IAAI,mGAA4B,MAAhC,IAAI,EAA6B,IAAI,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAE7C,0DAA0D;QAC1D,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,uBAAA,IAAI,6FAAsB,MAA1B,IAAI,EAAuB,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YACtE,OAAO;QACT,CAAC;QAED,IAAI,MAAM,uBAAA,IAAI,6FAAsB,MAA1B,IAAI,EAAuB,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;YACxD,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,6BAA6B,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAEpD,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EACF,MAAM,EACL,KAA6B,CAAC,OAAO,EACtC,+CAA+C,CAChD,CAAC;IACJ,CAAC;AACH,CAAC,sDAED,KAAK,4DACH,MAAuB,EACvB,OAAsC;IAEtC,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC;IACtB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAEpC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,uBAAuB,EAAE,EAAE,CAAC,CAAC;IAEvC,MAAM,sBAAsB,GAAG,uBAAA,IAAI,yDAAwB,EAAE,EAAE,KAAK,EAAE,CAAC;IAEvE,uBAAA,IAAI,yFAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;IAE/B,IAAI,sBAAsB,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,IAAA,kBAAS,EAAC,MAAM,CAAC,CAAC;IAExC,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;QACzB,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,GAChD,MAAM,uBAAA,IAAI,uFAAgB,MAApB,IAAI,EAAiB,SAAS,EAAE,KAAK,CAAC,CAAC;QAE/C,aAAa,CAAC,aAAa,GAAG,aAAa,CAAC;QAC5C,aAAa,CAAC,cAAc,GAAG,cAAc,CAAC;QAC9C,aAAa,CAAC,QAAQ,GAAG;YACvB,GAAG,aAAa,CAAC,QAAQ;YACzB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;QACF,aAAa,CAAC,SAAS,GAAG,OAAO,CAAC;QAClC,aAAa,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAC5C,CAAC;IAED,aAAa,CAAC,MAAM,GAAG,yBAAiB,CAAC,SAAS,CAAC;IAEnD,uBAAA,IAAI,0FAAmB,MAAvB,IAAI,EACF,aAAa,EACb,2EAA2E,CAC5E,CAAC;IAEF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC,oDAED,KAAK,0DACH,MAAuB,EACvB,SAAiB;IAEjB,MAAM,EACJ,OAAO,EACP,IAAI,EACJ,EAAE,EAAE,aAAa,EACjB,aAAa,EACb,QAAQ,EAAE,EAAE,KAAK,EAAE,GACpB,GAAG,MAAM,CAAC;IAEX,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,uBAAA,IAAI,mDAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,EAAE,CAAC;QACpC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,kCAAkC,EAAE,MAAM,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,IAAA,kCAAkB,EAAC,OAAO,EAAE,uBAAA,IAAI,4CAAW,CAAC,CAAC;IAE/D,wDAAwD;IACxD,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QAC/C,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,mCAAmC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uFAAuF;IACvF,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAExC,IAAI,WAAW,GAAG,SAAS,EAAE,CAAC;QAC5B,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,wCAAwC,EAAE;YAClD,gBAAgB,EAAE,WAAW;YAC7B,SAAS;SACV,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,6CAA6C;QAC7C,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,6FAAsB,MAA1B,IAAI,EAAuB,IAAI,CAAC,CAAC;QAE3D,8CAA8C;QAC9C,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEpC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EACF,mDAAmD,EACnD,aAAa,CACd,CAAC;YAEF,uBAAA,IAAI,0DAAyB,CAAC,GAAG,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,iBAAiB,GACrB,uBAAA,IAAI,0DAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC;QAE3D,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACpC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EACF,uFAAuF,EACvF,aAAa,CACd,CAAC;YAEF,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,GAAG,IAAA,2CAA2B,EAC/C,OAAO,EACP,uBAAA,IAAI,4CAAW,CAChB,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,qBAAqB,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;QACnE,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;QAE9C,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,2BAA2B,EAAE;YACrC,aAAa;YACb,qBAAqB;YACrB,eAAe;YACf,SAAS;YACT,SAAS;SACV,CAAC,CAAC;QAEH,IAAI,qBAAqB,GAAG,eAAe,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,gCAAgC,EAAE,aAAa,CAAC,CAAC;QAC3D,uBAAA,IAAI,0DAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE3C,uBAAA,IAAI,wFAAiB,MAArB,IAAI,EACF,MAAM,EACN,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAC5D,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,qCAAqC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,oDAED,KAAK,0DACH,MAAuB,EACvB,SAAiB;IAEjB,MAAM,EACJ,IAAI,EACJ,EAAE,EACF,QAAQ,EAAE,EAAE,KAAK,EAAE,GACpB,GAAG,MAAM,CAAC;IAEX,0BAA0B;IAC1B,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAExC,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,iBAAiB,GAAG,uBAAA,IAAI,0DAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEhE,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,iBAAiB,GAAG,CAAC,CAAC;QACtB,uBAAA,IAAI,0DAAyB,CAAC,GAAG,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,iBAAiB,GAAG,mBAAmB,EAAE,CAAC;QAC5C,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,kCAAkC,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACzE,uBAAA,IAAI,0DAAyB,CAAC,GAAG,CAAC,IAAI,EAAE,iBAAiB,GAAG,CAAC,CAAC,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,yBAAyB,EAAE,EAAE,CAAC,CAAC;IAEzC,uBAAA,IAAI,0DAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC,6FAEa,MAAuB;IACnC,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAEhC,OAAO,uBAAA,IAAI,6FAAsB,MAA1B,IAAI,CAAwB,CAAC,IAAI,CACtC,CAAC,EAAE,EAAE,EAAE,CACL,EAAE,CAAC,EAAE,KAAK,EAAE;QACZ,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;QAClC,EAAE,CAAC,MAAM,KAAK,yBAAiB,CAAC,SAAS;QACzC,EAAE,CAAC,QAAQ,CAAC,KAAK;QACjB,EAAE,CAAC,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK;QACpC,EAAE,CAAC,IAAI,KAAK,uBAAe,CAAC,QAAQ;QACpC,EAAE,CAAC,UAAU,KAAK,SAAS,CAC9B,CAAC;AACJ,CAAC;IAGC,OAAO,uBAAA,IAAI,qGAA8B,MAAlC,IAAI,CAAgC,CAAC,MAAM,CAChD,CAAC,EAAE,EAAE,EAAE,CACL,EAAE,CAAC,MAAM,KAAK,yBAAiB,CAAC,SAAS;QACzC,CAAC,EAAE,CAAC,oBAAoB;QACxB,CAAC,EAAE,CAAC,eAAe,CACtB,CAAC;AACJ,CAAC,mGAGC,MAAuB,EACvB,KAAa,EACb,OAAe;IAEf,uBAAA,IAAI,0FAAmB,MAAvB,IAAI,EACF;QACE,GAAG,MAAM;QACT,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;KAC5B,EACD,4DAA4D,CAC7D,CAAC;AACJ,CAAC,mGAEgB,MAAuB,EAAE,KAAY;IACpD,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,oBAAoB,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAClD,uBAAA,IAAI,yFAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACrD,CAAC,mGAEgB,MAAuB;IACtC,uBAAA,IAAI,sCAAK,MAAT,IAAI,EAAM,qBAAqB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC5C,uBAAA,IAAI,yFAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC,uGAEkB,MAAuB,EAAE,IAAY;IACtD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACrD,CAAC,qDAED,KAAK,2DACH,MAAe;IAEf,OAAO,MAAM,IAAA,wBAAK,EAAC,uBAAA,IAAI,8CAAa,MAAjB,IAAI,CAAe,EAAE,uBAAuB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7E,CAAC,oDAED,KAAK,0DAAuB,MAAe;IACzC,OAAO,MAAM,IAAA,wBAAK,EAAC,uBAAA,IAAI,8CAAa,MAAjB,IAAI,CAAe,EAAE,sBAAsB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5E,CAAC,8CAED,KAAK,oDACH,SAAiB,EACjB,yBAAkC;IAIlC,OAAO,MAAM,IAAA,wBAAK,EAAC,uBAAA,IAAI,8CAAa,MAAjB,IAAI,CAAe,EAAE,gBAAgB,EAAE;QACxD,SAAS;QACT,yBAAyB;KAC1B,CAAC,CAAC;AACL,CAAC,0DAED,KAAK,gEAA6B,OAAe;IAC/C,OAAO,MAAM,IAAA,wBAAK,EAAC,uBAAA,IAAI,8CAAa,MAAjB,IAAI,CAAe,EAAE,qBAAqB,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5E,CAAC;IAGC,MAAM,OAAO,GAAG,uBAAA,IAAI,6CAAY,MAAhB,IAAI,CAAc,CAAC;IACnC,OAAO,uBAAA,IAAI,kDAAiB,MAArB,IAAI,CAAmB,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;AACxE,CAAC;IAGC,MAAM,eAAe,GAAG,uBAAA,IAAI,qDAAoB,MAAxB,IAAI,CAAsB,CAAC;IACnD,OAAO,uBAAA,IAAI,kDAAiB,MAArB,IAAI,CAAmB,CAAC,MAAM,CACnC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,eAAe,KAAK,eAAe,CAC/C,CAAC;AACJ,CAAC","sourcesContent":["import { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type {\n BlockTracker,\n NetworkClientId,\n} from '@metamask/network-controller';\nimport type { Hex, Json } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { TransactionPoller } from './TransactionPoller';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n getAcceleratedPollingParams,\n getTimeoutAttempts,\n} from '../utils/feature-flags';\n\n/**\n * We wait this many blocks before emitting a 'transaction-dropped' event\n * This is because we could be talking to a node that is out of sync\n */\nconst DROPPED_BLOCK_COUNT = 3;\n\nconst RECEIPT_STATUS_SUCCESS = '0x1';\nconst RECEIPT_STATUS_FAILURE = '0x0';\nconst MAX_RETRY_BLOCK_DISTANCE = 50;\n\nconst KNOWN_TRANSACTION_ERRORS = [\n 'replacement transaction underpriced',\n 'known transaction',\n 'gas price too low to replace',\n 'transaction with the same hash was already imported',\n 'gateway timeout',\n 'nonce too low',\n];\n\nconst log = createModuleLogger(projectLogger, 'pending-transactions');\n\ntype SuccessfulTransactionReceipt = TransactionReceipt & {\n blockNumber: string;\n blockHash: string;\n};\n\ntype Events = {\n 'transaction-confirmed': [txMeta: TransactionMeta];\n 'transaction-dropped': [txMeta: TransactionMeta];\n 'transaction-failed': [txMeta: TransactionMeta, error: Error];\n 'transaction-updated': [txMeta: TransactionMeta, note: string];\n};\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface PendingTransactionTrackerEventEmitter extends EventEmitter {\n on<EventName extends keyof Events>(\n eventName: EventName,\n listener: (...args: Events[EventName]) => void,\n ): this;\n\n emit<EventName extends keyof Events>(\n eventName: EventName,\n ...args: Events[EventName]\n ): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n readonly #beforeCheckPendingTransaction: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n\n readonly #droppedBlockCountByHash: Map<string, number>;\n\n readonly #isTimeoutEnabled: (transactionMeta: TransactionMeta) => boolean;\n\n readonly #getChainId: () => string;\n\n readonly #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n readonly #getGlobalLock: () => Promise<() => void>;\n\n readonly #getNetworkClientId: () => NetworkClientId;\n\n readonly #getTransactions: () => TransactionMeta[];\n\n readonly #isResubmitEnabled: () => boolean;\n\n readonly #lastSeenTimestampByHash: Map<string, number>;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly #listener: any;\n\n readonly #log: debug.Debugger;\n\n readonly #messenger: TransactionControllerMessenger;\n\n readonly #publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => Promise<string>;\n\n #running: boolean;\n\n readonly #transactionPoller: TransactionPoller;\n\n #transactionToForcePoll: TransactionMeta | undefined;\n\n constructor({\n blockTracker,\n getChainId,\n getEthQuery,\n getGlobalLock,\n getNetworkClientId,\n getTransactions,\n isTimeoutEnabled,\n hooks,\n isResubmitEnabled,\n messenger,\n publishTransaction,\n }: {\n blockTracker: BlockTracker;\n getChainId: () => Hex;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getGlobalLock: () => Promise<() => void>;\n getNetworkClientId: () => string;\n getTransactions: () => TransactionMeta[];\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n };\n isResubmitEnabled?: () => boolean;\n isTimeoutEnabled: (transactionMeta: TransactionMeta) => boolean;\n messenger: TransactionControllerMessenger;\n publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => Promise<string>;\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getGlobalLock = getGlobalLock;\n this.#getNetworkClientId = getNetworkClientId;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? ((): boolean => true);\n this.#lastSeenTimestampByHash = new Map();\n this.#listener = this.#onLatestBlock.bind(this);\n this.#messenger = messenger;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#transactionToForcePoll = undefined;\n\n this.#transactionPoller = new TransactionPoller({\n blockTracker,\n chainId: getChainId(),\n messenger,\n });\n\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ??\n /* istanbul ignore next */\n ((): Promise<boolean> => Promise.resolve(true));\n\n this.#isTimeoutEnabled = isTimeoutEnabled;\n\n this.#log = createModuleLogger(\n log,\n `${getChainId()}:${getNetworkClientId()}`,\n );\n }\n\n startIfPendingTransactions = (): void => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start(pendingTransactions);\n } else {\n this.stop();\n }\n };\n\n /**\n * Adds a transaction to the polling mechanism for monitoring its status.\n *\n * This method forcefully adds a single transaction to the list of transactions\n * being polled, ensuring that its status is checked, event emitted but no update is performed.\n * It overrides the default behavior by prioritizing the given transaction for polling.\n *\n * @param transactionMeta - The transaction metadata to be added for polling.\n *\n * The transaction will now be monitored for updates, such as confirmation or failure.\n */\n addTransactionToPoll(transactionMeta: TransactionMeta): void {\n this.#start([transactionMeta]);\n this.#transactionToForcePoll = transactionMeta;\n }\n\n /**\n * Force checks the network if the given transaction is confirmed and updates it's status.\n *\n * @param txMeta - The transaction to check\n */\n async forceCheckTransaction(txMeta: TransactionMeta): Promise<void> {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n this.#log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start(pendingTransactions: TransactionMeta[]): void {\n this.#transactionPoller.setPendingTransactions(pendingTransactions);\n\n if (this.#running) {\n return;\n }\n\n this.#transactionPoller.start(this.#listener);\n this.#running = true;\n\n this.#log('Started polling');\n }\n\n stop(): void {\n if (!this.#running) {\n return;\n }\n\n this.#transactionPoller.stop();\n this.#running = false;\n\n this.#log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string): Promise<void> {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n this.#log('Failed to check transactions', error);\n } finally {\n releaseLock();\n }\n\n try {\n await this.#resubmitTransactions(latestBlockNumber);\n } catch (error) {\n /* istanbul ignore next */\n this.#log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions(): Promise<void> {\n this.#log('Checking transactions');\n\n const pendingTransactions: TransactionMeta[] = [\n ...this.#getPendingTransactions(),\n ...(this.#transactionToForcePoll ? [this.#transactionToForcePoll] : []),\n ];\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to check');\n return;\n }\n\n this.#log('Found pending transactions to check', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n await Promise.all(\n pendingTransactions.map((tx) => this.#checkTransaction(tx)),\n );\n }\n\n async #resubmitTransactions(latestBlockNumber: string): Promise<void> {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n this.#log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to resubmit');\n return;\n }\n\n this.#log('Found pending transactions to resubmit', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n for (const txMeta of pendingTransactions) {\n try {\n await this.#resubmitTransaction(txMeta, latestBlockNumber);\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n /* istanbul ignore next */\n const errorMessage =\n error.value?.message?.toLowerCase() ??\n error.message?.toLowerCase() ??\n String(error);\n\n if (this.#isKnownTransactionError(errorMessage)) {\n this.#log('Ignoring known transaction error', errorMessage);\n continue;\n }\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was an error when resubmitting this transaction.',\n );\n }\n }\n }\n\n #isKnownTransactionError(errorMessage: string): boolean {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ): Promise<void> {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n if (!(await this.#beforeCheckPendingTransaction(txMeta))) {\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, txMeta);\n\n const retryCount = (txMeta.retryCount ?? 0) + 1;\n\n this.#updateTransaction(\n merge({}, txMeta, { retryCount }),\n 'PendingTransactionTracker:transaction-retry - Retry count increased',\n );\n }\n\n #isResubmitDue(txMeta: TransactionMeta, latestBlockNumber: string): boolean {\n const txMetaWithFirstRetryBlockNumber = cloneDeep(txMeta);\n\n if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {\n txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;\n\n this.#updateTransaction(\n txMetaWithFirstRetryBlockNumber,\n 'PendingTransactionTracker:#isResubmitDue - First retry block number set',\n );\n }\n\n const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;\n\n const blocksSinceFirstRetry =\n Number.parseInt(latestBlockNumber, 16) -\n Number.parseInt(firstRetryBlockNumber, 16);\n\n const retryCount = txMeta.retryCount ?? 0;\n\n // Exponential backoff to limit retries at publishing\n // Capped at ~15 minutes between retries\n const requiredBlocksSinceFirstRetry = Math.min(\n MAX_RETRY_BLOCK_DISTANCE,\n Math.pow(2, retryCount),\n );\n\n return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;\n }\n\n #cleanTransaction(txMeta: TransactionMeta): void {\n const { hash, id } = txMeta;\n\n if (this.#transactionToForcePoll?.id === id) {\n this.#transactionToForcePoll = undefined;\n }\n\n if (hash) {\n this.#lastSeenTimestampByHash.delete(hash);\n }\n }\n\n async #checkTransaction(txMeta: TransactionMeta): Promise<void> {\n const {\n hash,\n id,\n isIntentComplete,\n txParams: { from },\n } = txMeta;\n\n if (isIntentComplete) {\n await this.#onTransactionConfirmed(txMeta);\n return;\n }\n\n if (!hash && (await this.#beforeCheckPendingTransaction(txMeta))) {\n const error = new Error(\n 'We had an error while submitting this transaction, please try again.',\n );\n\n error.name = 'NoTxHashError';\n\n this.#failTransaction(txMeta, error);\n\n return;\n }\n\n if (this.#isNonceTaken(txMeta)) {\n this.#log('Nonce already taken', id);\n this.#dropTransaction(txMeta);\n return;\n }\n\n try {\n const receipt = await this.#getTransactionReceipt(hash);\n const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;\n const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;\n\n if (isFailure) {\n this.#log('Transaction receipt has failed status');\n\n this.#failTransaction(txMeta, new Error('Transaction failed on-chain'));\n\n return;\n }\n\n const { blockNumber, blockHash } = receipt ?? {};\n\n if (isSuccess && blockNumber && blockHash) {\n await this.#onTransactionConfirmed(txMeta, {\n ...receipt,\n blockNumber,\n blockHash,\n });\n\n return;\n }\n\n this.#log('No receipt status', { hash, receipt });\n\n const nextNonceHex = await this.#getNetworkTransactionCount(from);\n const nextNonce = parseInt(nextNonceHex, 16);\n\n // Check if transaction should be failed due to no receipt\n if (!receipt && (await this.#isTransactionTimeout(txMeta, nextNonce))) {\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta, nextNonce)) {\n this.#dropTransaction(txMeta);\n }\n } catch (error) {\n this.#log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n (error as { message: string }).message,\n 'There was a problem loading this transaction.',\n );\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt?: SuccessfulTransactionReceipt,\n ): Promise<void> {\n const { id } = txMeta;\n const { blockHash } = receipt ?? {};\n\n this.#log('Transaction confirmed', id);\n\n const isForcePollTransaction = this.#transactionToForcePoll?.id === id;\n\n this.#cleanTransaction(txMeta);\n\n if (isForcePollTransaction) {\n this.hub.emit('transaction-confirmed', txMeta);\n return;\n }\n\n const updatedTxMeta = cloneDeep(txMeta);\n\n if (receipt && blockHash) {\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n }\n\n updatedTxMeta.status = TransactionStatus.confirmed;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionTimeout(\n txMeta: TransactionMeta,\n nextNonce: number,\n ): Promise<boolean> {\n const {\n chainId,\n hash,\n id: transactionId,\n submittedTime,\n txParams: { nonce },\n } = txMeta;\n\n if (!hash || !nonce) {\n return false;\n }\n\n if (!this.#isTimeoutEnabled(txMeta)) {\n this.#log('Timeout disabled for transaction', txMeta);\n return false;\n }\n\n const threshold = getTimeoutAttempts(chainId, this.#messenger);\n\n // Feature is disabled if threshold is undefined or zero\n if (threshold === undefined || threshold === 0) {\n this.#log('Timeout disabled due to threshold', { chainId, threshold });\n return false;\n }\n\n // Skip timeout if this transaction's nonce is a queued transaction with a future nonce\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber > nextNonce) {\n this.#log('Skipping timeout as queued transaction', {\n transactionNonce: nonceNumber,\n nextNonce,\n });\n return false;\n }\n\n try {\n // Check if transaction exists on the network\n const transaction = await this.#getTransactionByHash(hash);\n\n // If transaction exists, record the timestamp\n if (transaction !== null) {\n const currentTimestamp = Date.now();\n\n this.#log(\n 'Transaction found on network, recording timestamp',\n transactionId,\n );\n\n this.#lastSeenTimestampByHash.set(hash, currentTimestamp);\n return false;\n }\n\n const lastSeenTimestamp =\n this.#lastSeenTimestampByHash.get(hash) ?? submittedTime;\n\n if (lastSeenTimestamp === undefined) {\n this.#log(\n 'Transaction not yet seen on network and has no submitted time, skipping timeout check',\n transactionId,\n );\n\n return false;\n }\n\n const { blockTime } = getAcceleratedPollingParams(\n chainId,\n this.#messenger,\n );\n\n const currentTimestamp = Date.now();\n const durationSinceLastSeen = currentTimestamp - lastSeenTimestamp;\n const timeoutDuration = blockTime * threshold;\n\n this.#log('Checking timeout duration', {\n transactionId,\n durationSinceLastSeen,\n timeoutDuration,\n threshold,\n blockTime,\n });\n\n if (durationSinceLastSeen < timeoutDuration) {\n return false;\n }\n\n this.#log('Hit timeout duration threshold', transactionId);\n this.#lastSeenTimestampByHash.delete(hash);\n\n this.#failTransaction(\n txMeta,\n new Error('Transaction not found on network after timeout'),\n );\n\n return true;\n } catch (error) {\n this.#log('Failed to check transaction by hash', transactionId, error);\n return false;\n }\n }\n\n async #isTransactionDropped(\n txMeta: TransactionMeta,\n nextNonce: number,\n ): Promise<boolean> {\n const {\n hash,\n id,\n txParams: { nonce },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= nextNonce) {\n return false;\n }\n\n let droppedBlockCount = this.#droppedBlockCountByHash.get(hash);\n\n if (droppedBlockCount === undefined) {\n droppedBlockCount = 0;\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount);\n }\n\n if (droppedBlockCount < DROPPED_BLOCK_COUNT) {\n this.#log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n this.#log('Hit dropped block count', id);\n\n this.#droppedBlockCountByHash.delete(hash);\n return true;\n }\n\n #isNonceTaken(txMeta: TransactionMeta): boolean {\n const { id, txParams } = txMeta;\n\n return this.#getChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming &&\n tx.isTransfer === undefined,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getNetworkClientTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(\n txMeta: TransactionMeta,\n error: string,\n message: string,\n ): void {\n this.#updateTransaction(\n {\n ...txMeta,\n warning: { error, message },\n },\n 'PendingTransactionTracker:#warnTransaction - Warning added',\n );\n }\n\n #failTransaction(txMeta: TransactionMeta, error: Error): void {\n this.#log('Transaction failed', txMeta.id, error);\n this.#cleanTransaction(txMeta);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta): void {\n this.#log('Transaction dropped', txMeta.id);\n this.#cleanTransaction(txMeta);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string): void {\n this.hub.emit('transaction-updated', txMeta, note);\n }\n\n async #getTransactionReceipt(\n txHash?: string,\n ): Promise<TransactionReceipt | undefined> {\n return await query(this.#getEthQuery(), 'getTransactionReceipt', [txHash]);\n }\n\n async #getTransactionByHash(txHash?: string): Promise<Json> {\n return await query(this.#getEthQuery(), 'getTransactionByHash', [txHash]);\n }\n\n async #getBlockByHash(\n blockHash: string,\n includeTransactionDetails: boolean,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n return await query(this.#getEthQuery(), 'getBlockByHash', [\n blockHash,\n includeTransactionDetails,\n ]);\n }\n\n async #getNetworkTransactionCount(address: string): Promise<string> {\n return await query(this.#getEthQuery(), 'getTransactionCount', [address]);\n }\n\n #getChainTransactions(): TransactionMeta[] {\n const chainId = this.#getChainId();\n return this.#getTransactions().filter((tx) => tx.chainId === chainId);\n }\n\n #getNetworkClientTransactions(): TransactionMeta[] {\n const networkClientId = this.#getNetworkClientId();\n return this.#getTransactions().filter(\n (tx) => tx.networkClientId === networkClientId,\n );\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingTransactionTracker.d.cts","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,QAAQ,4BAA4B;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,qCAAqC;AACtC,OAAO,KAAK,EAAE,GAAG,EAAQ,wBAAwB;AAGjD,OAAO,YAAY,eAAe;AAKlC,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAsB,qBAAiB;
|
|
1
|
+
{"version":3,"file":"PendingTransactionTracker.d.cts","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,QAAQ,4BAA4B;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,qCAAqC;AACtC,OAAO,KAAK,EAAE,GAAG,EAAQ,wBAAwB;AAGjD,OAAO,YAAY,eAAe;AAKlC,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAsB,qBAAiB;AAiCpE,KAAK,MAAM,GAAG;IACZ,uBAAuB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnD,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACjD,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9D,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;CAChE,CAAC;AAKF,MAAM,WAAW,qCAAsC,SAAQ,YAAY;IACzE,EAAE,CAAC,SAAS,SAAS,MAAM,MAAM,EAC/B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,IAAI,GAC7C,IAAI,CAAC;IAER,IAAI,CAAC,SAAS,SAAS,MAAM,MAAM,EACjC,SAAS,EAAE,SAAS,EACpB,GAAG,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,GACzB,OAAO,CAAC;CACZ;AAED,qBAAa,yBAAyB;;IACpC,GAAG,EAAE,qCAAqC,CAAC;gBA2C/B,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,KAAK,EACL,iBAAiB,EACjB,SAAS,EACT,kBAAkB,GACnB,EAAE;QACD,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,EAAE,MAAM,GAAG,CAAC;QACtB,WAAW,EAAE,CAAC,eAAe,CAAC,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC7D,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QACzC,kBAAkB,EAAE,MAAM,MAAM,CAAC;QACjC,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,KAAK,CAAC,EAAE;YACN,6BAA6B,CAAC,EAAE,CAC9B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;SACvB,CAAC;QACF,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;QAClC,gBAAgB,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,OAAO,CAAC;QAChE,SAAS,EAAE,8BAA8B,CAAC;QAC1C,kBAAkB,EAAE,CAClB,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,MAAM,CAAC,CAAC;KACtB;IAoCD,0BAA0B,QAAO,IAAI,CAQnC;IAEF;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;IAK5D;;;;OAIG;IACG,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BnE,IAAI,IAAI,IAAI;CAkhBb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingTransactionTracker.d.mts","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,QAAQ,4BAA4B;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,qCAAqC;AACtC,OAAO,KAAK,EAAE,GAAG,EAAQ,wBAAwB;AAGjD,OAAO,YAAY,eAAe;AAKlC,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAsB,qBAAiB;
|
|
1
|
+
{"version":3,"file":"PendingTransactionTracker.d.mts","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,QAAQ,4BAA4B;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,qCAAqC;AACtC,OAAO,KAAK,EAAE,GAAG,EAAQ,wBAAwB;AAGjD,OAAO,YAAY,eAAe;AAKlC,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAsB,qBAAiB;AAiCpE,KAAK,MAAM,GAAG;IACZ,uBAAuB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnD,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACjD,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9D,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;CAChE,CAAC;AAKF,MAAM,WAAW,qCAAsC,SAAQ,YAAY;IACzE,EAAE,CAAC,SAAS,SAAS,MAAM,MAAM,EAC/B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,IAAI,GAC7C,IAAI,CAAC;IAER,IAAI,CAAC,SAAS,SAAS,MAAM,MAAM,EACjC,SAAS,EAAE,SAAS,EACpB,GAAG,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,GACzB,OAAO,CAAC;CACZ;AAED,qBAAa,yBAAyB;;IACpC,GAAG,EAAE,qCAAqC,CAAC;gBA2C/B,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,KAAK,EACL,iBAAiB,EACjB,SAAS,EACT,kBAAkB,GACnB,EAAE;QACD,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,EAAE,MAAM,GAAG,CAAC;QACtB,WAAW,EAAE,CAAC,eAAe,CAAC,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC7D,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QACzC,kBAAkB,EAAE,MAAM,MAAM,CAAC;QACjC,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,KAAK,CAAC,EAAE;YACN,6BAA6B,CAAC,EAAE,CAC9B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;SACvB,CAAC;QACF,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;QAClC,gBAAgB,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,OAAO,CAAC;QAChE,SAAS,EAAE,8BAA8B,CAAC;QAC1C,kBAAkB,EAAE,CAClB,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,MAAM,CAAC,CAAC;KACtB;IAoCD,0BAA0B,QAAO,IAAI,CAQnC;IAEF;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;IAK5D;;;;OAIG;IACG,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BnE,IAAI,IAAI,IAAI;CAkhBb"}
|
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _PendingTransactionTracker_instances, _PendingTransactionTracker_beforeCheckPendingTransaction, _PendingTransactionTracker_droppedBlockCountByHash, _PendingTransactionTracker_isTimeoutEnabled, _PendingTransactionTracker_getChainId, _PendingTransactionTracker_getEthQuery, _PendingTransactionTracker_getGlobalLock, _PendingTransactionTracker_getNetworkClientId, _PendingTransactionTracker_getTransactions, _PendingTransactionTracker_isResubmitEnabled, _PendingTransactionTracker_listener, _PendingTransactionTracker_log, _PendingTransactionTracker_messenger, _PendingTransactionTracker_publishTransaction, _PendingTransactionTracker_running,
|
|
12
|
+
var _PendingTransactionTracker_instances, _PendingTransactionTracker_beforeCheckPendingTransaction, _PendingTransactionTracker_droppedBlockCountByHash, _PendingTransactionTracker_isTimeoutEnabled, _PendingTransactionTracker_getChainId, _PendingTransactionTracker_getEthQuery, _PendingTransactionTracker_getGlobalLock, _PendingTransactionTracker_getNetworkClientId, _PendingTransactionTracker_getTransactions, _PendingTransactionTracker_isResubmitEnabled, _PendingTransactionTracker_lastSeenTimestampByHash, _PendingTransactionTracker_listener, _PendingTransactionTracker_log, _PendingTransactionTracker_messenger, _PendingTransactionTracker_publishTransaction, _PendingTransactionTracker_running, _PendingTransactionTracker_transactionPoller, _PendingTransactionTracker_transactionToForcePoll, _PendingTransactionTracker_start, _PendingTransactionTracker_onLatestBlock, _PendingTransactionTracker_checkTransactions, _PendingTransactionTracker_resubmitTransactions, _PendingTransactionTracker_isKnownTransactionError, _PendingTransactionTracker_resubmitTransaction, _PendingTransactionTracker_isResubmitDue, _PendingTransactionTracker_cleanTransaction, _PendingTransactionTracker_checkTransaction, _PendingTransactionTracker_onTransactionConfirmed, _PendingTransactionTracker_isTransactionTimeout, _PendingTransactionTracker_isTransactionDropped, _PendingTransactionTracker_isNonceTaken, _PendingTransactionTracker_getPendingTransactions, _PendingTransactionTracker_warnTransaction, _PendingTransactionTracker_failTransaction, _PendingTransactionTracker_dropTransaction, _PendingTransactionTracker_updateTransaction, _PendingTransactionTracker_getTransactionReceipt, _PendingTransactionTracker_getTransactionByHash, _PendingTransactionTracker_getBlockByHash, _PendingTransactionTracker_getNetworkTransactionCount, _PendingTransactionTracker_getChainTransactions, _PendingTransactionTracker_getNetworkClientTransactions;
|
|
13
13
|
import { query } from "@metamask/controller-utils";
|
|
14
14
|
// This package purposefully relies on Node's EventEmitter module.
|
|
15
15
|
// eslint-disable-next-line import-x/no-nodejs-modules
|
|
@@ -19,7 +19,7 @@ const { cloneDeep, merge } = $lodash;
|
|
|
19
19
|
import { TransactionPoller } from "./TransactionPoller.mjs";
|
|
20
20
|
import { createModuleLogger, projectLogger } from "../logger.mjs";
|
|
21
21
|
import { TransactionStatus, TransactionType } from "../types.mjs";
|
|
22
|
-
import { getTimeoutAttempts } from "../utils/feature-flags.mjs";
|
|
22
|
+
import { getAcceleratedPollingParams, getTimeoutAttempts } from "../utils/feature-flags.mjs";
|
|
23
23
|
/**
|
|
24
24
|
* We wait this many blocks before emitting a 'transaction-dropped' event
|
|
25
25
|
* This is because we could be talking to a node that is out of sync
|
|
@@ -49,6 +49,7 @@ export class PendingTransactionTracker {
|
|
|
49
49
|
_PendingTransactionTracker_getNetworkClientId.set(this, void 0);
|
|
50
50
|
_PendingTransactionTracker_getTransactions.set(this, void 0);
|
|
51
51
|
_PendingTransactionTracker_isResubmitEnabled.set(this, void 0);
|
|
52
|
+
_PendingTransactionTracker_lastSeenTimestampByHash.set(this, void 0);
|
|
52
53
|
// TODO: Replace `any` with type
|
|
53
54
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
55
|
_PendingTransactionTracker_listener.set(this, void 0);
|
|
@@ -56,7 +57,6 @@ export class PendingTransactionTracker {
|
|
|
56
57
|
_PendingTransactionTracker_messenger.set(this, void 0);
|
|
57
58
|
_PendingTransactionTracker_publishTransaction.set(this, void 0);
|
|
58
59
|
_PendingTransactionTracker_running.set(this, void 0);
|
|
59
|
-
_PendingTransactionTracker_timeoutCountByHash.set(this, void 0);
|
|
60
60
|
_PendingTransactionTracker_transactionPoller.set(this, void 0);
|
|
61
61
|
_PendingTransactionTracker_transactionToForcePoll.set(this, void 0);
|
|
62
62
|
this.startIfPendingTransactions = () => {
|
|
@@ -76,11 +76,11 @@ export class PendingTransactionTracker {
|
|
|
76
76
|
__classPrivateFieldSet(this, _PendingTransactionTracker_getNetworkClientId, getNetworkClientId, "f");
|
|
77
77
|
__classPrivateFieldSet(this, _PendingTransactionTracker_getTransactions, getTransactions, "f");
|
|
78
78
|
__classPrivateFieldSet(this, _PendingTransactionTracker_isResubmitEnabled, isResubmitEnabled ?? (() => true), "f");
|
|
79
|
+
__classPrivateFieldSet(this, _PendingTransactionTracker_lastSeenTimestampByHash, new Map(), "f");
|
|
79
80
|
__classPrivateFieldSet(this, _PendingTransactionTracker_listener, __classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_onLatestBlock).bind(this), "f");
|
|
80
81
|
__classPrivateFieldSet(this, _PendingTransactionTracker_messenger, messenger, "f");
|
|
81
82
|
__classPrivateFieldSet(this, _PendingTransactionTracker_publishTransaction, publishTransaction, "f");
|
|
82
83
|
__classPrivateFieldSet(this, _PendingTransactionTracker_running, false, "f");
|
|
83
|
-
__classPrivateFieldSet(this, _PendingTransactionTracker_timeoutCountByHash, new Map(), "f");
|
|
84
84
|
__classPrivateFieldSet(this, _PendingTransactionTracker_transactionToForcePoll, undefined, "f");
|
|
85
85
|
__classPrivateFieldSet(this, _PendingTransactionTracker_transactionPoller, new TransactionPoller({
|
|
86
86
|
blockTracker,
|
|
@@ -135,7 +135,7 @@ export class PendingTransactionTracker {
|
|
|
135
135
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Stopped polling');
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
_PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _PendingTransactionTracker_droppedBlockCountByHash = new WeakMap(), _PendingTransactionTracker_isTimeoutEnabled = new WeakMap(), _PendingTransactionTracker_getChainId = new WeakMap(), _PendingTransactionTracker_getEthQuery = new WeakMap(), _PendingTransactionTracker_getGlobalLock = new WeakMap(), _PendingTransactionTracker_getNetworkClientId = new WeakMap(), _PendingTransactionTracker_getTransactions = new WeakMap(), _PendingTransactionTracker_isResubmitEnabled = new WeakMap(),
|
|
138
|
+
_PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _PendingTransactionTracker_droppedBlockCountByHash = new WeakMap(), _PendingTransactionTracker_isTimeoutEnabled = new WeakMap(), _PendingTransactionTracker_getChainId = new WeakMap(), _PendingTransactionTracker_getEthQuery = new WeakMap(), _PendingTransactionTracker_getGlobalLock = new WeakMap(), _PendingTransactionTracker_getNetworkClientId = new WeakMap(), _PendingTransactionTracker_getTransactions = new WeakMap(), _PendingTransactionTracker_isResubmitEnabled = new WeakMap(), _PendingTransactionTracker_lastSeenTimestampByHash = new WeakMap(), _PendingTransactionTracker_listener = new WeakMap(), _PendingTransactionTracker_log = new WeakMap(), _PendingTransactionTracker_messenger = new WeakMap(), _PendingTransactionTracker_publishTransaction = new WeakMap(), _PendingTransactionTracker_running = new WeakMap(), _PendingTransactionTracker_transactionPoller = new WeakMap(), _PendingTransactionTracker_transactionToForcePoll = new WeakMap(), _PendingTransactionTracker_instances = new WeakSet(), _PendingTransactionTracker_start = function _PendingTransactionTracker_start(pendingTransactions) {
|
|
139
139
|
__classPrivateFieldGet(this, _PendingTransactionTracker_transactionPoller, "f").setPendingTransactions(pendingTransactions);
|
|
140
140
|
if (__classPrivateFieldGet(this, _PendingTransactionTracker_running, "f")) {
|
|
141
141
|
return;
|
|
@@ -236,10 +236,14 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
236
236
|
// Capped at ~15 minutes between retries
|
|
237
237
|
const requiredBlocksSinceFirstRetry = Math.min(MAX_RETRY_BLOCK_DISTANCE, Math.pow(2, retryCount));
|
|
238
238
|
return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;
|
|
239
|
-
},
|
|
240
|
-
|
|
239
|
+
}, _PendingTransactionTracker_cleanTransaction = function _PendingTransactionTracker_cleanTransaction(txMeta) {
|
|
240
|
+
const { hash, id } = txMeta;
|
|
241
|
+
if (__classPrivateFieldGet(this, _PendingTransactionTracker_transactionToForcePoll, "f")?.id === id) {
|
|
241
242
|
__classPrivateFieldSet(this, _PendingTransactionTracker_transactionToForcePoll, undefined, "f");
|
|
242
243
|
}
|
|
244
|
+
if (hash) {
|
|
245
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").delete(hash);
|
|
246
|
+
}
|
|
243
247
|
}, _PendingTransactionTracker_checkTransaction = async function _PendingTransactionTracker_checkTransaction(txMeta) {
|
|
244
248
|
const { hash, id, isIntentComplete, txParams: { from }, } = txMeta;
|
|
245
249
|
if (isIntentComplete) {
|
|
@@ -263,7 +267,7 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
263
267
|
const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;
|
|
264
268
|
if (isFailure) {
|
|
265
269
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction receipt has failed status');
|
|
266
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_failTransaction).call(this, txMeta, new Error('Transaction
|
|
270
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_failTransaction).call(this, txMeta, new Error('Transaction failed on-chain'));
|
|
267
271
|
return;
|
|
268
272
|
}
|
|
269
273
|
const { blockNumber, blockHash } = receipt ?? {};
|
|
@@ -294,8 +298,9 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
294
298
|
const { id } = txMeta;
|
|
295
299
|
const { blockHash } = receipt ?? {};
|
|
296
300
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction confirmed', id);
|
|
297
|
-
|
|
298
|
-
|
|
301
|
+
const isForcePollTransaction = __classPrivateFieldGet(this, _PendingTransactionTracker_transactionToForcePoll, "f")?.id === id;
|
|
302
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_cleanTransaction).call(this, txMeta);
|
|
303
|
+
if (isForcePollTransaction) {
|
|
299
304
|
this.hub.emit('transaction-confirmed', txMeta);
|
|
300
305
|
return;
|
|
301
306
|
}
|
|
@@ -315,7 +320,7 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
315
320
|
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_updateTransaction).call(this, updatedTxMeta, 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed');
|
|
316
321
|
this.hub.emit('transaction-confirmed', updatedTxMeta);
|
|
317
322
|
}, _PendingTransactionTracker_isTransactionTimeout = async function _PendingTransactionTracker_isTransactionTimeout(txMeta, nextNonce) {
|
|
318
|
-
const { chainId, hash, id: transactionId, txParams: { nonce }, } = txMeta;
|
|
323
|
+
const { chainId, hash, id: transactionId, submittedTime, txParams: { nonce }, } = txMeta;
|
|
319
324
|
if (!hash || !nonce) {
|
|
320
325
|
return false;
|
|
321
326
|
}
|
|
@@ -341,27 +346,34 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
341
346
|
try {
|
|
342
347
|
// Check if transaction exists on the network
|
|
343
348
|
const transaction = await __classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_getTransactionByHash).call(this, hash);
|
|
344
|
-
// If transaction exists,
|
|
349
|
+
// If transaction exists, record the timestamp
|
|
345
350
|
if (transaction !== null) {
|
|
346
|
-
|
|
347
|
-
__classPrivateFieldGet(this,
|
|
351
|
+
const currentTimestamp = Date.now();
|
|
352
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction found on network, recording timestamp', transactionId);
|
|
353
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").set(hash, currentTimestamp);
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
const lastSeenTimestamp = __classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").get(hash) ?? submittedTime;
|
|
357
|
+
if (lastSeenTimestamp === undefined) {
|
|
358
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction not yet seen on network and has no submitted time, skipping timeout check', transactionId);
|
|
348
359
|
return false;
|
|
349
360
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
__classPrivateFieldGet(this,
|
|
355
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Incrementing timeout counter', {
|
|
361
|
+
const { blockTime } = getAcceleratedPollingParams(chainId, __classPrivateFieldGet(this, _PendingTransactionTracker_messenger, "f"));
|
|
362
|
+
const currentTimestamp = Date.now();
|
|
363
|
+
const durationSinceLastSeen = currentTimestamp - lastSeenTimestamp;
|
|
364
|
+
const timeoutDuration = blockTime * threshold;
|
|
365
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Checking timeout duration', {
|
|
356
366
|
transactionId,
|
|
357
|
-
|
|
367
|
+
durationSinceLastSeen,
|
|
368
|
+
timeoutDuration,
|
|
358
369
|
threshold,
|
|
370
|
+
blockTime,
|
|
359
371
|
});
|
|
360
|
-
if (
|
|
372
|
+
if (durationSinceLastSeen < timeoutDuration) {
|
|
361
373
|
return false;
|
|
362
374
|
}
|
|
363
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Hit timeout threshold', transactionId);
|
|
364
|
-
__classPrivateFieldGet(this,
|
|
375
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Hit timeout duration threshold', transactionId);
|
|
376
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_lastSeenTimestampByHash, "f").delete(hash);
|
|
365
377
|
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_failTransaction).call(this, txMeta, new Error('Transaction not found on network after timeout'));
|
|
366
378
|
return true;
|
|
367
379
|
}
|
|
@@ -412,11 +424,11 @@ _PendingTransactionTracker_beforeCheckPendingTransaction = new WeakMap(), _Pendi
|
|
|
412
424
|
}, 'PendingTransactionTracker:#warnTransaction - Warning added');
|
|
413
425
|
}, _PendingTransactionTracker_failTransaction = function _PendingTransactionTracker_failTransaction(txMeta, error) {
|
|
414
426
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction failed', txMeta.id, error);
|
|
415
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m",
|
|
427
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_cleanTransaction).call(this, txMeta);
|
|
416
428
|
this.hub.emit('transaction-failed', txMeta, error);
|
|
417
429
|
}, _PendingTransactionTracker_dropTransaction = function _PendingTransactionTracker_dropTransaction(txMeta) {
|
|
418
430
|
__classPrivateFieldGet(this, _PendingTransactionTracker_log, "f").call(this, 'Transaction dropped', txMeta.id);
|
|
419
|
-
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m",
|
|
431
|
+
__classPrivateFieldGet(this, _PendingTransactionTracker_instances, "m", _PendingTransactionTracker_cleanTransaction).call(this, txMeta);
|
|
420
432
|
this.hub.emit('transaction-dropped', txMeta);
|
|
421
433
|
}, _PendingTransactionTracker_updateTransaction = function _PendingTransactionTracker_updateTransaction(txMeta, note) {
|
|
422
434
|
this.hub.emit('transaction-updated', txMeta, note);
|