@metamask/transaction-controller 40.0.0 → 41.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 (88) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/dist/TransactionController.cjs +169 -230
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts +98 -52
  5. package/dist/TransactionController.d.cts.map +1 -1
  6. package/dist/TransactionController.d.mts +98 -52
  7. package/dist/TransactionController.d.mts.map +1 -1
  8. package/dist/TransactionController.mjs +172 -233
  9. package/dist/TransactionController.mjs.map +1 -1
  10. package/dist/api/accounts-api.cjs +47 -0
  11. package/dist/api/accounts-api.cjs.map +1 -0
  12. package/dist/api/accounts-api.d.cts +43 -0
  13. package/dist/api/accounts-api.d.cts.map +1 -0
  14. package/dist/api/accounts-api.d.mts +43 -0
  15. package/dist/api/accounts-api.d.mts.map +1 -0
  16. package/dist/api/accounts-api.mjs +43 -0
  17. package/dist/api/accounts-api.mjs.map +1 -0
  18. package/dist/errors.cjs +8 -1
  19. package/dist/errors.cjs.map +1 -1
  20. package/dist/errors.d.cts +4 -0
  21. package/dist/errors.d.cts.map +1 -1
  22. package/dist/errors.d.mts +4 -0
  23. package/dist/errors.d.mts.map +1 -1
  24. package/dist/errors.mjs +6 -0
  25. package/dist/errors.mjs.map +1 -1
  26. package/dist/helpers/EtherscanRemoteTransactionSource.cjs +13 -12
  27. package/dist/helpers/EtherscanRemoteTransactionSource.cjs.map +1 -1
  28. package/dist/helpers/EtherscanRemoteTransactionSource.d.cts.map +1 -1
  29. package/dist/helpers/EtherscanRemoteTransactionSource.d.mts.map +1 -1
  30. package/dist/helpers/EtherscanRemoteTransactionSource.mjs +13 -12
  31. package/dist/helpers/EtherscanRemoteTransactionSource.mjs.map +1 -1
  32. package/dist/helpers/GasFeePoller.cjs +4 -4
  33. package/dist/helpers/GasFeePoller.cjs.map +1 -1
  34. package/dist/helpers/GasFeePoller.d.cts +1 -1
  35. package/dist/helpers/GasFeePoller.d.cts.map +1 -1
  36. package/dist/helpers/GasFeePoller.d.mts +1 -1
  37. package/dist/helpers/GasFeePoller.d.mts.map +1 -1
  38. package/dist/helpers/GasFeePoller.mjs +4 -4
  39. package/dist/helpers/GasFeePoller.mjs.map +1 -1
  40. package/dist/helpers/IncomingTransactionHelper.cjs +18 -11
  41. package/dist/helpers/IncomingTransactionHelper.cjs.map +1 -1
  42. package/dist/helpers/IncomingTransactionHelper.d.cts.map +1 -1
  43. package/dist/helpers/IncomingTransactionHelper.d.mts.map +1 -1
  44. package/dist/helpers/IncomingTransactionHelper.mjs +19 -12
  45. package/dist/helpers/IncomingTransactionHelper.mjs.map +1 -1
  46. package/dist/helpers/MethodDataHelper.cjs +78 -0
  47. package/dist/helpers/MethodDataHelper.cjs.map +1 -0
  48. package/dist/helpers/MethodDataHelper.d.cts +14 -0
  49. package/dist/helpers/MethodDataHelper.d.cts.map +1 -0
  50. package/dist/helpers/MethodDataHelper.d.mts +14 -0
  51. package/dist/helpers/MethodDataHelper.d.mts.map +1 -0
  52. package/dist/helpers/MethodDataHelper.mjs +71 -0
  53. package/dist/helpers/MethodDataHelper.mjs.map +1 -0
  54. package/dist/helpers/MultichainTrackingHelper.cjs +87 -104
  55. package/dist/helpers/MultichainTrackingHelper.cjs.map +1 -1
  56. package/dist/helpers/MultichainTrackingHelper.d.cts +16 -22
  57. package/dist/helpers/MultichainTrackingHelper.d.cts.map +1 -1
  58. package/dist/helpers/MultichainTrackingHelper.d.mts +16 -22
  59. package/dist/helpers/MultichainTrackingHelper.d.mts.map +1 -1
  60. package/dist/helpers/MultichainTrackingHelper.mjs +88 -109
  61. package/dist/helpers/MultichainTrackingHelper.mjs.map +1 -1
  62. package/dist/helpers/PendingTransactionTracker.cjs +24 -22
  63. package/dist/helpers/PendingTransactionTracker.cjs.map +1 -1
  64. package/dist/helpers/PendingTransactionTracker.d.cts.map +1 -1
  65. package/dist/helpers/PendingTransactionTracker.d.mts.map +1 -1
  66. package/dist/helpers/PendingTransactionTracker.mjs +24 -22
  67. package/dist/helpers/PendingTransactionTracker.mjs.map +1 -1
  68. package/dist/types.cjs.map +1 -1
  69. package/dist/types.d.cts +7 -3
  70. package/dist/types.d.cts.map +1 -1
  71. package/dist/types.d.mts +7 -3
  72. package/dist/types.d.mts.map +1 -1
  73. package/dist/types.mjs.map +1 -1
  74. package/dist/utils/etherscan.cjs +2 -1
  75. package/dist/utils/etherscan.cjs.map +1 -1
  76. package/dist/utils/etherscan.d.cts.map +1 -1
  77. package/dist/utils/etherscan.d.mts.map +1 -1
  78. package/dist/utils/etherscan.mjs +3 -2
  79. package/dist/utils/etherscan.mjs.map +1 -1
  80. package/dist/utils/validation.cjs +13 -1
  81. package/dist/utils/validation.cjs.map +1 -1
  82. package/dist/utils/validation.d.cts +7 -0
  83. package/dist/utils/validation.d.cts.map +1 -1
  84. package/dist/utils/validation.d.mts +7 -0
  85. package/dist/utils/validation.d.mts.map +1 -1
  86. package/dist/utils/validation.mjs +11 -0
  87. package/dist/utils/validation.mjs.map +1 -1
  88. package/package.json +1 -1
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
- var _TransactionController_instances, _TransactionController_internalEvents, _TransactionController_incomingTransactionOptions, _TransactionController_pendingTransactionOptions, _TransactionController_trace, _TransactionController_transactionHistoryLimit, _TransactionController_isSimulationEnabled, _TransactionController_testGasFeeFlows, _TransactionController_multichainTrackingHelper, _TransactionController_retryTransaction, _TransactionController_createNonceTracker, _TransactionController_createIncomingTransactionHelper, _TransactionController_createPendingTransactionTracker, _TransactionController_checkForPendingTransactionAndStartPolling, _TransactionController_stopAllTracking, _TransactionController_removeIncomingTransactionHelperListeners, _TransactionController_addIncomingTransactionHelperListeners, _TransactionController_removePendingTransactionTrackerListeners, _TransactionController_addPendingTransactionTrackerListeners, _TransactionController_getNonceTrackerPendingTransactions, _TransactionController_getGasFeeFlows, _TransactionController_getLayer1GasFeeFlows, _TransactionController_updateTransactionInternal, _TransactionController_updateSimulationData, _TransactionController_onGasFeePollerTransactionUpdate, _TransactionController_getNetworkClientId, _TransactionController_getGlobalNetworkClientId, _TransactionController_getGlobalChainId, _TransactionController_isCustomNetwork, _TransactionController_getSelectedAccount, _TransactionController_updateSubmitHistory;
12
+ var _TransactionController_instances, _TransactionController_internalEvents, _TransactionController_methodDataHelper, _TransactionController_incomingTransactionOptions, _TransactionController_pendingTransactionOptions, _TransactionController_trace, _TransactionController_transactionHistoryLimit, _TransactionController_isFirstTimeInteractionEnabled, _TransactionController_isSimulationEnabled, _TransactionController_testGasFeeFlows, _TransactionController_multichainTrackingHelper, _TransactionController_retryTransaction, _TransactionController_getChainId, _TransactionController_getNetworkClientId, _TransactionController_getEthQuery, _TransactionController_getProvider, _TransactionController_createNonceTracker, _TransactionController_createRemoteTransactionSource, _TransactionController_createIncomingTransactionHelper, _TransactionController_createPendingTransactionTracker, _TransactionController_checkForPendingTransactionAndStartPolling, _TransactionController_stopAllTracking, _TransactionController_removeIncomingTransactionHelperListeners, _TransactionController_addIncomingTransactionHelperListeners, _TransactionController_removePendingTransactionTrackerListeners, _TransactionController_addPendingTransactionTrackerListeners, _TransactionController_getNonceTrackerPendingTransactions, _TransactionController_getGasFeeFlows, _TransactionController_getLayer1GasFeeFlows, _TransactionController_updateTransactionInternal, _TransactionController_updateFirstTimeInteraction, _TransactionController_updateSimulationData, _TransactionController_onGasFeePollerTransactionUpdate, _TransactionController_getSelectedAccount, _TransactionController_updateSubmitHistory;
13
13
  function $importDefault(module) {
14
14
  if (module?.__esModule) {
15
15
  return module.default;
@@ -22,19 +22,19 @@ import { TransactionFactory } from "@ethereumjs/tx";
22
22
  import $ethereumjsutil from "@ethereumjs/util";
23
23
  const { bufferToHex } = $ethereumjsutil;
24
24
  import { BaseController } from "@metamask/base-controller";
25
- import { query, ApprovalType, ORIGIN_METAMASK, convertHexToDecimal, isInfuraNetworkType } from "@metamask/controller-utils";
25
+ import { query, ApprovalType, ORIGIN_METAMASK, convertHexToDecimal } from "@metamask/controller-utils";
26
26
  import $EthQuery from "@metamask/eth-query";
27
27
  const EthQuery = $importDefault($EthQuery);
28
28
  import { NetworkClientType } from "@metamask/network-controller";
29
29
  import { NonceTracker } from "@metamask/nonce-tracker";
30
30
  import { errorCodes, rpcErrors, providerErrors } from "@metamask/rpc-errors";
31
- import { add0x } from "@metamask/utils";
31
+ import { add0x, hexToNumber } from "@metamask/utils";
32
32
  import { Mutex } from "async-mutex";
33
- import { MethodRegistry } from "eth-method-registry";
34
33
  import { EventEmitter } from "events";
35
34
  import $lodash from "lodash";
36
35
  const { cloneDeep, mapValues, merge, pickBy, sortBy } = $lodash;
37
36
  import { v1 as random } from "uuid";
37
+ import { getAccountAddressRelationship } from "./api/accounts-api.mjs";
38
38
  import { DefaultGasFeeFlow } from "./gas-flows/DefaultGasFeeFlow.mjs";
39
39
  import { LineaGasFeeFlow } from "./gas-flows/LineaGasFeeFlow.mjs";
40
40
  import { OptimismLayer1GasFeeFlow } from "./gas-flows/OptimismLayer1GasFeeFlow.mjs";
@@ -43,6 +43,7 @@ import { TestGasFeeFlow } from "./gas-flows/TestGasFeeFlow.mjs";
43
43
  import { EtherscanRemoteTransactionSource } from "./helpers/EtherscanRemoteTransactionSource.mjs";
44
44
  import { GasFeePoller } from "./helpers/GasFeePoller.mjs";
45
45
  import { IncomingTransactionHelper } from "./helpers/IncomingTransactionHelper.mjs";
46
+ import { MethodDataHelper } from "./helpers/MethodDataHelper.mjs";
46
47
  import { MultichainTrackingHelper } from "./helpers/MultichainTrackingHelper.mjs";
47
48
  import { PendingTransactionTracker } from "./helpers/PendingTransactionTracker.mjs";
48
49
  import { projectLogger as log } from "./logger.mjs";
@@ -60,7 +61,7 @@ import { getSimulationData } from "./utils/simulation.mjs";
60
61
  import { updatePostTransactionBalance, updateSwapsTransaction } from "./utils/swaps.mjs";
61
62
  import { determineTransactionType } from "./utils/transaction-type.mjs";
62
63
  import { normalizeTransactionParams, isEIP1559Transaction, validateGasValues, validateIfTransactionUnapproved, normalizeTxError, normalizeGasFeeValues } from "./utils/utils.mjs";
63
- import { validateTransactionOrigin, validateTxParams } from "./utils/validation.mjs";
64
+ import { validateParamTo, validateTransactionOrigin, validateTxParams } from "./utils/validation.mjs";
64
65
  /**
65
66
  * Metadata for the TransactionController state, describing how to "anonymize"
66
67
  * the state and which parts should be persisted.
@@ -152,22 +153,10 @@ export class TransactionController extends BaseController {
152
153
  this.messagingSystem.publish(`${controllerName}:transactionFinished`, newTransactionMeta);
153
154
  __classPrivateFieldGet(this, _TransactionController_internalEvents, "f").emit(`${transactionMeta.id}:finished`, newTransactionMeta);
154
155
  }
155
- async registryLookup(fourBytePrefix) {
156
- const registryMethod = await this.registry.lookup(fourBytePrefix);
157
- if (!registryMethod) {
158
- return {
159
- registryMethod: '',
160
- parsedRegistryMethod: { name: undefined, args: undefined },
161
- };
162
- }
163
- const parsedRegistryMethod = this.registry.parse(registryMethod);
164
- return { registryMethod, parsedRegistryMethod };
165
- }
166
156
  /**
167
157
  * Constructs a TransactionController.
168
158
  *
169
159
  * @param options - The controller options.
170
- * @param options.blockTracker - The block tracker used to poll for new blocks data.
171
160
  * @param options.disableHistory - Whether to disable storing history in transaction metadata.
172
161
  * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
173
162
  * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
@@ -180,12 +169,10 @@ export class TransactionController extends BaseController {
180
169
  * @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.
181
170
  * @param options.getSavedGasFees - Gets the saved gas fee config.
182
171
  * @param options.incomingTransactions - Configuration options for incoming transaction support.
183
- * @param options.isMultichainEnabled - Enable multichain support.
172
+ * @param options.isFirstTimeInteractionEnabled - Whether first time interaction checks are enabled.
184
173
  * @param options.isSimulationEnabled - Whether new transactions will be automatically simulated.
185
174
  * @param options.messenger - The controller messenger.
186
- * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
187
175
  * @param options.pendingTransactions - Configuration options for pending transaction support.
188
- * @param options.provider - The provider used to create the underlying EthQuery instance.
189
176
  * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
190
177
  * @param options.sign - Function used to sign transactions.
191
178
  * @param options.state - Initial state to set on this controller.
@@ -194,7 +181,7 @@ export class TransactionController extends BaseController {
194
181
  * @param options.transactionHistoryLimit - Transaction history limit.
195
182
  * @param options.hooks - The controller hooks.
196
183
  */
197
- constructor({ blockTracker, disableHistory, disableSendFlowHistory, disableSwaps, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getExternalPendingTransactions, getGasFeeEstimates, getNetworkClientRegistry, getNetworkState, getPermittedAccounts, getSavedGasFees, incomingTransactions = {}, isMultichainEnabled = false, isSimulationEnabled, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, sign, state, testGasFeeFlows, trace, transactionHistoryLimit = 40, hooks, }) {
184
+ constructor({ disableHistory, disableSendFlowHistory, disableSwaps, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getExternalPendingTransactions, getGasFeeEstimates, getNetworkClientRegistry, getNetworkState, getPermittedAccounts, getSavedGasFees, incomingTransactions = {}, isFirstTimeInteractionEnabled, isSimulationEnabled, messenger, pendingTransactions = {}, securityProviderRequest, sign, state, testGasFeeFlows, trace, transactionHistoryLimit = 40, hooks, }) {
198
185
  super({
199
186
  name: controllerName,
200
187
  metadata,
@@ -207,18 +194,18 @@ export class TransactionController extends BaseController {
207
194
  _TransactionController_instances.add(this);
208
195
  _TransactionController_internalEvents.set(this, new EventEmitter());
209
196
  this.approvingTransactionIds = new Set();
197
+ _TransactionController_methodDataHelper.set(this, void 0);
210
198
  this.mutex = new Mutex();
211
199
  _TransactionController_incomingTransactionOptions.set(this, void 0);
212
200
  _TransactionController_pendingTransactionOptions.set(this, void 0);
213
201
  this.signAbortCallbacks = new Map();
214
202
  _TransactionController_trace.set(this, void 0);
215
203
  _TransactionController_transactionHistoryLimit.set(this, void 0);
204
+ _TransactionController_isFirstTimeInteractionEnabled.set(this, void 0);
216
205
  _TransactionController_isSimulationEnabled.set(this, void 0);
217
206
  _TransactionController_testGasFeeFlows.set(this, void 0);
218
207
  _TransactionController_multichainTrackingHelper.set(this, void 0);
219
208
  _TransactionController_checkForPendingTransactionAndStartPolling.set(this, () => {
220
- // PendingTransactionTracker reads state through its getTransactions hook
221
- this.pendingTransactionTracker.startIfPendingTransactions();
222
209
  __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").checkForPendingTransactionAndStartPolling();
223
210
  });
224
211
  this.messagingSystem = messenger;
@@ -226,9 +213,8 @@ export class TransactionController extends BaseController {
226
213
  this.isSendFlowHistoryDisabled = disableSendFlowHistory ?? false;
227
214
  this.isHistoryDisabled = disableHistory ?? false;
228
215
  this.isSwapsDisabled = disableSwaps ?? false;
216
+ __classPrivateFieldSet(this, _TransactionController_isFirstTimeInteractionEnabled, isFirstTimeInteractionEnabled ?? (() => true), "f");
229
217
  __classPrivateFieldSet(this, _TransactionController_isSimulationEnabled, isSimulationEnabled ?? (() => true), "f");
230
- // @ts-expect-error the type in eth-method-registry is inappropriate and should be changed
231
- this.registry = new MethodRegistry({ provider });
232
218
  this.getSavedGasFees = getSavedGasFees ?? ((_chainId) => undefined);
233
219
  this.getCurrentAccountEIP1559Compatibility =
234
220
  getCurrentAccountEIP1559Compatibility ?? (() => Promise.resolve(true));
@@ -256,18 +242,10 @@ export class TransactionController extends BaseController {
256
242
  hooks?.getAdditionalSignArguments ?? (() => []);
257
243
  this.publish =
258
244
  hooks?.publish ?? (() => Promise.resolve({ transactionHash: undefined }));
259
- this.nonceTracker = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createNonceTracker).call(this, {
260
- provider,
261
- blockTracker,
262
- });
263
245
  const findNetworkClientIdByChainId = (chainId) => {
264
246
  return this.messagingSystem.call(`NetworkController:findNetworkClientIdByChainId`, chainId);
265
247
  };
266
248
  __classPrivateFieldSet(this, _TransactionController_multichainTrackingHelper, new MultichainTrackingHelper({
267
- isMultichainEnabled,
268
- provider,
269
- nonceTracker: this.nonceTracker,
270
- incomingTransactionOptions: incomingTransactions,
271
249
  findNetworkClientIdByChainId,
272
250
  getNetworkClientById: ((networkClientId) => {
273
251
  return this.messagingSystem.call(`NetworkController:getNetworkClientById`, networkClientId);
@@ -278,33 +256,19 @@ export class TransactionController extends BaseController {
278
256
  createNonceTracker: __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createNonceTracker).bind(this),
279
257
  createIncomingTransactionHelper: __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createIncomingTransactionHelper).bind(this),
280
258
  createPendingTransactionTracker: __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createPendingTransactionTracker).bind(this),
259
+ createRemoteTransactionSource: __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createRemoteTransactionSource).bind(this),
281
260
  onNetworkStateChange: (listener) => {
282
261
  this.messagingSystem.subscribe('NetworkController:stateChange', listener);
283
262
  },
284
263
  }), "f");
285
264
  __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").initialize();
286
- const etherscanRemoteTransactionSource = new EtherscanRemoteTransactionSource({
287
- apiKeysByChainId: incomingTransactions.etherscanApiKeysByChainId,
288
- includeTokenTransfers: incomingTransactions.includeTokenTransfers,
289
- });
290
- this.incomingTransactionHelper = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createIncomingTransactionHelper).call(this, {
291
- blockTracker,
292
- etherscanRemoteTransactionSource,
293
- });
294
- this.pendingTransactionTracker = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_createPendingTransactionTracker).call(this, {
295
- provider,
296
- blockTracker,
297
- });
298
265
  this.gasFeeFlows = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGasFeeFlows).call(this);
299
266
  this.layer1GasFeeFlows = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getLayer1GasFeeFlows).call(this);
300
267
  const gasFeePoller = new GasFeePoller({
301
268
  findNetworkClientIdByChainId,
302
269
  gasFeeFlows: this.gasFeeFlows,
303
270
  getGasFeeControllerEstimates: this.getGasFeeEstimates,
304
- getProvider: (chainId, networkClientId) => __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getProvider({
305
- networkClientId,
306
- chainId,
307
- }),
271
+ getProvider: (networkClientId) => __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getProvider).call(this, { networkClientId }),
308
272
  getTransactions: () => this.state.transactions,
309
273
  layer1GasFeeFlows: this.layer1GasFeeFlows,
310
274
  onStateChange: (listener) => {
@@ -312,15 +276,18 @@ export class TransactionController extends BaseController {
312
276
  },
313
277
  });
314
278
  gasFeePoller.hub.on('transaction-updated', __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_onGasFeePollerTransactionUpdate).bind(this));
279
+ __classPrivateFieldSet(this, _TransactionController_methodDataHelper, new MethodDataHelper({
280
+ getProvider: (networkClientId) => __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getProvider).call(this, { networkClientId }),
281
+ getState: () => this.state.methodData,
282
+ }), "f");
283
+ __classPrivateFieldGet(this, _TransactionController_methodDataHelper, "f").hub.on('update', ({ fourBytePrefix, methodData }) => {
284
+ this.update((_state) => {
285
+ _state.methodData[fourBytePrefix] = methodData;
286
+ });
287
+ });
315
288
  // when transactionsController state changes
316
289
  // check for pending transactions and start polling if there are any
317
290
  this.messagingSystem.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _TransactionController_checkForPendingTransactionAndStartPolling, "f"));
318
- // TODO once v2 is merged make sure this only runs when
319
- // selectedNetworkClientId changes
320
- onNetworkStateChange(() => {
321
- log('Detected network change', this.getChainId());
322
- this.pendingTransactionTracker.startIfPendingTransactions();
323
- });
324
291
  this.onBootCleanup();
325
292
  __classPrivateFieldGet(this, _TransactionController_checkForPendingTransactionAndStartPolling, "f").call(this);
326
293
  }
@@ -334,25 +301,11 @@ export class TransactionController extends BaseController {
334
301
  * Handle new method data request.
335
302
  *
336
303
  * @param fourBytePrefix - The method prefix.
304
+ * @param networkClientId - The ID of the network client used to fetch the method data.
337
305
  * @returns The method data object corresponding to the given signature prefix.
338
306
  */
339
- async handleMethodData(fourBytePrefix) {
340
- const releaseLock = await this.mutex.acquire();
341
- try {
342
- const { methodData } = this.state;
343
- const knownMethod = Object.keys(methodData).find((knownFourBytePrefix) => fourBytePrefix === knownFourBytePrefix);
344
- if (knownMethod) {
345
- return methodData[fourBytePrefix];
346
- }
347
- const registry = await this.registryLookup(fourBytePrefix);
348
- this.update((state) => {
349
- state.methodData[fourBytePrefix] = registry;
350
- });
351
- return registry;
352
- }
353
- finally {
354
- releaseLock();
355
- }
307
+ async handleMethodData(fourBytePrefix, networkClientId) {
308
+ return __classPrivateFieldGet(this, _TransactionController_methodDataHelper, "f").lookup(fourBytePrefix, networkClientId);
356
309
  }
357
310
  /**
358
311
  * Add a new unapproved transaction to state. Parameters will be validated, a
@@ -360,40 +313,38 @@ export class TransactionController extends BaseController {
360
313
  * if not provided. If A `<tx.id>:unapproved` hub event will be emitted once added.
361
314
  *
362
315
  * @param txParams - Standard parameters for an Ethereum transaction.
363
- * @param opts - Additional options to control how the transaction is added.
364
- * @param opts.actionId - Unique ID to prevent duplicate requests.
365
- * @param opts.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.
366
- * @param opts.method - RPC method that requested the transaction.
367
- * @param opts.origin - The origin of the transaction request, such as a dApp hostname.
368
- * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
369
- * @param opts.securityAlertResponse - Response from security validator.
370
- * @param opts.sendFlowHistory - The sendFlowHistory entries to add.
371
- * @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.
372
- * @param opts.swaps - Options for swaps transactions.
373
- * @param opts.swaps.hasApproveTx - Whether the transaction has an approval transaction.
374
- * @param opts.swaps.meta - Metadata for swap transaction.
375
- * @param opts.networkClientId - The id of the network client for this transaction.
376
- * @param opts.traceContext - The parent context for any new traces.
316
+ * @param options - Additional options to control how the transaction is added.
317
+ * @param options.actionId - Unique ID to prevent duplicate requests.
318
+ * @param options.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.
319
+ * @param options.method - RPC method that requested the transaction.
320
+ * @param options.origin - The origin of the transaction request, such as a dApp hostname.
321
+ * @param options.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
322
+ * @param options.securityAlertResponse - Response from security validator.
323
+ * @param options.sendFlowHistory - The sendFlowHistory entries to add.
324
+ * @param options.type - Type of transaction to add, such as 'cancel' or 'swap'.
325
+ * @param options.swaps - Options for swaps transactions.
326
+ * @param options.swaps.hasApproveTx - Whether the transaction has an approval transaction.
327
+ * @param options.swaps.meta - Metadata for swap transaction.
328
+ * @param options.networkClientId - The id of the network client for this transaction.
329
+ * @param options.traceContext - The parent context for any new traces.
377
330
  * @returns Object containing a promise resolving to the transaction hash if approved.
378
331
  */
379
- async addTransaction(txParams, { actionId, deviceConfirmedOn, method, origin, requireApproval, securityAlertResponse, sendFlowHistory, swaps = {}, traceContext, type, networkClientId: requestNetworkClientId, } = {}) {
380
- log('Adding transaction', txParams);
332
+ async addTransaction(txParams, options) {
333
+ log('Adding transaction', txParams, options);
334
+ const { actionId, deviceConfirmedOn, method, networkClientId, origin, requireApproval, securityAlertResponse, sendFlowHistory, swaps = {}, traceContext, type, } = options;
381
335
  txParams = normalizeTransactionParams(txParams);
382
- if (requestNetworkClientId &&
383
- !__classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").has(requestNetworkClientId)) {
384
- throw new Error('The networkClientId for this transaction could not be found');
336
+ if (!__classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").has(networkClientId)) {
337
+ throw new Error(`Network client not found - ${networkClientId}`);
385
338
  }
386
- const networkClientId = requestNetworkClientId ?? __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGlobalNetworkClientId).call(this);
387
339
  const isEIP1559Compatible = await this.getEIP1559Compatibility(networkClientId);
388
340
  validateTxParams(txParams, isEIP1559Compatible);
389
341
  if (origin && this.getPermittedAccounts) {
390
342
  await validateTransactionOrigin(await this.getPermittedAccounts(origin), __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getSelectedAccount).call(this).address, txParams.from, origin);
391
343
  }
392
344
  const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
393
- const chainId = this.getChainId(networkClientId);
394
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
345
+ const chainId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getChainId).call(this, networkClientId);
346
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, {
395
347
  networkClientId,
396
- chainId,
397
348
  });
398
349
  const transactionType = type ?? (await determineTransactionType(txParams, ethQuery)).type;
399
350
  const existingTransactionMeta = this.getTransactionWithActionId(actionId);
@@ -407,15 +358,16 @@ export class TransactionController extends BaseController {
407
358
  dappSuggestedGasFees,
408
359
  deviceConfirmedOn,
409
360
  id: random(),
361
+ isFirstTimeInteraction: undefined,
362
+ networkClientId,
410
363
  origin,
411
364
  securityAlertResponse,
412
365
  status: TransactionStatus.unapproved,
413
366
  time: Date.now(),
414
367
  txParams,
368
+ type: transactionType,
415
369
  userEditedGasLimit: false,
416
370
  verifiedOnBlockchain: false,
417
- type: transactionType,
418
- networkClientId,
419
371
  };
420
372
  await __classPrivateFieldGet(this, _TransactionController_trace, "f").call(this, { name: 'Estimate Gas Properties', parentContext: traceContext }, (context) => this.updateGasProperties(addedTransactionMeta, {
421
373
  traceContext: context,
@@ -448,9 +400,14 @@ export class TransactionController extends BaseController {
448
400
  log('Error while updating simulation data', error);
449
401
  throw error;
450
402
  });
403
+ __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_updateFirstTimeInteraction).call(this, addedTransactionMeta, {
404
+ traceContext,
405
+ }).catch((error) => {
406
+ log('Error while updating first interaction properties', error);
407
+ });
451
408
  }
452
409
  else {
453
- log('Skipping simulation as approval not required');
410
+ log('Skipping simulation & first interaction update as approval not required');
454
411
  }
455
412
  this.messagingSystem.publish(`${controllerName}:unapprovedTransactionAdded`, addedTransactionMeta);
456
413
  }
@@ -464,29 +421,13 @@ export class TransactionController extends BaseController {
464
421
  transactionMeta: addedTransactionMeta,
465
422
  };
466
423
  }
467
- startIncomingTransactionPolling(networkClientIds = []) {
468
- if (networkClientIds.length === 0) {
469
- this.incomingTransactionHelper.start();
470
- return;
471
- }
424
+ startIncomingTransactionPolling(networkClientIds) {
472
425
  __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").startIncomingTransactionPolling(networkClientIds);
473
426
  }
474
- stopIncomingTransactionPolling(networkClientIds = []) {
475
- if (networkClientIds.length === 0) {
476
- this.incomingTransactionHelper.stop();
477
- return;
478
- }
427
+ stopIncomingTransactionPolling(networkClientIds) {
479
428
  __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").stopIncomingTransactionPolling(networkClientIds);
480
429
  }
481
- stopAllIncomingTransactionPolling() {
482
- this.incomingTransactionHelper.stop();
483
- __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").stopAllIncomingTransactionPolling();
484
- }
485
430
  async updateIncomingTransactions(networkClientIds = []) {
486
- if (networkClientIds.length === 0) {
487
- await this.incomingTransactionHelper.update();
488
- return;
489
- }
490
431
  await __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").updateIncomingTransactions(networkClientIds);
491
432
  }
492
433
  /**
@@ -550,7 +491,7 @@ export class TransactionController extends BaseController {
550
491
  * @returns The gas and gas price.
551
492
  */
552
493
  async estimateGas(transaction, networkClientId) {
553
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
494
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, {
554
495
  networkClientId,
555
496
  });
556
497
  const { estimatedGas, simulationFails } = await estimateGas(transaction, ethQuery);
@@ -564,7 +505,7 @@ export class TransactionController extends BaseController {
564
505
  * @param networkClientId - The network client id to use for the estimate.
565
506
  */
566
507
  async estimateGasBuffered(transaction, multiplier, networkClientId) {
567
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
508
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, {
568
509
  networkClientId,
569
510
  });
570
511
  const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas(transaction, ethQuery);
@@ -607,24 +548,21 @@ export class TransactionController extends BaseController {
607
548
  this.updateTransaction(updatedTransactionMeta, `${controllerName}:updatesecurityAlertResponse - securityAlertResponse updated`);
608
549
  }
609
550
  /**
610
- * Removes all transactions from state, optionally based on the current network.
551
+ * Remove transactions from state.
611
552
  *
612
- * @param ignoreNetwork - Determines whether to wipe all transactions, or just those on the
613
- * current network. If `true`, all transactions are wiped.
614
- * @param address - If specified, only transactions originating from this address will be
615
- * wiped on current network.
553
+ * @param options - The options bag.
554
+ * @param options.address - Remove transactions from this account only. Defaults to all accounts.
555
+ * @param options.chainId - Remove transactions for the specified chain only. Defaults to all chains.
616
556
  */
617
- wipeTransactions(ignoreNetwork, address) {
618
- /* istanbul ignore next */
619
- if (ignoreNetwork && !address) {
557
+ wipeTransactions({ address, chainId, } = {}) {
558
+ if (!chainId && !address) {
620
559
  this.update((state) => {
621
560
  state.transactions = [];
622
561
  });
623
562
  return;
624
563
  }
625
- const currentChainId = this.getChainId();
626
- const newTransactions = this.state.transactions.filter(({ chainId, txParams }) => {
627
- const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
564
+ const newTransactions = this.state.transactions.filter(({ chainId: txChainId, txParams }) => {
565
+ const isMatchingNetwork = !chainId || chainId === txChainId;
628
566
  if (!isMatchingNetwork) {
629
567
  return true;
630
568
  }
@@ -814,10 +752,8 @@ export class TransactionController extends BaseController {
814
752
  };
815
753
  editableParams.txParams = pickBy(editableParams.txParams);
816
754
  const updatedTransaction = merge({}, transactionMeta, editableParams);
817
- const provider = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getProvider({
818
- chainId: transactionMeta.chainId,
819
- networkClientId: transactionMeta.networkClientId,
820
- });
755
+ const { networkClientId } = transactionMeta;
756
+ const provider = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getProvider).call(this, { networkClientId });
821
757
  const ethQuery = new EthQuery(provider);
822
758
  const { type } = await determineTransactionType(updatedTransaction.txParams, ethQuery);
823
759
  updatedTransaction.type = type;
@@ -845,19 +781,9 @@ export class TransactionController extends BaseController {
845
781
  return '';
846
782
  }
847
783
  const initialTx = listOfTxParams[0];
848
- const common = this.getCommonConfiguration(initialTx.chainId);
849
- // We need to ensure we get the nonce using the the NonceTracker on the chain matching
850
- // the txParams. In this context we only have chainId available to us, but the
851
- // NonceTrackers are keyed by networkClientId. To workaround this, we attempt to find
852
- // a networkClientId that matches the chainId. As a fallback, the globally selected
853
- // network's NonceTracker will be used instead.
854
- let networkClientId;
855
- try {
856
- networkClientId = this.messagingSystem.call(`NetworkController:findNetworkClientIdByChainId`, initialTx.chainId);
857
- }
858
- catch (err) {
859
- log('failed to find networkClientId from chainId', err);
860
- }
784
+ const { chainId } = initialTx;
785
+ const common = this.getCommonConfiguration(chainId);
786
+ const networkClientId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getNetworkClientId).call(this, { chainId });
861
787
  const initialTxAsEthTx = TransactionFactory.fromTxData(initialTx, {
862
788
  common,
863
789
  });
@@ -939,14 +865,12 @@ export class TransactionController extends BaseController {
939
865
  * Search transaction metadata for matching entries.
940
866
  *
941
867
  * @param opts - Options bag.
942
- * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
943
868
  * @param opts.initialList - The transactions to search. Defaults to the current state.
944
- * @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.
945
869
  * @param opts.limit - The maximum number of transactions to return. No limit by default.
870
+ * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
946
871
  * @returns An array of transactions matching the provided options.
947
872
  */
948
- getTransactions({ searchCriteria = {}, initialList, filterToCurrentNetwork = true, limit, } = {}) {
949
- const chainId = this.getChainId();
873
+ getTransactions({ initialList, limit, searchCriteria = {}, } = {}) {
950
874
  // searchCriteria is an object that might have values that aren't predicate
951
875
  // methods. When providing any other value type (string, number, etc), we
952
876
  // consider this shorthand for "check the value at key for strict equality
@@ -964,9 +888,6 @@ export class TransactionController extends BaseController {
964
888
  // Combine sortBy and pickBy to transform our state object into an array of
965
889
  // matching transactions that are sorted by time.
966
890
  const filteredTransactions = sortBy(pickBy(transactionsToFilter, (transaction) => {
967
- if (filterToCurrentNetwork && transaction.chainId !== chainId) {
968
- return false;
969
- }
970
891
  // iterate over the predicateMethods keys to check if the transaction
971
892
  // matches the searchCriteria
972
893
  for (const [key, predicate] of Object.entries(predicateMethods)) {
@@ -1022,9 +943,9 @@ export class TransactionController extends BaseController {
1022
943
  return filteredTransactions;
1023
944
  }
1024
945
  async estimateGasFee({ transactionParams, chainId, networkClientId: requestNetworkClientId, }) {
1025
- const networkClientId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getNetworkClientId).call(this, {
1026
- networkClientId: requestNetworkClientId,
946
+ const { id: networkClientId, provider } = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getNetworkClient({
1027
947
  chainId,
948
+ networkClientId: requestNetworkClientId,
1028
949
  });
1029
950
  const transactionMeta = {
1030
951
  txParams: transactionParams,
@@ -1033,10 +954,7 @@ export class TransactionController extends BaseController {
1033
954
  };
1034
955
  // Guaranteed as the default gas fee flow matches all transactions.
1035
956
  const gasFeeFlow = getGasFeeFlow(transactionMeta, this.gasFeeFlows);
1036
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
1037
- networkClientId,
1038
- chainId,
1039
- });
957
+ const ethQuery = new EthQuery(provider);
1040
958
  const gasFeeControllerData = await this.getGasFeeEstimates({
1041
959
  networkClientId,
1042
960
  });
@@ -1055,9 +973,9 @@ export class TransactionController extends BaseController {
1055
973
  * @param request.networkClientId - The ID of a specific network client to process the transaction.
1056
974
  */
1057
975
  async getLayer1GasFee({ transactionParams, chainId, networkClientId, }) {
1058
- const provider = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getProvider({
1059
- networkClientId,
976
+ const provider = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getProvider).call(this, {
1060
977
  chainId,
978
+ networkClientId,
1061
979
  });
1062
980
  return await getTransactionLayer1GasFee({
1063
981
  layer1GasFeeFlows: this.layer1GasFeeFlows,
@@ -1128,15 +1046,10 @@ export class TransactionController extends BaseController {
1128
1046
  const isEIP1559Compatible = transactionMeta.txParams.type !== TransactionEnvelopeType.legacy &&
1129
1047
  (await this.getEIP1559Compatibility(transactionMeta.networkClientId));
1130
1048
  const { networkClientId, chainId } = transactionMeta;
1131
- const isCustomNetwork = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_isCustomNetwork).call(this, networkClientId);
1132
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
1133
- networkClientId,
1134
- chainId,
1135
- });
1136
- const provider = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getProvider({
1137
- networkClientId,
1138
- chainId,
1139
- });
1049
+ const isCustomNetwork = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getNetworkClient({ networkClientId })
1050
+ .configuration.type === NetworkClientType.Custom;
1051
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, { networkClientId });
1052
+ const provider = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getProvider).call(this, { networkClientId });
1140
1053
  await __classPrivateFieldGet(this, _TransactionController_trace, "f").call(this, { name: 'Update Gas', parentContext: traceContext }, async () => {
1141
1054
  await updateGas({
1142
1055
  ethQuery,
@@ -1294,10 +1207,8 @@ export class TransactionController extends BaseController {
1294
1207
  if (!rawTx) {
1295
1208
  return ApprovalState.NotApproved;
1296
1209
  }
1297
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
1298
- networkClientId: transactionMeta.networkClientId,
1299
- chainId: transactionMeta.chainId,
1300
- });
1210
+ const { networkClientId } = transactionMeta;
1211
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, { networkClientId });
1301
1212
  let preTxBalance;
1302
1213
  const shouldUpdatePreTxBalance = transactionMeta.type === TransactionType.swap;
1303
1214
  if (shouldUpdatePreTxBalance) {
@@ -1491,14 +1402,6 @@ export class TransactionController extends BaseController {
1491
1402
  const isCompleted = this.isLocalFinalState(transaction.status);
1492
1403
  return { meta: transaction, isCompleted };
1493
1404
  }
1494
- getChainId(networkClientId) {
1495
- const globalChainId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGlobalChainId).call(this);
1496
- const globalNetworkClientId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGlobalNetworkClientId).call(this);
1497
- if (!networkClientId || networkClientId === globalNetworkClientId) {
1498
- return globalChainId;
1499
- }
1500
- return this.messagingSystem.call(`NetworkController:getNetworkClientById`, networkClientId).configuration.chainId;
1501
- }
1502
1405
  prepareUnsignedEthTx(chainId, txParams) {
1503
1406
  return TransactionFactory.fromTxData(txParams, {
1504
1407
  freeze: false,
@@ -1524,14 +1427,16 @@ export class TransactionController extends BaseController {
1524
1427
  }
1525
1428
  onIncomingTransactions({ added, updated, }) {
1526
1429
  this.update((state) => {
1527
- const { transactions: currentTransactions } = state;
1528
- const updatedTransactions = [
1529
- ...added,
1530
- ...currentTransactions.map((originalTransaction) => {
1531
- const updatedTransaction = updated.find(({ hash }) => hash === originalTransaction.hash);
1532
- return updatedTransaction ?? originalTransaction;
1533
- }),
1534
- ];
1430
+ const { transactions } = state;
1431
+ const existingTransactions = transactions.map((tx) => updated.find(({ hash }) => hash === tx.hash) ?? tx);
1432
+ const updatedTransactions = [...added, ...existingTransactions].map((tx) => {
1433
+ const { chainId } = tx;
1434
+ const networkClientId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getNetworkClientId).call(this, { chainId });
1435
+ return {
1436
+ ...tx,
1437
+ networkClientId,
1438
+ };
1439
+ });
1535
1440
  state.transactions = this.trimTransactionsForState(updatedTransactions);
1536
1441
  });
1537
1442
  }
@@ -1724,7 +1629,7 @@ export class TransactionController extends BaseController {
1724
1629
  transactionMeta,
1725
1630
  });
1726
1631
  }
1727
- getNonceTrackerTransactions(status, address, chainId = this.getChainId()) {
1632
+ getNonceTrackerTransactions(status, address, chainId) {
1728
1633
  return getAndFormatTransactionsForNonceTracker(chainId, address, status, this.state.transactions);
1729
1634
  }
1730
1635
  onConfirmedTransaction(transactionMeta) {
@@ -1740,13 +1645,11 @@ export class TransactionController extends BaseController {
1740
1645
  }
1741
1646
  async updatePostBalance(transactionMeta) {
1742
1647
  try {
1743
- if (transactionMeta.type !== TransactionType.swap) {
1648
+ const { networkClientId, type } = transactionMeta;
1649
+ if (type !== TransactionType.swap) {
1744
1650
  return;
1745
1651
  }
1746
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
1747
- networkClientId: transactionMeta.networkClientId,
1748
- chainId: transactionMeta.chainId,
1749
- });
1652
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, { networkClientId });
1750
1653
  const { updatedTransactionMeta, approvalTransactionMeta } = await updatePostTransactionBalance(transactionMeta, {
1751
1654
  ethQuery,
1752
1655
  getTransaction: this.getTransaction.bind(this),
@@ -1768,7 +1671,6 @@ export class TransactionController extends BaseController {
1768
1671
  }
1769
1672
  catch (error) {
1770
1673
  if (this.isTransactionAlreadyConfirmedError(error)) {
1771
- await this.pendingTransactionTracker.forceCheckTransaction(transactionMeta);
1772
1674
  throw new Error('Previous transaction is already confirmed');
1773
1675
  }
1774
1676
  throw error;
@@ -1788,7 +1690,7 @@ export class TransactionController extends BaseController {
1788
1690
  error?.data?.message?.includes('nonce too low'));
1789
1691
  }
1790
1692
  }
1791
- _TransactionController_internalEvents = new WeakMap(), _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionController_pendingTransactionOptions = new WeakMap(), _TransactionController_trace = new WeakMap(), _TransactionController_transactionHistoryLimit = new WeakMap(), _TransactionController_isSimulationEnabled = new WeakMap(), _TransactionController_testGasFeeFlows = new WeakMap(), _TransactionController_multichainTrackingHelper = new WeakMap(), _TransactionController_checkForPendingTransactionAndStartPolling = new WeakMap(), _TransactionController_instances = new WeakSet(), _TransactionController_retryTransaction = async function _TransactionController_retryTransaction({ actionId, afterSubmit, estimatedBaseFee, gasValues, label, prepareTransactionParams, rate, transactionId, transactionType, }) {
1693
+ _TransactionController_internalEvents = new WeakMap(), _TransactionController_methodDataHelper = new WeakMap(), _TransactionController_incomingTransactionOptions = new WeakMap(), _TransactionController_pendingTransactionOptions = new WeakMap(), _TransactionController_trace = new WeakMap(), _TransactionController_transactionHistoryLimit = new WeakMap(), _TransactionController_isFirstTimeInteractionEnabled = new WeakMap(), _TransactionController_isSimulationEnabled = new WeakMap(), _TransactionController_testGasFeeFlows = new WeakMap(), _TransactionController_multichainTrackingHelper = new WeakMap(), _TransactionController_checkForPendingTransactionAndStartPolling = new WeakMap(), _TransactionController_instances = new WeakSet(), _TransactionController_retryTransaction = async function _TransactionController_retryTransaction({ actionId, afterSubmit, estimatedBaseFee, gasValues, label, prepareTransactionParams, rate, transactionId, transactionType, }) {
1792
1694
  // If transaction is found for same action id, do not create a new transaction.
1793
1695
  if (this.getTransactionWithActionId(actionId)) {
1794
1696
  return;
@@ -1823,10 +1725,8 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
1823
1725
  newFee,
1824
1726
  txParams: newTxParams,
1825
1727
  });
1826
- const ethQuery = __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getEthQuery({
1827
- networkClientId: transactionMeta.networkClientId,
1828
- chainId: transactionMeta.chainId,
1829
- });
1728
+ const { networkClientId } = transactionMeta;
1729
+ const ethQuery = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getEthQuery).call(this, { networkClientId });
1830
1730
  const newTransactionMeta = {
1831
1731
  ...transactionMetaWithRsv,
1832
1732
  actionId,
@@ -1855,6 +1755,23 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
1855
1755
  actionId,
1856
1756
  });
1857
1757
  afterSubmit?.(newTransactionMeta);
1758
+ }, _TransactionController_getChainId = function _TransactionController_getChainId(networkClientId) {
1759
+ return __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getNetworkClient({ networkClientId })
1760
+ .configuration.chainId;
1761
+ }, _TransactionController_getNetworkClientId = function _TransactionController_getNetworkClientId({ chainId, networkClientId, }) {
1762
+ if (networkClientId) {
1763
+ return networkClientId;
1764
+ }
1765
+ return __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getNetworkClient({
1766
+ chainId,
1767
+ }).id;
1768
+ }, _TransactionController_getEthQuery = function _TransactionController_getEthQuery({ chainId, networkClientId, }) {
1769
+ return new EthQuery(__classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getProvider).call(this, { chainId, networkClientId }));
1770
+ }, _TransactionController_getProvider = function _TransactionController_getProvider({ chainId, networkClientId, }) {
1771
+ return __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").getNetworkClient({
1772
+ chainId,
1773
+ networkClientId,
1774
+ }).provider;
1858
1775
  }, _TransactionController_createNonceTracker = function _TransactionController_createNonceTracker({ provider, blockTracker, chainId, }) {
1859
1776
  return new NonceTracker({
1860
1777
  // TODO: Fix types
@@ -1863,18 +1780,23 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
1863
1780
  // TODO: Fix types
1864
1781
  blockTracker,
1865
1782
  getPendingTransactions: __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getNonceTrackerPendingTransactions).bind(this, chainId),
1866
- getConfirmedTransactions: this.getNonceTrackerTransactions.bind(this, TransactionStatus.confirmed),
1783
+ getConfirmedTransactions: this.getNonceTrackerTransactions.bind(this, TransactionStatus.confirmed, chainId),
1784
+ });
1785
+ }, _TransactionController_createRemoteTransactionSource = function _TransactionController_createRemoteTransactionSource() {
1786
+ return new EtherscanRemoteTransactionSource({
1787
+ apiKeysByChainId: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").etherscanApiKeysByChainId,
1788
+ includeTokenTransfers: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").includeTokenTransfers,
1867
1789
  });
1868
- }, _TransactionController_createIncomingTransactionHelper = function _TransactionController_createIncomingTransactionHelper({ blockTracker, etherscanRemoteTransactionSource, chainId, }) {
1790
+ }, _TransactionController_createIncomingTransactionHelper = function _TransactionController_createIncomingTransactionHelper({ blockTracker, remoteTransactionSource, chainId, }) {
1869
1791
  const incomingTransactionHelper = new IncomingTransactionHelper({
1870
1792
  blockTracker,
1871
1793
  getCurrentAccount: () => __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getSelectedAccount).call(this),
1872
1794
  getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,
1873
1795
  getLocalTransactions: () => this.state.transactions,
1874
- getChainId: chainId ? () => chainId : this.getChainId.bind(this),
1796
+ getChainId: () => chainId,
1875
1797
  isEnabled: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").isEnabled,
1876
1798
  queryEntireHistory: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").queryEntireHistory,
1877
- remoteTransactionSource: etherscanRemoteTransactionSource,
1799
+ remoteTransactionSource,
1878
1800
  transactionLimit: __classPrivateFieldGet(this, _TransactionController_transactionHistoryLimit, "f"),
1879
1801
  updateTransactions: __classPrivateFieldGet(this, _TransactionController_incomingTransactionOptions, "f").updateTransactions,
1880
1802
  });
@@ -1882,15 +1804,14 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
1882
1804
  return incomingTransactionHelper;
1883
1805
  }, _TransactionController_createPendingTransactionTracker = function _TransactionController_createPendingTransactionTracker({ provider, blockTracker, chainId, }) {
1884
1806
  const ethQuery = new EthQuery(provider);
1885
- const getChainId = chainId ? () => chainId : this.getChainId.bind(this);
1886
1807
  const pendingTransactionTracker = new PendingTransactionTracker({
1887
1808
  blockTracker,
1888
- getChainId,
1809
+ getChainId: () => chainId,
1889
1810
  getEthQuery: () => ethQuery,
1890
1811
  getTransactions: () => this.state.transactions,
1891
1812
  isResubmitEnabled: __classPrivateFieldGet(this, _TransactionController_pendingTransactionOptions, "f").isResubmitEnabled,
1892
1813
  getGlobalLock: () => __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").acquireNonceLockForChainIdKey({
1893
- chainId: getChainId(),
1814
+ chainId,
1894
1815
  }),
1895
1816
  publishTransaction: (_ethQuery, transactionMeta) => this.publishTransaction(_ethQuery, transactionMeta, {
1896
1817
  skipSubmitHistory: true,
@@ -1903,10 +1824,6 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
1903
1824
  __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_addPendingTransactionTrackerListeners).call(this, pendingTransactionTracker);
1904
1825
  return pendingTransactionTracker;
1905
1826
  }, _TransactionController_stopAllTracking = function _TransactionController_stopAllTracking() {
1906
- this.pendingTransactionTracker.stop();
1907
- __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_removePendingTransactionTrackerListeners).call(this, this.pendingTransactionTracker);
1908
- this.incomingTransactionHelper.stop();
1909
- __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_removeIncomingTransactionHelperListeners).call(this, this.incomingTransactionHelper);
1910
1827
  __classPrivateFieldGet(this, _TransactionController_multichainTrackingHelper, "f").stopAllTracking();
1911
1828
  }, _TransactionController_removeIncomingTransactionHelperListeners = function _TransactionController_removeIncomingTransactionHelperListeners(incomingTransactionHelper) {
1912
1829
  incomingTransactionHelper.hub.removeAllListeners('transactions');
@@ -1966,6 +1883,48 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
1966
1883
  });
1967
1884
  }
1968
1885
  return transactionMeta;
1886
+ }, _TransactionController_updateFirstTimeInteraction = async function _TransactionController_updateFirstTimeInteraction(transactionMeta, { traceContext, } = {}) {
1887
+ if (!__classPrivateFieldGet(this, _TransactionController_isFirstTimeInteractionEnabled, "f").call(this)) {
1888
+ return;
1889
+ }
1890
+ const { chainId, id: transactionId, txParams: { to, from }, } = transactionMeta;
1891
+ const request = {
1892
+ chainId: hexToNumber(chainId),
1893
+ to: to,
1894
+ from,
1895
+ };
1896
+ validateParamTo(to);
1897
+ const existingTransaction = this.state.transactions.find((tx) => tx.chainId === chainId &&
1898
+ tx.txParams.from === from &&
1899
+ tx.txParams.to === to &&
1900
+ tx.id !== transactionId);
1901
+ // Check if there is an existing transaction with the same from, to, and chainId
1902
+ // else we continue to check the account address relationship from API
1903
+ if (existingTransaction) {
1904
+ return;
1905
+ }
1906
+ try {
1907
+ const { count } = await __classPrivateFieldGet(this, _TransactionController_trace, "f").call(this, { name: 'Account Address Relationship', parentContext: traceContext }, () => getAccountAddressRelationship(request));
1908
+ const isFirstTimeInteraction = count === undefined ? undefined : count === 0;
1909
+ const finalTransactionMeta = this.getTransaction(transactionId);
1910
+ /* istanbul ignore if */
1911
+ if (!finalTransactionMeta) {
1912
+ log('Cannot update first time interaction as transaction not found', transactionId);
1913
+ return;
1914
+ }
1915
+ __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_updateTransactionInternal).call(this, {
1916
+ transactionId,
1917
+ note: 'TransactionController#updateFirstInteraction - Update first time interaction',
1918
+ }, (txMeta) => {
1919
+ txMeta.isFirstTimeInteraction = isFirstTimeInteraction;
1920
+ });
1921
+ log('Updated first time interaction', transactionId, {
1922
+ isFirstTimeInteraction,
1923
+ });
1924
+ }
1925
+ catch (error) {
1926
+ log('Error fetching account address relationship, skipping first time interaction update', error);
1927
+ }
1969
1928
  }, _TransactionController_updateSimulationData = async function _TransactionController_updateSimulationData(transactionMeta, { blockTime, traceContext, } = {}) {
1970
1929
  const { id: transactionId, chainId, txParams, simulationData: prevSimulationData, } = transactionMeta;
1971
1930
  const { from, to, value, data } = txParams;
@@ -2021,26 +1980,6 @@ _TransactionController_internalEvents = new WeakMap(), _TransactionController_in
2021
1980
  txMeta.layer1GasFee = layer1GasFee;
2022
1981
  }
2023
1982
  });
2024
- }, _TransactionController_getNetworkClientId = function _TransactionController_getNetworkClientId({ networkClientId: requestNetworkClientId, chainId, }) {
2025
- const globalChainId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGlobalChainId).call(this);
2026
- const globalNetworkClientId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGlobalNetworkClientId).call(this);
2027
- if (requestNetworkClientId) {
2028
- return requestNetworkClientId;
2029
- }
2030
- if (!chainId || chainId === globalChainId) {
2031
- return globalNetworkClientId;
2032
- }
2033
- return this.messagingSystem.call(`NetworkController:findNetworkClientIdByChainId`, chainId);
2034
- }, _TransactionController_getGlobalNetworkClientId = function _TransactionController_getGlobalNetworkClientId() {
2035
- return this.getNetworkState().selectedNetworkClientId;
2036
- }, _TransactionController_getGlobalChainId = function _TransactionController_getGlobalChainId() {
2037
- return this.messagingSystem.call(`NetworkController:getNetworkClientById`, this.getNetworkState().selectedNetworkClientId).configuration.chainId;
2038
- }, _TransactionController_isCustomNetwork = function _TransactionController_isCustomNetwork(networkClientId) {
2039
- const globalNetworkClientId = __classPrivateFieldGet(this, _TransactionController_instances, "m", _TransactionController_getGlobalNetworkClientId).call(this);
2040
- if (!networkClientId || networkClientId === globalNetworkClientId) {
2041
- return !isInfuraNetworkType(this.getNetworkState().selectedNetworkClientId);
2042
- }
2043
- return (this.messagingSystem.call(`NetworkController:getNetworkClientById`, networkClientId).configuration.type === NetworkClientType.Custom);
2044
1983
  }, _TransactionController_getSelectedAccount = function _TransactionController_getSelectedAccount() {
2045
1984
  return this.messagingSystem.call('AccountsController:getSelectedAccount');
2046
1985
  }, _TransactionController_updateSubmitHistory = function _TransactionController_updateSubmitHistory(transactionMeta, hash) {