@metamask-previews/transaction-controller 23.1.0-preview.bf56dac → 24.0.0-preview.53232c55

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 (37) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/dist/TransactionController.d.ts +232 -46
  3. package/dist/TransactionController.d.ts.map +1 -1
  4. package/dist/TransactionController.js +278 -192
  5. package/dist/TransactionController.js.map +1 -1
  6. package/dist/constants.d.ts +3 -3
  7. package/dist/constants.js +4 -4
  8. package/dist/constants.js.map +1 -1
  9. package/dist/helpers/GasFeePoller.d.ts.map +1 -1
  10. package/dist/helpers/GasFeePoller.js +4 -5
  11. package/dist/helpers/GasFeePoller.js.map +1 -1
  12. package/dist/helpers/IncomingTransactionHelper.d.ts.map +1 -1
  13. package/dist/helpers/IncomingTransactionHelper.js +1 -2
  14. package/dist/helpers/IncomingTransactionHelper.js.map +1 -1
  15. package/dist/helpers/PendingTransactionTracker.d.ts.map +1 -1
  16. package/dist/helpers/PendingTransactionTracker.js +18 -22
  17. package/dist/helpers/PendingTransactionTracker.js.map +1 -1
  18. package/dist/index.d.ts +5 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +14 -19
  21. package/dist/index.js.map +1 -1
  22. package/dist/types.d.ts +24 -65
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/types.js.map +1 -1
  25. package/dist/utils/history.d.ts +9 -4
  26. package/dist/utils/history.d.ts.map +1 -1
  27. package/dist/utils/history.js +12 -7
  28. package/dist/utils/history.js.map +1 -1
  29. package/dist/utils/swaps.d.ts +8 -5
  30. package/dist/utils/swaps.d.ts.map +1 -1
  31. package/dist/utils/swaps.js +47 -41
  32. package/dist/utils/swaps.js.map +1 -1
  33. package/dist/utils/utils.d.ts +9 -1
  34. package/dist/utils/utils.d.ts.map +1 -1
  35. package/dist/utils/utils.js +35 -6
  36. package/dist/utils/utils.js.map +1 -1
  37. package/package.json +6 -5
@@ -22,9 +22,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
22
22
  var __importDefault = (this && this.__importDefault) || function (mod) {
23
23
  return (mod && mod.__esModule) ? mod : { "default": mod };
24
24
  };
25
- var _TransactionController_instances, _TransactionController_incomingTransactionOptions, _TransactionController_pendingTransactionOptions, _TransactionController_multichainTrackingHelper, _TransactionController_createNonceTracker, _TransactionController_createIncomingTransactionHelper, _TransactionController_createPendingTransactionTracker, _TransactionController_checkForPendingTransactionAndStartPolling, _TransactionController_stopAllTracking, _TransactionController_removeIncomingTransactionHelperListeners, _TransactionController_addIncomingTransactionHelperListeners, _TransactionController_removePendingTransactionTrackerListeners, _TransactionController_addPendingTransactionTrackerListeners, _TransactionController_getNonceTrackerPendingTransactions, _TransactionController_getGasFeeFlows, _TransactionController_updateTransactionInternal;
25
+ var _TransactionController_instances, _TransactionController_internalEvents, _TransactionController_incomingTransactionOptions, _TransactionController_pendingTransactionOptions, _TransactionController_transactionHistoryLimit, _TransactionController_multichainTrackingHelper, _TransactionController_createNonceTracker, _TransactionController_createIncomingTransactionHelper, _TransactionController_createPendingTransactionTracker, _TransactionController_checkForPendingTransactionAndStartPolling, _TransactionController_stopAllTracking, _TransactionController_removeIncomingTransactionHelperListeners, _TransactionController_addIncomingTransactionHelperListeners, _TransactionController_removePendingTransactionTrackerListeners, _TransactionController_addPendingTransactionTrackerListeners, _TransactionController_getNonceTrackerPendingTransactions, _TransactionController_getGasFeeFlows, _TransactionController_updateTransactionInternal;
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.TransactionController = exports.SPEED_UP_RATE = exports.CANCEL_RATE = exports.HARDFORK = void 0;
27
+ exports.TransactionController = exports.ApprovalState = exports.SPEED_UP_RATE = exports.CANCEL_RATE = exports.HARDFORK = void 0;
28
28
  const common_1 = require("@ethereumjs/common");
29
29
  const tx_1 = require("@ethereumjs/tx");
30
30
  const util_1 = require("@ethereumjs/util");
@@ -58,6 +58,24 @@ const swaps_1 = require("./utils/swaps");
58
58
  const transaction_type_1 = require("./utils/transaction-type");
59
59
  const utils_2 = require("./utils/utils");
60
60
  const validation_1 = require("./utils/validation");
61
+ /**
62
+ * Metadata for the TransactionController state, describing how to "anonymize"
63
+ * the state and which parts should be persisted.
64
+ */
65
+ const metadata = {
66
+ transactions: {
67
+ persist: true,
68
+ anonymous: false,
69
+ },
70
+ methodData: {
71
+ persist: true,
72
+ anonymous: false,
73
+ },
74
+ lastFetchedBlockNumbers: {
75
+ persist: true,
76
+ anonymous: false,
77
+ },
78
+ };
61
79
  exports.HARDFORK = common_1.Hardfork.London;
62
80
  /**
63
81
  * Multiplier used to determine a transaction's increased gas fee during cancellation
@@ -71,42 +89,82 @@ exports.SPEED_UP_RATE = 1.1;
71
89
  * The name of the {@link TransactionController}.
72
90
  */
73
91
  const controllerName = 'TransactionController';
92
+ /**
93
+ * Possible states of the approve transaction step.
94
+ */
95
+ var ApprovalState;
96
+ (function (ApprovalState) {
97
+ ApprovalState["Approved"] = "approved";
98
+ ApprovalState["NotApproved"] = "not-approved";
99
+ ApprovalState["SkippedViaBeforePublishHook"] = "skipped-via-before-publish-hook";
100
+ })(ApprovalState = exports.ApprovalState || (exports.ApprovalState = {}));
101
+ /**
102
+ * Get the default TransactionsController state.
103
+ *
104
+ * @returns The default TransactionsController state.
105
+ */
106
+ function getDefaultTransactionControllerState() {
107
+ return {
108
+ methodData: {},
109
+ transactions: [],
110
+ lastFetchedBlockNumbers: {},
111
+ };
112
+ }
74
113
  /**
75
114
  * Controller responsible for submitting and managing transactions.
76
115
  */
77
- class TransactionController extends base_controller_1.BaseControllerV1 {
78
- constructor({ blockTracker, disableHistory, disableSendFlowHistory, disableSwaps, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getExternalPendingTransactions, getGasFeeEstimates, getNetworkState, getPermittedAccounts, getSavedGasFees, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, getNetworkClientRegistry, isMultichainEnabled = false, hooks, }, config, state) {
116
+ class TransactionController extends base_controller_1.BaseController {
117
+ /**
118
+ * Constructs a TransactionController.
119
+ *
120
+ * @param options - The controller options.
121
+ * @param options.blockTracker - The block tracker used to poll for new blocks data.
122
+ * @param options.disableHistory - Whether to disable storing history in transaction metadata.
123
+ * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
124
+ * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
125
+ * @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.
126
+ * @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.
127
+ * @param options.getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.
128
+ * @param options.getGasFeeEstimates - Callback to retrieve gas fee estimates.
129
+ * @param options.getNetworkClientRegistry - Gets the network client registry.
130
+ * @param options.getNetworkState - Gets the state of the network controller.
131
+ * @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.
132
+ * @param options.getSavedGasFees - Gets the saved gas fee config.
133
+ * @param options.getSelectedAddress - Gets the address of the currently selected account.
134
+ * @param options.incomingTransactions - Configuration options for incoming transaction support.
135
+ * @param options.isMultichainEnabled - Enable multichain support.
136
+ * @param options.messenger - The controller messenger.
137
+ * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
138
+ * @param options.pendingTransactions - Configuration options for pending transaction support.
139
+ * @param options.provider - The provider used to create the underlying EthQuery instance.
140
+ * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
141
+ * @param options.sign - Function used to sign transactions.
142
+ * @param options.state - Initial state to set on this controller.
143
+ * @param options.transactionHistoryLimit - Transaction history limit.
144
+ * @param options.hooks - The controller hooks.
145
+ */
146
+ constructor({ blockTracker, disableHistory, disableSendFlowHistory, disableSwaps, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getExternalPendingTransactions, getGasFeeEstimates, getNetworkClientRegistry, getNetworkState, getPermittedAccounts, getSavedGasFees, getSelectedAddress, incomingTransactions = {}, isMultichainEnabled = false, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, sign, state, transactionHistoryLimit = 40, hooks, }) {
79
147
  var _a, _b, _c, _d, _e, _f;
80
- super(config, state);
148
+ super({
149
+ name: controllerName,
150
+ metadata,
151
+ messenger,
152
+ state: Object.assign(Object.assign({}, getDefaultTransactionControllerState()), state),
153
+ });
81
154
  _TransactionController_instances.add(this);
155
+ _TransactionController_internalEvents.set(this, new events_1.EventEmitter());
82
156
  this.inProcessOfSigning = new Set();
83
157
  this.mutex = new async_mutex_1.Mutex();
84
158
  _TransactionController_incomingTransactionOptions.set(this, void 0);
85
159
  _TransactionController_pendingTransactionOptions.set(this, void 0);
86
160
  this.signAbortCallbacks = new Map();
161
+ _TransactionController_transactionHistoryLimit.set(this, void 0);
87
162
  _TransactionController_multichainTrackingHelper.set(this, void 0);
88
- /**
89
- * EventEmitter instance used to listen to specific transactional events
90
- */
91
- this.hub = new events_1.EventEmitter();
92
- /**
93
- * Name of this controller used during composition
94
- */
95
- this.name = 'TransactionController';
96
163
  _TransactionController_checkForPendingTransactionAndStartPolling.set(this, () => {
97
164
  // PendingTransactionTracker reads state through its getTransactions hook
98
165
  this.pendingTransactionTracker.startIfPendingTransactions();
99
166
  __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").checkForPendingTransactionAndStartPolling();
100
167
  });
101
- this.defaultConfig = {
102
- txHistoryLimit: 40,
103
- };
104
- this.defaultState = {
105
- methodData: {},
106
- transactions: [],
107
- lastFetchedBlockNumbers: {},
108
- };
109
- this.initialize();
110
168
  this.messagingSystem = messenger;
111
169
  this.getNetworkState = getNetworkState;
112
170
  this.isSendFlowHistoryDisabled = disableSendFlowHistory !== null && disableSendFlowHistory !== void 0 ? disableSendFlowHistory : false;
@@ -128,6 +186,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
128
186
  this.securityProviderRequest = securityProviderRequest;
129
187
  __classPrivateFieldSet(this, _TransactionController_incomingTransactionOptions, incomingTransactions, "f");
130
188
  __classPrivateFieldSet(this, _TransactionController_pendingTransactionOptions, pendingTransactions, "f");
189
+ __classPrivateFieldSet(this, _TransactionController_transactionHistoryLimit, transactionHistoryLimit, "f");
190
+ this.sign = sign;
131
191
  this.afterSign = (_a = hooks === null || hooks === void 0 ? void 0 : hooks.afterSign) !== null && _a !== void 0 ? _a : (() => true);
132
192
  this.beforeApproveOnInit = (_b = hooks === null || hooks === void 0 ? void 0 : hooks.beforeApproveOnInit) !== null && _b !== void 0 ? _b : (() => true);
133
193
  this.beforeCheckPendingTransaction =
@@ -187,13 +247,13 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
187
247
  getGasFeeControllerEstimates: this.getGasFeeEstimates,
188
248
  getTransactions: () => this.state.transactions,
189
249
  onStateChange: (listener) => {
190
- this.subscribe(listener);
250
+ this.messagingSystem.subscribe('TransactionController:stateChange', listener);
191
251
  },
192
252
  });
193
253
  gasFeePoller.hub.on('transaction-updated', (transactionMeta) => __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_updateTransactionInternal).call(this, transactionMeta, { skipHistory: true }));
194
254
  // when transactionsController state changes
195
255
  // check for pending transactions and start polling if there are any
196
- this.subscribe(__classPrivateFieldGet(this, _TransactionController_checkForPendingTransactionAndStartPolling, "f"));
256
+ this.messagingSystem.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _TransactionController_checkForPendingTransactionAndStartPolling, "f"));
197
257
  // TODO once v2 is merged make sure this only runs when
198
258
  // selectedNetworkClientId changes
199
259
  onNetworkStateChange(() => {
@@ -205,18 +265,25 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
205
265
  }
206
266
  failTransaction(transactionMeta, error, actionId) {
207
267
  const newTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { error: (0, utils_2.normalizeTxError)(error), status: types_1.TransactionStatus.failed });
208
- this.hub.emit('transaction-failed', {
268
+ this.messagingSystem.publish(`${controllerName}:transactionFailed`, {
209
269
  actionId,
210
270
  error: error.message,
211
271
  transactionMeta: newTransactionMeta,
212
272
  });
213
273
  this.updateTransaction(newTransactionMeta, 'TransactionController#failTransaction - Add error message and set status to failed');
214
274
  this.onTransactionStatusChange(newTransactionMeta);
215
- this.hub.emit(`${transactionMeta.id}:finished`, newTransactionMeta);
275
+ this.messagingSystem.publish(`${controllerName}:transactionFinished`, newTransactionMeta);
276
+ __classPrivateFieldGet(this, _TransactionController_internalEvents, "f").emit(`${transactionMeta.id}:finished`, newTransactionMeta);
216
277
  }
217
278
  registryLookup(fourBytePrefix) {
218
279
  return __awaiter(this, void 0, void 0, function* () {
219
280
  const registryMethod = yield this.registry.lookup(fourBytePrefix);
281
+ if (!registryMethod) {
282
+ return {
283
+ registryMethod: '',
284
+ parsedRegistryMethod: { name: undefined, args: undefined },
285
+ };
286
+ }
220
287
  const parsedRegistryMethod = this.registry.parse(registryMethod);
221
288
  return { registryMethod, parsedRegistryMethod };
222
289
  });
@@ -243,8 +310,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
243
310
  return methodData[fourBytePrefix];
244
311
  }
245
312
  const registry = yield this.registryLookup(fourBytePrefix);
246
- this.update({
247
- methodData: Object.assign(Object.assign({}, methodData), { [fourBytePrefix]: registry }),
313
+ this.update((state) => {
314
+ state.methodData[fourBytePrefix] = registry;
248
315
  });
249
316
  return registry;
250
317
  }
@@ -277,7 +344,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
277
344
  addTransaction(txParams, { actionId, deviceConfirmedOn, method, origin, requireApproval, securityAlertResponse, sendFlowHistory, swaps = {}, type, networkClientId, } = {}) {
278
345
  return __awaiter(this, void 0, void 0, function* () {
279
346
  (0, logger_1.projectLogger)('Adding transaction', txParams);
280
- txParams = (0, utils_2.normalizeTxParams)(txParams);
347
+ txParams = (0, utils_2.normalizeTransactionParams)(txParams);
281
348
  if (networkClientId &&
282
349
  !__classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").has(networkClientId)) {
283
350
  throw new Error('The networkClientId for this transaction could not be found');
@@ -296,7 +363,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
296
363
  const transactionType = type !== null && type !== void 0 ? type : (yield (0, transaction_type_1.determineTransactionType)(txParams, ethQuery)).type;
297
364
  const existingTransactionMeta = this.getTransactionWithActionId(actionId);
298
365
  // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
299
- const transactionMeta = existingTransactionMeta || {
366
+ let addedTransactionMeta = existingTransactionMeta
367
+ ? Object.assign({}, existingTransactionMeta) : {
300
368
  // Add actionId to txMeta to check if same actionId is seen again
301
369
  actionId,
302
370
  chainId,
@@ -313,38 +381,37 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
313
381
  type: transactionType,
314
382
  networkClientId,
315
383
  };
316
- yield this.updateGasProperties(transactionMeta);
384
+ yield this.updateGasProperties(addedTransactionMeta);
317
385
  // Checks if a transaction already exists with a given actionId
318
386
  if (!existingTransactionMeta) {
319
387
  // Set security provider response
320
388
  if (method && this.securityProviderRequest) {
321
- const securityProviderResponse = yield this.securityProviderRequest(transactionMeta, method);
322
- transactionMeta.securityProviderResponse = securityProviderResponse;
389
+ const securityProviderResponse = yield this.securityProviderRequest(addedTransactionMeta, method);
390
+ addedTransactionMeta.securityProviderResponse =
391
+ securityProviderResponse;
323
392
  }
324
393
  if (!this.isSendFlowHistoryDisabled) {
325
- transactionMeta.sendFlowHistory = sendFlowHistory !== null && sendFlowHistory !== void 0 ? sendFlowHistory : [];
394
+ addedTransactionMeta.sendFlowHistory = sendFlowHistory !== null && sendFlowHistory !== void 0 ? sendFlowHistory : [];
326
395
  }
327
396
  // Initial history push
328
397
  if (!this.isHistoryDisabled) {
329
- (0, history_1.addInitialHistorySnapshot)(transactionMeta);
398
+ addedTransactionMeta = (0, history_1.addInitialHistorySnapshot)(addedTransactionMeta);
330
399
  }
331
- yield (0, swaps_1.updateSwapsTransaction)(transactionMeta, transactionType, swaps, {
400
+ addedTransactionMeta = (0, swaps_1.updateSwapsTransaction)(addedTransactionMeta, transactionType, swaps, {
332
401
  isSwapsDisabled: this.isSwapsDisabled,
333
402
  cancelTransaction: this.cancelTransaction.bind(this),
334
- // TODO: Replace `any` with type
335
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
336
- controllerHubEmitter: this.hub.emit.bind(this.hub),
403
+ messenger: this.messagingSystem,
337
404
  });
338
- this.addMetadata(transactionMeta);
339
- this.hub.emit(`unapprovedTransaction`, transactionMeta);
405
+ this.addMetadata(addedTransactionMeta);
406
+ this.messagingSystem.publish(`${controllerName}:unapprovedTransactionAdded`, addedTransactionMeta);
340
407
  }
341
408
  return {
342
- result: this.processApproval(transactionMeta, {
409
+ result: this.processApproval(addedTransactionMeta, {
343
410
  isExisting: Boolean(existingTransactionMeta),
344
411
  requireApproval,
345
412
  actionId,
346
413
  }),
347
- transactionMeta,
414
+ transactionMeta: addedTransactionMeta,
348
415
  };
349
416
  });
350
417
  }
@@ -476,15 +543,16 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
476
543
  };
477
544
  this.addMetadata(cancelTransactionMeta);
478
545
  // stopTransaction has no approval request, so we assume the user has already approved the transaction
479
- this.hub.emit('transaction-approved', {
546
+ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
480
547
  transactionMeta: cancelTransactionMeta,
481
548
  actionId,
482
549
  });
483
- this.hub.emit('transaction-submitted', {
550
+ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
484
551
  transactionMeta: cancelTransactionMeta,
485
552
  actionId,
486
553
  });
487
- this.hub.emit(`${cancelTransactionMeta.id}:finished`, cancelTransactionMeta);
554
+ this.messagingSystem.publish(`${controllerName}:transactionFinished`, cancelTransactionMeta);
555
+ __classPrivateFieldGet(this, _TransactionController_internalEvents, "f").emit(`${transactionMeta.id}:finished`, cancelTransactionMeta);
488
556
  });
489
557
  }
490
558
  /**
@@ -542,33 +610,33 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
542
610
  ? Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas, type: types_1.TransactionEnvelopeType.feeMarket }) : Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, gasPrice: newGasPrice });
543
611
  const unsignedEthTx = this.prepareUnsignedEthTx(transactionMeta.chainId, txParams);
544
612
  const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
545
- yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
613
+ const transactionMetaWithRsv = yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
546
614
  const rawTx = (0, util_1.bufferToHex)(signedTx.serialize());
547
615
  const newFee = (_c = txParams.maxFeePerGas) !== null && _c !== void 0 ? _c : txParams.gasPrice;
548
616
  const oldFee = txParams.maxFeePerGas
549
- ? transactionMeta.txParams.maxFeePerGas
550
- : transactionMeta.txParams.gasPrice;
617
+ ? transactionMetaWithRsv.txParams.maxFeePerGas
618
+ : transactionMetaWithRsv.txParams.gasPrice;
551
619
  (0, logger_1.projectLogger)('Submitting speed up transaction', { oldFee, newFee, txParams });
552
620
  const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
553
621
  networkClientId: transactionMeta.networkClientId,
554
622
  chainId: transactionMeta.chainId,
555
623
  });
556
624
  const hash = yield this.publishTransactionForRetry(ethQuery, rawTx, transactionMeta);
557
- const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
625
+ const baseTransactionMeta = Object.assign(Object.assign({}, transactionMetaWithRsv), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
558
626
  actionId, originalGasEstimate: transactionMeta.txParams.gas, type: types_1.TransactionType.retry, originalType: transactionMeta.type });
559
627
  const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas
560
628
  ? Object.assign(Object.assign({}, baseTransactionMeta), { txParams: Object.assign(Object.assign({}, transactionMeta.txParams), { maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas }) }) : Object.assign(Object.assign({}, baseTransactionMeta), { txParams: Object.assign(Object.assign({}, transactionMeta.txParams), { gasPrice: newGasPrice }) });
561
629
  this.addMetadata(newTransactionMeta);
562
630
  // speedUpTransaction has no approval request, so we assume the user has already approved the transaction
563
- this.hub.emit('transaction-approved', {
631
+ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
564
632
  transactionMeta: newTransactionMeta,
565
633
  actionId,
566
634
  });
567
- this.hub.emit('transaction-submitted', {
635
+ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
568
636
  transactionMeta: newTransactionMeta,
569
637
  actionId,
570
638
  });
571
- this.hub.emit(`${transactionMeta.id}:speedup`, newTransactionMeta);
639
+ this.messagingSystem.publish(`${controllerName}:speedupTransactionAdded`, newTransactionMeta);
572
640
  });
573
641
  }
574
642
  /**
@@ -633,8 +701,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
633
701
  if (!transactionMeta) {
634
702
  throw new Error(`Cannot update security alert response as no transaction metadata found`);
635
703
  }
636
- const updatedMeta = (0, lodash_1.merge)(transactionMeta, { securityAlertResponse });
637
- this.updateTransaction(updatedMeta, 'TransactionController:updatesecurityAlertResponse - securityAlertResponse updated');
704
+ const updatedTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { securityAlertResponse });
705
+ this.updateTransaction(updatedTransactionMeta, `${controllerName}:updatesecurityAlertResponse - securityAlertResponse updated`);
638
706
  }
639
707
  /**
640
708
  * Removes all transactions from state, optionally based on the current network.
@@ -647,7 +715,9 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
647
715
  wipeTransactions(ignoreNetwork, address) {
648
716
  /* istanbul ignore next */
649
717
  if (ignoreNetwork && !address) {
650
- this.update({ transactions: [] });
718
+ this.update((state) => {
719
+ state.transactions = [];
720
+ });
651
721
  return;
652
722
  }
653
723
  const currentChainId = this.getChainId();
@@ -660,8 +730,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
660
730
  const isMatchingAddress = !address || ((_a = txParams.from) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase();
661
731
  return !isMatchingAddress;
662
732
  });
663
- this.update({
664
- transactions: this.trimTransactionsForState(newTransactions),
733
+ this.update((state) => {
734
+ state.transactions = this.trimTransactionsForState(newTransactions);
665
735
  });
666
736
  }
667
737
  /**
@@ -674,26 +744,23 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
674
744
  confirmExternalTransaction(transactionMeta, transactionReceipt, baseFeePerGas) {
675
745
  return __awaiter(this, void 0, void 0, function* () {
676
746
  // Run validation and add external transaction to state.
677
- this.addExternalTransaction(transactionMeta);
747
+ const newTransactionMeta = this.addExternalTransaction(transactionMeta);
678
748
  try {
679
- const transactionId = transactionMeta.id;
749
+ const transactionId = newTransactionMeta.id;
680
750
  // Make sure status is confirmed and define gasUsed as in receipt.
681
- transactionMeta.status = types_1.TransactionStatus.confirmed;
682
- transactionMeta.txReceipt = transactionReceipt;
751
+ const updatedTransactionMeta = Object.assign(Object.assign({}, newTransactionMeta), { status: types_1.TransactionStatus.confirmed, txReceipt: transactionReceipt });
683
752
  if (baseFeePerGas) {
684
- transactionMeta.baseFeePerGas = baseFeePerGas;
753
+ updatedTransactionMeta.baseFeePerGas = baseFeePerGas;
685
754
  }
686
755
  // Update same nonce local transactions as dropped and define replacedBy properties.
687
756
  this.markNonceDuplicatesDropped(transactionId);
688
757
  // Update external provided transaction with updated gas values and confirmed status.
689
- this.updateTransaction(transactionMeta, 'TransactionController:confirmExternalTransaction - Add external transaction');
690
- this.onTransactionStatusChange(transactionMeta);
758
+ this.updateTransaction(updatedTransactionMeta, `${controllerName}:confirmExternalTransaction - Add external transaction`);
759
+ this.onTransactionStatusChange(updatedTransactionMeta);
691
760
  // Intentional given potential duration of process.
692
761
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
693
- this.updatePostBalance(transactionMeta);
694
- this.hub.emit('transaction-confirmed', {
695
- transactionMeta,
696
- });
762
+ this.updatePostBalance(updatedTransactionMeta);
763
+ this.messagingSystem.publish(`${controllerName}:transactionConfirmed`, updatedTransactionMeta);
697
764
  }
698
765
  catch (error) {
699
766
  console.error('Failed to confirm external transaction', error);
@@ -709,7 +776,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
709
776
  * @returns The updated transactionMeta.
710
777
  */
711
778
  updateTransactionSendFlowHistory(transactionID, currentSendFlowHistoryLength, sendFlowHistoryToAdd) {
712
- var _a, _b;
779
+ var _a;
713
780
  if (this.isSendFlowHistoryDisabled) {
714
781
  throw new Error('Send flow history is disabled for the current transaction controller');
715
782
  }
@@ -718,13 +785,10 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
718
785
  throw new Error(`Cannot update send flow history as no transaction metadata found`);
719
786
  }
720
787
  (0, utils_2.validateIfTransactionUnapproved)(transactionMeta, 'updateTransactionSendFlowHistory');
721
- if (currentSendFlowHistoryLength ===
722
- (((_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.sendFlowHistory) === null || _a === void 0 ? void 0 : _a.length) || 0)) {
723
- transactionMeta.sendFlowHistory = [
724
- ...((_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.sendFlowHistory) !== null && _b !== void 0 ? _b : []),
725
- ...sendFlowHistoryToAdd,
726
- ];
727
- this.updateTransaction(transactionMeta, 'TransactionController:updateTransactionSendFlowHistory - sendFlowHistory updated');
788
+ const sendFlowHistory = (_a = transactionMeta.sendFlowHistory) !== null && _a !== void 0 ? _a : [];
789
+ if (currentSendFlowHistoryLength === sendFlowHistory.length) {
790
+ const updatedTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { sendFlowHistory: [...sendFlowHistory, ...sendFlowHistoryToAdd] });
791
+ this.updateTransaction(updatedTransactionMeta, `${controllerName}:updateTransactionSendFlowHistory - sendFlowHistory updated`);
728
792
  }
729
793
  return this.getTransaction(transactionID);
730
794
  }
@@ -774,7 +838,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
774
838
  transactionGasFees = (0, lodash_1.pickBy)(transactionGasFees);
775
839
  // merge updated gas values with existing transaction meta
776
840
  const updatedMeta = (0, lodash_1.merge)(transactionMeta, transactionGasFees);
777
- this.updateTransaction(updatedMeta, 'TransactionController:updateTransactionGasFees - gas values updated');
841
+ this.updateTransaction(updatedMeta, `${controllerName}:updateTransactionGasFees - gas values updated`);
778
842
  return this.getTransaction(transactionId);
779
843
  }
780
844
  /**
@@ -806,7 +870,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
806
870
  transactionPreviousGas.previousGas = (0, lodash_1.pickBy)(transactionPreviousGas.previousGas);
807
871
  // merge updated previous gas values with existing transaction meta
808
872
  const updatedMeta = (0, lodash_1.merge)(transactionMeta, transactionPreviousGas);
809
- this.updateTransaction(updatedMeta, 'TransactionController:updatePreviousGasParams - Previous gas values updated');
873
+ this.updateTransaction(updatedMeta, `${controllerName}:updatePreviousGasParams - Previous gas values updated`);
810
874
  return this.getTransaction(transactionId);
811
875
  }
812
876
  getNonceLock(address, networkClientId) {
@@ -950,16 +1014,16 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
950
1014
  ].includes(status)) {
951
1015
  throw new Error(`Cannot update custodial transaction with status: ${status}`);
952
1016
  }
953
- const updatedTransactionMeta = (0, lodash_1.merge)(transactionMeta, (0, lodash_1.pickBy)({ hash, status }));
1017
+ const updatedTransactionMeta = (0, lodash_1.merge)({}, transactionMeta, (0, lodash_1.pickBy)({ hash, status }));
954
1018
  if (status === types_1.TransactionStatus.submitted) {
955
1019
  updatedTransactionMeta.submittedTime = new Date().getTime();
956
1020
  }
957
1021
  if (status === types_1.TransactionStatus.failed) {
958
1022
  updatedTransactionMeta.error = (0, utils_2.normalizeTxError)(new Error(errorMessage));
959
1023
  }
960
- this.updateTransaction(updatedTransactionMeta, `TransactionController:updateCustodialTransaction - Custodial transaction updated`);
1024
+ this.updateTransaction(updatedTransactionMeta, `${controllerName}:updateCustodialTransaction - Custodial transaction updated`);
961
1025
  if ([types_1.TransactionStatus.submitted, types_1.TransactionStatus.failed].includes(status)) {
962
- this.hub.emit(`${transactionMeta.id}:finished`, updatedTransactionMeta);
1026
+ this.messagingSystem.publish(`${controllerName}:transactionFinished`, updatedTransactionMeta);
963
1027
  }
964
1028
  }
965
1029
  /**
@@ -1072,7 +1136,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1072
1136
  if (!this.sign) {
1073
1137
  throw new Error('No sign method defined.');
1074
1138
  }
1075
- const normalizedTransactionParams = (0, utils_2.normalizeTxParams)(transactionParams);
1139
+ const normalizedTransactionParams = (0, utils_2.normalizeTransactionParams)(transactionParams);
1076
1140
  const type = (0, utils_2.isEIP1559Transaction)(normalizedTransactionParams)
1077
1141
  ? types_1.TransactionEnvelopeType.feeMarket
1078
1142
  : types_1.TransactionEnvelopeType.legacy;
@@ -1090,7 +1154,9 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1090
1154
  */
1091
1155
  clearUnapprovedTransactions() {
1092
1156
  const transactions = this.state.transactions.filter(({ status }) => status !== types_1.TransactionStatus.unapproved);
1093
- this.update({ transactions: this.trimTransactionsForState(transactions) });
1157
+ this.update((state) => {
1158
+ state.transactions = this.trimTransactionsForState(transactions);
1159
+ });
1094
1160
  }
1095
1161
  /**
1096
1162
  * Stop the signing process for a specific transaction.
@@ -1110,9 +1176,12 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1110
1176
  this.signAbortCallbacks.delete(transactionId);
1111
1177
  }
1112
1178
  addMetadata(transactionMeta) {
1113
- const { transactions } = this.state;
1114
- transactions.push(transactionMeta);
1115
- this.update({ transactions: this.trimTransactionsForState(transactions) });
1179
+ this.update((state) => {
1180
+ state.transactions = this.trimTransactionsForState([
1181
+ ...state.transactions,
1182
+ transactionMeta,
1183
+ ]);
1184
+ });
1116
1185
  }
1117
1186
  updateGasProperties(transactionMeta) {
1118
1187
  return __awaiter(this, void 0, void 0, function* () {
@@ -1176,13 +1245,6 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1176
1245
  shouldShowRequest,
1177
1246
  });
1178
1247
  resultCallbacks = acceptResult.resultCallbacks;
1179
- if (resultCallbacks) {
1180
- this.hub.once(`${transactionId}:publish-skip`, () => {
1181
- resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
1182
- // Remove the reference to prevent additional reports once submitted.
1183
- resultCallbacks = undefined;
1184
- });
1185
- }
1186
1248
  const approvalValue = acceptResult.value;
1187
1249
  const updatedTransaction = approvalValue === null || approvalValue === void 0 ? void 0 : approvalValue.txMeta;
1188
1250
  if (updatedTransaction) {
@@ -1195,9 +1257,13 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1195
1257
  }
1196
1258
  const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
1197
1259
  if (!isTxCompleted) {
1198
- yield this.approveTransaction(transactionId);
1260
+ const approvalResult = yield this.approveTransaction(transactionId);
1261
+ if (approvalResult === ApprovalState.SkippedViaBeforePublishHook &&
1262
+ resultCallbacks) {
1263
+ resultCallbacks.success();
1264
+ }
1199
1265
  const updatedTransactionMeta = this.getTransaction(transactionId);
1200
- this.hub.emit('transaction-approved', {
1266
+ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
1201
1267
  transactionMeta: updatedTransactionMeta,
1202
1268
  actionId,
1203
1269
  });
@@ -1247,42 +1313,42 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1247
1313
  const releaseLock = yield this.mutex.acquire();
1248
1314
  const index = transactions.findIndex(({ id }) => transactionId === id);
1249
1315
  const transactionMeta = transactions[index];
1316
+ const updatedTransactionMeta = Object.assign({}, transactionMeta);
1250
1317
  const { txParams: { from }, networkClientId, } = transactionMeta;
1251
1318
  let releaseNonceLock;
1252
1319
  try {
1253
1320
  if (!this.sign) {
1254
1321
  releaseLock();
1255
1322
  this.failTransaction(transactionMeta, new Error('No sign method defined.'));
1256
- return;
1323
+ return ApprovalState.NotApproved;
1257
1324
  }
1258
1325
  else if (!transactionMeta.chainId) {
1259
1326
  releaseLock();
1260
1327
  this.failTransaction(transactionMeta, new Error('No chainId defined.'));
1261
- return;
1328
+ return ApprovalState.NotApproved;
1262
1329
  }
1263
1330
  if (this.inProcessOfSigning.has(transactionId)) {
1264
1331
  (0, logger_1.projectLogger)('Skipping approval as signing in progress', transactionId);
1265
- return;
1332
+ return ApprovalState.NotApproved;
1266
1333
  }
1267
1334
  const [nonce, releaseNonce] = yield (0, nonce_1.getNextNonce)(transactionMeta, (address) => __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getNonceLock(address, networkClientId));
1268
1335
  releaseNonceLock = releaseNonce;
1269
- transactionMeta.status = types_1.TransactionStatus.approved;
1270
- transactionMeta.txParams.nonce = nonce;
1271
- transactionMeta.txParams.chainId = transactionMeta.chainId;
1272
- const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
1273
- this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction approved');
1274
- this.onTransactionStatusChange(transactionMeta);
1275
- const isEIP1559 = (0, utils_2.isEIP1559Transaction)(transactionMeta.txParams);
1336
+ updatedTransactionMeta.status = types_1.TransactionStatus.approved;
1337
+ updatedTransactionMeta.txParams = Object.assign(Object.assign({}, updatedTransactionMeta.txParams), { nonce, chainId: transactionMeta.chainId });
1338
+ const baseTxParams = Object.assign(Object.assign({}, updatedTransactionMeta.txParams), { gasLimit: updatedTransactionMeta.txParams.gas });
1339
+ this.updateTransaction(updatedTransactionMeta, 'TransactionController#approveTransaction - Transaction approved');
1340
+ this.onTransactionStatusChange(updatedTransactionMeta);
1341
+ const isEIP1559 = (0, utils_2.isEIP1559Transaction)(updatedTransactionMeta.txParams);
1276
1342
  const txParams = isEIP1559
1277
- ? Object.assign(Object.assign({}, baseTxParams), { estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee, type: types_1.TransactionEnvelopeType.feeMarket }) : baseTxParams;
1278
- const rawTx = yield this.signTransaction(transactionMeta, txParams);
1279
- if (!this.beforePublish(transactionMeta)) {
1343
+ ? Object.assign(Object.assign({}, baseTxParams), { estimatedBaseFee: updatedTransactionMeta.txParams.estimatedBaseFee, type: types_1.TransactionEnvelopeType.feeMarket }) : baseTxParams;
1344
+ const rawTx = yield this.signTransaction(updatedTransactionMeta, txParams);
1345
+ if (!this.beforePublish(updatedTransactionMeta)) {
1280
1346
  (0, logger_1.projectLogger)('Skipping publishing transaction based on hook');
1281
- this.hub.emit(`${transactionMeta.id}:publish-skip`, transactionMeta);
1282
- return;
1347
+ this.messagingSystem.publish(`${controllerName}:transactionPublishingSkipped`, updatedTransactionMeta);
1348
+ return ApprovalState.SkippedViaBeforePublishHook;
1283
1349
  }
1284
1350
  if (!rawTx) {
1285
- return;
1351
+ return ApprovalState.NotApproved;
1286
1352
  }
1287
1353
  const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
1288
1354
  networkClientId: transactionMeta.networkClientId,
@@ -1291,8 +1357,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1291
1357
  if (transactionMeta.type === types_1.TransactionType.swap) {
1292
1358
  (0, logger_1.projectLogger)('Determining pre-transaction balance');
1293
1359
  const preTxBalance = yield (0, controller_utils_1.query)(ethQuery, 'getBalance', [from]);
1294
- transactionMeta.preTxBalance = preTxBalance;
1295
- (0, logger_1.projectLogger)('Updated pre-transaction balance', transactionMeta.preTxBalance);
1360
+ updatedTransactionMeta.preTxBalance = preTxBalance;
1361
+ (0, logger_1.projectLogger)('Updated pre-transaction balance', updatedTransactionMeta.preTxBalance);
1296
1362
  }
1297
1363
  (0, logger_1.projectLogger)('Publishing transaction', txParams);
1298
1364
  let { transactionHash: hash } = yield this.publish(transactionMeta, rawTx);
@@ -1300,20 +1366,23 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1300
1366
  hash = yield this.publishTransaction(ethQuery, rawTx);
1301
1367
  }
1302
1368
  (0, logger_1.projectLogger)('Publish successful', hash);
1303
- transactionMeta.hash = hash;
1304
- transactionMeta.status = types_1.TransactionStatus.submitted;
1305
- transactionMeta.submittedTime = new Date().getTime();
1306
- this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
1307
- this.hub.emit('transaction-submitted', {
1308
- transactionMeta,
1369
+ updatedTransactionMeta.hash = hash;
1370
+ updatedTransactionMeta.status = types_1.TransactionStatus.submitted;
1371
+ updatedTransactionMeta.submittedTime = new Date().getTime();
1372
+ this.updateTransaction(updatedTransactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
1373
+ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
1374
+ transactionMeta: updatedTransactionMeta,
1309
1375
  });
1310
- this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
1311
- this.onTransactionStatusChange(transactionMeta);
1376
+ this.messagingSystem.publish(`${controllerName}:transactionFinished`, updatedTransactionMeta);
1377
+ __classPrivateFieldGet(this, _TransactionController_internalEvents, "f").emit(`${updatedTransactionMeta.id}:finished`, updatedTransactionMeta);
1378
+ this.onTransactionStatusChange(updatedTransactionMeta);
1379
+ return ApprovalState.Approved;
1312
1380
  // TODO: Replace `any` with type
1313
1381
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1314
1382
  }
1315
1383
  catch (error) {
1316
1384
  this.failTransaction(transactionMeta, error);
1385
+ return ApprovalState.NotApproved;
1317
1386
  }
1318
1387
  finally {
1319
1388
  this.inProcessOfSigning.delete(transactionId);
@@ -1340,15 +1409,18 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1340
1409
  if (!transactionMeta) {
1341
1410
  return;
1342
1411
  }
1343
- transactionMeta.status = types_1.TransactionStatus.rejected;
1344
- const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
1345
- this.update({ transactions: this.trimTransactionsForState(transactions) });
1346
- this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
1347
- this.hub.emit('transaction-rejected', {
1348
- transactionMeta,
1412
+ this.update((state) => {
1413
+ const transactions = state.transactions.filter(({ id }) => id !== transactionId);
1414
+ state.transactions = this.trimTransactionsForState(transactions);
1415
+ });
1416
+ const updatedTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { status: types_1.TransactionStatus.rejected });
1417
+ this.messagingSystem.publish(`${controllerName}:transactionFinished`, updatedTransactionMeta);
1418
+ __classPrivateFieldGet(this, _TransactionController_internalEvents, "f").emit(`${transactionMeta.id}:finished`, updatedTransactionMeta);
1419
+ this.messagingSystem.publish(`${controllerName}:transactionRejected`, {
1420
+ transactionMeta: updatedTransactionMeta,
1349
1421
  actionId,
1350
1422
  });
1351
- this.onTransactionStatusChange(transactionMeta);
1423
+ this.onTransactionStatusChange(updatedTransactionMeta);
1352
1424
  }
1353
1425
  /**
1354
1426
  * Trim the amount of transactions that are set on the state. Checks
@@ -1357,25 +1429,25 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1357
1429
  * Pending or unapproved transactions will not be removed by this
1358
1430
  * operation. For safety of presenting a fully functional transaction UI
1359
1431
  * representation, this function will not break apart transactions with the
1360
- * same nonce, created on the same day, per network. Not accounting for transactions of the same
1361
- * nonce, same day and network combo can result in confusing or broken experiences
1362
- * in the UI. The transactions are then updated using the BaseControllerV1 update.
1432
+ * same nonce, created on the same day, per network. Not accounting for
1433
+ * transactions of the same nonce, same day and network combo can result in
1434
+ * confusing or broken experiences in the UI.
1363
1435
  *
1364
1436
  * @param transactions - The transactions to be applied to the state.
1365
1437
  * @returns The trimmed list of transactions.
1366
1438
  */
1367
1439
  trimTransactionsForState(transactions) {
1368
1440
  const nonceNetworkSet = new Set();
1369
- const txsToKeep = transactions
1441
+ const txsToKeep = [...transactions]
1370
1442
  .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order
1371
1443
  .filter((tx) => {
1372
1444
  const { chainId, status, txParams, time } = tx;
1373
1445
  if (txParams) {
1374
- const key = `${txParams.nonce}-${(0, controller_utils_1.convertHexToDecimal)(chainId)}-${new Date(time).toDateString()}`;
1446
+ const key = `${String(txParams.nonce)}-${(0, controller_utils_1.convertHexToDecimal)(chainId)}-${new Date(time).toDateString()}`;
1375
1447
  if (nonceNetworkSet.has(key)) {
1376
1448
  return true;
1377
1449
  }
1378
- else if (nonceNetworkSet.size < this.config.txHistoryLimit ||
1450
+ else if (nonceNetworkSet.size < __classPrivateFieldGet(this, _TransactionController_transactionHistoryLimit, "f") ||
1379
1451
  !this.isFinalState(status)) {
1380
1452
  nonceNetworkSet.add(key);
1381
1453
  return true;
@@ -1472,21 +1544,23 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1472
1544
  return common_1.Common.custom(customChainParams);
1473
1545
  }
1474
1546
  onIncomingTransactions({ added, updated, }) {
1475
- const { transactions: currentTransactions } = this.state;
1476
- const updatedTransactions = [
1477
- ...added,
1478
- ...currentTransactions.map((originalTransaction) => {
1479
- const updatedTransaction = updated.find(({ hash }) => hash === originalTransaction.hash);
1480
- return updatedTransaction !== null && updatedTransaction !== void 0 ? updatedTransaction : originalTransaction;
1481
- }),
1482
- ];
1483
- this.update({
1484
- transactions: this.trimTransactionsForState(updatedTransactions),
1547
+ this.update((state) => {
1548
+ const { transactions: currentTransactions } = state;
1549
+ const updatedTransactions = [
1550
+ ...added,
1551
+ ...currentTransactions.map((originalTransaction) => {
1552
+ const updatedTransaction = updated.find(({ hash }) => hash === originalTransaction.hash);
1553
+ return updatedTransaction !== null && updatedTransaction !== void 0 ? updatedTransaction : originalTransaction;
1554
+ }),
1555
+ ];
1556
+ state.transactions = this.trimTransactionsForState(updatedTransactions);
1485
1557
  });
1486
1558
  }
1487
1559
  onUpdatedLastFetchedBlockNumbers({ lastFetchedBlockNumbers, blockNumber, }) {
1488
- this.update({ lastFetchedBlockNumbers });
1489
- this.hub.emit('incomingTransactionBlock', blockNumber);
1560
+ this.update((state) => {
1561
+ state.lastFetchedBlockNumbers = lastFetchedBlockNumbers;
1562
+ });
1563
+ this.messagingSystem.publish(`${controllerName}:incomingTransactionBlockReceived`, blockNumber);
1490
1564
  }
1491
1565
  generateDappSuggestedGasFees(txParams, origin) {
1492
1566
  if (!origin || origin === controller_utils_1.ORIGIN_METAMASK) {
@@ -1517,6 +1591,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1517
1591
  * Validates and adds external provided transaction to state.
1518
1592
  *
1519
1593
  * @param transactionMeta - Nominated external transaction to be added to state.
1594
+ * @returns The new transaction.
1520
1595
  */
1521
1596
  addExternalTransaction(transactionMeta) {
1522
1597
  var _a, _b;
@@ -1529,15 +1604,16 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1529
1604
  const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
1530
1605
  (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
1531
1606
  // Make sure provided external transaction has non empty history array
1532
- if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
1533
- if (!this.isHistoryDisabled) {
1534
- (0, history_1.addInitialHistorySnapshot)(transactionMeta);
1535
- }
1536
- }
1537
- const updatedTransactions = [...transactions, transactionMeta];
1538
- this.update({
1539
- transactions: this.trimTransactionsForState(updatedTransactions),
1607
+ const newTransactionMeta = ((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length === 0 && !this.isHistoryDisabled
1608
+ ? (0, history_1.addInitialHistorySnapshot)(transactionMeta)
1609
+ : transactionMeta;
1610
+ this.update((state) => {
1611
+ state.transactions = this.trimTransactionsForState([
1612
+ ...state.transactions,
1613
+ newTransactionMeta,
1614
+ ]);
1540
1615
  });
1616
+ return newTransactionMeta;
1541
1617
  }
1542
1618
  /**
1543
1619
  * Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions
@@ -1554,20 +1630,26 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1554
1630
  const nonce = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.nonce;
1555
1631
  const from = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.from;
1556
1632
  const { chainId } = transactionMeta;
1557
- const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.id !== transactionId &&
1633
+ const sameNonceTransactions = this.state.transactions.filter((transaction) => transaction.id !== transactionId &&
1558
1634
  transaction.txParams.from === from &&
1559
1635
  transaction.txParams.nonce === nonce &&
1560
1636
  transaction.chainId === chainId &&
1561
1637
  transaction.type !== types_1.TransactionType.incoming);
1562
- if (!sameNonceTxs.length) {
1638
+ const sameNonceTransactionIds = sameNonceTransactions.map((transaction) => transaction.id);
1639
+ if (sameNonceTransactions.length === 0) {
1563
1640
  return;
1564
1641
  }
1565
- // Mark all same nonce transactions as dropped and give it a replacedBy hash
1566
- for (const transaction of sameNonceTxs) {
1567
- transaction.replacedBy = transactionMeta.hash;
1568
- transaction.replacedById = transactionMeta.id;
1569
- // Drop any transaction that wasn't previously failed (off chain failure)
1570
- if (transaction.status !== types_1.TransactionStatus.failed) {
1642
+ this.update((state) => {
1643
+ for (const transaction of state.transactions) {
1644
+ if (sameNonceTransactionIds.includes(transaction.id)) {
1645
+ transaction.replacedBy = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.hash;
1646
+ transaction.replacedById = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.id;
1647
+ }
1648
+ }
1649
+ });
1650
+ for (const transaction of this.state.transactions) {
1651
+ if (sameNonceTransactionIds.includes(transaction.id) &&
1652
+ transaction.status !== types_1.TransactionStatus.failed) {
1571
1653
  this.setTransactionStatusDropped(transaction);
1572
1654
  }
1573
1655
  }
@@ -1578,12 +1660,12 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1578
1660
  * @param transactionMeta - TransactionMeta of transaction to be marked as dropped.
1579
1661
  */
1580
1662
  setTransactionStatusDropped(transactionMeta) {
1581
- transactionMeta.status = types_1.TransactionStatus.dropped;
1582
- this.hub.emit('transaction-dropped', {
1583
- transactionMeta,
1663
+ const updatedTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { status: types_1.TransactionStatus.dropped });
1664
+ this.messagingSystem.publish(`${controllerName}:transactionDropped`, {
1665
+ transactionMeta: updatedTransactionMeta,
1584
1666
  });
1585
- this.updateTransaction(transactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
1586
- this.onTransactionStatusChange(transactionMeta);
1667
+ this.updateTransaction(updatedTransactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
1668
+ this.onTransactionStatusChange(updatedTransactionMeta);
1587
1669
  }
1588
1670
  /**
1589
1671
  * Get transaction with provided actionId.
@@ -1597,7 +1679,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1597
1679
  waitForTransactionFinished(transactionId) {
1598
1680
  return __awaiter(this, void 0, void 0, function* () {
1599
1681
  return new Promise((resolve) => {
1600
- this.hub.once(`${transactionId}:finished`, (txMeta) => {
1682
+ __classPrivateFieldGet(this, _TransactionController_internalEvents, "f").once(`${transactionId}:finished`, (txMeta) => {
1601
1683
  resolve(txMeta);
1602
1684
  });
1603
1685
  });
@@ -1612,13 +1694,15 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1612
1694
  */
1613
1695
  updateTransactionMetaRSV(transactionMeta, signedTx) {
1614
1696
  return __awaiter(this, void 0, void 0, function* () {
1697
+ const transactionMetaWithRsv = Object.assign({}, transactionMeta);
1615
1698
  for (const key of ['r', 's', 'v']) {
1616
1699
  const value = signedTx[key];
1617
1700
  if (value === undefined || value === null) {
1618
1701
  continue;
1619
1702
  }
1620
- transactionMeta[key] = (0, utils_1.add0x)(value.toString(16));
1703
+ transactionMetaWithRsv[key] = (0, utils_1.add0x)(value.toString(16));
1621
1704
  }
1705
+ return transactionMetaWithRsv;
1622
1706
  });
1623
1707
  }
1624
1708
  getEIP1559Compatibility(networkClientId) {
@@ -1648,18 +1732,19 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1648
1732
  (0, logger_1.projectLogger)('Skipping signed status based on hook');
1649
1733
  return undefined;
1650
1734
  }
1651
- yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
1652
- transactionMeta.status = types_1.TransactionStatus.signed;
1653
- this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction signed');
1654
- this.onTransactionStatusChange(transactionMeta);
1735
+ const transactionMetaWithRsv = Object.assign(Object.assign({}, (yield this.updateTransactionMetaRSV(transactionMeta, signedTx))), { status: types_1.TransactionStatus.signed });
1736
+ this.updateTransaction(transactionMetaWithRsv, 'TransactionController#approveTransaction - Transaction signed');
1737
+ this.onTransactionStatusChange(transactionMetaWithRsv);
1655
1738
  const rawTx = (0, util_1.bufferToHex)(signedTx.serialize());
1656
- transactionMeta.rawTx = rawTx;
1657
- this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - RawTransaction added');
1739
+ const transactionMetaWithRawTx = Object.assign(Object.assign({}, transactionMetaWithRsv), { rawTx });
1740
+ this.updateTransaction(transactionMetaWithRawTx, 'TransactionController#approveTransaction - RawTransaction added');
1658
1741
  return rawTx;
1659
1742
  });
1660
1743
  }
1661
1744
  onTransactionStatusChange(transactionMeta) {
1662
- this.hub.emit('transaction-status-update', { transactionMeta });
1745
+ this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, {
1746
+ transactionMeta,
1747
+ });
1663
1748
  }
1664
1749
  getNonceTrackerTransactions(status, address, chainId = this.getChainId()) {
1665
1750
  return (0, nonce_1.getAndFormatTransactionsForNonceTracker)(chainId, address, status, this.state.transactions);
@@ -1667,8 +1752,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1667
1752
  onConfirmedTransaction(transactionMeta) {
1668
1753
  (0, logger_1.projectLogger)('Processing confirmed transaction', transactionMeta.id);
1669
1754
  this.markNonceDuplicatesDropped(transactionMeta.id);
1670
- this.hub.emit('transaction-confirmed', { transactionMeta });
1671
- this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
1755
+ this.messagingSystem.publish(`${controllerName}:transactionConfirmed`, transactionMeta);
1672
1756
  this.onTransactionStatusChange(transactionMeta);
1673
1757
  // Intentional given potential duration of process.
1674
1758
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
@@ -1689,7 +1773,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1689
1773
  getTransaction: this.getTransaction.bind(this),
1690
1774
  updateTransaction: this.updateTransaction.bind(this),
1691
1775
  });
1692
- this.hub.emit('post-transaction-balance-updated', {
1776
+ this.messagingSystem.publish(`${controllerName}:postTransactionBalanceUpdated`, {
1693
1777
  transactionMeta: updatedTransactionMeta,
1694
1778
  approvalTransactionMeta,
1695
1779
  });
@@ -1731,7 +1815,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1731
1815
  }
1732
1816
  }
1733
1817
  exports.TransactionController = TransactionController;
1734
- _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionController_pendingTransactionOptions = new WeakMap(), _TransactionController_multichainTrackingHelper = new WeakMap(), _TransactionController_checkForPendingTransactionAndStartPolling = new WeakMap(), _TransactionController_instances = new WeakSet(), _TransactionController_createNonceTracker = function _TransactionController_createNonceTracker({ provider, blockTracker, chainId, }) {
1818
+ _TransactionController_internalEvents = new WeakMap(), _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionController_pendingTransactionOptions = new WeakMap(), _TransactionController_transactionHistoryLimit = new WeakMap(), _TransactionController_multichainTrackingHelper = new WeakMap(), _TransactionController_checkForPendingTransactionAndStartPolling = new WeakMap(), _TransactionController_instances = new WeakSet(), _TransactionController_createNonceTracker = function _TransactionController_createNonceTracker({ provider, blockTracker, chainId, }) {
1735
1819
  return new nonce_tracker_1.NonceTracker({
1736
1820
  // TODO: Replace `any` with type
1737
1821
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1749,7 +1833,7 @@ _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionC
1749
1833
  isEnabled: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").isEnabled,
1750
1834
  queryEntireHistory: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").queryEntireHistory,
1751
1835
  remoteTransactionSource: etherscanRemoteTransactionSource,
1752
- transactionLimit: this.config.txHistoryLimit,
1836
+ transactionLimit: __classPrivateFieldGet(this, _TransactionController_transactionHistoryLimit, "f"),
1753
1837
  updateTransactions: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").updateTransactions,
1754
1838
  });
1755
1839
  __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_addIncomingTransactionHelperListeners).call(this, incomingTransactionHelper);
@@ -1758,7 +1842,9 @@ _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionC
1758
1842
  const ethQuery = new eth_query_1.default(provider);
1759
1843
  const getChainId = chainId ? () => chainId : this.getChainId.bind(this);
1760
1844
  const pendingTransactionTracker = new PendingTransactionTracker_1.PendingTransactionTracker({
1761
- approveTransaction: this.approveTransaction.bind(this),
1845
+ approveTransaction: (transactionId) => __awaiter(this, void 0, void 0, function* () {
1846
+ yield this.approveTransaction(transactionId);
1847
+ }),
1762
1848
  blockTracker,
1763
1849
  getChainId,
1764
1850
  getEthQuery: () => ethQuery,
@@ -1804,14 +1890,14 @@ _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionC
1804
1890
  }, _TransactionController_getGasFeeFlows = function _TransactionController_getGasFeeFlows() {
1805
1891
  return [new LineaGasFeeFlow_1.LineaGasFeeFlow(), new DefaultGasFeeFlow_1.DefaultGasFeeFlow()];
1806
1892
  }, _TransactionController_updateTransactionInternal = function _TransactionController_updateTransactionInternal(transactionMeta, { note, skipHistory }) {
1807
- const { transactions } = this.state;
1808
- transactionMeta.txParams = (0, utils_2.normalizeTxParams)(transactionMeta.txParams);
1809
- (0, validation_1.validateTxParams)(transactionMeta.txParams);
1810
- if (skipHistory !== true) {
1811
- (0, history_1.updateTransactionHistory)(transactionMeta, note !== null && note !== void 0 ? note : 'Transaction updated');
1812
- }
1813
- const index = transactions.findIndex(({ id }) => transactionMeta.id === id);
1814
- transactions[index] = transactionMeta;
1815
- this.update({ transactions: this.trimTransactionsForState(transactions) });
1893
+ const normalizedTransaction = Object.assign(Object.assign({}, transactionMeta), { txParams: (0, utils_2.normalizeTransactionParams)(transactionMeta.txParams) });
1894
+ (0, validation_1.validateTxParams)(normalizedTransaction.txParams);
1895
+ const transactionWithUpdatedHistory = skipHistory === true
1896
+ ? normalizedTransaction
1897
+ : (0, history_1.updateTransactionHistory)(normalizedTransaction, note !== null && note !== void 0 ? note : 'Transaction updated');
1898
+ this.update((state) => {
1899
+ const index = state.transactions.findIndex(({ id }) => transactionMeta.id === id);
1900
+ state.transactions[index] = transactionWithUpdatedHistory;
1901
+ });
1816
1902
  };
1817
1903
  //# sourceMappingURL=TransactionController.js.map