@metamask/transaction-controller 17.0.0 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,7 +24,7 @@ const eth_method_registry_1 = __importDefault(require("eth-method-registry"));
24
24
  const ethereumjs_util_1 = require("ethereumjs-util");
25
25
  const events_1 = require("events");
26
26
  const lodash_1 = require("lodash");
27
- const nonce_tracker_1 = __importDefault(require("nonce-tracker"));
27
+ const nonce_tracker_1 = require("nonce-tracker");
28
28
  const uuid_1 = require("uuid");
29
29
  const EtherscanRemoteTransactionSource_1 = require("./helpers/EtherscanRemoteTransactionSource");
30
30
  const IncomingTransactionHelper_1 = require("./helpers/IncomingTransactionHelper");
@@ -55,7 +55,7 @@ const controllerName = 'TransactionController';
55
55
  /**
56
56
  * Controller responsible for submitting and managing transactions.
57
57
  */
58
- class TransactionController extends base_controller_1.BaseController {
58
+ class TransactionController extends base_controller_1.BaseControllerV1 {
59
59
  /**
60
60
  * Creates a TransactionController instance.
61
61
  *
@@ -123,7 +123,7 @@ class TransactionController extends base_controller_1.BaseController {
123
123
  this.registry = new eth_method_registry_1.default({ provider });
124
124
  this.getSavedGasFees = getSavedGasFees !== null && getSavedGasFees !== void 0 ? getSavedGasFees : ((_chainId) => undefined);
125
125
  this.getCurrentAccountEIP1559Compatibility =
126
- getCurrentAccountEIP1559Compatibility;
126
+ getCurrentAccountEIP1559Compatibility !== null && getCurrentAccountEIP1559Compatibility !== void 0 ? getCurrentAccountEIP1559Compatibility : (() => Promise.resolve(true));
127
127
  this.getCurrentNetworkEIP1559Compatibility =
128
128
  getCurrentNetworkEIP1559Compatibility;
129
129
  this.getGasFeeEstimates =
@@ -140,11 +140,12 @@ class TransactionController extends base_controller_1.BaseController {
140
140
  this.beforePublish = (_d = hooks === null || hooks === void 0 ? void 0 : hooks.beforePublish) !== null && _d !== void 0 ? _d : (() => true);
141
141
  this.getAdditionalSignArguments =
142
142
  (_e = hooks === null || hooks === void 0 ? void 0 : hooks.getAdditionalSignArguments) !== null && _e !== void 0 ? _e : (() => []);
143
- this.nonceTracker = new nonce_tracker_1.default({
143
+ this.nonceTracker = new nonce_tracker_1.NonceTracker({
144
+ // @ts-expect-error provider types misaligned: SafeEventEmitterProvider vs Record<string,string>
144
145
  provider,
145
146
  blockTracker,
146
- getPendingTransactions: (address) => (0, utils_1.getAndFormatTransactionsForNonceTracker)(address, types_1.TransactionStatus.submitted, this.state.transactions),
147
- getConfirmedTransactions: (address) => (0, utils_1.getAndFormatTransactionsForNonceTracker)(address, types_1.TransactionStatus.confirmed, this.state.transactions),
147
+ getPendingTransactions: this.getNonceTrackerTransactions.bind(this, types_1.TransactionStatus.submitted),
148
+ getConfirmedTransactions: this.getNonceTrackerTransactions.bind(this, types_1.TransactionStatus.confirmed),
148
149
  });
149
150
  this.incomingTransactionHelper = new IncomingTransactionHelper_1.IncomingTransactionHelper({
150
151
  blockTracker,
@@ -192,6 +193,7 @@ class TransactionController extends base_controller_1.BaseController {
192
193
  transactionMeta: newTransactionMeta,
193
194
  });
194
195
  this.updateTransaction(newTransactionMeta, 'TransactionController#failTransaction - Add error message and set status to failed');
196
+ this.onTransactionStatusChange(newTransactionMeta);
195
197
  this.hub.emit(`${transactionMeta.id}:finished`, newTransactionMeta);
196
198
  }
197
199
  registryLookup(fourBytePrefix) {
@@ -249,7 +251,7 @@ class TransactionController extends base_controller_1.BaseController {
249
251
  */
250
252
  addTransaction(txParams, { actionId, deviceConfirmedOn, method, origin, requireApproval, securityAlertResponse, sendFlowHistory, swaps = {}, type, } = {}) {
251
253
  return __awaiter(this, void 0, void 0, function* () {
252
- const chainId = this.getChainId();
254
+ (0, logger_1.projectLogger)('Adding transaction', txParams);
253
255
  txParams = (0, utils_1.normalizeTxParams)(txParams);
254
256
  const isEIP1559Compatible = yield this.getEIP1559Compatibility();
255
257
  (0, validation_1.validateTxParams)(txParams, isEIP1559Compatible);
@@ -259,6 +261,7 @@ class TransactionController extends base_controller_1.BaseController {
259
261
  const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
260
262
  const transactionType = type !== null && type !== void 0 ? type : (yield (0, transaction_type_1.determineTransactionType)(txParams, this.ethQuery)).type;
261
263
  const existingTransactionMeta = this.getTransactionWithActionId(actionId);
264
+ const chainId = this.getChainId();
262
265
  // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
263
266
  const transactionMeta = existingTransactionMeta || {
264
267
  // Add actionId to txMeta to check if same actionId is seen again
@@ -338,6 +341,8 @@ class TransactionController extends base_controller_1.BaseController {
338
341
  return;
339
342
  }
340
343
  if (gasValues) {
344
+ // Not good practice to reassign a parameter but temporarily avoiding a larger refactor.
345
+ gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
341
346
  (0, utils_1.validateGasValues)(gasValues);
342
347
  }
343
348
  const transactionMeta = this.getTransaction(transactionId);
@@ -373,7 +378,7 @@ class TransactionController extends base_controller_1.BaseController {
373
378
  gasLimit: transactionMeta.txParams.gas,
374
379
  maxFeePerGas: newMaxFeePerGas,
375
380
  maxPriorityFeePerGas: newMaxPriorityFeePerGas,
376
- type: '2',
381
+ type: types_1.TransactionEnvelopeType.feeMarket,
377
382
  nonce: transactionMeta.txParams.nonce,
378
383
  to: transactionMeta.txParams.from,
379
384
  value: '0x0',
@@ -432,6 +437,8 @@ class TransactionController extends base_controller_1.BaseController {
432
437
  return;
433
438
  }
434
439
  if (gasValues) {
440
+ // Not good practice to reassign a parameter but temporarily avoiding a larger refactor.
441
+ gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
435
442
  (0, utils_1.validateGasValues)(gasValues);
436
443
  }
437
444
  const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
@@ -464,7 +471,7 @@ class TransactionController extends base_controller_1.BaseController {
464
471
  (0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
465
472
  (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
466
473
  const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas
467
- ? Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas, type: '2' }) : Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, gasPrice: newGasPrice });
474
+ ? 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 });
468
475
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
469
476
  const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
470
477
  yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
@@ -606,29 +613,16 @@ class TransactionController extends base_controller_1.BaseController {
606
613
  this.markNonceDuplicatesDropped(transactionId);
607
614
  // Update external provided transaction with updated gas values and confirmed status.
608
615
  this.updateTransaction(transactionMeta, 'TransactionController:confirmExternalTransaction - Add external transaction');
609
- if (transactionMeta.type === types_1.TransactionType.swap) {
610
- (0, swaps_1.updatePostTransactionBalance)(transactionMeta, {
611
- ethQuery: this.ethQuery,
612
- getTransaction: this.getTransaction.bind(this),
613
- updateTransaction: this.updateTransaction.bind(this),
614
- })
615
- .then(({ updatedTransactionMeta, approvalTransactionMeta }) => {
616
- this.hub.emit('post-transaction-balance-updated', {
617
- transactionMeta: updatedTransactionMeta,
618
- approvalTransactionMeta,
619
- });
620
- })
621
- .catch((error) => {
622
- /* istanbul ignore next */
623
- (0, logger_1.projectLogger)('Error while updating post transaction balance', error);
624
- });
625
- }
616
+ this.onTransactionStatusChange(transactionMeta);
617
+ // Intentional given potential duration of process.
618
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
619
+ this.updatePostBalance(transactionMeta);
626
620
  this.hub.emit('transaction-confirmed', {
627
621
  transactionMeta,
628
622
  });
629
623
  }
630
624
  catch (error) {
631
- console.error(error);
625
+ console.error('Failed to confirm external transaction', error);
632
626
  }
633
627
  });
634
628
  }
@@ -749,6 +743,44 @@ class TransactionController extends base_controller_1.BaseController {
749
743
  return this.nonceTracker.getNonceLock(address);
750
744
  });
751
745
  }
746
+ /**
747
+ * Updates the editable parameters of a transaction.
748
+ *
749
+ * @param txId - The ID of the transaction to update.
750
+ * @param params - The editable parameters to update.
751
+ * @param params.data - Data to pass with the transaction.
752
+ * @param params.gas - Maximum number of units of gas to use for the transaction.
753
+ * @param params.gasPrice - Price per gas for legacy transactions.
754
+ * @param params.from - Address to send the transaction from.
755
+ * @param params.to - Address to send the transaction to.
756
+ * @param params.value - Value associated with the transaction.
757
+ * @returns The updated transaction metadata.
758
+ */
759
+ updateEditableParams(txId, { data, gas, gasPrice, from, to, value, }) {
760
+ return __awaiter(this, void 0, void 0, function* () {
761
+ const transactionMeta = this.getTransaction(txId);
762
+ if (!transactionMeta) {
763
+ throw new Error(`Cannot update editable params as no transaction metadata found`);
764
+ }
765
+ (0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateEditableParams');
766
+ const editableParams = {
767
+ txParams: {
768
+ data,
769
+ from,
770
+ to,
771
+ value,
772
+ gas,
773
+ gasPrice,
774
+ },
775
+ };
776
+ editableParams.txParams = (0, lodash_1.pickBy)(editableParams.txParams);
777
+ const updatedTransaction = (0, lodash_1.merge)(transactionMeta, editableParams);
778
+ const { type } = yield (0, transaction_type_1.determineTransactionType)(updatedTransaction.txParams, this.ethQuery);
779
+ updatedTransaction.type = type;
780
+ this.updateTransaction(updatedTransaction, `Update Editable Params for ${txId}`);
781
+ return this.getTransaction(txId);
782
+ });
783
+ }
752
784
  /**
753
785
  * Signs and returns the raw transaction data for provided transaction params list.
754
786
  *
@@ -801,14 +833,12 @@ class TransactionController extends base_controller_1.BaseController {
801
833
  *
802
834
  * @param transactionId - The ID of the transaction to update.
803
835
  * @param options - The custodial transaction options to update.
804
- * @param options.custodyStatus - The new custody status value to be assigned.
805
836
  * @param options.errorMessage - The error message to be assigned in case transaction status update to failed.
806
837
  * @param options.hash - The new hash value to be assigned.
807
838
  * @param options.status - The new status value to be assigned.
808
839
  */
809
- updateCustodialTransaction(transactionId, { custodyStatus, errorMessage, hash, status, }) {
810
- let transactionMeta;
811
- transactionMeta = this.getTransaction(transactionId);
840
+ updateCustodialTransaction(transactionId, { errorMessage, hash, status, }) {
841
+ const transactionMeta = this.getTransaction(transactionId);
812
842
  if (!transactionMeta) {
813
843
  throw new Error(`Cannot update custodial transaction as no transaction metadata found`);
814
844
  }
@@ -823,23 +853,112 @@ class TransactionController extends base_controller_1.BaseController {
823
853
  ].includes(status)) {
824
854
  throw new Error(`Cannot update custodial transaction with status: ${status}`);
825
855
  }
826
- if (status === types_1.TransactionStatus.signed) {
827
- transactionMeta.status = status;
828
- }
856
+ const updatedTransactionMeta = (0, lodash_1.merge)(transactionMeta, (0, lodash_1.pickBy)({ hash, status }));
829
857
  if (status === types_1.TransactionStatus.submitted) {
830
- transactionMeta.submittedTime = new Date().getTime();
831
- transactionMeta.status = status;
858
+ updatedTransactionMeta.submittedTime = new Date().getTime();
832
859
  }
833
860
  if (status === types_1.TransactionStatus.failed) {
834
- transactionMeta = Object.assign(Object.assign({}, transactionMeta), { error: (0, utils_1.normalizeTxError)(new Error(errorMessage)), status: types_1.TransactionStatus.failed });
861
+ updatedTransactionMeta.error = (0, utils_1.normalizeTxError)(new Error(errorMessage));
835
862
  }
836
- if (custodyStatus) {
837
- transactionMeta.custodyStatus = custodyStatus;
863
+ this.updateTransaction(updatedTransactionMeta, `TransactionController:updateCustodialTransaction - Custodial transaction updated`);
864
+ }
865
+ /**
866
+ * Creates approvals for all unapproved transactions persisted.
867
+ */
868
+ initApprovals() {
869
+ const chainId = this.getChainId();
870
+ const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
871
+ transaction.chainId === chainId);
872
+ for (const txMeta of unapprovedTxs) {
873
+ this.processApproval(txMeta, {
874
+ shouldShowRequest: false,
875
+ }).catch((error) => {
876
+ if ((error === null || error === void 0 ? void 0 : error.code) === rpc_errors_1.errorCodes.provider.userRejectedRequest) {
877
+ return;
878
+ }
879
+ console.error('Error during persisted transaction approval', error);
880
+ });
838
881
  }
839
- if (hash) {
840
- transactionMeta.hash = hash;
882
+ }
883
+ /**
884
+ * Search transaction metadata for matching entries.
885
+ *
886
+ * @param opts - Options bag.
887
+ * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
888
+ * @param opts.initialList - The transactions to search. Defaults to the current state.
889
+ * @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.
890
+ * @param opts.limit - The maximum number of transactions to return. No limit by default.
891
+ * @returns An array of transactions matching the provided options.
892
+ */
893
+ getTransactions({ searchCriteria = {}, initialList, filterToCurrentNetwork = true, limit, } = {}) {
894
+ const chainId = this.getChainId();
895
+ // searchCriteria is an object that might have values that aren't predicate
896
+ // methods. When providing any other value type (string, number, etc), we
897
+ // consider this shorthand for "check the value at key for strict equality
898
+ // with the provided value". To conform this object to be only methods, we
899
+ // mapValues (lodash) such that every value on the object is a method that
900
+ // returns a boolean.
901
+ const predicateMethods = (0, lodash_1.mapValues)(searchCriteria, (predicate) => {
902
+ return typeof predicate === 'function'
903
+ ? predicate
904
+ : (v) => v === predicate;
905
+ });
906
+ const transactionsToFilter = initialList !== null && initialList !== void 0 ? initialList : this.state.transactions;
907
+ // Combine sortBy and pickBy to transform our state object into an array of
908
+ // matching transactions that are sorted by time.
909
+ const filteredTransactions = (0, lodash_1.sortBy)((0, lodash_1.pickBy)(transactionsToFilter, (transaction) => {
910
+ if (filterToCurrentNetwork && transaction.chainId !== chainId) {
911
+ return false;
912
+ }
913
+ // iterate over the predicateMethods keys to check if the transaction
914
+ // matches the searchCriteria
915
+ for (const [key, predicate] of Object.entries(predicateMethods)) {
916
+ // We return false early as soon as we know that one of the specified
917
+ // search criteria do not match the transaction. This prevents
918
+ // needlessly checking all criteria when we already know the criteria
919
+ // are not fully satisfied. We check both txParams and the base
920
+ // object as predicate keys can be either.
921
+ if (key in transaction.txParams) {
922
+ if (predicate(transaction.txParams[key]) === false) {
923
+ return false;
924
+ }
925
+ }
926
+ else if (predicate(transaction[key]) === false) {
927
+ return false;
928
+ }
929
+ }
930
+ return true;
931
+ }), 'time');
932
+ if (limit !== undefined) {
933
+ // We need to have all transactions of a given nonce in order to display
934
+ // necessary details in the UI. We use the size of this set to determine
935
+ // whether we have reached the limit provided, thus ensuring that all
936
+ // transactions of nonces we include will be sent to the UI.
937
+ const nonces = new Set();
938
+ const txs = [];
939
+ // By default, the transaction list we filter from is sorted by time ASC.
940
+ // To ensure that filtered results prefers the newest transactions we
941
+ // iterate from right to left, inserting transactions into front of a new
942
+ // array. The original order is preserved, but we ensure that newest txs
943
+ // are preferred.
944
+ for (let i = filteredTransactions.length - 1; i > -1; i--) {
945
+ const txMeta = filteredTransactions[i];
946
+ const { nonce } = txMeta.txParams;
947
+ if (!nonces.has(nonce)) {
948
+ if (nonces.size < limit) {
949
+ nonces.add(nonce);
950
+ }
951
+ else {
952
+ continue;
953
+ }
954
+ }
955
+ // Push transaction into the beginning of our array to ensure the
956
+ // original order is preserved.
957
+ txs.unshift(txMeta);
958
+ }
959
+ return txs;
841
960
  }
842
- this.updateTransaction(transactionMeta, `TransactionController:updateCustodialTransaction - Custodial transaction updated`);
961
+ return filteredTransactions;
843
962
  }
844
963
  signExternalTransaction(transactionParams) {
845
964
  return __awaiter(this, void 0, void 0, function* () {
@@ -874,7 +993,8 @@ class TransactionController extends base_controller_1.BaseController {
874
993
  }
875
994
  updateGasProperties(transactionMeta) {
876
995
  return __awaiter(this, void 0, void 0, function* () {
877
- const isEIP1559Compatible = yield this.getEIP1559Compatibility();
996
+ const isEIP1559Compatible = (yield this.getEIP1559Compatibility()) &&
997
+ transactionMeta.txParams.type !== types_1.TransactionEnvelopeType.legacy;
878
998
  const chainId = this.getChainId();
879
999
  yield (0, gas_1.updateGas)({
880
1000
  ethQuery: this.ethQuery,
@@ -895,8 +1015,6 @@ class TransactionController extends base_controller_1.BaseController {
895
1015
  return this.state.transactions.filter((transaction) => transaction.status === status && transaction.chainId === chainId);
896
1016
  }
897
1017
  onBootCleanup() {
898
- this.createApprovalsForUnapprovedTransactions();
899
- this.loadGasValuesForUnapprovedTransactions();
900
1018
  this.submitApprovedTransactions();
901
1019
  }
902
1020
  /**
@@ -916,26 +1034,6 @@ class TransactionController extends base_controller_1.BaseController {
916
1034
  });
917
1035
  }
918
1036
  }
919
- /**
920
- * Update the gas values of all unapproved transactions on current chain.
921
- */
922
- loadGasValuesForUnapprovedTransactions() {
923
- return __awaiter(this, void 0, void 0, function* () {
924
- const unapprovedTransactions = this.getCurrentChainTransactionsByStatus(types_1.TransactionStatus.unapproved);
925
- const results = yield Promise.allSettled(unapprovedTransactions.map((transactionMeta) => __awaiter(this, void 0, void 0, function* () {
926
- yield this.updateGasProperties(transactionMeta);
927
- this.updateTransaction(transactionMeta, 'TransactionController:loadGasValuesForUnapprovedTransactions - Gas values updated');
928
- })));
929
- for (const [index, result] of results.entries()) {
930
- if (result.status === 'rejected') {
931
- const transactionMeta = unapprovedTransactions[index];
932
- this.failTransaction(transactionMeta, result.reason);
933
- /* istanbul ignore next */
934
- console.error('Error while loading gas values for persisted transaction id: ', transactionMeta.id, result.reason);
935
- }
936
- }
937
- });
938
- }
939
1037
  /**
940
1038
  * Force to submit approved transactions on current chain.
941
1039
  */
@@ -965,6 +1063,13 @@ class TransactionController extends base_controller_1.BaseController {
965
1063
  shouldShowRequest,
966
1064
  });
967
1065
  resultCallbacks = acceptResult.resultCallbacks;
1066
+ if (resultCallbacks) {
1067
+ this.hub.once(`${transactionId}:publish-skip`, () => {
1068
+ resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
1069
+ // Remove the reference to prevent additional reports once submitted.
1070
+ resultCallbacks = undefined;
1071
+ });
1072
+ }
968
1073
  }
969
1074
  const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
970
1075
  if (!isTxCompleted) {
@@ -1036,7 +1141,6 @@ class TransactionController extends base_controller_1.BaseController {
1036
1141
  (0, logger_1.projectLogger)('Skipping approval as signing in progress', transactionId);
1037
1142
  return;
1038
1143
  }
1039
- const { approved: status } = types_1.TransactionStatus;
1040
1144
  let nonceToUse = nonce;
1041
1145
  // if a nonce already exists on the transactionMeta it means this is a speedup or cancel transaction
1042
1146
  // so we want to reuse that nonce and hope that it beats the previous attempt to chain. Otherwise use a new locked nonce
@@ -1044,23 +1148,19 @@ class TransactionController extends base_controller_1.BaseController {
1044
1148
  nonceLock = yield this.nonceTracker.getNonceLock(from);
1045
1149
  nonceToUse = (0, ethereumjs_util_1.addHexPrefix)(nonceLock.nextNonce.toString(16));
1046
1150
  }
1047
- transactionMeta.status = status;
1151
+ transactionMeta.status = types_1.TransactionStatus.approved;
1048
1152
  transactionMeta.txParams.nonce = nonceToUse;
1049
1153
  transactionMeta.txParams.chainId = chainId;
1050
1154
  const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
1051
1155
  this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction approved');
1156
+ this.onTransactionStatusChange(transactionMeta);
1052
1157
  const isEIP1559 = (0, utils_1.isEIP1559Transaction)(transactionMeta.txParams);
1053
1158
  const txParams = isEIP1559
1054
- ? Object.assign(Object.assign({}, baseTxParams), { maxFeePerGas: transactionMeta.txParams.maxFeePerGas, maxPriorityFeePerGas: transactionMeta.txParams.maxPriorityFeePerGas, estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee,
1055
- // specify type 2 if maxFeePerGas and maxPriorityFeePerGas are set
1056
- type: '2' }) : baseTxParams;
1057
- // delete gasPrice if maxFeePerGas and maxPriorityFeePerGas are set
1058
- if (isEIP1559) {
1059
- delete txParams.gasPrice;
1060
- }
1061
- const rawTx = yield this.signTransaction(transactionMeta);
1159
+ ? Object.assign(Object.assign({}, baseTxParams), { estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee, type: types_1.TransactionEnvelopeType.feeMarket }) : baseTxParams;
1160
+ const rawTx = yield this.signTransaction(transactionMeta, txParams);
1062
1161
  if (!this.beforePublish(transactionMeta)) {
1063
1162
  (0, logger_1.projectLogger)('Skipping publishing transaction based on hook');
1163
+ this.hub.emit(`${transactionMeta.id}:publish-skip`, transactionMeta);
1064
1164
  return;
1065
1165
  }
1066
1166
  if (!rawTx) {
@@ -1070,11 +1170,12 @@ class TransactionController extends base_controller_1.BaseController {
1070
1170
  transactionMeta.hash = hash;
1071
1171
  transactionMeta.status = types_1.TransactionStatus.submitted;
1072
1172
  transactionMeta.submittedTime = new Date().getTime();
1173
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
1073
1174
  this.hub.emit('transaction-submitted', {
1074
1175
  transactionMeta,
1075
1176
  });
1076
- this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
1077
1177
  this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
1178
+ this.onTransactionStatusChange(transactionMeta);
1078
1179
  }
1079
1180
  catch (error) {
1080
1181
  this.failTransaction(transactionMeta, error);
@@ -1107,13 +1208,14 @@ class TransactionController extends base_controller_1.BaseController {
1107
1208
  return;
1108
1209
  }
1109
1210
  transactionMeta.status = types_1.TransactionStatus.rejected;
1211
+ const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
1212
+ this.update({ transactions: this.trimTransactionsForState(transactions) });
1110
1213
  this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
1111
1214
  this.hub.emit('transaction-rejected', {
1112
1215
  transactionMeta,
1113
1216
  actionId,
1114
1217
  });
1115
- const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
1116
- this.update({ transactions: this.trimTransactionsForState(transactions) });
1218
+ this.onTransactionStatusChange(transactionMeta);
1117
1219
  }
1118
1220
  /**
1119
1221
  * Trim the amount of transactions that are set on the state. Checks
@@ -1124,7 +1226,7 @@ class TransactionController extends base_controller_1.BaseController {
1124
1226
  * representation, this function will not break apart transactions with the
1125
1227
  * same nonce, created on the same day, per network. Not accounting for transactions of the same
1126
1228
  * nonce, same day and network combo can result in confusing or broken experiences
1127
- * in the UI. The transactions are then updated using the BaseController update.
1229
+ * in the UI. The transactions are then updated using the BaseControllerV1 update.
1128
1230
  *
1129
1231
  * @param transactions - The transactions to be applied to the state.
1130
1232
  * @returns The trimmed list of transactions.
@@ -1288,25 +1390,23 @@ class TransactionController extends base_controller_1.BaseController {
1288
1390
  */
1289
1391
  addExternalTransaction(transactionMeta) {
1290
1392
  var _a, _b;
1291
- return __awaiter(this, void 0, void 0, function* () {
1292
- const chainId = this.getChainId();
1293
- const { transactions } = this.state;
1294
- const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
1295
- const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
1296
- transaction.chainId === chainId);
1297
- const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
1298
- const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
1299
- (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
1300
- // Make sure provided external transaction has non empty history array
1301
- if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
1302
- if (!this.isHistoryDisabled) {
1303
- (0, history_1.addInitialHistorySnapshot)(transactionMeta);
1304
- }
1393
+ const chainId = this.getChainId();
1394
+ const { transactions } = this.state;
1395
+ const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
1396
+ const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
1397
+ transaction.chainId === chainId);
1398
+ const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
1399
+ const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
1400
+ (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
1401
+ // Make sure provided external transaction has non empty history array
1402
+ if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
1403
+ if (!this.isHistoryDisabled) {
1404
+ (0, history_1.addInitialHistorySnapshot)(transactionMeta);
1305
1405
  }
1306
- const updatedTransactions = [...transactions, transactionMeta];
1307
- this.update({
1308
- transactions: this.trimTransactionsForState(updatedTransactions),
1309
- });
1406
+ }
1407
+ const updatedTransactions = [...transactions, transactionMeta];
1408
+ this.update({
1409
+ transactions: this.trimTransactionsForState(updatedTransactions),
1310
1410
  });
1311
1411
  }
1312
1412
  /**
@@ -1351,6 +1451,7 @@ class TransactionController extends base_controller_1.BaseController {
1351
1451
  transactionMeta,
1352
1452
  });
1353
1453
  this.updateTransaction(transactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
1454
+ this.onTransactionStatusChange(transactionMeta);
1354
1455
  }
1355
1456
  /**
1356
1457
  * Get transaction with provided actionId.
@@ -1391,26 +1492,22 @@ class TransactionController extends base_controller_1.BaseController {
1391
1492
  });
1392
1493
  }
1393
1494
  getEIP1559Compatibility() {
1394
- var _a, _b;
1395
1495
  return __awaiter(this, void 0, void 0, function* () {
1396
1496
  const currentNetworkIsEIP1559Compatible = yield this.getCurrentNetworkEIP1559Compatibility();
1397
- const currentAccountIsEIP1559Compatible = (_b = (_a = this.getCurrentAccountEIP1559Compatibility) === null || _a === void 0 ? void 0 : _a.call(this)) !== null && _b !== void 0 ? _b : true;
1497
+ const currentAccountIsEIP1559Compatible = yield this.getCurrentAccountEIP1559Compatibility();
1398
1498
  return (currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible);
1399
1499
  });
1400
1500
  }
1401
1501
  addPendingTransactionTrackerListeners() {
1402
- this.pendingTransactionTracker.hub.on('transaction-confirmed', (transactionMeta) => {
1403
- this.hub.emit('transaction-confirmed', { transactionMeta });
1404
- this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
1405
- });
1502
+ this.pendingTransactionTracker.hub.on('transaction-confirmed', this.onConfirmedTransaction.bind(this));
1406
1503
  this.pendingTransactionTracker.hub.on('transaction-dropped', this.setTransactionStatusDropped.bind(this));
1407
1504
  this.pendingTransactionTracker.hub.on('transaction-failed', this.failTransaction.bind(this));
1408
1505
  this.pendingTransactionTracker.hub.on('transaction-updated', this.updateTransaction.bind(this));
1409
1506
  }
1410
- signTransaction(transactionMeta) {
1507
+ signTransaction(transactionMeta, txParams) {
1411
1508
  var _a;
1412
1509
  return __awaiter(this, void 0, void 0, function* () {
1413
- const { txParams } = transactionMeta;
1510
+ (0, logger_1.projectLogger)('Signing transaction', txParams);
1414
1511
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
1415
1512
  this.inProcessOfSigning.add(transactionMeta.id);
1416
1513
  const signedTx = yield ((_a = this.sign) === null || _a === void 0 ? void 0 : _a.call(this, unsignedEthTx, txParams.from, ...this.getAdditionalSignArguments(transactionMeta)));
@@ -1419,19 +1516,58 @@ class TransactionController extends base_controller_1.BaseController {
1419
1516
  return undefined;
1420
1517
  }
1421
1518
  if (!this.afterSign(transactionMeta, signedTx)) {
1519
+ this.updateTransaction(transactionMeta, 'TransactionController#signTransaction - Update after sign');
1422
1520
  (0, logger_1.projectLogger)('Skipping signed status based on hook');
1423
1521
  return undefined;
1424
1522
  }
1425
1523
  yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
1426
1524
  transactionMeta.status = types_1.TransactionStatus.signed;
1427
1525
  this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction signed');
1526
+ this.onTransactionStatusChange(transactionMeta);
1428
1527
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
1429
1528
  transactionMeta.rawTx = rawTx;
1430
1529
  this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - RawTransaction added');
1431
1530
  return rawTx;
1432
1531
  });
1433
1532
  }
1533
+ onTransactionStatusChange(transactionMeta) {
1534
+ this.hub.emit('transaction-status-update', { transactionMeta });
1535
+ }
1536
+ getNonceTrackerTransactions(status, address) {
1537
+ const currentChainId = this.getChainId();
1538
+ return (0, utils_1.getAndFormatTransactionsForNonceTracker)(currentChainId, address, status, this.state.transactions);
1539
+ }
1540
+ onConfirmedTransaction(transactionMeta) {
1541
+ (0, logger_1.projectLogger)('Processing confirmed transaction', transactionMeta.id);
1542
+ this.hub.emit('transaction-confirmed', { transactionMeta });
1543
+ this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
1544
+ this.onTransactionStatusChange(transactionMeta);
1545
+ // Intentional given potential duration of process.
1546
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
1547
+ this.updatePostBalance(transactionMeta);
1548
+ }
1549
+ updatePostBalance(transactionMeta) {
1550
+ return __awaiter(this, void 0, void 0, function* () {
1551
+ try {
1552
+ if (transactionMeta.type !== types_1.TransactionType.swap) {
1553
+ return;
1554
+ }
1555
+ const { updatedTransactionMeta, approvalTransactionMeta } = yield (0, swaps_1.updatePostTransactionBalance)(transactionMeta, {
1556
+ ethQuery: this.ethQuery,
1557
+ getTransaction: this.getTransaction.bind(this),
1558
+ updateTransaction: this.updateTransaction.bind(this),
1559
+ });
1560
+ this.hub.emit('post-transaction-balance-updated', {
1561
+ transactionMeta: updatedTransactionMeta,
1562
+ approvalTransactionMeta,
1563
+ });
1564
+ }
1565
+ catch (error) {
1566
+ /* istanbul ignore next */
1567
+ (0, logger_1.projectLogger)('Error while updating post transaction balance', error);
1568
+ }
1569
+ });
1570
+ }
1434
1571
  }
1435
1572
  exports.TransactionController = TransactionController;
1436
- exports.default = TransactionController;
1437
1573
  //# sourceMappingURL=TransactionController.js.map