@metamask/transaction-controller 18.0.0 → 18.2.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.
Files changed (62) hide show
  1. package/dist/EtherscanRemoteTransactionSource.d.ts +15 -0
  2. package/dist/EtherscanRemoteTransactionSource.d.ts.map +1 -0
  3. package/dist/EtherscanRemoteTransactionSource.js +122 -0
  4. package/dist/EtherscanRemoteTransactionSource.js.map +1 -0
  5. package/dist/IncomingTransactionHelper.d.ts +25 -0
  6. package/dist/IncomingTransactionHelper.d.ts.map +1 -0
  7. package/dist/IncomingTransactionHelper.js +198 -0
  8. package/dist/IncomingTransactionHelper.js.map +1 -0
  9. package/dist/TransactionController.d.ts +7 -1
  10. package/dist/TransactionController.d.ts.map +1 -1
  11. package/dist/TransactionController.js +55 -23
  12. package/dist/TransactionController.js.map +1 -1
  13. package/dist/constants.d.ts +4 -0
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/constants.js +5 -1
  16. package/dist/constants.js.map +1 -1
  17. package/dist/etherscan.d.ts +64 -0
  18. package/dist/etherscan.d.ts.map +1 -0
  19. package/dist/etherscan.js +109 -0
  20. package/dist/etherscan.js.map +1 -0
  21. package/dist/external-transactions.d.ts +10 -0
  22. package/dist/external-transactions.d.ts.map +1 -0
  23. package/dist/external-transactions.js +36 -0
  24. package/dist/external-transactions.js.map +1 -0
  25. package/dist/helpers/EtherscanRemoteTransactionSource.d.ts.map +1 -1
  26. package/dist/helpers/EtherscanRemoteTransactionSource.js +1 -0
  27. package/dist/helpers/EtherscanRemoteTransactionSource.js.map +1 -1
  28. package/dist/history.d.ts +15 -0
  29. package/dist/history.d.ts.map +1 -0
  30. package/dist/history.js +75 -0
  31. package/dist/history.js.map +1 -0
  32. package/dist/mocks/txsMock.d.ts +64 -0
  33. package/dist/mocks/txsMock.d.ts.map +1 -0
  34. package/dist/mocks/txsMock.js +515 -0
  35. package/dist/mocks/txsMock.js.map +1 -0
  36. package/dist/transaction-type.d.ts +14 -0
  37. package/dist/transaction-type.d.ts.map +1 -0
  38. package/dist/transaction-type.js +114 -0
  39. package/dist/transaction-type.js.map +1 -0
  40. package/dist/types.d.ts +2 -0
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/types.js.map +1 -1
  43. package/dist/utils/gas.d.ts.map +1 -1
  44. package/dist/utils/gas.js +4 -1
  45. package/dist/utils/gas.js.map +1 -1
  46. package/dist/utils/history.d.ts.map +1 -1
  47. package/dist/utils/history.js +3 -0
  48. package/dist/utils/history.js.map +1 -1
  49. package/dist/utils/nonce.d.ts +21 -0
  50. package/dist/utils/nonce.d.ts.map +1 -0
  51. package/dist/utils/nonce.js +76 -0
  52. package/dist/utils/nonce.js.map +1 -0
  53. package/dist/utils/utils.d.ts +0 -12
  54. package/dist/utils/utils.d.ts.map +1 -1
  55. package/dist/utils/utils.js +1 -33
  56. package/dist/utils/utils.js.map +1 -1
  57. package/dist/utils.d.ts +72 -0
  58. package/dist/utils.d.ts.map +1 -0
  59. package/dist/utils.js +235 -0
  60. package/dist/utils.js.map +1 -0
  61. package/package.json +3 -3
  62. package/CHANGELOG.md +0 -339
@@ -35,6 +35,7 @@ const external_transactions_1 = require("./utils/external-transactions");
35
35
  const gas_1 = require("./utils/gas");
36
36
  const gas_fees_1 = require("./utils/gas-fees");
37
37
  const history_1 = require("./utils/history");
38
+ const nonce_1 = require("./utils/nonce");
38
39
  const swaps_1 = require("./utils/swaps");
39
40
  const transaction_type_1 = require("./utils/transaction-type");
40
41
  const utils_1 = require("./utils/utils");
@@ -61,6 +62,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
61
62
  *
62
63
  * @param options - The controller options.
63
64
  * @param options.blockTracker - The block tracker used to poll for new blocks data.
65
+ * @param options.cancelMultiplier - Multiplier used to determine a transaction's increased gas fee during cancellation.
64
66
  * @param options.disableHistory - Whether to disable storing history in transaction metadata.
65
67
  * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
66
68
  * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
@@ -82,6 +84,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
82
84
  * @param options.pendingTransactions.isResubmitEnabled - Whether transaction publishing is automatically retried.
83
85
  * @param options.provider - The provider used to create the underlying EthQuery instance.
84
86
  * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
87
+ * @param options.speedUpMultiplier - Multiplier used to determine a transaction's increased gas fee during speed up.
85
88
  * @param options.hooks - The controller hooks.
86
89
  * @param options.hooks.afterSign - Additional logic to execute after signing a transaction. Return false to not change the status to signed.
87
90
  * @param options.hooks.beforeApproveOnInit - Additional logic to execute before starting an approval flow for a transaction during initialization. Return false to skip the transaction.
@@ -91,7 +94,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
91
94
  * @param config - Initial options used to configure this controller.
92
95
  * @param state - Initial state to set on this controller.
93
96
  */
94
- constructor({ blockTracker, disableHistory, disableSendFlowHistory, disableSwaps, getSavedGasFees, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getGasFeeEstimates, getNetworkState, getPermittedAccounts, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, hooks = {}, }, config, state) {
97
+ constructor({ blockTracker, cancelMultiplier, disableHistory, disableSendFlowHistory, disableSwaps, getSavedGasFees, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getGasFeeEstimates, getNetworkState, getPermittedAccounts, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, speedUpMultiplier, hooks = {}, }, config, state) {
95
98
  var _a, _b, _c, _d, _e;
96
99
  super(config, state);
97
100
  this.inProcessOfSigning = new Set();
@@ -131,6 +134,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
131
134
  this.getPermittedAccounts = getPermittedAccounts;
132
135
  this.getSelectedAddress = getSelectedAddress;
133
136
  this.securityProviderRequest = securityProviderRequest;
137
+ this.cancelMultiplier = cancelMultiplier !== null && cancelMultiplier !== void 0 ? cancelMultiplier : exports.CANCEL_RATE;
138
+ this.speedUpMultiplier = speedUpMultiplier !== null && speedUpMultiplier !== void 0 ? speedUpMultiplier : exports.SPEED_UP_RATE;
134
139
  this.afterSign = (_a = hooks === null || hooks === void 0 ? void 0 : hooks.afterSign) !== null && _a !== void 0 ? _a : (() => true);
135
140
  this.beforeApproveOnInit = (_b = hooks === null || hooks === void 0 ? void 0 : hooks.beforeApproveOnInit) !== null && _b !== void 0 ? _b : (() => true);
136
141
  this.beforeCheckPendingTransaction =
@@ -334,7 +339,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
334
339
  * @param options.estimatedBaseFee - The estimated base fee of the transaction.
335
340
  */
336
341
  stopTransaction(transactionId, gasValues, { estimatedBaseFee, actionId, } = {}) {
337
- var _a, _b;
342
+ var _a, _b, _c;
338
343
  return __awaiter(this, void 0, void 0, function* () {
339
344
  // If transaction is found for same action id, do not create a cancel transaction.
340
345
  if (this.getTransactionWithActionId(actionId)) {
@@ -345,6 +350,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
345
350
  gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
346
351
  (0, utils_1.validateGasValues)(gasValues);
347
352
  }
353
+ (0, logger_1.projectLogger)('Creating cancel transaction', transactionId, gasValues);
348
354
  const transactionMeta = this.getTransaction(transactionId);
349
355
  if (!transactionMeta) {
350
356
  return;
@@ -353,21 +359,21 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
353
359
  throw new Error('No sign method defined.');
354
360
  }
355
361
  // gasPrice (legacy non EIP1559)
356
- const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, exports.CANCEL_RATE);
362
+ const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, this.cancelMultiplier);
357
363
  const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
358
364
  const newGasPrice = (gasPriceFromValues &&
359
365
  (0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
360
366
  minGasPrice;
361
367
  // maxFeePerGas (EIP1559)
362
368
  const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
363
- const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, exports.CANCEL_RATE);
369
+ const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, this.cancelMultiplier);
364
370
  const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
365
371
  const newMaxFeePerGas = (maxFeePerGasValues &&
366
372
  (0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
367
373
  (existingMaxFeePerGas && minMaxFeePerGas);
368
374
  // maxPriorityFeePerGas (EIP1559)
369
375
  const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
370
- const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, exports.CANCEL_RATE);
376
+ const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, this.cancelMultiplier);
371
377
  const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
372
378
  const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
373
379
  (0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
@@ -394,6 +400,15 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
394
400
  const unsignedEthTx = this.prepareUnsignedEthTx(newTxParams);
395
401
  const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
396
402
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
403
+ const newFee = (_c = newTxParams.maxFeePerGas) !== null && _c !== void 0 ? _c : newTxParams.gasPrice;
404
+ const oldFee = newTxParams.maxFeePerGas
405
+ ? transactionMeta.txParams.maxFeePerGas
406
+ : transactionMeta.txParams.gasPrice;
407
+ (0, logger_1.projectLogger)('Submitting cancel transaction', {
408
+ oldFee,
409
+ newFee,
410
+ txParams: newTxParams,
411
+ });
397
412
  const hash = yield this.publishTransaction(rawTx);
398
413
  const cancelTransactionMeta = {
399
414
  actionId,
@@ -430,7 +445,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
430
445
  * @param options.estimatedBaseFee - The estimated base fee of the transaction.
431
446
  */
432
447
  speedUpTransaction(transactionId, gasValues, { actionId, estimatedBaseFee, } = {}) {
433
- var _a, _b;
448
+ var _a, _b, _c;
434
449
  return __awaiter(this, void 0, void 0, function* () {
435
450
  // If transaction is found for same action id, do not create a new speed up transaction.
436
451
  if (this.getTransactionWithActionId(actionId)) {
@@ -441,6 +456,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
441
456
  gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
442
457
  (0, utils_1.validateGasValues)(gasValues);
443
458
  }
459
+ (0, logger_1.projectLogger)('Creating speed up transaction', transactionId, gasValues);
444
460
  const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
445
461
  /* istanbul ignore next */
446
462
  if (!transactionMeta) {
@@ -451,21 +467,21 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
451
467
  throw new Error('No sign method defined.');
452
468
  }
453
469
  // gasPrice (legacy non EIP1559)
454
- const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, exports.SPEED_UP_RATE);
470
+ const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, this.speedUpMultiplier);
455
471
  const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
456
472
  const newGasPrice = (gasPriceFromValues &&
457
473
  (0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
458
474
  minGasPrice;
459
475
  // maxFeePerGas (EIP1559)
460
476
  const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
461
- const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, exports.SPEED_UP_RATE);
477
+ const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, this.speedUpMultiplier);
462
478
  const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
463
479
  const newMaxFeePerGas = (maxFeePerGasValues &&
464
480
  (0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
465
481
  (existingMaxFeePerGas && minMaxFeePerGas);
466
482
  // maxPriorityFeePerGas (EIP1559)
467
483
  const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
468
- const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, exports.SPEED_UP_RATE);
484
+ const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, this.speedUpMultiplier);
469
485
  const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
470
486
  const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
471
487
  (0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
@@ -476,6 +492,11 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
476
492
  const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
477
493
  yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
478
494
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
495
+ const newFee = (_c = txParams.maxFeePerGas) !== null && _c !== void 0 ? _c : txParams.gasPrice;
496
+ const oldFee = txParams.maxFeePerGas
497
+ ? transactionMeta.txParams.maxFeePerGas
498
+ : transactionMeta.txParams.gasPrice;
499
+ (0, logger_1.projectLogger)('Submitting speed up transaction', { oldFee, newFee, txParams });
479
500
  const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
480
501
  const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
481
502
  actionId, originalGasEstimate: transactionMeta.txParams.gas, type: types_1.TransactionType.retry, originalType: transactionMeta.type });
@@ -1070,6 +1091,15 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1070
1091
  resultCallbacks = undefined;
1071
1092
  });
1072
1093
  }
1094
+ const approvalValue = acceptResult.value;
1095
+ const updatedTransaction = approvalValue === null || approvalValue === void 0 ? void 0 : approvalValue.txMeta;
1096
+ if (updatedTransaction) {
1097
+ (0, logger_1.projectLogger)('Updating transaction with approval data', {
1098
+ customNonce: updatedTransaction.customNonceValue,
1099
+ params: updatedTransaction.txParams,
1100
+ });
1101
+ this.updateTransaction(updatedTransaction, 'TransactionController#processApproval - Updated with approval data');
1102
+ }
1073
1103
  }
1074
1104
  const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
1075
1105
  if (!isTxCompleted) {
@@ -1124,8 +1154,8 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1124
1154
  const chainId = this.getChainId();
1125
1155
  const index = transactions.findIndex(({ id }) => transactionId === id);
1126
1156
  const transactionMeta = transactions[index];
1127
- const { txParams: { nonce, from }, } = transactionMeta;
1128
- let nonceLock;
1157
+ const { txParams: { from }, } = transactionMeta;
1158
+ let releaseNonceLock;
1129
1159
  try {
1130
1160
  if (!this.sign) {
1131
1161
  releaseLock();
@@ -1141,15 +1171,10 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1141
1171
  (0, logger_1.projectLogger)('Skipping approval as signing in progress', transactionId);
1142
1172
  return;
1143
1173
  }
1144
- let nonceToUse = nonce;
1145
- // if a nonce already exists on the transactionMeta it means this is a speedup or cancel transaction
1146
- // so we want to reuse that nonce and hope that it beats the previous attempt to chain. Otherwise use a new locked nonce
1147
- if (!nonceToUse) {
1148
- nonceLock = yield this.nonceTracker.getNonceLock(from);
1149
- nonceToUse = (0, ethereumjs_util_1.addHexPrefix)(nonceLock.nextNonce.toString(16));
1150
- }
1174
+ const [nonce, releaseNonce] = yield (0, nonce_1.getNextNonce)(transactionMeta, this.nonceTracker);
1175
+ releaseNonceLock = releaseNonce;
1151
1176
  transactionMeta.status = types_1.TransactionStatus.approved;
1152
- transactionMeta.txParams.nonce = nonceToUse;
1177
+ transactionMeta.txParams.nonce = nonce;
1153
1178
  transactionMeta.txParams.chainId = chainId;
1154
1179
  const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
1155
1180
  this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction approved');
@@ -1166,7 +1191,15 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1166
1191
  if (!rawTx) {
1167
1192
  return;
1168
1193
  }
1194
+ if (transactionMeta.type === types_1.TransactionType.swap) {
1195
+ (0, logger_1.projectLogger)('Determining pre-transaction balance');
1196
+ const preTxBalance = yield (0, controller_utils_1.query)(this.ethQuery, 'getBalance', [from]);
1197
+ transactionMeta.preTxBalance = preTxBalance;
1198
+ (0, logger_1.projectLogger)('Updated pre-transaction balance', transactionMeta.preTxBalance);
1199
+ }
1200
+ (0, logger_1.projectLogger)('Publishing transaction', txParams);
1169
1201
  const hash = yield this.publishTransaction(rawTx);
1202
+ (0, logger_1.projectLogger)('Publish successful', hash);
1170
1203
  transactionMeta.hash = hash;
1171
1204
  transactionMeta.status = types_1.TransactionStatus.submitted;
1172
1205
  transactionMeta.submittedTime = new Date().getTime();
@@ -1183,9 +1216,7 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1183
1216
  finally {
1184
1217
  this.inProcessOfSigning.delete(transactionId);
1185
1218
  // must set transaction to submitted/failed before releasing lock
1186
- if (nonceLock) {
1187
- nonceLock.releaseLock();
1188
- }
1219
+ releaseNonceLock === null || releaseNonceLock === void 0 ? void 0 : releaseNonceLock();
1189
1220
  releaseLock();
1190
1221
  }
1191
1222
  });
@@ -1535,10 +1566,11 @@ class TransactionController extends base_controller_1.BaseControllerV1 {
1535
1566
  }
1536
1567
  getNonceTrackerTransactions(status, address) {
1537
1568
  const currentChainId = this.getChainId();
1538
- return (0, utils_1.getAndFormatTransactionsForNonceTracker)(currentChainId, address, status, this.state.transactions);
1569
+ return (0, nonce_1.getAndFormatTransactionsForNonceTracker)(currentChainId, address, status, this.state.transactions);
1539
1570
  }
1540
1571
  onConfirmedTransaction(transactionMeta) {
1541
1572
  (0, logger_1.projectLogger)('Processing confirmed transaction', transactionMeta.id);
1573
+ this.markNonceDuplicatesDropped(transactionMeta.id);
1542
1574
  this.hub.emit('transaction-confirmed', { transactionMeta });
1543
1575
  this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
1544
1576
  this.onTransactionStatusChange(transactionMeta);