@metamask/transaction-controller 10.0.0 → 11.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/dist/EtherscanRemoteTransactionSource.d.ts +2 -2
  3. package/dist/EtherscanRemoteTransactionSource.d.ts.map +1 -1
  4. package/dist/EtherscanRemoteTransactionSource.js +42 -19
  5. package/dist/EtherscanRemoteTransactionSource.js.map +1 -1
  6. package/dist/IncomingTransactionHelper.d.ts +4 -3
  7. package/dist/IncomingTransactionHelper.d.ts.map +1 -1
  8. package/dist/IncomingTransactionHelper.js +40 -25
  9. package/dist/IncomingTransactionHelper.js.map +1 -1
  10. package/dist/TransactionController.d.ts +73 -25
  11. package/dist/TransactionController.d.ts.map +1 -1
  12. package/dist/TransactionController.js +221 -98
  13. package/dist/TransactionController.js.map +1 -1
  14. package/dist/constants.d.ts +2 -0
  15. package/dist/constants.d.ts.map +1 -1
  16. package/dist/constants.js +26 -26
  17. package/dist/constants.js.map +1 -1
  18. package/dist/etherscan.d.ts +5 -6
  19. package/dist/etherscan.d.ts.map +1 -1
  20. package/dist/etherscan.js +7 -14
  21. package/dist/etherscan.js.map +1 -1
  22. package/dist/external-transactions.js +5 -5
  23. package/dist/external-transactions.js.map +1 -1
  24. package/dist/history.d.ts +15 -0
  25. package/dist/history.d.ts.map +1 -0
  26. package/dist/history.js +75 -0
  27. package/dist/history.js.map +1 -0
  28. package/dist/logger.d.ts +6 -0
  29. package/dist/logger.d.ts.map +1 -0
  30. package/dist/logger.js +8 -0
  31. package/dist/logger.js.map +1 -0
  32. package/dist/types.d.ts +107 -19
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/types.js.map +1 -1
  35. package/dist/utils.d.ts +19 -10
  36. package/dist/utils.d.ts.map +1 -1
  37. package/dist/utils.js +49 -34
  38. package/dist/utils.js.map +1 -1
  39. package/package.json +5 -3
@@ -23,10 +23,12 @@ const eth_method_registry_1 = __importDefault(require("eth-method-registry"));
23
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
+ const lodash_1 = require("lodash");
26
27
  const nonce_tracker_1 = __importDefault(require("nonce-tracker"));
27
28
  const uuid_1 = require("uuid");
28
29
  const EtherscanRemoteTransactionSource_1 = require("./EtherscanRemoteTransactionSource");
29
30
  const external_transactions_1 = require("./external-transactions");
31
+ const history_1 = require("./history");
30
32
  const IncomingTransactionHelper_1 = require("./IncomingTransactionHelper");
31
33
  const types_1 = require("./types");
32
34
  const utils_1 = require("./utils");
@@ -52,20 +54,22 @@ class TransactionController extends base_controller_1.BaseController {
52
54
  *
53
55
  * @param options - The controller options.
54
56
  * @param options.blockTracker - The block tracker used to poll for new blocks data.
57
+ * @param options.disableHistory - Whether to disable storing history in transaction metadata.
58
+ * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
55
59
  * @param options.getNetworkState - Gets the state of the network controller.
56
60
  * @param options.getSelectedAddress - Gets the address of the currently selected account.
57
61
  * @param options.incomingTransactions - Configuration options for incoming transaction support.
58
- * @param options.incomingTransactions.apiKey - An optional API key to use when fetching remote transaction data.
59
62
  * @param options.incomingTransactions.includeTokenTransfers - Whether or not to include ERC20 token transfers.
60
63
  * @param options.incomingTransactions.isEnabled - Whether or not incoming transaction retrieval is enabled.
61
- * @param options.incomingTransactions.updateTransactions - Whether or not to update local transactions using remote transaction data.
64
+ * @param options.incomingTransactions.queryEntireHistory - Whether to initially query the entire transaction history or only recent blocks.
65
+ * @param options.incomingTransactions.updateTransactions - Whether to update local transactions using remote transaction data.
62
66
  * @param options.messenger - The controller messenger.
63
67
  * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
64
68
  * @param options.provider - The provider used to create the underlying EthQuery instance.
65
69
  * @param config - Initial options used to configure this controller.
66
70
  * @param state - Initial state to set on this controller.
67
71
  */
68
- constructor({ blockTracker, getNetworkState, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, provider, }, config, state) {
72
+ constructor({ blockTracker, disableHistory, disableSendFlowHistory, getNetworkState, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, provider, }, config, state) {
69
73
  super(config, state);
70
74
  this.mutex = new async_mutex_1.Mutex();
71
75
  /**
@@ -90,6 +94,8 @@ class TransactionController extends base_controller_1.BaseController {
90
94
  this.messagingSystem = messenger;
91
95
  this.getNetworkState = getNetworkState;
92
96
  this.ethQuery = new eth_query_1.default(provider);
97
+ this.isSendFlowHistoryDisabled = disableSendFlowHistory !== null && disableSendFlowHistory !== void 0 ? disableSendFlowHistory : false;
98
+ this.isHistoryDisabled = disableHistory !== null && disableHistory !== void 0 ? disableHistory : false;
93
99
  this.registry = new eth_method_registry_1.default({ provider });
94
100
  this.nonceTracker = new nonce_tracker_1.default({
95
101
  provider,
@@ -100,10 +106,11 @@ class TransactionController extends base_controller_1.BaseController {
100
106
  this.incomingTransactionHelper = new IncomingTransactionHelper_1.IncomingTransactionHelper({
101
107
  blockTracker,
102
108
  getCurrentAccount: getSelectedAddress,
109
+ getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,
103
110
  getNetworkState,
104
111
  isEnabled: incomingTransactions.isEnabled,
112
+ queryEntireHistory: incomingTransactions.queryEntireHistory,
105
113
  remoteTransactionSource: new EtherscanRemoteTransactionSource_1.EtherscanRemoteTransactionSource({
106
- apiKey: incomingTransactions.apiKey,
107
114
  includeTokenTransfers: incomingTransactions.includeTokenTransfers,
108
115
  }),
109
116
  transactionLimit: this.config.txHistoryLimit,
@@ -119,7 +126,7 @@ class TransactionController extends base_controller_1.BaseController {
119
126
  }
120
127
  failTransaction(transactionMeta, error) {
121
128
  const newTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { error, status: types_1.TransactionStatus.failed });
122
- this.updateTransaction(newTransactionMeta);
129
+ this.updateTransaction(newTransactionMeta, 'TransactionController#failTransaction - Add error message and set status to failed');
123
130
  this.hub.emit(`${transactionMeta.id}:finished`, newTransactionMeta);
124
131
  }
125
132
  registryLookup(fourBytePrefix) {
@@ -175,43 +182,46 @@ class TransactionController extends base_controller_1.BaseController {
175
182
  * unique transaction id will be generated, and gas and gasPrice will be calculated
176
183
  * if not provided. If A `<tx.id>:unapproved` hub event will be emitted once added.
177
184
  *
178
- * @param transaction - The transaction object to add.
185
+ * @param txParams - Standard parameters for an Ethereum transaction.
179
186
  * @param opts - Additional options to control how the transaction is added.
180
187
  * @param opts.actionId - Unique ID to prevent duplicate requests.
181
188
  * @param opts.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.
182
189
  * @param opts.origin - The origin of the transaction request, such as a dApp hostname.
183
190
  * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
184
191
  * @param opts.securityAlertResponse - Response from security validator.
192
+ * @param opts.sendFlowHistory - The sendFlowHistory entries to add.
185
193
  * @returns Object containing a promise resolving to the transaction hash if approved.
186
194
  */
187
- addTransaction(transaction, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, } = {}) {
195
+ addTransaction(txParams, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, sendFlowHistory, } = {}) {
188
196
  return __awaiter(this, void 0, void 0, function* () {
189
197
  const { chainId, networkId } = this.getChainAndNetworkId();
190
198
  const { transactions } = this.state;
191
- transaction = (0, utils_1.normalizeTransaction)(transaction);
192
- (0, utils_1.validateTransaction)(transaction);
193
- const dappSuggestedGasFees = this.generateDappSuggestedGasFees(transaction, origin);
199
+ txParams = (0, utils_1.normalizeTxParams)(txParams);
200
+ (0, utils_1.validateTxParams)(txParams);
201
+ const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
194
202
  const existingTransactionMeta = this.getTransactionWithActionId(actionId);
195
203
  // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
196
204
  const transactionMeta = existingTransactionMeta || {
205
+ // Add actionId to txMeta to check if same actionId is seen again
206
+ actionId,
207
+ chainId,
208
+ dappSuggestedGasFees,
209
+ deviceConfirmedOn,
197
210
  id: (0, uuid_1.v1)(),
198
211
  networkID: networkId !== null && networkId !== void 0 ? networkId : undefined,
199
- chainId,
200
212
  origin,
213
+ securityAlertResponse,
201
214
  status: types_1.TransactionStatus.unapproved,
202
215
  time: Date.now(),
203
- transaction,
204
- deviceConfirmedOn,
216
+ txParams,
217
+ userEditedGasLimit: false,
205
218
  verifiedOnBlockchain: false,
206
- dappSuggestedGasFees,
207
- securityAlertResponse,
208
- // Add actionId to txMeta to check if same actionId is seen again
209
- actionId,
210
219
  };
211
220
  try {
212
- const { gas, estimateGasError } = yield this.estimateGas(transaction);
213
- transaction.gas = gas;
214
- transaction.estimateGasError = estimateGasError;
221
+ const { gas, estimateGasError } = yield this.estimateGas(txParams);
222
+ txParams.gas = gas;
223
+ txParams.estimateGasError = estimateGasError;
224
+ transactionMeta.originalGasEstimate = gas;
215
225
  }
216
226
  catch (error) {
217
227
  this.failTransaction(transactionMeta, error);
@@ -219,6 +229,13 @@ class TransactionController extends base_controller_1.BaseController {
219
229
  }
220
230
  // Checks if a transaction already exists with a given actionId
221
231
  if (!existingTransactionMeta) {
232
+ if (!this.isSendFlowHistoryDisabled) {
233
+ transactionMeta.sendFlowHistory = sendFlowHistory !== null && sendFlowHistory !== void 0 ? sendFlowHistory : [];
234
+ }
235
+ // Initial history push
236
+ if (!this.isHistoryDisabled) {
237
+ (0, history_1.addInitialHistorySnapshot)(transactionMeta);
238
+ }
222
239
  transactions.push(transactionMeta);
223
240
  this.update({
224
241
  transactions: this.trimTransactionsForState(transactions),
@@ -265,18 +282,18 @@ class TransactionController extends base_controller_1.BaseController {
265
282
  * Attempts to cancel a transaction based on its ID by setting its status to "rejected"
266
283
  * and emitting a `<tx.id>:finished` hub event.
267
284
  *
268
- * @param transactionID - The ID of the transaction to cancel.
285
+ * @param transactionId - The ID of the transaction to cancel.
269
286
  * @param gasValues - The gas values to use for the cancellation transaction.
270
287
  * @param options - The options for the cancellation transaction.
271
288
  * @param options.estimatedBaseFee - The estimated base fee of the transaction.
272
289
  */
273
- stopTransaction(transactionID, gasValues, { estimatedBaseFee } = {}) {
290
+ stopTransaction(transactionId, gasValues, { estimatedBaseFee } = {}) {
274
291
  var _a, _b;
275
292
  return __awaiter(this, void 0, void 0, function* () {
276
293
  if (gasValues) {
277
294
  (0, utils_1.validateGasValues)(gasValues);
278
295
  }
279
- const transactionMeta = this.state.transactions.find(({ id }) => id === transactionID);
296
+ const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
280
297
  if (!transactionMeta) {
281
298
  return;
282
299
  }
@@ -284,20 +301,20 @@ class TransactionController extends base_controller_1.BaseController {
284
301
  throw new Error('No sign method defined.');
285
302
  }
286
303
  // gasPrice (legacy non EIP1559)
287
- const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.transaction.gasPrice, exports.CANCEL_RATE);
304
+ const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, exports.CANCEL_RATE);
288
305
  const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
289
306
  const newGasPrice = (gasPriceFromValues &&
290
307
  (0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
291
308
  minGasPrice;
292
309
  // maxFeePerGas (EIP1559)
293
- const existingMaxFeePerGas = (_a = transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
310
+ const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
294
311
  const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, exports.CANCEL_RATE);
295
312
  const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
296
313
  const newMaxFeePerGas = (maxFeePerGasValues &&
297
314
  (0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
298
315
  (existingMaxFeePerGas && minMaxFeePerGas);
299
316
  // maxPriorityFeePerGas (EIP1559)
300
- const existingMaxPriorityFeePerGas = (_b = transactionMeta.transaction) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
317
+ const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
301
318
  const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, exports.CANCEL_RATE);
302
319
  const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
303
320
  const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
@@ -305,25 +322,26 @@ class TransactionController extends base_controller_1.BaseController {
305
322
  (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
306
323
  const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas
307
324
  ? {
308
- from: transactionMeta.transaction.from,
309
- gasLimit: transactionMeta.transaction.gas,
325
+ from: transactionMeta.txParams.from,
326
+ gasLimit: transactionMeta.txParams.gas,
310
327
  maxFeePerGas: newMaxFeePerGas,
311
328
  maxPriorityFeePerGas: newMaxPriorityFeePerGas,
312
329
  type: 2,
313
- nonce: transactionMeta.transaction.nonce,
314
- to: transactionMeta.transaction.from,
330
+ nonce: transactionMeta.txParams.nonce,
331
+ to: transactionMeta.txParams.from,
315
332
  value: '0x0',
316
333
  }
317
334
  : {
318
- from: transactionMeta.transaction.from,
319
- gasLimit: transactionMeta.transaction.gas,
335
+ from: transactionMeta.txParams.from,
336
+ gasLimit: transactionMeta.txParams.gas,
320
337
  gasPrice: newGasPrice,
321
- nonce: transactionMeta.transaction.nonce,
322
- to: transactionMeta.transaction.from,
338
+ nonce: transactionMeta.txParams.nonce,
339
+ to: transactionMeta.txParams.from,
323
340
  value: '0x0',
324
341
  };
325
342
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
326
- const signedTx = yield this.sign(unsignedEthTx, transactionMeta.transaction.from);
343
+ const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
344
+ yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
327
345
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
328
346
  yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
329
347
  transactionMeta.estimatedBaseFee = estimatedBaseFee;
@@ -334,13 +352,13 @@ class TransactionController extends base_controller_1.BaseController {
334
352
  /**
335
353
  * Attempts to speed up a transaction increasing transaction gasPrice by ten percent.
336
354
  *
337
- * @param transactionID - The ID of the transaction to speed up.
355
+ * @param transactionId - The ID of the transaction to speed up.
338
356
  * @param gasValues - The gas values to use for the speed up transaction.
339
357
  * @param options - The options for the speed up transaction.
340
358
  * @param options.actionId - Unique ID to prevent duplicate requests
341
359
  * @param options.estimatedBaseFee - The estimated base fee of the transaction.
342
360
  */
343
- speedUpTransaction(transactionID, gasValues, { actionId, estimatedBaseFee, } = {}) {
361
+ speedUpTransaction(transactionId, gasValues, { actionId, estimatedBaseFee, } = {}) {
344
362
  var _a, _b;
345
363
  return __awaiter(this, void 0, void 0, function* () {
346
364
  // If transaction is found for same action id, do not create a new speed up transaction.
@@ -350,7 +368,7 @@ class TransactionController extends base_controller_1.BaseController {
350
368
  if (gasValues) {
351
369
  (0, utils_1.validateGasValues)(gasValues);
352
370
  }
353
- const transactionMeta = this.state.transactions.find(({ id }) => id === transactionID);
371
+ const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
354
372
  /* istanbul ignore next */
355
373
  if (!transactionMeta) {
356
374
  return;
@@ -361,37 +379,36 @@ class TransactionController extends base_controller_1.BaseController {
361
379
  }
362
380
  const { transactions } = this.state;
363
381
  // gasPrice (legacy non EIP1559)
364
- const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.transaction.gasPrice, exports.SPEED_UP_RATE);
382
+ const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, exports.SPEED_UP_RATE);
365
383
  const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
366
384
  const newGasPrice = (gasPriceFromValues &&
367
385
  (0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
368
386
  minGasPrice;
369
387
  // maxFeePerGas (EIP1559)
370
- const existingMaxFeePerGas = (_a = transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
388
+ const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
371
389
  const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, exports.SPEED_UP_RATE);
372
390
  const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
373
391
  const newMaxFeePerGas = (maxFeePerGasValues &&
374
392
  (0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
375
393
  (existingMaxFeePerGas && minMaxFeePerGas);
376
394
  // maxPriorityFeePerGas (EIP1559)
377
- const existingMaxPriorityFeePerGas = (_b = transactionMeta.transaction) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
395
+ const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
378
396
  const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, exports.SPEED_UP_RATE);
379
397
  const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
380
398
  const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
381
399
  (0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
382
400
  (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
383
401
  const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas
384
- ? Object.assign(Object.assign({}, transactionMeta.transaction), { gasLimit: transactionMeta.transaction.gas, maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas, type: 2 }) : Object.assign(Object.assign({}, transactionMeta.transaction), { gasLimit: transactionMeta.transaction.gas, gasPrice: newGasPrice });
402
+ ? 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 });
385
403
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
386
- const signedTx = yield this.sign(unsignedEthTx, transactionMeta.transaction.from);
404
+ const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
405
+ yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
387
406
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
388
- const transactionHash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [
389
- rawTx,
390
- ]);
391
- const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), transactionHash,
392
- actionId });
407
+ const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
408
+ const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
409
+ actionId, originalGasEstimate: transactionMeta.txParams.gas });
393
410
  const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas
394
- ? Object.assign(Object.assign({}, baseTransactionMeta), { transaction: Object.assign(Object.assign({}, transactionMeta.transaction), { maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas }) }) : Object.assign(Object.assign({}, baseTransactionMeta), { transaction: Object.assign(Object.assign({}, transactionMeta.transaction), { gasPrice: newGasPrice }) });
411
+ ? 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 }) });
395
412
  transactions.push(newTransactionMeta);
396
413
  this.update({ transactions: this.trimTransactionsForState(transactions) });
397
414
  this.hub.emit(`${transactionMeta.id}:speedup`, newTransactionMeta);
@@ -421,7 +438,7 @@ class TransactionController extends base_controller_1.BaseController {
421
438
  false,
422
439
  ]);
423
440
  // 2. If to is not defined or this is not a contract address, and there is no data use 0x5208 / 21000.
424
- // If the newtwork is a custom network then bypass this check and fetch 'estimateGas'.
441
+ // If the network is a custom network then bypass this check and fetch 'estimateGas'.
425
442
  /* istanbul ignore next */
426
443
  const code = to ? yield (0, controller_utils_1.query)(this.ethQuery, 'getCode', [to]) : undefined;
427
444
  /* istanbul ignore next */
@@ -502,11 +519,15 @@ class TransactionController extends base_controller_1.BaseController {
502
519
  * Updates an existing transaction in state.
503
520
  *
504
521
  * @param transactionMeta - The new transaction to store in state.
522
+ * @param note - A note or update reason to include in the transaction history.
505
523
  */
506
- updateTransaction(transactionMeta) {
524
+ updateTransaction(transactionMeta, note) {
507
525
  const { transactions } = this.state;
508
- transactionMeta.transaction = (0, utils_1.normalizeTransaction)(transactionMeta.transaction);
509
- (0, utils_1.validateTransaction)(transactionMeta.transaction);
526
+ transactionMeta.txParams = (0, utils_1.normalizeTxParams)(transactionMeta.txParams);
527
+ (0, utils_1.validateTxParams)(transactionMeta.txParams);
528
+ if (!this.isHistoryDisabled) {
529
+ (0, history_1.updateTransactionHistory)(transactionMeta, note);
530
+ }
510
531
  const index = transactions.findIndex(({ id }) => transactionMeta.id === id);
511
532
  transactions[index] = transactionMeta;
512
533
  this.update({ transactions: this.trimTransactionsForState(transactions) });
@@ -526,7 +547,7 @@ class TransactionController extends base_controller_1.BaseController {
526
547
  return;
527
548
  }
528
549
  const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
529
- const newTransactions = this.state.transactions.filter(({ networkID, chainId, transaction }) => {
550
+ const newTransactions = this.state.transactions.filter(({ networkID, chainId, txParams }) => {
530
551
  var _a;
531
552
  // Using fallback to networkID only when there is no chainId present. Should be removed when networkID is completely removed.
532
553
  const isMatchingNetwork = ignoreNetwork ||
@@ -535,7 +556,7 @@ class TransactionController extends base_controller_1.BaseController {
535
556
  if (!isMatchingNetwork) {
536
557
  return true;
537
558
  }
538
- const isMatchingAddress = !address || ((_a = transaction.from) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase();
559
+ const isMatchingAddress = !address || ((_a = txParams.from) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase();
539
560
  return !isMatchingAddress;
540
561
  });
541
562
  this.update({
@@ -570,13 +591,88 @@ class TransactionController extends base_controller_1.BaseController {
570
591
  // Update same nonce local transactions as dropped and define replacedBy properties.
571
592
  this.markNonceDuplicatesDropped(transactionId);
572
593
  // Update external provided transaction with updated gas values and confirmed status.
573
- this.updateTransaction(transactionMeta);
594
+ this.updateTransaction(transactionMeta, 'TransactionController:confirmExternalTransaction - Add external transaction');
574
595
  }
575
596
  catch (error) {
576
597
  console.error(error);
577
598
  }
578
599
  });
579
600
  }
601
+ /**
602
+ * Append new send flow history to a transaction.
603
+ *
604
+ * @param transactionID - The ID of the transaction to update.
605
+ * @param currentSendFlowHistoryLength - The length of the current sendFlowHistory array.
606
+ * @param sendFlowHistoryToAdd - The sendFlowHistory entries to add.
607
+ * @returns The updated transactionMeta.
608
+ */
609
+ updateTransactionSendFlowHistory(transactionID, currentSendFlowHistoryLength, sendFlowHistoryToAdd) {
610
+ var _a, _b;
611
+ if (this.isSendFlowHistoryDisabled) {
612
+ throw new Error('Send flow history is disabled for the current transaction controller');
613
+ }
614
+ const transactionMeta = this.getTransaction(transactionID);
615
+ if (!transactionMeta) {
616
+ throw new Error(`Cannot update send flow history as no transaction metadata found`);
617
+ }
618
+ (0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateTransactionSendFlowHistory');
619
+ if (currentSendFlowHistoryLength ===
620
+ (((_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.sendFlowHistory) === null || _a === void 0 ? void 0 : _a.length) || 0)) {
621
+ transactionMeta.sendFlowHistory = [
622
+ ...((_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.sendFlowHistory) !== null && _b !== void 0 ? _b : []),
623
+ ...sendFlowHistoryToAdd,
624
+ ];
625
+ this.updateTransaction(transactionMeta, 'TransactionController:updateTransactionSendFlowHistory - sendFlowHistory updated');
626
+ }
627
+ return this.getTransaction(transactionID);
628
+ }
629
+ /**
630
+ * Update the gas values of a transaction.
631
+ *
632
+ * @param transactionId - The ID of the transaction to update.
633
+ * @param gasValues - Gas values to update.
634
+ * @param gasValues.gas - Same as transaction.gasLimit.
635
+ * @param gasValues.gasLimit - Maxmimum number of units of gas to use for this transaction.
636
+ * @param gasValues.gasPrice - Price per gas for legacy transactions.
637
+ * @param gasValues.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.
638
+ * @param gasValues.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.
639
+ * @param gasValues.estimateUsed - Which estimate level was used.
640
+ * @param gasValues.estimateSuggested - Which estimate level that the API suggested.
641
+ * @param gasValues.defaultGasEstimates - The default estimate for gas.
642
+ * @param gasValues.originalGasEstimate - Original estimate for gas.
643
+ * @param gasValues.userEditedGasLimit - The gas limit supplied by user.
644
+ * @param gasValues.userFeeLevel - Estimate level user selected.
645
+ * @returns The updated transactionMeta.
646
+ */
647
+ updateTransactionGasFees(transactionId, { defaultGasEstimates, estimateUsed, estimateSuggested, gas, gasLimit, gasPrice, maxPriorityFeePerGas, maxFeePerGas, originalGasEstimate, userEditedGasLimit, userFeeLevel, }) {
648
+ const transactionMeta = this.getTransaction(transactionId);
649
+ if (!transactionMeta) {
650
+ throw new Error(`Cannot update transaction as no transaction metadata found`);
651
+ }
652
+ (0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateTransactionGasFees');
653
+ let transactionGasFees = {
654
+ txParams: {
655
+ gas,
656
+ gasLimit,
657
+ gasPrice,
658
+ maxPriorityFeePerGas,
659
+ maxFeePerGas,
660
+ },
661
+ defaultGasEstimates,
662
+ estimateUsed,
663
+ estimateSuggested,
664
+ originalGasEstimate,
665
+ userEditedGasLimit,
666
+ userFeeLevel,
667
+ };
668
+ // only update what is defined
669
+ transactionGasFees.txParams = (0, lodash_1.pickBy)(transactionGasFees.txParams);
670
+ transactionGasFees = (0, lodash_1.pickBy)(transactionGasFees);
671
+ // merge updated gas values with existing transaction meta
672
+ const updatedMeta = (0, lodash_1.merge)(transactionMeta, transactionGasFees);
673
+ this.updateTransaction(updatedMeta, 'TransactionController:updateTransactionGasFees - gas values updated');
674
+ return this.getTransaction(transactionId);
675
+ }
580
676
  processApproval(transactionMeta, { isExisting = false, requireApproval, shouldShowRequest = true, }) {
581
677
  return __awaiter(this, void 0, void 0, function* () {
582
678
  const transactionId = transactionMeta.id;
@@ -622,7 +718,7 @@ class TransactionController extends base_controller_1.BaseController {
622
718
  throw cancelError;
623
719
  case types_1.TransactionStatus.submitted:
624
720
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
625
- return finalMeta.transactionHash;
721
+ return finalMeta.hash;
626
722
  default:
627
723
  const internalError = eth_rpc_errors_1.ethErrors.rpc.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finalMeta || transactionId)}`);
628
724
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(internalError);
@@ -636,16 +732,16 @@ class TransactionController extends base_controller_1.BaseController {
636
732
  * using the sign configuration property, then published to the blockchain.
637
733
  * A `<tx.id>:finished` hub event is fired after success or failure.
638
734
  *
639
- * @param transactionID - The ID of the transaction to approve.
735
+ * @param transactionId - The ID of the transaction to approve.
640
736
  */
641
- approveTransaction(transactionID) {
737
+ approveTransaction(transactionId) {
642
738
  return __awaiter(this, void 0, void 0, function* () {
643
739
  const { transactions } = this.state;
644
740
  const releaseLock = yield this.mutex.acquire();
645
741
  const { chainId } = this.getChainAndNetworkId();
646
- const index = transactions.findIndex(({ id }) => transactionID === id);
742
+ const index = transactions.findIndex(({ id }) => transactionId === id);
647
743
  const transactionMeta = transactions[index];
648
- const { transaction: { nonce, from }, } = transactionMeta;
744
+ const { txParams: { nonce, from }, } = transactionMeta;
649
745
  let nonceLock;
650
746
  try {
651
747
  if (!this.sign) {
@@ -667,12 +763,12 @@ class TransactionController extends base_controller_1.BaseController {
667
763
  nonceToUse = (0, ethereumjs_util_1.addHexPrefix)(nonceLock.nextNonce.toString(16));
668
764
  }
669
765
  transactionMeta.status = status;
670
- transactionMeta.transaction.nonce = nonceToUse;
671
- transactionMeta.transaction.chainId = chainId;
672
- const baseTxParams = Object.assign(Object.assign({}, transactionMeta.transaction), { gasLimit: transactionMeta.transaction.gas });
673
- const isEIP1559 = (0, utils_1.isEIP1559Transaction)(transactionMeta.transaction);
766
+ transactionMeta.txParams.nonce = nonceToUse;
767
+ transactionMeta.txParams.chainId = chainId;
768
+ const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
769
+ const isEIP1559 = (0, utils_1.isEIP1559Transaction)(transactionMeta.txParams);
674
770
  const txParams = isEIP1559
675
- ? Object.assign(Object.assign({}, baseTxParams), { maxFeePerGas: transactionMeta.transaction.maxFeePerGas, maxPriorityFeePerGas: transactionMeta.transaction.maxPriorityFeePerGas, estimatedBaseFee: transactionMeta.transaction.estimatedBaseFee,
771
+ ? Object.assign(Object.assign({}, baseTxParams), { maxFeePerGas: transactionMeta.txParams.maxFeePerGas, maxPriorityFeePerGas: transactionMeta.txParams.maxPriorityFeePerGas, estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee,
676
772
  // specify type 2 if maxFeePerGas and maxPriorityFeePerGas are set
677
773
  type: 2 }) : baseTxParams;
678
774
  // delete gasPrice if maxFeePerGas and maxPriorityFeePerGas are set
@@ -681,18 +777,17 @@ class TransactionController extends base_controller_1.BaseController {
681
777
  }
682
778
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
683
779
  const signedTx = yield this.sign(unsignedEthTx, from);
780
+ yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
684
781
  transactionMeta.status = types_1.TransactionStatus.signed;
685
- this.updateTransaction(transactionMeta);
782
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction signed');
686
783
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
687
784
  transactionMeta.rawTx = rawTx;
688
- this.updateTransaction(transactionMeta);
689
- const transactionHash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [
690
- rawTx,
691
- ]);
692
- transactionMeta.transactionHash = transactionHash;
785
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - RawTransaction added');
786
+ const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
787
+ transactionMeta.hash = hash;
693
788
  transactionMeta.status = types_1.TransactionStatus.submitted;
694
789
  transactionMeta.submittedTime = new Date().getTime();
695
- this.updateTransaction(transactionMeta);
790
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
696
791
  this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
697
792
  }
698
793
  catch (error) {
@@ -711,16 +806,16 @@ class TransactionController extends base_controller_1.BaseController {
711
806
  * Cancels a transaction based on its ID by setting its status to "rejected"
712
807
  * and emitting a `<tx.id>:finished` hub event.
713
808
  *
714
- * @param transactionID - The ID of the transaction to cancel.
809
+ * @param transactionId - The ID of the transaction to cancel.
715
810
  */
716
- cancelTransaction(transactionID) {
717
- const transactionMeta = this.state.transactions.find(({ id }) => id === transactionID);
811
+ cancelTransaction(transactionId) {
812
+ const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
718
813
  if (!transactionMeta) {
719
814
  return;
720
815
  }
721
816
  transactionMeta.status = types_1.TransactionStatus.rejected;
722
817
  this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
723
- const transactions = this.state.transactions.filter(({ id }) => id !== transactionID);
818
+ const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
724
819
  this.update({ transactions: this.trimTransactionsForState(transactions) });
725
820
  }
726
821
  /**
@@ -739,10 +834,12 @@ class TransactionController extends base_controller_1.BaseController {
739
834
  */
740
835
  trimTransactionsForState(transactions) {
741
836
  const nonceNetworkSet = new Set();
742
- const txsToKeep = transactions.reverse().filter((tx) => {
743
- const { chainId, networkID, status, transaction, time } = tx;
744
- if (transaction) {
745
- const key = `${transaction.nonce}-${chainId ? (0, controller_utils_1.convertHexToDecimal)(chainId) : networkID}-${new Date(time).toDateString()}`;
837
+ const txsToKeep = transactions
838
+ .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order
839
+ .filter((tx) => {
840
+ const { chainId, networkID, status, txParams, time } = tx;
841
+ if (txParams) {
842
+ const key = `${txParams.nonce}-${chainId ? (0, controller_utils_1.convertHexToDecimal)(chainId) : networkID}-${new Date(time).toDateString()}`;
746
843
  if (nonceNetworkSet.has(key)) {
747
844
  return true;
748
845
  }
@@ -754,7 +851,7 @@ class TransactionController extends base_controller_1.BaseController {
754
851
  }
755
852
  return false;
756
853
  });
757
- txsToKeep.reverse();
854
+ txsToKeep.reverse(); // Ascending time order
758
855
  return txsToKeep;
759
856
  }
760
857
  /**
@@ -792,11 +889,11 @@ class TransactionController extends base_controller_1.BaseController {
792
889
  */
793
890
  blockchainTransactionStateReconciler(meta) {
794
891
  return __awaiter(this, void 0, void 0, function* () {
795
- const { status, transactionHash } = meta;
892
+ const { status, hash } = meta;
796
893
  switch (status) {
797
894
  case types_1.TransactionStatus.confirmed:
798
895
  const txReceipt = yield (0, controller_utils_1.query)(this.ethQuery, 'getTransactionReceipt', [
799
- transactionHash,
896
+ hash,
800
897
  ]);
801
898
  if (!txReceipt) {
802
899
  return [meta, false];
@@ -805,7 +902,7 @@ class TransactionController extends base_controller_1.BaseController {
805
902
  txReceipt.blockHash,
806
903
  ]);
807
904
  meta.verifiedOnBlockchain = true;
808
- meta.transaction.gasUsed = txReceipt.gasUsed;
905
+ meta.txParams.gasUsed = txReceipt.gasUsed;
809
906
  meta.txReceipt = txReceipt;
810
907
  meta.baseFeePerGas = txBlock === null || txBlock === void 0 ? void 0 : txBlock.baseFeePerGas;
811
908
  meta.blockTimestamp = txBlock === null || txBlock === void 0 ? void 0 : txBlock.timestamp;
@@ -819,10 +916,10 @@ class TransactionController extends base_controller_1.BaseController {
819
916
  return [meta, true];
820
917
  case types_1.TransactionStatus.submitted:
821
918
  const txObj = yield (0, controller_utils_1.query)(this.ethQuery, 'getTransactionByHash', [
822
- transactionHash,
919
+ hash,
823
920
  ]);
824
921
  if (!txObj) {
825
- const receiptShowsFailedStatus = yield this.checkTxReceiptStatusIsFailed(transactionHash);
922
+ const receiptShowsFailedStatus = yield this.checkTxReceiptStatusIsFailed(hash);
826
923
  // Case the txObj is evaluated as false, a second check will
827
924
  // determine if the tx failed or it is pending or confirmed
828
925
  if (receiptShowsFailedStatus) {
@@ -933,7 +1030,7 @@ class TransactionController extends base_controller_1.BaseController {
933
1030
  const updatedTransactions = [
934
1031
  ...added,
935
1032
  ...currentTransactions.map((originalTransaction) => {
936
- const updatedTransaction = updated.find(({ transactionHash }) => transactionHash === originalTransaction.transactionHash);
1033
+ const updatedTransaction = updated.find(({ hash }) => hash === originalTransaction.hash);
937
1034
  return updatedTransaction !== null && updatedTransaction !== void 0 ? updatedTransaction : originalTransaction;
938
1035
  }),
939
1036
  ];
@@ -945,11 +1042,11 @@ class TransactionController extends base_controller_1.BaseController {
945
1042
  this.update({ lastFetchedBlockNumbers });
946
1043
  this.hub.emit('incomingTransactionBlock', blockNumber);
947
1044
  }
948
- generateDappSuggestedGasFees(transaction, origin) {
1045
+ generateDappSuggestedGasFees(txParams, origin) {
949
1046
  if (!origin || origin === controller_utils_1.ORIGIN_METAMASK) {
950
1047
  return undefined;
951
1048
  }
952
- const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = transaction;
1049
+ const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = txParams;
953
1050
  if (gasPrice === undefined &&
954
1051
  maxFeePerGas === undefined &&
955
1052
  maxPriorityFeePerGas === undefined &&
@@ -976,16 +1073,22 @@ class TransactionController extends base_controller_1.BaseController {
976
1073
  * @param transactionMeta - Nominated external transaction to be added to state.
977
1074
  */
978
1075
  addExternalTransaction(transactionMeta) {
979
- var _a;
1076
+ var _a, _b;
980
1077
  return __awaiter(this, void 0, void 0, function* () {
981
1078
  const { networkId, chainId } = this.getChainAndNetworkId();
982
1079
  const { transactions } = this.state;
983
- const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.from;
984
- const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.transaction.from === fromAddress &&
1080
+ const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
1081
+ const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
985
1082
  (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
986
1083
  const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
987
1084
  const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
988
1085
  (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
1086
+ // Make sure provided external transaction has non empty history array
1087
+ if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
1088
+ if (!this.isHistoryDisabled) {
1089
+ (0, history_1.addInitialHistorySnapshot)(transactionMeta);
1090
+ }
1091
+ }
989
1092
  const updatedTransactions = [...transactions, transactionMeta];
990
1093
  this.update({
991
1094
  transactions: this.trimTransactionsForState(updatedTransactions),
@@ -1002,10 +1105,10 @@ class TransactionController extends base_controller_1.BaseController {
1002
1105
  var _a, _b;
1003
1106
  const { networkId, chainId } = this.getChainAndNetworkId();
1004
1107
  const transactionMeta = this.getTransaction(transactionId);
1005
- const nonce = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.nonce;
1006
- const from = (_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.transaction) === null || _b === void 0 ? void 0 : _b.from;
1007
- const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.transaction.from === from &&
1008
- transaction.transaction.nonce === nonce &&
1108
+ const nonce = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.nonce;
1109
+ const from = (_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.from;
1110
+ const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.txParams.from === from &&
1111
+ transaction.txParams.nonce === nonce &&
1009
1112
  (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
1010
1113
  if (!sameNonceTxs.length) {
1011
1114
  return;
@@ -1030,7 +1133,7 @@ class TransactionController extends base_controller_1.BaseController {
1030
1133
  */
1031
1134
  setTransactionStatusDropped(transactionMeta) {
1032
1135
  transactionMeta.status = types_1.TransactionStatus.dropped;
1033
- this.updateTransaction(transactionMeta);
1136
+ this.updateTransaction(transactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
1034
1137
  }
1035
1138
  /**
1036
1139
  * Get transaction with provided actionId.
@@ -1050,6 +1153,26 @@ class TransactionController extends base_controller_1.BaseController {
1050
1153
  });
1051
1154
  });
1052
1155
  }
1156
+ /**
1157
+ * Updates the r, s, and v properties of a TransactionMeta object
1158
+ * with values from a signed transaction.
1159
+ *
1160
+ * @param transactionMeta - The TransactionMeta object to update.
1161
+ * @param signedTx - The encompassing type for all transaction types containing r, s, and v values.
1162
+ */
1163
+ updateTransactionMetaRSV(transactionMeta, signedTx) {
1164
+ return __awaiter(this, void 0, void 0, function* () {
1165
+ if (signedTx.r) {
1166
+ transactionMeta.r = (0, ethereumjs_util_1.addHexPrefix)(signedTx.r.toString(16));
1167
+ }
1168
+ if (signedTx.s) {
1169
+ transactionMeta.s = (0, ethereumjs_util_1.addHexPrefix)(signedTx.s.toString(16));
1170
+ }
1171
+ if (signedTx.v) {
1172
+ transactionMeta.v = (0, ethereumjs_util_1.addHexPrefix)(signedTx.v.toString(16));
1173
+ }
1174
+ });
1175
+ }
1053
1176
  }
1054
1177
  exports.TransactionController = TransactionController;
1055
1178
  exports.default = TransactionController;