@metamask/transaction-controller 11.0.0 → 13.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.
@@ -18,9 +18,9 @@ const tx_1 = require("@ethereumjs/tx");
18
18
  const base_controller_1 = require("@metamask/base-controller");
19
19
  const controller_utils_1 = require("@metamask/controller-utils");
20
20
  const eth_query_1 = __importDefault(require("@metamask/eth-query"));
21
+ const rpc_errors_1 = require("@metamask/rpc-errors");
21
22
  const async_mutex_1 = require("async-mutex");
22
23
  const eth_method_registry_1 = __importDefault(require("eth-method-registry"));
23
- const eth_rpc_errors_1 = require("eth-rpc-errors");
24
24
  const ethereumjs_util_1 = require("ethereumjs-util");
25
25
  const events_1 = require("events");
26
26
  const lodash_1 = require("lodash");
@@ -30,6 +30,7 @@ const EtherscanRemoteTransactionSource_1 = require("./EtherscanRemoteTransaction
30
30
  const external_transactions_1 = require("./external-transactions");
31
31
  const history_1 = require("./history");
32
32
  const IncomingTransactionHelper_1 = require("./IncomingTransactionHelper");
33
+ const transaction_type_1 = require("./transaction-type");
33
34
  const types_1 = require("./types");
34
35
  const utils_1 = require("./utils");
35
36
  exports.HARDFORK = common_1.Hardfork.London;
@@ -56,6 +57,8 @@ class TransactionController extends base_controller_1.BaseController {
56
57
  * @param options.blockTracker - The block tracker used to poll for new blocks data.
57
58
  * @param options.disableHistory - Whether to disable storing history in transaction metadata.
58
59
  * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
60
+ * @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.
61
+ * @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.
59
62
  * @param options.getNetworkState - Gets the state of the network controller.
60
63
  * @param options.getSelectedAddress - Gets the address of the currently selected account.
61
64
  * @param options.incomingTransactions - Configuration options for incoming transaction support.
@@ -69,7 +72,7 @@ class TransactionController extends base_controller_1.BaseController {
69
72
  * @param config - Initial options used to configure this controller.
70
73
  * @param state - Initial state to set on this controller.
71
74
  */
72
- constructor({ blockTracker, disableHistory, disableSendFlowHistory, getNetworkState, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, provider, }, config, state) {
75
+ constructor({ blockTracker, disableHistory, disableSendFlowHistory, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getNetworkState, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, provider, }, config, state) {
73
76
  super(config, state);
74
77
  this.mutex = new async_mutex_1.Mutex();
75
78
  /**
@@ -97,6 +100,10 @@ class TransactionController extends base_controller_1.BaseController {
97
100
  this.isSendFlowHistoryDisabled = disableSendFlowHistory !== null && disableSendFlowHistory !== void 0 ? disableSendFlowHistory : false;
98
101
  this.isHistoryDisabled = disableHistory !== null && disableHistory !== void 0 ? disableHistory : false;
99
102
  this.registry = new eth_method_registry_1.default({ provider });
103
+ this.getCurrentAccountEIP1559Compatibility =
104
+ getCurrentAccountEIP1559Compatibility;
105
+ this.getCurrentNetworkEIP1559Compatibility =
106
+ getCurrentNetworkEIP1559Compatibility;
100
107
  this.nonceTracker = new nonce_tracker_1.default({
101
108
  provider,
102
109
  blockTracker,
@@ -190,15 +197,18 @@ class TransactionController extends base_controller_1.BaseController {
190
197
  * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
191
198
  * @param opts.securityAlertResponse - Response from security validator.
192
199
  * @param opts.sendFlowHistory - The sendFlowHistory entries to add.
200
+ * @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.
193
201
  * @returns Object containing a promise resolving to the transaction hash if approved.
194
202
  */
195
- addTransaction(txParams, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, sendFlowHistory, } = {}) {
203
+ addTransaction(txParams, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, sendFlowHistory, type, } = {}) {
196
204
  return __awaiter(this, void 0, void 0, function* () {
197
- const { chainId, networkId } = this.getChainAndNetworkId();
205
+ const chainId = this.getChainId();
198
206
  const { transactions } = this.state;
199
207
  txParams = (0, utils_1.normalizeTxParams)(txParams);
200
- (0, utils_1.validateTxParams)(txParams);
208
+ const isEIP1559Compatible = yield this.getEIP1559Compatibility();
209
+ (0, utils_1.validateTxParams)(txParams, isEIP1559Compatible);
201
210
  const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
211
+ const transactionType = type !== null && type !== void 0 ? type : (yield (0, transaction_type_1.determineTransactionType)(txParams, this.ethQuery)).type;
202
212
  const existingTransactionMeta = this.getTransactionWithActionId(actionId);
203
213
  // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
204
214
  const transactionMeta = existingTransactionMeta || {
@@ -208,7 +218,6 @@ class TransactionController extends base_controller_1.BaseController {
208
218
  dappSuggestedGasFees,
209
219
  deviceConfirmedOn,
210
220
  id: (0, uuid_1.v1)(),
211
- networkID: networkId !== null && networkId !== void 0 ? networkId : undefined,
212
221
  origin,
213
222
  securityAlertResponse,
214
223
  status: types_1.TransactionStatus.unapproved,
@@ -216,6 +225,7 @@ class TransactionController extends base_controller_1.BaseController {
216
225
  txParams,
217
226
  userEditedGasLimit: false,
218
227
  verifiedOnBlockchain: false,
228
+ type: transactionType,
219
229
  };
220
230
  try {
221
231
  const { gas, estimateGasError } = yield this.estimateGas(txParams);
@@ -266,9 +276,9 @@ class TransactionController extends base_controller_1.BaseController {
266
276
  * Creates approvals for all unapproved transactions persisted.
267
277
  */
268
278
  initApprovals() {
269
- const { networkId, chainId } = this.getChainAndNetworkId();
279
+ const chainId = this.getChainId();
270
280
  const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
271
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
281
+ transaction.chainId === chainId);
272
282
  for (const txMeta of unapprovedTxs) {
273
283
  this.processApproval(txMeta, {
274
284
  shouldShowRequest: false,
@@ -406,7 +416,7 @@ class TransactionController extends base_controller_1.BaseController {
406
416
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
407
417
  const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
408
418
  const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
409
- actionId, originalGasEstimate: transactionMeta.txParams.gas });
419
+ actionId, originalGasEstimate: transactionMeta.txParams.gas, type: types_1.TransactionType.retry });
410
420
  const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas
411
421
  ? 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 }) });
412
422
  transactions.push(newTransactionMeta);
@@ -492,14 +502,10 @@ class TransactionController extends base_controller_1.BaseController {
492
502
  queryTransactionStatuses() {
493
503
  return __awaiter(this, void 0, void 0, function* () {
494
504
  const { transactions } = this.state;
495
- const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
505
+ const currentChainId = this.getChainId();
496
506
  let gotUpdates = false;
497
507
  yield (0, controller_utils_1.safelyExecute)(() => Promise.all(transactions.map((meta, index) => __awaiter(this, void 0, void 0, function* () {
498
- // Using fallback to networkID only when there is no chainId present.
499
- // Should be removed when networkID is completely removed.
500
- const txBelongsToCurrentChain = meta.chainId === currentChainId ||
501
- (!meta.chainId && meta.networkID === currentNetworkID);
502
- if (!meta.verifiedOnBlockchain && txBelongsToCurrentChain) {
508
+ if (!meta.verifiedOnBlockchain && meta.chainId === currentChainId) {
503
509
  const [reconciledTx, updateRequired] = yield this.blockchainTransactionStateReconciler(meta);
504
510
  if (updateRequired) {
505
511
  transactions[index] = reconciledTx;
@@ -546,13 +552,10 @@ class TransactionController extends base_controller_1.BaseController {
546
552
  this.update({ transactions: [] });
547
553
  return;
548
554
  }
549
- const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
550
- const newTransactions = this.state.transactions.filter(({ networkID, chainId, txParams }) => {
555
+ const currentChainId = this.getChainId();
556
+ const newTransactions = this.state.transactions.filter(({ chainId, txParams }) => {
551
557
  var _a;
552
- // Using fallback to networkID only when there is no chainId present. Should be removed when networkID is completely removed.
553
- const isMatchingNetwork = ignoreNetwork ||
554
- chainId === currentChainId ||
555
- (!chainId && networkID === currentNetworkID);
558
+ const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
556
559
  if (!isMatchingNetwork) {
557
560
  return true;
558
561
  }
@@ -697,9 +700,9 @@ class TransactionController extends base_controller_1.BaseController {
697
700
  catch (error) {
698
701
  const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
699
702
  if (!isTxCompleted) {
700
- if (error.code === eth_rpc_errors_1.errorCodes.provider.userRejectedRequest) {
703
+ if (error.code === rpc_errors_1.errorCodes.provider.userRejectedRequest) {
701
704
  this.cancelTransaction(transactionId);
702
- throw eth_rpc_errors_1.ethErrors.provider.userRejectedRequest('User rejected the transaction');
705
+ throw rpc_errors_1.providerErrors.userRejectedRequest('User rejected the transaction');
703
706
  }
704
707
  else {
705
708
  this.failTransaction(meta, error);
@@ -711,16 +714,16 @@ class TransactionController extends base_controller_1.BaseController {
711
714
  switch (finalMeta === null || finalMeta === void 0 ? void 0 : finalMeta.status) {
712
715
  case types_1.TransactionStatus.failed:
713
716
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(finalMeta.error);
714
- throw eth_rpc_errors_1.ethErrors.rpc.internal(finalMeta.error.message);
717
+ throw rpc_errors_1.rpcErrors.internal(finalMeta.error.message);
715
718
  case types_1.TransactionStatus.cancelled:
716
- const cancelError = eth_rpc_errors_1.ethErrors.rpc.internal('User cancelled the transaction');
719
+ const cancelError = rpc_errors_1.rpcErrors.internal('User cancelled the transaction');
717
720
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(cancelError);
718
721
  throw cancelError;
719
722
  case types_1.TransactionStatus.submitted:
720
723
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
721
724
  return finalMeta.hash;
722
725
  default:
723
- const internalError = eth_rpc_errors_1.ethErrors.rpc.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finalMeta || transactionId)}`);
726
+ const internalError = rpc_errors_1.rpcErrors.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finalMeta || transactionId)}`);
724
727
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(internalError);
725
728
  throw internalError;
726
729
  }
@@ -738,7 +741,7 @@ class TransactionController extends base_controller_1.BaseController {
738
741
  return __awaiter(this, void 0, void 0, function* () {
739
742
  const { transactions } = this.state;
740
743
  const releaseLock = yield this.mutex.acquire();
741
- const { chainId } = this.getChainAndNetworkId();
744
+ const chainId = this.getChainId();
742
745
  const index = transactions.findIndex(({ id }) => transactionId === id);
743
746
  const transactionMeta = transactions[index];
744
747
  const { txParams: { nonce, from }, } = transactionMeta;
@@ -837,9 +840,9 @@ class TransactionController extends base_controller_1.BaseController {
837
840
  const txsToKeep = transactions
838
841
  .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order
839
842
  .filter((tx) => {
840
- const { chainId, networkID, status, txParams, time } = tx;
843
+ const { chainId, status, txParams, time } = tx;
841
844
  if (txParams) {
842
- const key = `${txParams.nonce}-${chainId ? (0, controller_utils_1.convertHexToDecimal)(chainId) : networkID}-${new Date(time).toDateString()}`;
845
+ const key = `${txParams.nonce}-${(0, controller_utils_1.convertHexToDecimal)(chainId)}-${new Date(time).toDateString()}`;
843
846
  if (nonceNetworkSet.has(key)) {
844
847
  return true;
845
848
  }
@@ -990,10 +993,9 @@ class TransactionController extends base_controller_1.BaseController {
990
993
  const isCompleted = this.isLocalFinalState(transaction.status);
991
994
  return { meta: transaction, isCompleted };
992
995
  }
993
- getChainAndNetworkId() {
994
- const { networkId, providerConfig } = this.getNetworkState();
995
- const chainId = providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.chainId;
996
- return { networkId, chainId };
996
+ getChainId() {
997
+ const { providerConfig } = this.getNetworkState();
998
+ return providerConfig.chainId;
997
999
  }
998
1000
  prepareUnsignedEthTx(txParams) {
999
1001
  return tx_1.TransactionFactory.fromTxData(txParams, {
@@ -1011,7 +1013,7 @@ class TransactionController extends base_controller_1.BaseController {
1011
1013
  * @returns common configuration object
1012
1014
  */
1013
1015
  getCommonConfiguration() {
1014
- const { networkId, providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
1016
+ const { providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
1015
1017
  if (chain !== controller_utils_1.RPC &&
1016
1018
  chain !== controller_utils_1.NetworkType['linea-goerli'] &&
1017
1019
  chain !== controller_utils_1.NetworkType['linea-mainnet']) {
@@ -1020,7 +1022,6 @@ class TransactionController extends base_controller_1.BaseController {
1020
1022
  const customChainParams = {
1021
1023
  name,
1022
1024
  chainId: parseInt(chainId, 16),
1023
- networkId: networkId === null ? NaN : parseInt(networkId, undefined),
1024
1025
  defaultHardfork: exports.HARDFORK,
1025
1026
  };
1026
1027
  return common_1.Common.custom(customChainParams);
@@ -1075,11 +1076,11 @@ class TransactionController extends base_controller_1.BaseController {
1075
1076
  addExternalTransaction(transactionMeta) {
1076
1077
  var _a, _b;
1077
1078
  return __awaiter(this, void 0, void 0, function* () {
1078
- const { networkId, chainId } = this.getChainAndNetworkId();
1079
+ const chainId = this.getChainId();
1079
1080
  const { transactions } = this.state;
1080
1081
  const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
1081
1082
  const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
1082
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
1083
+ transaction.chainId === chainId);
1083
1084
  const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
1084
1085
  const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
1085
1086
  (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
@@ -1103,13 +1104,13 @@ class TransactionController extends base_controller_1.BaseController {
1103
1104
  */
1104
1105
  markNonceDuplicatesDropped(transactionId) {
1105
1106
  var _a, _b;
1106
- const { networkId, chainId } = this.getChainAndNetworkId();
1107
+ const chainId = this.getChainId();
1107
1108
  const transactionMeta = this.getTransaction(transactionId);
1108
1109
  const nonce = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.nonce;
1109
1110
  const from = (_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.from;
1110
1111
  const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.txParams.from === from &&
1111
1112
  transaction.txParams.nonce === nonce &&
1112
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
1113
+ transaction.chainId === chainId);
1113
1114
  if (!sameNonceTxs.length) {
1114
1115
  return;
1115
1116
  }
@@ -1173,6 +1174,14 @@ class TransactionController extends base_controller_1.BaseController {
1173
1174
  }
1174
1175
  });
1175
1176
  }
1177
+ getEIP1559Compatibility() {
1178
+ var _a, _b;
1179
+ return __awaiter(this, void 0, void 0, function* () {
1180
+ const currentNetworkIsEIP1559Compatible = yield this.getCurrentNetworkEIP1559Compatibility();
1181
+ const currentAccountIsEIP1559Compatible = (_b = (_a = this.getCurrentAccountEIP1559Compatibility) === null || _a === void 0 ? void 0 : _a.call(this)) !== null && _b !== void 0 ? _b : true;
1182
+ return (currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible);
1183
+ });
1184
+ }
1176
1185
  }
1177
1186
  exports.TransactionController = TransactionController;
1178
1187
  exports.default = TransactionController;