@metamask-previews/transaction-controller 10.0.0-preview.0f6a2fb → 10.0.0-preview.9c9148f

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.
@@ -58,7 +58,8 @@ class TransactionController extends base_controller_1.BaseController {
58
58
  * @param options.incomingTransactions.apiKey - An optional API key to use when fetching remote transaction data.
59
59
  * @param options.incomingTransactions.includeTokenTransfers - Whether or not to include ERC20 token transfers.
60
60
  * @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.
61
+ * @param options.incomingTransactions.queryEntireHistory - Whether to initially query the entire transaction history or only recent blocks.
62
+ * @param options.incomingTransactions.updateTransactions - Whether to update local transactions using remote transaction data.
62
63
  * @param options.messenger - The controller messenger.
63
64
  * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
64
65
  * @param options.provider - The provider used to create the underlying EthQuery instance.
@@ -100,8 +101,10 @@ class TransactionController extends base_controller_1.BaseController {
100
101
  this.incomingTransactionHelper = new IncomingTransactionHelper_1.IncomingTransactionHelper({
101
102
  blockTracker,
102
103
  getCurrentAccount: getSelectedAddress,
104
+ getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,
103
105
  getNetworkState,
104
106
  isEnabled: incomingTransactions.isEnabled,
107
+ queryEntireHistory: incomingTransactions.queryEntireHistory,
105
108
  remoteTransactionSource: new EtherscanRemoteTransactionSource_1.EtherscanRemoteTransactionSource({
106
109
  apiKey: incomingTransactions.apiKey,
107
110
  includeTokenTransfers: incomingTransactions.includeTokenTransfers,
@@ -186,7 +189,7 @@ class TransactionController extends base_controller_1.BaseController {
186
189
  */
187
190
  addTransaction(transaction, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, } = {}) {
188
191
  return __awaiter(this, void 0, void 0, function* () {
189
- const { chainId, networkId } = this.getChainAndNetworkId();
192
+ const chainId = this.getChainId();
190
193
  const { transactions } = this.state;
191
194
  transaction = (0, utils_1.normalizeTransaction)(transaction);
192
195
  (0, utils_1.validateTransaction)(transaction);
@@ -195,7 +198,6 @@ class TransactionController extends base_controller_1.BaseController {
195
198
  // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
196
199
  const transactionMeta = existingTransactionMeta || {
197
200
  id: (0, uuid_1.v1)(),
198
- networkID: networkId !== null && networkId !== void 0 ? networkId : undefined,
199
201
  chainId,
200
202
  origin,
201
203
  status: types_1.TransactionStatus.unapproved,
@@ -212,6 +214,7 @@ class TransactionController extends base_controller_1.BaseController {
212
214
  const { gas, estimateGasError } = yield this.estimateGas(transaction);
213
215
  transaction.gas = gas;
214
216
  transaction.estimateGasError = estimateGasError;
217
+ transactionMeta.originalGasEstimate = gas;
215
218
  }
216
219
  catch (error) {
217
220
  this.failTransaction(transactionMeta, error);
@@ -249,9 +252,9 @@ class TransactionController extends base_controller_1.BaseController {
249
252
  * Creates approvals for all unapproved transactions persisted.
250
253
  */
251
254
  initApprovals() {
252
- const { networkId, chainId } = this.getChainAndNetworkId();
255
+ const chainId = this.getChainId();
253
256
  const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
254
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
257
+ (0, utils_1.transactionMatchesChainId)(transaction, chainId));
255
258
  for (const txMeta of unapprovedTxs) {
256
259
  this.processApproval(txMeta, {
257
260
  shouldShowRequest: false,
@@ -385,11 +388,9 @@ class TransactionController extends base_controller_1.BaseController {
385
388
  const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
386
389
  const signedTx = yield this.sign(unsignedEthTx, transactionMeta.transaction.from);
387
390
  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 });
391
+ const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
392
+ const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
393
+ actionId, originalGasEstimate: transactionMeta.transaction.gas });
393
394
  const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas
394
395
  ? 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 }) });
395
396
  transactions.push(newTransactionMeta);
@@ -421,7 +422,7 @@ class TransactionController extends base_controller_1.BaseController {
421
422
  false,
422
423
  ]);
423
424
  // 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'.
425
+ // If the network is a custom network then bypass this check and fetch 'estimateGas'.
425
426
  /* istanbul ignore next */
426
427
  const code = to ? yield (0, controller_utils_1.query)(this.ethQuery, 'getCode', [to]) : undefined;
427
428
  /* istanbul ignore next */
@@ -475,14 +476,11 @@ class TransactionController extends base_controller_1.BaseController {
475
476
  queryTransactionStatuses() {
476
477
  return __awaiter(this, void 0, void 0, function* () {
477
478
  const { transactions } = this.state;
478
- const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
479
+ const currentChainId = this.getChainId();
479
480
  let gotUpdates = false;
480
481
  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) {
482
+ if (!meta.verifiedOnBlockchain &&
483
+ (0, utils_1.transactionMatchesChainId)(meta, currentChainId)) {
486
484
  const [reconciledTx, updateRequired] = yield this.blockchainTransactionStateReconciler(meta);
487
485
  if (updateRequired) {
488
486
  transactions[index] = reconciledTx;
@@ -525,13 +523,10 @@ class TransactionController extends base_controller_1.BaseController {
525
523
  this.update({ transactions: [] });
526
524
  return;
527
525
  }
528
- const { chainId: currentChainId, networkId: currentNetworkID } = this.getChainAndNetworkId();
529
- const newTransactions = this.state.transactions.filter(({ networkID, chainId, transaction }) => {
526
+ const currentChainId = this.getChainId();
527
+ const newTransactions = this.state.transactions.filter(({ chainId, transaction }) => {
530
528
  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);
529
+ const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
535
530
  if (!isMatchingNetwork) {
536
531
  return true;
537
532
  }
@@ -622,7 +617,7 @@ class TransactionController extends base_controller_1.BaseController {
622
617
  throw cancelError;
623
618
  case types_1.TransactionStatus.submitted:
624
619
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
625
- return finalMeta.transactionHash;
620
+ return finalMeta.hash;
626
621
  default:
627
622
  const internalError = eth_rpc_errors_1.ethErrors.rpc.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finalMeta || transactionId)}`);
628
623
  resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(internalError);
@@ -642,7 +637,7 @@ class TransactionController extends base_controller_1.BaseController {
642
637
  return __awaiter(this, void 0, void 0, function* () {
643
638
  const { transactions } = this.state;
644
639
  const releaseLock = yield this.mutex.acquire();
645
- const { chainId } = this.getChainAndNetworkId();
640
+ const chainId = this.getChainId();
646
641
  const index = transactions.findIndex(({ id }) => transactionID === id);
647
642
  const transactionMeta = transactions[index];
648
643
  const { transaction: { nonce, from }, } = transactionMeta;
@@ -686,10 +681,8 @@ class TransactionController extends base_controller_1.BaseController {
686
681
  const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
687
682
  transactionMeta.rawTx = rawTx;
688
683
  this.updateTransaction(transactionMeta);
689
- const transactionHash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [
690
- rawTx,
691
- ]);
692
- transactionMeta.transactionHash = transactionHash;
684
+ const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
685
+ transactionMeta.hash = hash;
693
686
  transactionMeta.status = types_1.TransactionStatus.submitted;
694
687
  transactionMeta.submittedTime = new Date().getTime();
695
688
  this.updateTransaction(transactionMeta);
@@ -739,7 +732,9 @@ class TransactionController extends base_controller_1.BaseController {
739
732
  */
740
733
  trimTransactionsForState(transactions) {
741
734
  const nonceNetworkSet = new Set();
742
- const txsToKeep = transactions.reverse().filter((tx) => {
735
+ const txsToKeep = transactions
736
+ .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order
737
+ .filter((tx) => {
743
738
  const { chainId, networkID, status, transaction, time } = tx;
744
739
  if (transaction) {
745
740
  const key = `${transaction.nonce}-${chainId ? (0, controller_utils_1.convertHexToDecimal)(chainId) : networkID}-${new Date(time).toDateString()}`;
@@ -754,7 +749,7 @@ class TransactionController extends base_controller_1.BaseController {
754
749
  }
755
750
  return false;
756
751
  });
757
- txsToKeep.reverse();
752
+ txsToKeep.reverse(); // Ascending time order
758
753
  return txsToKeep;
759
754
  }
760
755
  /**
@@ -792,11 +787,11 @@ class TransactionController extends base_controller_1.BaseController {
792
787
  */
793
788
  blockchainTransactionStateReconciler(meta) {
794
789
  return __awaiter(this, void 0, void 0, function* () {
795
- const { status, transactionHash } = meta;
790
+ const { status, hash } = meta;
796
791
  switch (status) {
797
792
  case types_1.TransactionStatus.confirmed:
798
793
  const txReceipt = yield (0, controller_utils_1.query)(this.ethQuery, 'getTransactionReceipt', [
799
- transactionHash,
794
+ hash,
800
795
  ]);
801
796
  if (!txReceipt) {
802
797
  return [meta, false];
@@ -819,10 +814,10 @@ class TransactionController extends base_controller_1.BaseController {
819
814
  return [meta, true];
820
815
  case types_1.TransactionStatus.submitted:
821
816
  const txObj = yield (0, controller_utils_1.query)(this.ethQuery, 'getTransactionByHash', [
822
- transactionHash,
817
+ hash,
823
818
  ]);
824
819
  if (!txObj) {
825
- const receiptShowsFailedStatus = yield this.checkTxReceiptStatusIsFailed(transactionHash);
820
+ const receiptShowsFailedStatus = yield this.checkTxReceiptStatusIsFailed(hash);
826
821
  // Case the txObj is evaluated as false, a second check will
827
822
  // determine if the tx failed or it is pending or confirmed
828
823
  if (receiptShowsFailedStatus) {
@@ -893,10 +888,9 @@ class TransactionController extends base_controller_1.BaseController {
893
888
  const isCompleted = this.isLocalFinalState(transaction.status);
894
889
  return { meta: transaction, isCompleted };
895
890
  }
896
- getChainAndNetworkId() {
897
- const { networkId, providerConfig } = this.getNetworkState();
898
- const chainId = providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.chainId;
899
- return { networkId, chainId };
891
+ getChainId() {
892
+ const { providerConfig } = this.getNetworkState();
893
+ return providerConfig.chainId;
900
894
  }
901
895
  prepareUnsignedEthTx(txParams) {
902
896
  return tx_1.TransactionFactory.fromTxData(txParams, {
@@ -914,7 +908,7 @@ class TransactionController extends base_controller_1.BaseController {
914
908
  * @returns common configuration object
915
909
  */
916
910
  getCommonConfiguration() {
917
- const { networkId, providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
911
+ const { providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
918
912
  if (chain !== controller_utils_1.RPC &&
919
913
  chain !== controller_utils_1.NetworkType['linea-goerli'] &&
920
914
  chain !== controller_utils_1.NetworkType['linea-mainnet']) {
@@ -923,7 +917,6 @@ class TransactionController extends base_controller_1.BaseController {
923
917
  const customChainParams = {
924
918
  name,
925
919
  chainId: parseInt(chainId, 16),
926
- networkId: networkId === null ? NaN : parseInt(networkId, undefined),
927
920
  defaultHardfork: exports.HARDFORK,
928
921
  };
929
922
  return common_1.Common.custom(customChainParams);
@@ -933,7 +926,7 @@ class TransactionController extends base_controller_1.BaseController {
933
926
  const updatedTransactions = [
934
927
  ...added,
935
928
  ...currentTransactions.map((originalTransaction) => {
936
- const updatedTransaction = updated.find(({ transactionHash }) => transactionHash === originalTransaction.transactionHash);
929
+ const updatedTransaction = updated.find(({ hash }) => hash === originalTransaction.hash);
937
930
  return updatedTransaction !== null && updatedTransaction !== void 0 ? updatedTransaction : originalTransaction;
938
931
  }),
939
932
  ];
@@ -978,11 +971,11 @@ class TransactionController extends base_controller_1.BaseController {
978
971
  addExternalTransaction(transactionMeta) {
979
972
  var _a;
980
973
  return __awaiter(this, void 0, void 0, function* () {
981
- const { networkId, chainId } = this.getChainAndNetworkId();
974
+ const chainId = this.getChainId();
982
975
  const { transactions } = this.state;
983
976
  const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.from;
984
977
  const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.transaction.from === fromAddress &&
985
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
978
+ (0, utils_1.transactionMatchesChainId)(transaction, chainId));
986
979
  const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
987
980
  const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
988
981
  (0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
@@ -1000,13 +993,13 @@ class TransactionController extends base_controller_1.BaseController {
1000
993
  */
1001
994
  markNonceDuplicatesDropped(transactionId) {
1002
995
  var _a, _b;
1003
- const { networkId, chainId } = this.getChainAndNetworkId();
996
+ const chainId = this.getChainId();
1004
997
  const transactionMeta = this.getTransaction(transactionId);
1005
998
  const nonce = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.transaction) === null || _a === void 0 ? void 0 : _a.nonce;
1006
999
  const from = (_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.transaction) === null || _b === void 0 ? void 0 : _b.from;
1007
1000
  const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.transaction.from === from &&
1008
1001
  transaction.transaction.nonce === nonce &&
1009
- (0, utils_1.transactionMatchesNetwork)(transaction, chainId, networkId));
1002
+ (0, utils_1.transactionMatchesChainId)(transaction, chainId));
1010
1003
  if (!sameNonceTxs.length) {
1011
1004
  return;
1012
1005
  }