@metamask-previews/transaction-controller 10.0.0-preview.0f6a2fb → 10.0.0-preview.76bc0ab

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 (38) hide show
  1. package/dist/EtherscanRemoteTransactionSource.d.ts +3 -3
  2. package/dist/EtherscanRemoteTransactionSource.d.ts.map +1 -1
  3. package/dist/EtherscanRemoteTransactionSource.js +48 -25
  4. package/dist/EtherscanRemoteTransactionSource.js.map +1 -1
  5. package/dist/IncomingTransactionHelper.d.ts +4 -3
  6. package/dist/IncomingTransactionHelper.d.ts.map +1 -1
  7. package/dist/IncomingTransactionHelper.js +41 -31
  8. package/dist/IncomingTransactionHelper.js.map +1 -1
  9. package/dist/TransactionController.d.ts +74 -26
  10. package/dist/TransactionController.d.ts.map +1 -1
  11. package/dist/TransactionController.js +237 -124
  12. package/dist/TransactionController.js.map +1 -1
  13. package/dist/constants.d.ts +2 -19
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/constants.js +26 -45
  16. package/dist/constants.js.map +1 -1
  17. package/dist/etherscan.d.ts +5 -6
  18. package/dist/etherscan.d.ts.map +1 -1
  19. package/dist/etherscan.js +7 -14
  20. package/dist/etherscan.js.map +1 -1
  21. package/dist/external-transactions.js +5 -5
  22. package/dist/external-transactions.js.map +1 -1
  23. package/dist/history.d.ts +15 -0
  24. package/dist/history.d.ts.map +1 -0
  25. package/dist/history.js +75 -0
  26. package/dist/history.js.map +1 -0
  27. package/dist/logger.d.ts +6 -0
  28. package/dist/logger.d.ts.map +1 -0
  29. package/dist/logger.js +8 -0
  30. package/dist/logger.js.map +1 -0
  31. package/dist/types.d.ts +112 -27
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/types.js.map +1 -1
  34. package/dist/utils.d.ts +16 -18
  35. package/dist/utils.d.ts.map +1 -1
  36. package/dist/utils.js +44 -48
  37. package/dist/utils.js.map +1 -1
  38. package/package.json +3 -1
@@ -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,45 @@ 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
- const { chainId, networkId } = this.getChainAndNetworkId();
197
+ const chainId = this.getChainId();
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 || {
197
- id: (0, uuid_1.v1)(),
198
- networkID: networkId !== null && networkId !== void 0 ? networkId : undefined,
205
+ // Add actionId to txMeta to check if same actionId is seen again
206
+ actionId,
199
207
  chainId,
208
+ dappSuggestedGasFees,
209
+ deviceConfirmedOn,
210
+ id: (0, uuid_1.v1)(),
200
211
  origin,
212
+ securityAlertResponse,
201
213
  status: types_1.TransactionStatus.unapproved,
202
214
  time: Date.now(),
203
- transaction,
204
- deviceConfirmedOn,
215
+ txParams,
216
+ userEditedGasLimit: false,
205
217
  verifiedOnBlockchain: false,
206
- dappSuggestedGasFees,
207
- securityAlertResponse,
208
- // Add actionId to txMeta to check if same actionId is seen again
209
- actionId,
210
218
  };
211
219
  try {
212
- const { gas, estimateGasError } = yield this.estimateGas(transaction);
213
- transaction.gas = gas;
214
- transaction.estimateGasError = estimateGasError;
220
+ const { gas, estimateGasError } = yield this.estimateGas(txParams);
221
+ txParams.gas = gas;
222
+ txParams.estimateGasError = estimateGasError;
223
+ transactionMeta.originalGasEstimate = gas;
215
224
  }
216
225
  catch (error) {
217
226
  this.failTransaction(transactionMeta, error);
@@ -219,6 +228,13 @@ class TransactionController extends base_controller_1.BaseController {
219
228
  }
220
229
  // Checks if a transaction already exists with a given actionId
221
230
  if (!existingTransactionMeta) {
231
+ if (!this.isSendFlowHistoryDisabled) {
232
+ transactionMeta.sendFlowHistory = sendFlowHistory !== null && sendFlowHistory !== void 0 ? sendFlowHistory : [];
233
+ }
234
+ // Initial history push
235
+ if (!this.isHistoryDisabled) {
236
+ (0, history_1.addInitialHistorySnapshot)(transactionMeta);
237
+ }
222
238
  transactions.push(transactionMeta);
223
239
  this.update({
224
240
  transactions: this.trimTransactionsForState(transactions),
@@ -249,9 +265,9 @@ class TransactionController extends base_controller_1.BaseController {
249
265
  * Creates approvals for all unapproved transactions persisted.
250
266
  */
251
267
  initApprovals() {
252
- const { networkId, chainId } = this.getChainAndNetworkId();
268
+ const chainId = this.getChainId();
253
269
  const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
254
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
270
+ transaction.chainId === chainId);
255
271
  for (const txMeta of unapprovedTxs) {
256
272
  this.processApproval(txMeta, {
257
273
  shouldShowRequest: false,
@@ -265,18 +281,18 @@ class TransactionController extends base_controller_1.BaseController {
265
281
  * Attempts to cancel a transaction based on its ID by setting its status to "rejected"
266
282
  * and emitting a `<tx.id>:finished` hub event.
267
283
  *
268
- * @param transactionID - The ID of the transaction to cancel.
284
+ * @param transactionId - The ID of the transaction to cancel.
269
285
  * @param gasValues - The gas values to use for the cancellation transaction.
270
286
  * @param options - The options for the cancellation transaction.
271
287
  * @param options.estimatedBaseFee - The estimated base fee of the transaction.
272
288
  */
273
- stopTransaction(transactionID, gasValues, { estimatedBaseFee } = {}) {
289
+ stopTransaction(transactionId, gasValues, { estimatedBaseFee } = {}) {
274
290
  var _a, _b;
275
291
  return __awaiter(this, void 0, void 0, function* () {
276
292
  if (gasValues) {
277
293
  (0, utils_1.validateGasValues)(gasValues);
278
294
  }
279
- const transactionMeta = this.state.transactions.find(({ id }) => id === transactionID);
295
+ const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
280
296
  if (!transactionMeta) {
281
297
  return;
282
298
  }
@@ -284,20 +300,20 @@ class TransactionController extends base_controller_1.BaseController {
284
300
  throw new Error('No sign method defined.');
285
301
  }
286
302
  // gasPrice (legacy non EIP1559)
287
- const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.transaction.gasPrice, exports.CANCEL_RATE);
303
+ const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, exports.CANCEL_RATE);
288
304
  const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
289
305
  const newGasPrice = (gasPriceFromValues &&
290
306
  (0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
291
307
  minGasPrice;
292
308
  // maxFeePerGas (EIP1559)
293
- const existingMaxFeePerGas = (_a = transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
309
+ const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
294
310
  const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, exports.CANCEL_RATE);
295
311
  const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
296
312
  const newMaxFeePerGas = (maxFeePerGasValues &&
297
313
  (0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
298
314
  (existingMaxFeePerGas && minMaxFeePerGas);
299
315
  // maxPriorityFeePerGas (EIP1559)
300
- const existingMaxPriorityFeePerGas = (_b = transactionMeta.transaction) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
316
+ const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
301
317
  const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, exports.CANCEL_RATE);
302
318
  const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
303
319
  const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
@@ -305,25 +321,26 @@ class TransactionController extends base_controller_1.BaseController {
305
321
  (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
306
322
  const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas
307
323
  ? {
308
- from: transactionMeta.transaction.from,
309
- gasLimit: transactionMeta.transaction.gas,
324
+ from: transactionMeta.txParams.from,
325
+ gasLimit: transactionMeta.txParams.gas,
310
326
  maxFeePerGas: newMaxFeePerGas,
311
327
  maxPriorityFeePerGas: newMaxPriorityFeePerGas,
312
328
  type: 2,
313
- nonce: transactionMeta.transaction.nonce,
314
- to: transactionMeta.transaction.from,
329
+ nonce: transactionMeta.txParams.nonce,
330
+ to: transactionMeta.txParams.from,
315
331
  value: '0x0',
316
332
  }
317
333
  : {
318
- from: transactionMeta.transaction.from,
319
- gasLimit: transactionMeta.transaction.gas,
334
+ from: transactionMeta.txParams.from,
335
+ gasLimit: transactionMeta.txParams.gas,
320
336
  gasPrice: newGasPrice,
321
- nonce: transactionMeta.transaction.nonce,
322
- to: transactionMeta.transaction.from,
337
+ nonce: transactionMeta.txParams.nonce,
338
+ to: transactionMeta.txParams.from,
323
339
  value: '0x0',
324
340
  };
325
341
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
326
- const signedTx = yield this.sign(unsignedEthTx, transactionMeta.transaction.from);
342
+ const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
343
+ yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
327
344
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
328
345
  yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
329
346
  transactionMeta.estimatedBaseFee = estimatedBaseFee;
@@ -334,13 +351,13 @@ class TransactionController extends base_controller_1.BaseController {
334
351
  /**
335
352
  * Attempts to speed up a transaction increasing transaction gasPrice by ten percent.
336
353
  *
337
- * @param transactionID - The ID of the transaction to speed up.
354
+ * @param transactionId - The ID of the transaction to speed up.
338
355
  * @param gasValues - The gas values to use for the speed up transaction.
339
356
  * @param options - The options for the speed up transaction.
340
357
  * @param options.actionId - Unique ID to prevent duplicate requests
341
358
  * @param options.estimatedBaseFee - The estimated base fee of the transaction.
342
359
  */
343
- speedUpTransaction(transactionID, gasValues, { actionId, estimatedBaseFee, } = {}) {
360
+ speedUpTransaction(transactionId, gasValues, { actionId, estimatedBaseFee, } = {}) {
344
361
  var _a, _b;
345
362
  return __awaiter(this, void 0, void 0, function* () {
346
363
  // If transaction is found for same action id, do not create a new speed up transaction.
@@ -350,7 +367,7 @@ class TransactionController extends base_controller_1.BaseController {
350
367
  if (gasValues) {
351
368
  (0, utils_1.validateGasValues)(gasValues);
352
369
  }
353
- const transactionMeta = this.state.transactions.find(({ id }) => id === transactionID);
370
+ const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
354
371
  /* istanbul ignore next */
355
372
  if (!transactionMeta) {
356
373
  return;
@@ -361,37 +378,36 @@ class TransactionController extends base_controller_1.BaseController {
361
378
  }
362
379
  const { transactions } = this.state;
363
380
  // gasPrice (legacy non EIP1559)
364
- const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.transaction.gasPrice, exports.SPEED_UP_RATE);
381
+ const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, exports.SPEED_UP_RATE);
365
382
  const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
366
383
  const newGasPrice = (gasPriceFromValues &&
367
384
  (0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
368
385
  minGasPrice;
369
386
  // maxFeePerGas (EIP1559)
370
- const existingMaxFeePerGas = (_a = transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
387
+ const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
371
388
  const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, exports.SPEED_UP_RATE);
372
389
  const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
373
390
  const newMaxFeePerGas = (maxFeePerGasValues &&
374
391
  (0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
375
392
  (existingMaxFeePerGas && minMaxFeePerGas);
376
393
  // maxPriorityFeePerGas (EIP1559)
377
- const existingMaxPriorityFeePerGas = (_b = transactionMeta.transaction) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
394
+ const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
378
395
  const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, exports.SPEED_UP_RATE);
379
396
  const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
380
397
  const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
381
398
  (0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
382
399
  (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
383
400
  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 });
401
+ ? 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
402
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
386
- const signedTx = yield this.sign(unsignedEthTx, transactionMeta.transaction.from);
403
+ const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
404
+ yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
387
405
  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 });
406
+ const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
407
+ const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
408
+ actionId, originalGasEstimate: transactionMeta.txParams.gas });
393
409
  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 }) });
410
+ ? 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
411
  transactions.push(newTransactionMeta);
396
412
  this.update({ transactions: this.trimTransactionsForState(transactions) });
397
413
  this.hub.emit(`${transactionMeta.id}:speedup`, newTransactionMeta);
@@ -421,7 +437,7 @@ class TransactionController extends base_controller_1.BaseController {
421
437
  false,
422
438
  ]);
423
439
  // 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'.
440
+ // If the network is a custom network then bypass this check and fetch 'estimateGas'.
425
441
  /* istanbul ignore next */
426
442
  const code = to ? yield (0, controller_utils_1.query)(this.ethQuery, 'getCode', [to]) : undefined;
427
443
  /* istanbul ignore next */
@@ -475,14 +491,10 @@ class TransactionController extends base_controller_1.BaseController {
475
491
  queryTransactionStatuses() {
476
492
  return __awaiter(this, void 0, void 0, function* () {
477
493
  const { transactions } = this.state;
478
- const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
494
+ const currentChainId = this.getChainId();
479
495
  let gotUpdates = false;
480
496
  yield (0, controller_utils_1.safelyExecute)(() => Promise.all(transactions.map((meta, index) => __awaiter(this, void 0, void 0, function* () {
481
- // Using fallback to networkID only when there is no chainId present.
482
- // Should be removed when networkID is completely removed.
483
- const txBelongsToCurrentChain = meta.chainId === currentChainId ||
484
- (!meta.chainId && meta.networkID === currentNetworkID);
485
- if (!meta.verifiedOnBlockchain && txBelongsToCurrentChain) {
497
+ if (!meta.verifiedOnBlockchain && meta.chainId === currentChainId) {
486
498
  const [reconciledTx, updateRequired] = yield this.blockchainTransactionStateReconciler(meta);
487
499
  if (updateRequired) {
488
500
  transactions[index] = reconciledTx;
@@ -502,11 +514,15 @@ class TransactionController extends base_controller_1.BaseController {
502
514
  * Updates an existing transaction in state.
503
515
  *
504
516
  * @param transactionMeta - The new transaction to store in state.
517
+ * @param note - A note or update reason to include in the transaction history.
505
518
  */
506
- updateTransaction(transactionMeta) {
519
+ updateTransaction(transactionMeta, note) {
507
520
  const { transactions } = this.state;
508
- transactionMeta.transaction = (0, utils_1.normalizeTransaction)(transactionMeta.transaction);
509
- (0, utils_1.validateTransaction)(transactionMeta.transaction);
521
+ transactionMeta.txParams = (0, utils_1.normalizeTxParams)(transactionMeta.txParams);
522
+ (0, utils_1.validateTxParams)(transactionMeta.txParams);
523
+ if (!this.isHistoryDisabled) {
524
+ (0, history_1.updateTransactionHistory)(transactionMeta, note);
525
+ }
510
526
  const index = transactions.findIndex(({ id }) => transactionMeta.id === id);
511
527
  transactions[index] = transactionMeta;
512
528
  this.update({ transactions: this.trimTransactionsForState(transactions) });
@@ -525,17 +541,14 @@ class TransactionController extends base_controller_1.BaseController {
525
541
  this.update({ transactions: [] });
526
542
  return;
527
543
  }
528
- const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
529
- const newTransactions = this.state.transactions.filter(({ networkID, chainId, transaction }) => {
544
+ const currentChainId = this.getChainId();
545
+ const newTransactions = this.state.transactions.filter(({ chainId, txParams }) => {
530
546
  var _a;
531
- // Using fallback to networkID only when there is no chainId present. Should be removed when networkID is completely removed.
532
- const isMatchingNetwork = ignoreNetwork ||
533
- chainId === currentChainId ||
534
- (!chainId && networkID === currentNetworkID);
547
+ const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
535
548
  if (!isMatchingNetwork) {
536
549
  return true;
537
550
  }
538
- const isMatchingAddress = !address || ((_a = transaction.from) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase();
551
+ const isMatchingAddress = !address || ((_a = txParams.from) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase();
539
552
  return !isMatchingAddress;
540
553
  });
541
554
  this.update({
@@ -570,13 +583,88 @@ class TransactionController extends base_controller_1.BaseController {
570
583
  // Update same nonce local transactions as dropped and define replacedBy properties.
571
584
  this.markNonceDuplicatesDropped(transactionId);
572
585
  // Update external provided transaction with updated gas values and confirmed status.
573
- this.updateTransaction(transactionMeta);
586
+ this.updateTransaction(transactionMeta, 'TransactionController:confirmExternalTransaction - Add external transaction');
574
587
  }
575
588
  catch (error) {
576
589
  console.error(error);
577
590
  }
578
591
  });
579
592
  }
593
+ /**
594
+ * Append new send flow history to a transaction.
595
+ *
596
+ * @param transactionID - The ID of the transaction to update.
597
+ * @param currentSendFlowHistoryLength - The length of the current sendFlowHistory array.
598
+ * @param sendFlowHistoryToAdd - The sendFlowHistory entries to add.
599
+ * @returns The updated transactionMeta.
600
+ */
601
+ updateTransactionSendFlowHistory(transactionID, currentSendFlowHistoryLength, sendFlowHistoryToAdd) {
602
+ var _a, _b;
603
+ if (this.isSendFlowHistoryDisabled) {
604
+ throw new Error('Send flow history is disabled for the current transaction controller');
605
+ }
606
+ const transactionMeta = this.getTransaction(transactionID);
607
+ if (!transactionMeta) {
608
+ throw new Error(`Cannot update send flow history as no transaction metadata found`);
609
+ }
610
+ (0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateTransactionSendFlowHistory');
611
+ if (currentSendFlowHistoryLength ===
612
+ (((_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.sendFlowHistory) === null || _a === void 0 ? void 0 : _a.length) || 0)) {
613
+ transactionMeta.sendFlowHistory = [
614
+ ...((_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.sendFlowHistory) !== null && _b !== void 0 ? _b : []),
615
+ ...sendFlowHistoryToAdd,
616
+ ];
617
+ this.updateTransaction(transactionMeta, 'TransactionController:updateTransactionSendFlowHistory - sendFlowHistory updated');
618
+ }
619
+ return this.getTransaction(transactionID);
620
+ }
621
+ /**
622
+ * Update the gas values of a transaction.
623
+ *
624
+ * @param transactionId - The ID of the transaction to update.
625
+ * @param gasValues - Gas values to update.
626
+ * @param gasValues.gas - Same as transaction.gasLimit.
627
+ * @param gasValues.gasLimit - Maxmimum number of units of gas to use for this transaction.
628
+ * @param gasValues.gasPrice - Price per gas for legacy transactions.
629
+ * @param gasValues.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.
630
+ * @param gasValues.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.
631
+ * @param gasValues.estimateUsed - Which estimate level was used.
632
+ * @param gasValues.estimateSuggested - Which estimate level that the API suggested.
633
+ * @param gasValues.defaultGasEstimates - The default estimate for gas.
634
+ * @param gasValues.originalGasEstimate - Original estimate for gas.
635
+ * @param gasValues.userEditedGasLimit - The gas limit supplied by user.
636
+ * @param gasValues.userFeeLevel - Estimate level user selected.
637
+ * @returns The updated transactionMeta.
638
+ */
639
+ updateTransactionGasFees(transactionId, { defaultGasEstimates, estimateUsed, estimateSuggested, gas, gasLimit, gasPrice, maxPriorityFeePerGas, maxFeePerGas, originalGasEstimate, userEditedGasLimit, userFeeLevel, }) {
640
+ const transactionMeta = this.getTransaction(transactionId);
641
+ if (!transactionMeta) {
642
+ throw new Error(`Cannot update transaction as no transaction metadata found`);
643
+ }
644
+ (0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateTransactionGasFees');
645
+ let transactionGasFees = {
646
+ txParams: {
647
+ gas,
648
+ gasLimit,
649
+ gasPrice,
650
+ maxPriorityFeePerGas,
651
+ maxFeePerGas,
652
+ },
653
+ defaultGasEstimates,
654
+ estimateUsed,
655
+ estimateSuggested,
656
+ originalGasEstimate,
657
+ userEditedGasLimit,
658
+ userFeeLevel,
659
+ };
660
+ // only update what is defined
661
+ transactionGasFees.txParams = (0, lodash_1.pickBy)(transactionGasFees.txParams);
662
+ transactionGasFees = (0, lodash_1.pickBy)(transactionGasFees);
663
+ // merge updated gas values with existing transaction meta
664
+ const updatedMeta = (0, lodash_1.merge)(transactionMeta, transactionGasFees);
665
+ this.updateTransaction(updatedMeta, 'TransactionController:updateTransactionGasFees - gas values updated');
666
+ return this.getTransaction(transactionId);
667
+ }
580
668
  processApproval(transactionMeta, { isExisting = false, requireApproval, shouldShowRequest = true, }) {
581
669
  return __awaiter(this, void 0, void 0, function* () {
582
670
  const transactionId = transactionMeta.id;
@@ -622,7 +710,7 @@ class TransactionController extends base_controller_1.BaseController {
622
710
  throw cancelError;
623
711
  case types_1.TransactionStatus.submitted:
624
712
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
625
- return finalMeta.transactionHash;
713
+ return finalMeta.hash;
626
714
  default:
627
715
  const internalError = eth_rpc_errors_1.ethErrors.rpc.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finalMeta || transactionId)}`);
628
716
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(internalError);
@@ -636,16 +724,16 @@ class TransactionController extends base_controller_1.BaseController {
636
724
  * using the sign configuration property, then published to the blockchain.
637
725
  * A `<tx.id>:finished` hub event is fired after success or failure.
638
726
  *
639
- * @param transactionID - The ID of the transaction to approve.
727
+ * @param transactionId - The ID of the transaction to approve.
640
728
  */
641
- approveTransaction(transactionID) {
729
+ approveTransaction(transactionId) {
642
730
  return __awaiter(this, void 0, void 0, function* () {
643
731
  const { transactions } = this.state;
644
732
  const releaseLock = yield this.mutex.acquire();
645
- const { chainId } = this.getChainAndNetworkId();
646
- const index = transactions.findIndex(({ id }) => transactionID === id);
733
+ const chainId = this.getChainId();
734
+ const index = transactions.findIndex(({ id }) => transactionId === id);
647
735
  const transactionMeta = transactions[index];
648
- const { transaction: { nonce, from }, } = transactionMeta;
736
+ const { txParams: { nonce, from }, } = transactionMeta;
649
737
  let nonceLock;
650
738
  try {
651
739
  if (!this.sign) {
@@ -667,12 +755,12 @@ class TransactionController extends base_controller_1.BaseController {
667
755
  nonceToUse = (0, ethereumjs_util_1.addHexPrefix)(nonceLock.nextNonce.toString(16));
668
756
  }
669
757
  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);
758
+ transactionMeta.txParams.nonce = nonceToUse;
759
+ transactionMeta.txParams.chainId = chainId;
760
+ const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
761
+ const isEIP1559 = (0, utils_1.isEIP1559Transaction)(transactionMeta.txParams);
674
762
  const txParams = isEIP1559
675
- ? Object.assign(Object.assign({}, baseTxParams), { maxFeePerGas: transactionMeta.transaction.maxFeePerGas, maxPriorityFeePerGas: transactionMeta.transaction.maxPriorityFeePerGas, estimatedBaseFee: transactionMeta.transaction.estimatedBaseFee,
763
+ ? Object.assign(Object.assign({}, baseTxParams), { maxFeePerGas: transactionMeta.txParams.maxFeePerGas, maxPriorityFeePerGas: transactionMeta.txParams.maxPriorityFeePerGas, estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee,
676
764
  // specify type 2 if maxFeePerGas and maxPriorityFeePerGas are set
677
765
  type: 2 }) : baseTxParams;
678
766
  // delete gasPrice if maxFeePerGas and maxPriorityFeePerGas are set
@@ -681,18 +769,17 @@ class TransactionController extends base_controller_1.BaseController {
681
769
  }
682
770
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
683
771
  const signedTx = yield this.sign(unsignedEthTx, from);
772
+ yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
684
773
  transactionMeta.status = types_1.TransactionStatus.signed;
685
- this.updateTransaction(transactionMeta);
774
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction signed');
686
775
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
687
776
  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;
777
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - RawTransaction added');
778
+ const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
779
+ transactionMeta.hash = hash;
693
780
  transactionMeta.status = types_1.TransactionStatus.submitted;
694
781
  transactionMeta.submittedTime = new Date().getTime();
695
- this.updateTransaction(transactionMeta);
782
+ this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
696
783
  this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
697
784
  }
698
785
  catch (error) {
@@ -711,16 +798,16 @@ class TransactionController extends base_controller_1.BaseController {
711
798
  * Cancels a transaction based on its ID by setting its status to "rejected"
712
799
  * and emitting a `<tx.id>:finished` hub event.
713
800
  *
714
- * @param transactionID - The ID of the transaction to cancel.
801
+ * @param transactionId - The ID of the transaction to cancel.
715
802
  */
716
- cancelTransaction(transactionID) {
717
- const transactionMeta = this.state.transactions.find(({ id }) => id === transactionID);
803
+ cancelTransaction(transactionId) {
804
+ const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
718
805
  if (!transactionMeta) {
719
806
  return;
720
807
  }
721
808
  transactionMeta.status = types_1.TransactionStatus.rejected;
722
809
  this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
723
- const transactions = this.state.transactions.filter(({ id }) => id !== transactionID);
810
+ const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
724
811
  this.update({ transactions: this.trimTransactionsForState(transactions) });
725
812
  }
726
813
  /**
@@ -739,10 +826,12 @@ class TransactionController extends base_controller_1.BaseController {
739
826
  */
740
827
  trimTransactionsForState(transactions) {
741
828
  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()}`;
829
+ const txsToKeep = transactions
830
+ .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order
831
+ .filter((tx) => {
832
+ const { chainId, status, txParams, time } = tx;
833
+ if (txParams) {
834
+ const key = `${txParams.nonce}-${(0, controller_utils_1.convertHexToDecimal)(chainId)}-${new Date(time).toDateString()}`;
746
835
  if (nonceNetworkSet.has(key)) {
747
836
  return true;
748
837
  }
@@ -754,7 +843,7 @@ class TransactionController extends base_controller_1.BaseController {
754
843
  }
755
844
  return false;
756
845
  });
757
- txsToKeep.reverse();
846
+ txsToKeep.reverse(); // Ascending time order
758
847
  return txsToKeep;
759
848
  }
760
849
  /**
@@ -792,11 +881,11 @@ class TransactionController extends base_controller_1.BaseController {
792
881
  */
793
882
  blockchainTransactionStateReconciler(meta) {
794
883
  return __awaiter(this, void 0, void 0, function* () {
795
- const { status, transactionHash } = meta;
884
+ const { status, hash } = meta;
796
885
  switch (status) {
797
886
  case types_1.TransactionStatus.confirmed:
798
887
  const txReceipt = yield (0, controller_utils_1.query)(this.ethQuery, 'getTransactionReceipt', [
799
- transactionHash,
888
+ hash,
800
889
  ]);
801
890
  if (!txReceipt) {
802
891
  return [meta, false];
@@ -805,7 +894,7 @@ class TransactionController extends base_controller_1.BaseController {
805
894
  txReceipt.blockHash,
806
895
  ]);
807
896
  meta.verifiedOnBlockchain = true;
808
- meta.transaction.gasUsed = txReceipt.gasUsed;
897
+ meta.txParams.gasUsed = txReceipt.gasUsed;
809
898
  meta.txReceipt = txReceipt;
810
899
  meta.baseFeePerGas = txBlock === null || txBlock === void 0 ? void 0 : txBlock.baseFeePerGas;
811
900
  meta.blockTimestamp = txBlock === null || txBlock === void 0 ? void 0 : txBlock.timestamp;
@@ -819,10 +908,10 @@ class TransactionController extends base_controller_1.BaseController {
819
908
  return [meta, true];
820
909
  case types_1.TransactionStatus.submitted:
821
910
  const txObj = yield (0, controller_utils_1.query)(this.ethQuery, 'getTransactionByHash', [
822
- transactionHash,
911
+ hash,
823
912
  ]);
824
913
  if (!txObj) {
825
- const receiptShowsFailedStatus = yield this.checkTxReceiptStatusIsFailed(transactionHash);
914
+ const receiptShowsFailedStatus = yield this.checkTxReceiptStatusIsFailed(hash);
826
915
  // Case the txObj is evaluated as false, a second check will
827
916
  // determine if the tx failed or it is pending or confirmed
828
917
  if (receiptShowsFailedStatus) {
@@ -893,10 +982,9 @@ class TransactionController extends base_controller_1.BaseController {
893
982
  const isCompleted = this.isLocalFinalState(transaction.status);
894
983
  return { meta: transaction, isCompleted };
895
984
  }
896
- getChainAndNetworkId() {
897
- const { networkId, providerConfig } = this.getNetworkState();
898
- const chainId = providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.chainId;
899
- return { networkId, chainId };
985
+ getChainId() {
986
+ const { providerConfig } = this.getNetworkState();
987
+ return providerConfig.chainId;
900
988
  }
901
989
  prepareUnsignedEthTx(txParams) {
902
990
  return tx_1.TransactionFactory.fromTxData(txParams, {
@@ -914,7 +1002,7 @@ class TransactionController extends base_controller_1.BaseController {
914
1002
  * @returns common configuration object
915
1003
  */
916
1004
  getCommonConfiguration() {
917
- const { networkId, providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
1005
+ const { providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
918
1006
  if (chain !== controller_utils_1.RPC &&
919
1007
  chain !== controller_utils_1.NetworkType['linea-goerli'] &&
920
1008
  chain !== controller_utils_1.NetworkType['linea-mainnet']) {
@@ -923,7 +1011,6 @@ class TransactionController extends base_controller_1.BaseController {
923
1011
  const customChainParams = {
924
1012
  name,
925
1013
  chainId: parseInt(chainId, 16),
926
- networkId: networkId === null ? NaN : parseInt(networkId, undefined),
927
1014
  defaultHardfork: exports.HARDFORK,
928
1015
  };
929
1016
  return common_1.Common.custom(customChainParams);
@@ -933,7 +1020,7 @@ class TransactionController extends base_controller_1.BaseController {
933
1020
  const updatedTransactions = [
934
1021
  ...added,
935
1022
  ...currentTransactions.map((originalTransaction) => {
936
- const updatedTransaction = updated.find(({ transactionHash }) => transactionHash === originalTransaction.transactionHash);
1023
+ const updatedTransaction = updated.find(({ hash }) => hash === originalTransaction.hash);
937
1024
  return updatedTransaction !== null && updatedTransaction !== void 0 ? updatedTransaction : originalTransaction;
938
1025
  }),
939
1026
  ];
@@ -945,11 +1032,11 @@ class TransactionController extends base_controller_1.BaseController {
945
1032
  this.update({ lastFetchedBlockNumbers });
946
1033
  this.hub.emit('incomingTransactionBlock', blockNumber);
947
1034
  }
948
- generateDappSuggestedGasFees(transaction, origin) {
1035
+ generateDappSuggestedGasFees(txParams, origin) {
949
1036
  if (!origin || origin === controller_utils_1.ORIGIN_METAMASK) {
950
1037
  return undefined;
951
1038
  }
952
- const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = transaction;
1039
+ const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = txParams;
953
1040
  if (gasPrice === undefined &&
954
1041
  maxFeePerGas === undefined &&
955
1042
  maxPriorityFeePerGas === undefined &&
@@ -976,16 +1063,22 @@ class TransactionController extends base_controller_1.BaseController {
976
1063
  * @param transactionMeta - Nominated external transaction to be added to state.
977
1064
  */
978
1065
  addExternalTransaction(transactionMeta) {
979
- var _a;
1066
+ var _a, _b;
980
1067
  return __awaiter(this, void 0, void 0, function* () {
981
- const { networkId, chainId } = this.getChainAndNetworkId();
1068
+ const chainId = this.getChainId();
982
1069
  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 &&
985
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
1070
+ const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
1071
+ const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
1072
+ transaction.chainId === chainId);
986
1073
  const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
987
1074
  const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
988
1075
  (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
1076
+ // Make sure provided external transaction has non empty history array
1077
+ if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
1078
+ if (!this.isHistoryDisabled) {
1079
+ (0, history_1.addInitialHistorySnapshot)(transactionMeta);
1080
+ }
1081
+ }
989
1082
  const updatedTransactions = [...transactions, transactionMeta];
990
1083
  this.update({
991
1084
  transactions: this.trimTransactionsForState(updatedTransactions),
@@ -1000,13 +1093,13 @@ class TransactionController extends base_controller_1.BaseController {
1000
1093
  */
1001
1094
  markNonceDuplicatesDropped(transactionId) {
1002
1095
  var _a, _b;
1003
- const { networkId, chainId } = this.getChainAndNetworkId();
1096
+ const chainId = this.getChainId();
1004
1097
  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 &&
1009
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
1098
+ const nonce = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.nonce;
1099
+ const from = (_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.from;
1100
+ const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.txParams.from === from &&
1101
+ transaction.txParams.nonce === nonce &&
1102
+ transaction.chainId === chainId);
1010
1103
  if (!sameNonceTxs.length) {
1011
1104
  return;
1012
1105
  }
@@ -1030,7 +1123,7 @@ class TransactionController extends base_controller_1.BaseController {
1030
1123
  */
1031
1124
  setTransactionStatusDropped(transactionMeta) {
1032
1125
  transactionMeta.status = types_1.TransactionStatus.dropped;
1033
- this.updateTransaction(transactionMeta);
1126
+ this.updateTransaction(transactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
1034
1127
  }
1035
1128
  /**
1036
1129
  * Get transaction with provided actionId.
@@ -1050,6 +1143,26 @@ class TransactionController extends base_controller_1.BaseController {
1050
1143
  });
1051
1144
  });
1052
1145
  }
1146
+ /**
1147
+ * Updates the r, s, and v properties of a TransactionMeta object
1148
+ * with values from a signed transaction.
1149
+ *
1150
+ * @param transactionMeta - The TransactionMeta object to update.
1151
+ * @param signedTx - The encompassing type for all transaction types containing r, s, and v values.
1152
+ */
1153
+ updateTransactionMetaRSV(transactionMeta, signedTx) {
1154
+ return __awaiter(this, void 0, void 0, function* () {
1155
+ if (signedTx.r) {
1156
+ transactionMeta.r = (0, ethereumjs_util_1.addHexPrefix)(signedTx.r.toString(16));
1157
+ }
1158
+ if (signedTx.s) {
1159
+ transactionMeta.s = (0, ethereumjs_util_1.addHexPrefix)(signedTx.s.toString(16));
1160
+ }
1161
+ if (signedTx.v) {
1162
+ transactionMeta.v = (0, ethereumjs_util_1.addHexPrefix)(signedTx.v.toString(16));
1163
+ }
1164
+ });
1165
+ }
1053
1166
  }
1054
1167
  exports.TransactionController = TransactionController;
1055
1168
  exports.default = TransactionController;