@metamask-previews/transaction-controller 36.0.0-preview-37450416 → 36.0.0-preview-0e3283a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/TransactionController.js +4 -4
  2. package/dist/TransactionController.mjs +3 -3
  3. package/dist/{chunk-CFU75H44.js → chunk-5HYWLTVQ.js} +4 -10
  4. package/dist/chunk-5HYWLTVQ.js.map +1 -0
  5. package/dist/{chunk-7M2R5AHC.mjs → chunk-6B5BEO3R.mjs} +13 -4
  6. package/dist/chunk-6B5BEO3R.mjs.map +1 -0
  7. package/dist/{chunk-6DODV6OV.js → chunk-ULD4JC3Q.js} +13 -4
  8. package/dist/chunk-ULD4JC3Q.js.map +1 -0
  9. package/dist/{chunk-EH5OUNFZ.mjs → chunk-VGFPVAKX.mjs} +4 -10
  10. package/dist/chunk-VGFPVAKX.mjs.map +1 -0
  11. package/dist/{chunk-ZRBWVQS4.js → chunk-VKWOHNDO.js} +57 -51
  12. package/dist/chunk-VKWOHNDO.js.map +1 -0
  13. package/dist/{chunk-X4OBYE4B.mjs → chunk-XTMJ25EF.mjs} +55 -49
  14. package/dist/chunk-XTMJ25EF.mjs.map +1 -0
  15. package/dist/helpers/GasFeePoller.js +2 -2
  16. package/dist/helpers/GasFeePoller.mjs +1 -1
  17. package/dist/helpers/PendingTransactionTracker.js +2 -2
  18. package/dist/helpers/PendingTransactionTracker.mjs +1 -1
  19. package/dist/index.js +5 -12
  20. package/dist/index.mjs +4 -11
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/dist/types/TransactionController.d.ts +9 -3
  23. package/dist/types/TransactionController.d.ts.map +1 -1
  24. package/dist/types/helpers/GasFeePoller.d.ts.map +1 -1
  25. package/dist/types/helpers/PendingTransactionTracker.d.ts +2 -1
  26. package/dist/types/helpers/PendingTransactionTracker.d.ts.map +1 -1
  27. package/dist/types/index.d.ts +1 -2
  28. package/dist/types/index.d.ts.map +1 -1
  29. package/package.json +1 -1
  30. package/dist/chunk-6DODV6OV.js.map +0 -1
  31. package/dist/chunk-7M2R5AHC.mjs.map +0 -1
  32. package/dist/chunk-CFU75H44.js.map +0 -1
  33. package/dist/chunk-EH5OUNFZ.mjs.map +0 -1
  34. package/dist/chunk-X4OBYE4B.mjs.map +0 -1
  35. package/dist/chunk-ZRBWVQS4.js.map +0 -1
@@ -4,14 +4,14 @@
4
4
 
5
5
 
6
6
 
7
- var _chunkZRBWVQS4js = require('./chunk-ZRBWVQS4.js');
7
+ var _chunkVKWOHNDOjs = require('./chunk-VKWOHNDO.js');
8
8
  require('./chunk-PRUNMTRD.js');
9
9
  require('./chunk-5QVDIVJH.js');
10
10
  require('./chunk-NNCUD3QF.js');
11
11
  require('./chunk-KT6UAKBB.js');
12
12
  require('./chunk-SD6CWFDF.js');
13
13
  require('./chunk-4OYPDGHO.js');
14
- require('./chunk-6DODV6OV.js');
14
+ require('./chunk-ULD4JC3Q.js');
15
15
  require('./chunk-7LXE4KHV.js');
16
16
  require('./chunk-V72C4MCR.js');
17
17
  require('./chunk-TIE3CPF7.js');
@@ -19,7 +19,7 @@ require('./chunk-NYKRCWBG.js');
19
19
  require('./chunk-WR5F34OW.js');
20
20
  require('./chunk-YVCX6Z75.js');
21
21
  require('./chunk-TJMQEH57.js');
22
- require('./chunk-CFU75H44.js');
22
+ require('./chunk-5HYWLTVQ.js');
23
23
  require('./chunk-2XKEAKQG.js');
24
24
  require('./chunk-RHDPOIS4.js');
25
25
  require('./chunk-6OLJWLKK.js');
@@ -42,5 +42,5 @@ require('./chunk-Z4BLTVTB.js');
42
42
 
43
43
 
44
44
 
45
- exports.ApprovalState = _chunkZRBWVQS4js.ApprovalState; exports.CANCEL_RATE = _chunkZRBWVQS4js.CANCEL_RATE; exports.HARDFORK = _chunkZRBWVQS4js.HARDFORK; exports.SPEED_UP_RATE = _chunkZRBWVQS4js.SPEED_UP_RATE; exports.TransactionController = _chunkZRBWVQS4js.TransactionController;
45
+ exports.ApprovalState = _chunkVKWOHNDOjs.ApprovalState; exports.CANCEL_RATE = _chunkVKWOHNDOjs.CANCEL_RATE; exports.HARDFORK = _chunkVKWOHNDOjs.HARDFORK; exports.SPEED_UP_RATE = _chunkVKWOHNDOjs.SPEED_UP_RATE; exports.TransactionController = _chunkVKWOHNDOjs.TransactionController;
46
46
  //# sourceMappingURL=TransactionController.js.map
@@ -4,14 +4,14 @@ import {
4
4
  HARDFORK,
5
5
  SPEED_UP_RATE,
6
6
  TransactionController
7
- } from "./chunk-X4OBYE4B.mjs";
7
+ } from "./chunk-XTMJ25EF.mjs";
8
8
  import "./chunk-6DDVVUJC.mjs";
9
9
  import "./chunk-JOQK7A5G.mjs";
10
10
  import "./chunk-3AVRGHUO.mjs";
11
11
  import "./chunk-K4KOSAGM.mjs";
12
12
  import "./chunk-KG4UW4K4.mjs";
13
13
  import "./chunk-X4XSEYPL.mjs";
14
- import "./chunk-7M2R5AHC.mjs";
14
+ import "./chunk-6B5BEO3R.mjs";
15
15
  import "./chunk-FRKQ3Z2L.mjs";
16
16
  import "./chunk-5G6OHAXI.mjs";
17
17
  import "./chunk-SMC5Q6ZH.mjs";
@@ -19,7 +19,7 @@ import "./chunk-VEVVBHP3.mjs";
19
19
  import "./chunk-Z4GV3YQQ.mjs";
20
20
  import "./chunk-FG74Z3F5.mjs";
21
21
  import "./chunk-FMRLPVFZ.mjs";
22
- import "./chunk-EH5OUNFZ.mjs";
22
+ import "./chunk-VGFPVAKX.mjs";
23
23
  import "./chunk-NOHEXQ7Y.mjs";
24
24
  import "./chunk-3ZV5YEUV.mjs";
25
25
  import "./chunk-4V4XIPCI.mjs";
@@ -105,11 +105,7 @@ stop_fn = function() {
105
105
  };
106
106
  _onTimeout = new WeakSet();
107
107
  onTimeout_fn = async function() {
108
- try {
109
- await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateUnapprovedTransactions, updateUnapprovedTransactions_fn).call(this);
110
- } catch (error) {
111
- log("Update failed", error);
112
- }
108
+ await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateUnapprovedTransactions, updateUnapprovedTransactions_fn).call(this);
113
109
  _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _timeout, setTimeout(() => _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _onTimeout, onTimeout_fn).call(this), INTERVAL_MILLISECONDS));
114
110
  };
115
111
  _updateUnapprovedTransactions = new WeakSet();
@@ -121,15 +117,13 @@ updateUnapprovedTransactions_fn = async function() {
121
117
  log("Found unapproved transactions", unapprovedTransactions.length);
122
118
  const gasFeeControllerDataByChainId = await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGasFeeControllerData, getGasFeeControllerData_fn).call(this, unapprovedTransactions);
123
119
  log("Retrieved gas fee controller data", gasFeeControllerDataByChainId);
124
- await Promise.allSettled(
120
+ await Promise.all(
125
121
  unapprovedTransactions.flatMap((tx) => {
126
122
  const { chainId } = tx;
127
123
  const gasFeeControllerData = gasFeeControllerDataByChainId.get(
128
124
  chainId
129
125
  );
130
- return _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateUnapprovedTransaction, updateUnapprovedTransaction_fn).call(this, tx, gasFeeControllerData).catch((error) => {
131
- log("Failed to update transaction", tx.id, error);
132
- });
126
+ return _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateUnapprovedTransaction, updateUnapprovedTransaction_fn).call(this, tx, gasFeeControllerData);
133
127
  })
134
128
  );
135
129
  };
@@ -231,4 +225,4 @@ getGasFeeControllerData_fn = async function(transactions) {
231
225
 
232
226
 
233
227
  exports.GasFeePoller = GasFeePoller;
234
- //# sourceMappingURL=chunk-CFU75H44.js.map
228
+ //# sourceMappingURL=chunk-5HYWLTVQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/GasFeePoller.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n Layer1GasFeeFlow,\n} from '../types';\nimport { TransactionStatus, type TransactionMeta } from '../types';\nimport { getGasFeeFlow } from '../utils/gas-flow';\nimport { getTransactionLayer1GasFee } from '../utils/layer1-gas-fee-flow';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-poller');\n\nconst INTERVAL_MILLISECONDS = 10000;\n\n/**\n * Automatically polls and updates suggested gas fees on unapproved transactions.\n */\nexport class GasFeePoller {\n hub: EventEmitter = new EventEmitter();\n\n #findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n\n #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n #getProvider: (chainId: Hex, networkClientId?: NetworkClientId) => Provider;\n\n #getTransactions: () => TransactionMeta[];\n\n #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n * @param options - The options for this instance.\n * @param options.findNetworkClientIdByChainId - Callback to find the network client ID by chain ID.\n * @param options.gasFeeFlows - The gas fee flows to use to obtain suitable gas fees.\n * @param options.getGasFeeControllerEstimates - Callback to obtain the default fee estimates.\n * @param options.getProvider - Callback to obtain a provider instance.\n * @param options.getTransactions - Callback to obtain the transaction data.\n * @param options.layer1GasFeeFlows - The layer 1 gas fee flows to use to obtain suitable layer 1 gas fees.\n * @param options.onStateChange - Callback to register a listener for controller state changes.\n */\n constructor({\n findNetworkClientIdByChainId,\n gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n getProvider: (chainId: Hex, networkClientId?: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#gasFeeFlows = gasFeeFlows;\n this.#layer1GasFeeFlows = layer1GasFeeFlows;\n this.#getGasFeeControllerEstimates = getGasFeeControllerEstimates;\n this.#getProvider = getProvider;\n this.#getTransactions = getTransactions;\n\n onStateChange(() => {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (unapprovedTransactions.length) {\n this.#start();\n } else {\n this.#stop();\n }\n });\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n // Intentionally not awaiting since this starts the timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#onTimeout();\n\n this.#running = true;\n\n log('Started polling');\n }\n\n #stop() {\n if (!this.#running) {\n return;\n }\n\n clearTimeout(this.#timeout);\n\n this.#timeout = undefined;\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onTimeout() {\n await this.#updateUnapprovedTransactions();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateUnapprovedTransactions() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (!unapprovedTransactions.length) {\n return;\n }\n\n log('Found unapproved transactions', unapprovedTransactions.length);\n\n const gasFeeControllerDataByChainId = await this.#getGasFeeControllerData(\n unapprovedTransactions,\n );\n\n log('Retrieved gas fee controller data', gasFeeControllerDataByChainId);\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => {\n const { chainId } = tx;\n\n const gasFeeControllerData = gasFeeControllerDataByChainId.get(\n chainId,\n ) as GasFeeState;\n\n return this.#updateUnapprovedTransaction(tx, gasFeeControllerData);\n }),\n );\n }\n\n async #updateUnapprovedTransaction(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ) {\n const { id } = transactionMeta;\n\n const [gasFeeEstimatesResponse, layer1GasFee] = await Promise.all([\n this.#updateTransactionGasFeeEstimates(\n transactionMeta,\n gasFeeControllerData,\n ),\n this.#updateTransactionLayer1GasFee(transactionMeta),\n ]);\n\n if (!gasFeeEstimatesResponse && !layer1GasFee) {\n return;\n }\n\n this.hub.emit('transaction-updated', {\n transactionId: id,\n gasFeeEstimates: gasFeeEstimatesResponse?.gasFeeEstimates,\n gasFeeEstimatesLoaded: gasFeeEstimatesResponse?.gasFeeEstimatesLoaded,\n layer1GasFee,\n });\n }\n\n async #updateTransactionGasFeeEstimates(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ): Promise<\n | { gasFeeEstimates?: GasFeeEstimates; gasFeeEstimatesLoaded: boolean }\n | undefined\n > {\n const { chainId, networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(chainId, networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (gasFeeFlow) {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n };\n\n let gasFeeEstimates: GasFeeEstimates | undefined;\n\n if (gasFeeFlow) {\n try {\n const response = await gasFeeFlow.getGasFees(request);\n gasFeeEstimates = response.estimates;\n } catch (error) {\n log('Failed to get suggested gas fees', transactionMeta.id, error);\n }\n }\n\n if (!gasFeeEstimates && transactionMeta.gasFeeEstimatesLoaded) {\n return undefined;\n }\n\n log('Updated gas fee estimates', {\n gasFeeEstimates,\n transaction: transactionMeta.id,\n });\n\n return { gasFeeEstimates, gasFeeEstimatesLoaded: true };\n }\n\n async #updateTransactionLayer1GasFee(\n transactionMeta: TransactionMeta,\n ): Promise<Hex | undefined> {\n const { chainId, networkClientId } = transactionMeta;\n const provider = this.#getProvider(chainId, networkClientId);\n\n const layer1GasFee = await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n\n if (layer1GasFee) {\n log('Updated layer 1 gas fee', layer1GasFee, transactionMeta.id);\n }\n\n return layer1GasFee;\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n\n async #getGasFeeControllerData(\n transactions: TransactionMeta[],\n ): Promise<Map<string, GasFeeState>> {\n const networkClientIdsByChainId = new Map<Hex, NetworkClientId>();\n\n for (const transaction of transactions) {\n const { chainId, networkClientId: transactionNetworkClientId } =\n transaction;\n\n if (networkClientIdsByChainId.has(chainId)) {\n continue;\n }\n\n const networkClientId =\n transactionNetworkClientId ??\n (this.#findNetworkClientIdByChainId(chainId) as string);\n\n networkClientIdsByChainId.set(chainId, networkClientId);\n }\n\n log('Extracted network client IDs by chain ID', networkClientIdsByChainId);\n\n const entryPromises = Array.from(networkClientIdsByChainId.entries()).map(\n async ([chainId, networkClientId]) => {\n return [\n chainId,\n await this.#getGasFeeControllerEstimates({ networkClientId }),\n ] as const;\n },\n );\n\n return new Map(await Promise.all(entryPromises));\n }\n}\n"]}
@@ -26,9 +26,10 @@ var KNOWN_TRANSACTION_ERRORS = [
26
26
  "nonce too low"
27
27
  ];
28
28
  var log = createModuleLogger(projectLogger, "pending-transactions");
29
- var _blockTracker, _droppedBlockCountByHash, _getChainId, _getEthQuery, _getTransactions, _isResubmitEnabled, _listener, _getGlobalLock, _publishTransaction, _running, _beforeCheckPendingTransaction, _beforePublish, _start, start_fn, _onLatestBlock, onLatestBlock_fn, _checkTransactions, checkTransactions_fn, _resubmitTransactions, resubmitTransactions_fn, _isKnownTransactionError, isKnownTransactionError_fn, _resubmitTransaction, resubmitTransaction_fn, _isResubmitDue, isResubmitDue_fn, _checkTransaction, checkTransaction_fn, _onTransactionConfirmed, onTransactionConfirmed_fn, _isTransactionDropped, isTransactionDropped_fn, _isNonceTaken, isNonceTaken_fn, _getPendingTransactions, getPendingTransactions_fn, _warnTransaction, warnTransaction_fn, _failTransaction, failTransaction_fn, _dropTransaction, dropTransaction_fn, _updateTransaction, updateTransaction_fn, _getTransactionReceipt, getTransactionReceipt_fn, _getBlockByHash, getBlockByHash_fn, _getNetworkTransactionCount, getNetworkTransactionCount_fn, _getCurrentChainTransactions, getCurrentChainTransactions_fn;
29
+ var _approveTransaction, _blockTracker, _droppedBlockCountByHash, _getChainId, _getEthQuery, _getTransactions, _isResubmitEnabled, _listener, _getGlobalLock, _publishTransaction, _running, _beforeCheckPendingTransaction, _beforePublish, _start, start_fn, _onLatestBlock, onLatestBlock_fn, _checkTransactions, checkTransactions_fn, _resubmitTransactions, resubmitTransactions_fn, _isKnownTransactionError, isKnownTransactionError_fn, _resubmitTransaction, resubmitTransaction_fn, _isResubmitDue, isResubmitDue_fn, _checkTransaction, checkTransaction_fn, _onTransactionConfirmed, onTransactionConfirmed_fn, _isTransactionDropped, isTransactionDropped_fn, _isNonceTaken, isNonceTaken_fn, _getPendingTransactions, getPendingTransactions_fn, _warnTransaction, warnTransaction_fn, _failTransaction, failTransaction_fn, _dropTransaction, dropTransaction_fn, _updateTransaction, updateTransaction_fn, _getTransactionReceipt, getTransactionReceipt_fn, _getBlockByHash, getBlockByHash_fn, _getNetworkTransactionCount, getNetworkTransactionCount_fn, _getCurrentChainTransactions, getCurrentChainTransactions_fn;
30
30
  var PendingTransactionTracker = class {
31
31
  constructor({
32
+ approveTransaction,
32
33
  blockTracker,
33
34
  getChainId,
34
35
  getEthQuery,
@@ -58,6 +59,7 @@ var PendingTransactionTracker = class {
58
59
  __privateAdd(this, _getBlockByHash);
59
60
  __privateAdd(this, _getNetworkTransactionCount);
60
61
  __privateAdd(this, _getCurrentChainTransactions);
62
+ __privateAdd(this, _approveTransaction, void 0);
61
63
  __privateAdd(this, _blockTracker, void 0);
62
64
  __privateAdd(this, _droppedBlockCountByHash, void 0);
63
65
  __privateAdd(this, _getChainId, void 0);
@@ -81,6 +83,7 @@ var PendingTransactionTracker = class {
81
83
  }
82
84
  };
83
85
  this.hub = new EventEmitter();
86
+ __privateSet(this, _approveTransaction, approveTransaction);
84
87
  __privateSet(this, _blockTracker, blockTracker);
85
88
  __privateSet(this, _droppedBlockCountByHash, /* @__PURE__ */ new Map());
86
89
  __privateSet(this, _getChainId, getChainId);
@@ -118,6 +121,7 @@ var PendingTransactionTracker = class {
118
121
  log("Stopped polling");
119
122
  }
120
123
  };
124
+ _approveTransaction = new WeakMap();
121
125
  _blockTracker = new WeakMap();
122
126
  _droppedBlockCountByHash = new WeakMap();
123
127
  _getChainId = new WeakMap();
@@ -190,10 +194,10 @@ resubmitTransactions_fn = async function(latestBlockNumber) {
190
194
  try {
191
195
  await __privateMethod(this, _resubmitTransaction, resubmitTransaction_fn).call(this, txMeta, latestBlockNumber);
192
196
  } catch (error) {
193
- const errorMessage = error.value?.message?.toLowerCase() || error.message?.toLowerCase() || String(error);
197
+ const errorMessage = error.value?.message?.toLowerCase() || error.message.toLowerCase();
194
198
  if (__privateMethod(this, _isKnownTransactionError, isKnownTransactionError_fn).call(this, errorMessage)) {
195
199
  log("Ignoring known transaction error", errorMessage);
196
- continue;
200
+ return;
197
201
  }
198
202
  __privateMethod(this, _warnTransaction, warnTransaction_fn).call(this, txMeta, error.message, "There was an error when resubmitting this transaction.");
199
203
  }
@@ -214,6 +218,11 @@ resubmitTransaction_fn = async function(txMeta, latestBlockNumber) {
214
218
  if (!__privateGet(this, _beforePublish).call(this, txMeta)) {
215
219
  return;
216
220
  }
221
+ if (!rawTx?.length) {
222
+ log("Approving transaction as no raw value");
223
+ await __privateGet(this, _approveTransaction).call(this, txMeta.id);
224
+ return;
225
+ }
217
226
  const ethQuery = __privateGet(this, _getEthQuery).call(this, txMeta.networkClientId);
218
227
  await __privateGet(this, _publishTransaction).call(this, ethQuery, rawTx);
219
228
  const retryCount = (txMeta.retryCount ?? 0) + 1;
@@ -387,4 +396,4 @@ getCurrentChainTransactions_fn = function() {
387
396
  export {
388
397
  PendingTransactionTracker
389
398
  };
390
- //# sourceMappingURL=chunk-7M2R5AHC.mjs.map
399
+ //# sourceMappingURL=chunk-6B5BEO3R.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/PendingTransactionTracker.ts"],"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 EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): this;\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n #approveTransaction: (transactionId: string) => Promise<void>;\n\n #blockTracker: BlockTracker;\n\n #droppedBlockCountByHash: Map<string, number>;\n\n #getChainId: () => string;\n\n #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n #getTransactions: () => TransactionMeta[];\n\n #isResubmitEnabled: () => boolean;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #listener: any;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise<string>;\n\n #running: boolean;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n approveTransaction,\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n approveTransaction: (transactionId: string) => Promise<void>;\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise<string>;\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n };\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#approveTransaction = approveTransaction;\n this.#blockTracker = blockTracker;\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? (() => true);\n this.#listener = this.#onLatestBlock.bind(this);\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#beforePublish = hooks?.beforePublish ?? (() => true);\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ?? (() => true);\n }\n\n startIfPendingTransactions = () => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start();\n } else {\n this.stop();\n }\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) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n this.#blockTracker.on('latest', this.#listener);\n this.#running = true;\n\n log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#blockTracker.removeListener('latest', this.#listener);\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n 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 log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to check');\n return;\n }\n\n 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) {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to resubmit');\n return;\n }\n\n 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() || error.message.toLowerCase();\n\n if (this.#isKnownTransactionError(errorMessage)) {\n log('Ignoring known transaction error', errorMessage);\n return;\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) {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ) {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n const { rawTx } = txMeta;\n\n if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n if (!rawTx?.length) {\n log('Approving transaction as no raw value');\n await this.#approveTransaction(txMeta.id);\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, rawTx);\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 async #checkTransaction(txMeta: TransactionMeta) {\n const { hash, id } = txMeta;\n\n if (!hash && 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 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 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 // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was a problem loading this transaction.',\n );\n\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta)) {\n this.#dropTransaction(txMeta);\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt: SuccessfulTransactionReceipt,\n ) {\n const { id } = txMeta;\n const { blockHash } = receipt;\n\n log('Transaction confirmed', id);\n\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n const updatedTxMeta = cloneDeep(txMeta);\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.status = TransactionStatus.confirmed;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionDropped(txMeta: TransactionMeta) {\n const {\n hash,\n id,\n txParams: { nonce, from },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const networkNextNonceHex = await this.#getNetworkTransactionCount(from);\n const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= networkNextNonceNumber) {\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 log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n 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.#getCurrentChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getCurrentChainTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(txMeta: TransactionMeta, error: string, message: string) {\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) {\n log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n log('Transaction dropped', txMeta.id);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string) {\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 #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 #getCurrentChainTransactions(): TransactionMeta[] {\n const currentChainId = this.#getChainId();\n\n return this.#getTransactions().filter(\n (tx) => tx.chainId === currentChainId,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,aAAa;AAMtB,OAAO,kBAAkB;AACzB,SAAS,WAAW,aAAa;AAUjC,IAAM,sBAAsB;AAE5B,IAAM,yBAAyB;AAC/B,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;AAEjC,IAAM,2BAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,MAAM,mBAAmB,eAAe,sBAAsB;AAhCpE;AA8DO,IAAM,4BAAN,MAAgC;AAAA,EA+BrC,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAeG;AA+CH;AAsBA,uBAAM;AAoBN,uBAAM;AAoBN,uBAAM;AA2CN;AAMA,uBAAM;AA+BN;AA8BA,uBAAM;AAmEN,uBAAM;AA+BN,uBAAM;AAuCN;AAaA;AASA;AAUA;AAKA;AAKA;AAIA,uBAAM;AAMN,uBAAM;AAYN,uBAAM;AAIN;AA7dA;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAIA;AAAA;AAAA;AAEA;AAEA;AAEA;AAEA;AAEA;AA8CA,sCAA6B,MAAM;AACjC,YAAM,sBAAsB,sBAAK,oDAAL;AAE5B,UAAI,oBAAoB,QAAQ;AAC9B,8BAAK,kBAAL;AAAA,MACF,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AA1BE,SAAK,MAAM,IAAI,aAAa;AAE5B,uBAAK,qBAAsB;AAC3B,uBAAK,eAAgB;AACrB,uBAAK,0BAA2B,oBAAI,IAAI;AACxC,uBAAK,aAAc;AACnB,uBAAK,cAAe;AACpB,uBAAK,kBAAmB;AACxB,uBAAK,oBAAqB,sBAAsB,MAAM;AACtD,uBAAK,WAAY,sBAAK,kCAAe,KAAK,IAAI;AAC9C,uBAAK,gBAAiB;AACtB,uBAAK,qBAAsB;AAC3B,uBAAK,UAAW;AAChB,uBAAK,gBAAiB,OAAO,kBAAkB,MAAM;AACrD,uBAAK,gCACH,OAAO,kCAAkC,MAAM;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,sBAAsB,QAAyB;AACnD,UAAM,cAAc,MAAM,mBAAK,gBAAL;AAE1B,QAAI;AACF,YAAM,sBAAK,wCAAL,WAAuB;AAAA,IAC/B,SAAS,OAAO;AAEd,UAAI,+BAA+B,KAAK;AAAA,IAC1C,UAAE;AACA,kBAAY;AAAA,IACd;AAAA,EACF;AAAA,EAaA,OAAO;AACL,QAAI,CAAC,mBAAK,WAAU;AAClB;AAAA,IACF;AAEA,uBAAK,eAAc,eAAe,UAAU,mBAAK,UAAS;AAC1D,uBAAK,UAAW;AAEhB,QAAI,iBAAiB;AAAA,EACvB;AA4WF;AApeE;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAIA;AAEA;AAEA;AAEA;AAEA;AAEA;AA0EA;AAAA,WAAM,WAAG;AACP,MAAI,mBAAK,WAAU;AACjB;AAAA,EACF;AAEA,qBAAK,eAAc,GAAG,UAAU,mBAAK,UAAS;AAC9C,qBAAK,UAAW;AAEhB,MAAI,iBAAiB;AACvB;AAaM;AAAA,mBAAc,eAAC,mBAA2B;AAC9C,QAAM,cAAc,MAAM,mBAAK,gBAAL;AAE1B,MAAI;AACF,UAAM,sBAAK,0CAAL;AAAA,EACR,SAAS,OAAO;AAEd,QAAI,gCAAgC,KAAK;AAAA,EAC3C,UAAE;AACA,gBAAY;AAAA,EACd;AAEA,MAAI;AACF,UAAM,sBAAK,gDAAL,WAA2B;AAAA,EACnC,SAAS,OAAO;AAEd,QAAI,mCAAmC,KAAK;AAAA,EAC9C;AACF;AAEM;AAAA,uBAAkB,iBAAG;AACzB,MAAI,uBAAuB;AAE3B,QAAM,sBAAsB,sBAAK,oDAAL;AAE5B,MAAI,CAAC,oBAAoB,QAAQ;AAC/B,QAAI,kCAAkC;AACtC;AAAA,EACF;AAEA,MAAI,uCAAuC;AAAA,IACzC,OAAO,oBAAoB;AAAA,IAC3B,KAAK,oBAAoB,IAAI,CAAC,OAAO,GAAG,EAAE;AAAA,EAC5C,CAAC;AAED,QAAM,QAAQ;AAAA,IACZ,oBAAoB,IAAI,CAAC,OAAO,sBAAK,wCAAL,WAAuB,GAAG;AAAA,EAC5D;AACF;AAEM;AAAA,0BAAqB,eAAC,mBAA2B;AACrD,MAAI,CAAC,mBAAK,oBAAL,cAA6B,CAAC,mBAAK,WAAU;AAChD;AAAA,EACF;AAEA,MAAI,2BAA2B;AAE/B,QAAM,sBAAsB,sBAAK,oDAAL;AAE5B,MAAI,CAAC,oBAAoB,QAAQ;AAC/B,QAAI,qCAAqC;AACzC;AAAA,EACF;AAEA,MAAI,0CAA0C;AAAA,IAC5C,OAAO,oBAAoB;AAAA,IAC3B,KAAK,oBAAoB,IAAI,CAAC,OAAO,GAAG,EAAE;AAAA,EAC5C,CAAC;AAED,aAAW,UAAU,qBAAqB;AACxC,QAAI;AACF,YAAM,sBAAK,8CAAL,WAA0B,QAAQ;AAAA,IAG1C,SAAS,OAAY;AAEnB,YAAM,eACJ,MAAM,OAAO,SAAS,YAAY,KAAK,MAAM,QAAQ,YAAY;AAEnE,UAAI,sBAAK,sDAAL,WAA8B,eAAe;AAC/C,YAAI,oCAAoC,YAAY;AACpD;AAAA,MACF;AAEA,4BAAK,sCAAL,WACE,QACA,MAAM,SACN;AAAA,IAEJ;AAAA,EACF;AACF;AAEA;AAAA,6BAAwB,SAAC,cAAsB;AAC7C,SAAO,yBAAyB;AAAA,IAAK,CAAC,eACpC,aAAa,SAAS,UAAU;AAAA,EAClC;AACF;AAEM;AAAA,yBAAoB,eACxB,QACA,mBACA;AACA,MAAI,CAAC,sBAAK,kCAAL,WAAoB,QAAQ,oBAAoB;AACnD;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,IAAI;AAElB,MAAI,CAAC,mBAAK,gBAAL,WAAoB,SAAS;AAChC;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,QAAQ;AAClB,QAAI,uCAAuC;AAC3C,UAAM,mBAAK,qBAAL,WAAyB,OAAO;AACtC;AAAA,EACF;AAEA,QAAM,WAAW,mBAAK,cAAL,WAAkB,OAAO;AAC1C,QAAM,mBAAK,qBAAL,WAAyB,UAAU;AAEzC,QAAM,cAAc,OAAO,cAAc,KAAK;AAE9C,wBAAK,0CAAL,WACE,MAAM,CAAC,GAAG,QAAQ,EAAE,WAAW,CAAC,GAChC;AAEJ;AAEA;AAAA,mBAAc,SAAC,QAAyB,mBAAoC;AAC1E,QAAM,kCAAkC,UAAU,MAAM;AAExD,MAAI,CAAC,gCAAgC,uBAAuB;AAC1D,oCAAgC,wBAAwB;AAExD,0BAAK,0CAAL,WACE,iCACA;AAAA,EAEJ;AAEA,QAAM,EAAE,sBAAsB,IAAI;AAElC,QAAM,wBACJ,OAAO,SAAS,mBAAmB,EAAE,IACrC,OAAO,SAAS,uBAAuB,EAAE;AAE3C,QAAM,aAAa,OAAO,cAAc;AAIxC,QAAM,gCAAgC,KAAK;AAAA,IACzC;AAAA,IACA,KAAK,IAAI,GAAG,UAAU;AAAA,EACxB;AAEA,SAAO,yBAAyB;AAClC;AAEM;AAAA,sBAAiB,eAAC,QAAyB;AAC/C,QAAM,EAAE,MAAM,GAAG,IAAI;AAErB,MAAI,CAAC,QAAQ,mBAAK,gCAAL,WAAoC,SAAS;AACxD,UAAM,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAEA,UAAM,OAAO;AAEb,0BAAK,sCAAL,WAAsB,QAAQ;AAE9B;AAAA,EACF;AAEA,MAAI,sBAAK,gCAAL,WAAmB,SAAS;AAC9B,QAAI,uBAAuB,EAAE;AAC7B,0BAAK,sCAAL,WAAsB;AACtB;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,sBAAK,kDAAL,WAA4B;AAClD,UAAM,YAAY,SAAS,WAAW;AACtC,UAAM,YAAY,SAAS,WAAW;AAEtC,QAAI,WAAW;AACb,UAAI,uCAAuC;AAE3C,4BAAK,sCAAL,WACE,QACA,IAAI,MAAM,iCAAiC;AAG7C;AAAA,IACF;AAEA,UAAM,EAAE,aAAa,UAAU,IAAI,WAAW,CAAC;AAE/C,QAAI,aAAa,eAAe,WAAW;AACzC,YAAM,sBAAK,oDAAL,WAA6B,QAAQ;AAAA,QACzC,GAAG;AAAA,QACH;AAAA,QACA;AAAA,MACF;AAEA;AAAA,IACF;AAAA,EAGF,SAAS,OAAY;AACnB,QAAI,+BAA+B,IAAI,KAAK;AAE5C,0BAAK,sCAAL,WACE,QACA,MAAM,SACN;AAGF;AAAA,EACF;AAEA,MAAI,MAAM,sBAAK,gDAAL,WAA2B,SAAS;AAC5C,0BAAK,sCAAL,WAAsB;AAAA,EACxB;AACF;AAEM;AAAA,4BAAuB,eAC3B,QACA,SACA;AACA,QAAM,EAAE,GAAG,IAAI;AACf,QAAM,EAAE,UAAU,IAAI;AAEtB,MAAI,yBAAyB,EAAE;AAE/B,QAAM,EAAE,eAAe,WAAW,eAAe,IAC/C,MAAM,sBAAK,oCAAL,WAAqB,WAAW;AAExC,QAAM,gBAAgB,UAAU,MAAM;AACtC,gBAAc,gBAAgB;AAC9B,gBAAc,iBAAiB;AAC/B,gBAAc;AACd,gBAAc,WAAW;AAAA,IACvB,GAAG,cAAc;AAAA,IACjB,SAAS,QAAQ;AAAA,EACnB;AACA,gBAAc,YAAY;AAC1B,gBAAc,uBAAuB;AAErC,wBAAK,0CAAL,WACE,eACA;AAGF,OAAK,IAAI,KAAK,yBAAyB,aAAa;AACtD;AAEM;AAAA,0BAAqB,eAAC,QAAyB;AACnD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,UAAU,EAAE,OAAO,KAAK;AAAA,EAC1B,IAAI;AAGJ,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,sBAAsB,MAAM,sBAAK,4DAAL,WAAiC;AACnE,QAAM,yBAAyB,SAAS,qBAAqB,EAAE;AAC/D,QAAM,cAAc,SAAS,OAAO,EAAE;AAEtC,MAAI,eAAe,wBAAwB;AACzC,WAAO;AAAA,EACT;AAEA,MAAI,oBAAoB,mBAAK,0BAAyB,IAAI,IAAI;AAE9D,MAAI,sBAAsB,QAAW;AACnC,wBAAoB;AACpB,uBAAK,0BAAyB,IAAI,MAAM,iBAAiB;AAAA,EAC3D;AAEA,MAAI,oBAAoB,qBAAqB;AAC3C,QAAI,oCAAoC,EAAE,IAAI,kBAAkB,CAAC;AACjE,uBAAK,0BAAyB,IAAI,MAAM,oBAAoB,CAAC;AAC7D,WAAO;AAAA,EACT;AAEA,MAAI,2BAA2B,EAAE;AAEjC,qBAAK,0BAAyB,OAAO,IAAI;AACzC,SAAO;AACT;AAEA;AAAA,kBAAa,SAAC,QAAkC;AAC9C,QAAM,EAAE,IAAI,SAAS,IAAI;AAEzB,SAAO,sBAAK,8DAAL,WAAoC;AAAA,IACzC,CAAC,OACC,GAAG,OAAO,MACV,GAAG,SAAS,SAAS,SAAS,QAC9B,GAAG,0CACH,GAAG,SAAS,UAAU,SAAS,SAC/B,GAAG;AAAA,EACP;AACF;AAEA;AAAA,4BAAuB,WAAsB;AAC3C,SAAO,sBAAK,8DAAL,WAAoC;AAAA,IACzC,CAAC,OACC,GAAG,0CACH,CAAC,GAAG,wBACJ,CAAC,GAAG;AAAA,EACR;AACF;AAEA;AAAA,qBAAgB,SAAC,QAAyB,OAAe,SAAiB;AACxE,wBAAK,0CAAL,WACE;AAAA,IACE,GAAG;AAAA,IACH,SAAS,EAAE,OAAO,QAAQ;AAAA,EAC5B,GACA;AAEJ;AAEA;AAAA,qBAAgB,SAAC,QAAyB,OAAc;AACtD,MAAI,sBAAsB,OAAO,IAAI,KAAK;AAC1C,OAAK,IAAI,KAAK,sBAAsB,QAAQ,KAAK;AACnD;AAEA;AAAA,qBAAgB,SAAC,QAAyB;AACxC,MAAI,uBAAuB,OAAO,EAAE;AACpC,OAAK,IAAI,KAAK,uBAAuB,MAAM;AAC7C;AAEA;AAAA,uBAAkB,SAAC,QAAyB,MAAc;AACxD,OAAK,IAAI,KAAK,uBAAuB,QAAQ,IAAI;AACnD;AAEM;AAAA,2BAAsB,eAC1B,QACyC;AACzC,SAAO,MAAM,MAAM,mBAAK,cAAL,YAAqB,yBAAyB,CAAC,MAAM,CAAC;AAC3E;AAEM;AAAA,oBAAe,eACnB,WACA,2BAGc;AACd,SAAO,MAAM,MAAM,mBAAK,cAAL,YAAqB,kBAAkB;AAAA,IACxD;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEM;AAAA,gCAA2B,eAAC,SAAkC;AAClE,SAAO,MAAM,MAAM,mBAAK,cAAL,YAAqB,uBAAuB,CAAC,OAAO,CAAC;AAC1E;AAEA;AAAA,iCAA4B,WAAsB;AAChD,QAAM,iBAAiB,mBAAK,aAAL;AAEvB,SAAO,mBAAK,kBAAL,WAAwB;AAAA,IAC7B,CAAC,OAAO,GAAG,YAAY;AAAA,EACzB;AACF;","names":[]}
@@ -26,9 +26,10 @@ var KNOWN_TRANSACTION_ERRORS = [
26
26
  "nonce too low"
27
27
  ];
28
28
  var log = _chunkS6VGOPUYjs.createModuleLogger.call(void 0, _chunkS6VGOPUYjs.projectLogger, "pending-transactions");
29
- var _blockTracker, _droppedBlockCountByHash, _getChainId, _getEthQuery, _getTransactions, _isResubmitEnabled, _listener, _getGlobalLock, _publishTransaction, _running, _beforeCheckPendingTransaction, _beforePublish, _start, start_fn, _onLatestBlock, onLatestBlock_fn, _checkTransactions, checkTransactions_fn, _resubmitTransactions, resubmitTransactions_fn, _isKnownTransactionError, isKnownTransactionError_fn, _resubmitTransaction, resubmitTransaction_fn, _isResubmitDue, isResubmitDue_fn, _checkTransaction, checkTransaction_fn, _onTransactionConfirmed, onTransactionConfirmed_fn, _isTransactionDropped, isTransactionDropped_fn, _isNonceTaken, isNonceTaken_fn, _getPendingTransactions, getPendingTransactions_fn, _warnTransaction, warnTransaction_fn, _failTransaction, failTransaction_fn, _dropTransaction, dropTransaction_fn, _updateTransaction, updateTransaction_fn, _getTransactionReceipt, getTransactionReceipt_fn, _getBlockByHash, getBlockByHash_fn, _getNetworkTransactionCount, getNetworkTransactionCount_fn, _getCurrentChainTransactions, getCurrentChainTransactions_fn;
29
+ var _approveTransaction, _blockTracker, _droppedBlockCountByHash, _getChainId, _getEthQuery, _getTransactions, _isResubmitEnabled, _listener, _getGlobalLock, _publishTransaction, _running, _beforeCheckPendingTransaction, _beforePublish, _start, start_fn, _onLatestBlock, onLatestBlock_fn, _checkTransactions, checkTransactions_fn, _resubmitTransactions, resubmitTransactions_fn, _isKnownTransactionError, isKnownTransactionError_fn, _resubmitTransaction, resubmitTransaction_fn, _isResubmitDue, isResubmitDue_fn, _checkTransaction, checkTransaction_fn, _onTransactionConfirmed, onTransactionConfirmed_fn, _isTransactionDropped, isTransactionDropped_fn, _isNonceTaken, isNonceTaken_fn, _getPendingTransactions, getPendingTransactions_fn, _warnTransaction, warnTransaction_fn, _failTransaction, failTransaction_fn, _dropTransaction, dropTransaction_fn, _updateTransaction, updateTransaction_fn, _getTransactionReceipt, getTransactionReceipt_fn, _getBlockByHash, getBlockByHash_fn, _getNetworkTransactionCount, getNetworkTransactionCount_fn, _getCurrentChainTransactions, getCurrentChainTransactions_fn;
30
30
  var PendingTransactionTracker = class {
31
31
  constructor({
32
+ approveTransaction,
32
33
  blockTracker,
33
34
  getChainId,
34
35
  getEthQuery,
@@ -58,6 +59,7 @@ var PendingTransactionTracker = class {
58
59
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getBlockByHash);
59
60
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getNetworkTransactionCount);
60
61
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getCurrentChainTransactions);
62
+ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _approveTransaction, void 0);
61
63
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _blockTracker, void 0);
62
64
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _droppedBlockCountByHash, void 0);
63
65
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getChainId, void 0);
@@ -81,6 +83,7 @@ var PendingTransactionTracker = class {
81
83
  }
82
84
  };
83
85
  this.hub = new (0, _events2.default)();
86
+ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _approveTransaction, approveTransaction);
84
87
  _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _blockTracker, blockTracker);
85
88
  _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _droppedBlockCountByHash, /* @__PURE__ */ new Map());
86
89
  _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _getChainId, getChainId);
@@ -118,6 +121,7 @@ var PendingTransactionTracker = class {
118
121
  log("Stopped polling");
119
122
  }
120
123
  };
124
+ _approveTransaction = new WeakMap();
121
125
  _blockTracker = new WeakMap();
122
126
  _droppedBlockCountByHash = new WeakMap();
123
127
  _getChainId = new WeakMap();
@@ -190,10 +194,10 @@ resubmitTransactions_fn = async function(latestBlockNumber) {
190
194
  try {
191
195
  await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _resubmitTransaction, resubmitTransaction_fn).call(this, txMeta, latestBlockNumber);
192
196
  } catch (error) {
193
- const errorMessage = error.value?.message?.toLowerCase() || error.message?.toLowerCase() || String(error);
197
+ const errorMessage = error.value?.message?.toLowerCase() || error.message.toLowerCase();
194
198
  if (_chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _isKnownTransactionError, isKnownTransactionError_fn).call(this, errorMessage)) {
195
199
  log("Ignoring known transaction error", errorMessage);
196
- continue;
200
+ return;
197
201
  }
198
202
  _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _warnTransaction, warnTransaction_fn).call(this, txMeta, error.message, "There was an error when resubmitting this transaction.");
199
203
  }
@@ -214,6 +218,11 @@ resubmitTransaction_fn = async function(txMeta, latestBlockNumber) {
214
218
  if (!_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _beforePublish).call(this, txMeta)) {
215
219
  return;
216
220
  }
221
+ if (!rawTx?.length) {
222
+ log("Approving transaction as no raw value");
223
+ await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _approveTransaction).call(this, txMeta.id);
224
+ return;
225
+ }
217
226
  const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getEthQuery).call(this, txMeta.networkClientId);
218
227
  await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _publishTransaction).call(this, ethQuery, rawTx);
219
228
  const retryCount = (txMeta.retryCount ?? 0) + 1;
@@ -387,4 +396,4 @@ getCurrentChainTransactions_fn = function() {
387
396
 
388
397
 
389
398
  exports.PendingTransactionTracker = PendingTransactionTracker;
390
- //# sourceMappingURL=chunk-6DODV6OV.js.map
399
+ //# sourceMappingURL=chunk-ULD4JC3Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"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 EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): this;\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n #approveTransaction: (transactionId: string) => Promise<void>;\n\n #blockTracker: BlockTracker;\n\n #droppedBlockCountByHash: Map<string, number>;\n\n #getChainId: () => string;\n\n #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n #getTransactions: () => TransactionMeta[];\n\n #isResubmitEnabled: () => boolean;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #listener: any;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise<string>;\n\n #running: boolean;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n approveTransaction,\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n approveTransaction: (transactionId: string) => Promise<void>;\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise<string>;\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n };\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#approveTransaction = approveTransaction;\n this.#blockTracker = blockTracker;\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? (() => true);\n this.#listener = this.#onLatestBlock.bind(this);\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#beforePublish = hooks?.beforePublish ?? (() => true);\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ?? (() => true);\n }\n\n startIfPendingTransactions = () => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start();\n } else {\n this.stop();\n }\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) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n this.#blockTracker.on('latest', this.#listener);\n this.#running = true;\n\n log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#blockTracker.removeListener('latest', this.#listener);\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n 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 log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to check');\n return;\n }\n\n 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) {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to resubmit');\n return;\n }\n\n 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() || error.message.toLowerCase();\n\n if (this.#isKnownTransactionError(errorMessage)) {\n log('Ignoring known transaction error', errorMessage);\n return;\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) {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ) {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n const { rawTx } = txMeta;\n\n if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n if (!rawTx?.length) {\n log('Approving transaction as no raw value');\n await this.#approveTransaction(txMeta.id);\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, rawTx);\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 async #checkTransaction(txMeta: TransactionMeta) {\n const { hash, id } = txMeta;\n\n if (!hash && 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 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 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 // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was a problem loading this transaction.',\n );\n\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta)) {\n this.#dropTransaction(txMeta);\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt: SuccessfulTransactionReceipt,\n ) {\n const { id } = txMeta;\n const { blockHash } = receipt;\n\n log('Transaction confirmed', id);\n\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n const updatedTxMeta = cloneDeep(txMeta);\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.status = TransactionStatus.confirmed;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionDropped(txMeta: TransactionMeta) {\n const {\n hash,\n id,\n txParams: { nonce, from },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const networkNextNonceHex = await this.#getNetworkTransactionCount(from);\n const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= networkNextNonceNumber) {\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 log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n 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.#getCurrentChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getCurrentChainTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(txMeta: TransactionMeta, error: string, message: string) {\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) {\n log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n log('Transaction dropped', txMeta.id);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string) {\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 #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 #getCurrentChainTransactions(): TransactionMeta[] {\n const currentChainId = this.#getChainId();\n\n return this.#getTransactions().filter(\n (tx) => tx.chainId === currentChainId,\n );\n }\n}\n"]}
@@ -105,11 +105,7 @@ stop_fn = function() {
105
105
  };
106
106
  _onTimeout = new WeakSet();
107
107
  onTimeout_fn = async function() {
108
- try {
109
- await __privateMethod(this, _updateUnapprovedTransactions, updateUnapprovedTransactions_fn).call(this);
110
- } catch (error) {
111
- log("Update failed", error);
112
- }
108
+ await __privateMethod(this, _updateUnapprovedTransactions, updateUnapprovedTransactions_fn).call(this);
113
109
  __privateSet(this, _timeout, setTimeout(() => __privateMethod(this, _onTimeout, onTimeout_fn).call(this), INTERVAL_MILLISECONDS));
114
110
  };
115
111
  _updateUnapprovedTransactions = new WeakSet();
@@ -121,15 +117,13 @@ updateUnapprovedTransactions_fn = async function() {
121
117
  log("Found unapproved transactions", unapprovedTransactions.length);
122
118
  const gasFeeControllerDataByChainId = await __privateMethod(this, _getGasFeeControllerData, getGasFeeControllerData_fn).call(this, unapprovedTransactions);
123
119
  log("Retrieved gas fee controller data", gasFeeControllerDataByChainId);
124
- await Promise.allSettled(
120
+ await Promise.all(
125
121
  unapprovedTransactions.flatMap((tx) => {
126
122
  const { chainId } = tx;
127
123
  const gasFeeControllerData = gasFeeControllerDataByChainId.get(
128
124
  chainId
129
125
  );
130
- return __privateMethod(this, _updateUnapprovedTransaction, updateUnapprovedTransaction_fn).call(this, tx, gasFeeControllerData).catch((error) => {
131
- log("Failed to update transaction", tx.id, error);
132
- });
126
+ return __privateMethod(this, _updateUnapprovedTransaction, updateUnapprovedTransaction_fn).call(this, tx, gasFeeControllerData);
133
127
  })
134
128
  );
135
129
  };
@@ -231,4 +225,4 @@ getGasFeeControllerData_fn = async function(transactions) {
231
225
  export {
232
226
  GasFeePoller
233
227
  };
234
- //# sourceMappingURL=chunk-EH5OUNFZ.mjs.map
228
+ //# sourceMappingURL=chunk-VGFPVAKX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/GasFeePoller.ts"],"sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n Layer1GasFeeFlow,\n} from '../types';\nimport { TransactionStatus, type TransactionMeta } from '../types';\nimport { getGasFeeFlow } from '../utils/gas-flow';\nimport { getTransactionLayer1GasFee } from '../utils/layer1-gas-fee-flow';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-poller');\n\nconst INTERVAL_MILLISECONDS = 10000;\n\n/**\n * Automatically polls and updates suggested gas fees on unapproved transactions.\n */\nexport class GasFeePoller {\n hub: EventEmitter = new EventEmitter();\n\n #findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n\n #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n #getProvider: (chainId: Hex, networkClientId?: NetworkClientId) => Provider;\n\n #getTransactions: () => TransactionMeta[];\n\n #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n * @param options - The options for this instance.\n * @param options.findNetworkClientIdByChainId - Callback to find the network client ID by chain ID.\n * @param options.gasFeeFlows - The gas fee flows to use to obtain suitable gas fees.\n * @param options.getGasFeeControllerEstimates - Callback to obtain the default fee estimates.\n * @param options.getProvider - Callback to obtain a provider instance.\n * @param options.getTransactions - Callback to obtain the transaction data.\n * @param options.layer1GasFeeFlows - The layer 1 gas fee flows to use to obtain suitable layer 1 gas fees.\n * @param options.onStateChange - Callback to register a listener for controller state changes.\n */\n constructor({\n findNetworkClientIdByChainId,\n gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n getProvider: (chainId: Hex, networkClientId?: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#gasFeeFlows = gasFeeFlows;\n this.#layer1GasFeeFlows = layer1GasFeeFlows;\n this.#getGasFeeControllerEstimates = getGasFeeControllerEstimates;\n this.#getProvider = getProvider;\n this.#getTransactions = getTransactions;\n\n onStateChange(() => {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (unapprovedTransactions.length) {\n this.#start();\n } else {\n this.#stop();\n }\n });\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n // Intentionally not awaiting since this starts the timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#onTimeout();\n\n this.#running = true;\n\n log('Started polling');\n }\n\n #stop() {\n if (!this.#running) {\n return;\n }\n\n clearTimeout(this.#timeout);\n\n this.#timeout = undefined;\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onTimeout() {\n await this.#updateUnapprovedTransactions();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateUnapprovedTransactions() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (!unapprovedTransactions.length) {\n return;\n }\n\n log('Found unapproved transactions', unapprovedTransactions.length);\n\n const gasFeeControllerDataByChainId = await this.#getGasFeeControllerData(\n unapprovedTransactions,\n );\n\n log('Retrieved gas fee controller data', gasFeeControllerDataByChainId);\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => {\n const { chainId } = tx;\n\n const gasFeeControllerData = gasFeeControllerDataByChainId.get(\n chainId,\n ) as GasFeeState;\n\n return this.#updateUnapprovedTransaction(tx, gasFeeControllerData);\n }),\n );\n }\n\n async #updateUnapprovedTransaction(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ) {\n const { id } = transactionMeta;\n\n const [gasFeeEstimatesResponse, layer1GasFee] = await Promise.all([\n this.#updateTransactionGasFeeEstimates(\n transactionMeta,\n gasFeeControllerData,\n ),\n this.#updateTransactionLayer1GasFee(transactionMeta),\n ]);\n\n if (!gasFeeEstimatesResponse && !layer1GasFee) {\n return;\n }\n\n this.hub.emit('transaction-updated', {\n transactionId: id,\n gasFeeEstimates: gasFeeEstimatesResponse?.gasFeeEstimates,\n gasFeeEstimatesLoaded: gasFeeEstimatesResponse?.gasFeeEstimatesLoaded,\n layer1GasFee,\n });\n }\n\n async #updateTransactionGasFeeEstimates(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ): Promise<\n | { gasFeeEstimates?: GasFeeEstimates; gasFeeEstimatesLoaded: boolean }\n | undefined\n > {\n const { chainId, networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(chainId, networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (gasFeeFlow) {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n };\n\n let gasFeeEstimates: GasFeeEstimates | undefined;\n\n if (gasFeeFlow) {\n try {\n const response = await gasFeeFlow.getGasFees(request);\n gasFeeEstimates = response.estimates;\n } catch (error) {\n log('Failed to get suggested gas fees', transactionMeta.id, error);\n }\n }\n\n if (!gasFeeEstimates && transactionMeta.gasFeeEstimatesLoaded) {\n return undefined;\n }\n\n log('Updated gas fee estimates', {\n gasFeeEstimates,\n transaction: transactionMeta.id,\n });\n\n return { gasFeeEstimates, gasFeeEstimatesLoaded: true };\n }\n\n async #updateTransactionLayer1GasFee(\n transactionMeta: TransactionMeta,\n ): Promise<Hex | undefined> {\n const { chainId, networkClientId } = transactionMeta;\n const provider = this.#getProvider(chainId, networkClientId);\n\n const layer1GasFee = await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n\n if (layer1GasFee) {\n log('Updated layer 1 gas fee', layer1GasFee, transactionMeta.id);\n }\n\n return layer1GasFee;\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n\n async #getGasFeeControllerData(\n transactions: TransactionMeta[],\n ): Promise<Map<string, GasFeeState>> {\n const networkClientIdsByChainId = new Map<Hex, NetworkClientId>();\n\n for (const transaction of transactions) {\n const { chainId, networkClientId: transactionNetworkClientId } =\n transaction;\n\n if (networkClientIdsByChainId.has(chainId)) {\n continue;\n }\n\n const networkClientId =\n transactionNetworkClientId ??\n (this.#findNetworkClientIdByChainId(chainId) as string);\n\n networkClientIdsByChainId.set(chainId, networkClientId);\n }\n\n log('Extracted network client IDs by chain ID', networkClientIdsByChainId);\n\n const entryPromises = Array.from(networkClientIdsByChainId.entries()).map(\n async ([chainId, networkClientId]) => {\n return [\n chainId,\n await this.#getGasFeeControllerEstimates({ networkClientId }),\n ] as const;\n },\n );\n\n return new Map(await Promise.all(entryPromises));\n }\n}\n"],"mappings":"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","names":[]}