@metamask-previews/bridge-status-controller 71.2.1-preview-d3514bcb5 → 71.2.1-preview-ce4057bcb

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 (126) hide show
  1. package/CHANGELOG.md +22 -5
  2. package/dist/bridge-status-controller-method-action-types.cjs.map +1 -1
  3. package/dist/bridge-status-controller-method-action-types.d.cts +5 -1
  4. package/dist/bridge-status-controller-method-action-types.d.cts.map +1 -1
  5. package/dist/bridge-status-controller-method-action-types.d.mts +5 -1
  6. package/dist/bridge-status-controller-method-action-types.d.mts.map +1 -1
  7. package/dist/bridge-status-controller-method-action-types.mjs.map +1 -1
  8. package/dist/bridge-status-controller.cjs +161 -374
  9. package/dist/bridge-status-controller.cjs.map +1 -1
  10. package/dist/bridge-status-controller.d.cts +27 -7
  11. package/dist/bridge-status-controller.d.cts.map +1 -1
  12. package/dist/bridge-status-controller.d.mts +27 -7
  13. package/dist/bridge-status-controller.d.mts.map +1 -1
  14. package/dist/bridge-status-controller.mjs +162 -378
  15. package/dist/bridge-status-controller.mjs.map +1 -1
  16. package/dist/index.cjs +4 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +1 -0
  19. package/dist/index.d.cts.map +1 -1
  20. package/dist/index.d.mts +1 -0
  21. package/dist/index.d.mts.map +1 -1
  22. package/dist/index.mjs +1 -0
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/strategy/batch-sell-strategy.cjs +101 -0
  25. package/dist/strategy/batch-sell-strategy.cjs.map +1 -0
  26. package/dist/strategy/batch-sell-strategy.d.cts +10 -0
  27. package/dist/strategy/batch-sell-strategy.d.cts.map +1 -0
  28. package/dist/strategy/batch-sell-strategy.d.mts +10 -0
  29. package/dist/strategy/batch-sell-strategy.d.mts.map +1 -0
  30. package/dist/strategy/batch-sell-strategy.mjs +97 -0
  31. package/dist/strategy/batch-sell-strategy.mjs.map +1 -0
  32. package/dist/strategy/batch-strategy.cjs +64 -0
  33. package/dist/strategy/batch-strategy.cjs.map +1 -0
  34. package/dist/strategy/batch-strategy.d.cts +10 -0
  35. package/dist/strategy/batch-strategy.d.cts.map +1 -0
  36. package/dist/strategy/batch-strategy.d.mts +10 -0
  37. package/dist/strategy/batch-strategy.d.mts.map +1 -0
  38. package/dist/strategy/batch-strategy.mjs +60 -0
  39. package/dist/strategy/batch-strategy.mjs.map +1 -0
  40. package/dist/strategy/evm-strategy.cjs +149 -0
  41. package/dist/strategy/evm-strategy.cjs.map +1 -0
  42. package/dist/strategy/evm-strategy.d.cts +38 -0
  43. package/dist/strategy/evm-strategy.d.cts.map +1 -0
  44. package/dist/strategy/evm-strategy.d.mts +38 -0
  45. package/dist/strategy/evm-strategy.d.mts.map +1 -0
  46. package/dist/strategy/evm-strategy.mjs +143 -0
  47. package/dist/strategy/evm-strategy.mjs.map +1 -0
  48. package/dist/strategy/index.cjs +70 -0
  49. package/dist/strategy/index.cjs.map +1 -0
  50. package/dist/strategy/index.d.cts +12 -0
  51. package/dist/strategy/index.d.cts.map +1 -0
  52. package/dist/strategy/index.d.mts +12 -0
  53. package/dist/strategy/index.d.mts.map +1 -0
  54. package/dist/strategy/index.mjs +68 -0
  55. package/dist/strategy/index.mjs.map +1 -0
  56. package/dist/strategy/intent-strategy.cjs +160 -0
  57. package/dist/strategy/intent-strategy.cjs.map +1 -0
  58. package/dist/strategy/intent-strategy.d.cts +17 -0
  59. package/dist/strategy/intent-strategy.d.cts.map +1 -0
  60. package/dist/strategy/intent-strategy.d.mts +17 -0
  61. package/dist/strategy/intent-strategy.d.mts.map +1 -0
  62. package/dist/strategy/intent-strategy.mjs +156 -0
  63. package/dist/strategy/intent-strategy.mjs.map +1 -0
  64. package/dist/strategy/non-evm-strategy.cjs +80 -0
  65. package/dist/strategy/non-evm-strategy.cjs.map +1 -0
  66. package/dist/strategy/non-evm-strategy.d.cts +15 -0
  67. package/dist/strategy/non-evm-strategy.d.cts.map +1 -0
  68. package/dist/strategy/non-evm-strategy.d.mts +15 -0
  69. package/dist/strategy/non-evm-strategy.d.mts.map +1 -0
  70. package/dist/strategy/non-evm-strategy.mjs +76 -0
  71. package/dist/strategy/non-evm-strategy.mjs.map +1 -0
  72. package/dist/strategy/types.cjs +13 -0
  73. package/dist/strategy/types.cjs.map +1 -0
  74. package/dist/strategy/types.d.cts +77 -0
  75. package/dist/strategy/types.d.cts.map +1 -0
  76. package/dist/strategy/types.d.mts +77 -0
  77. package/dist/strategy/types.d.mts.map +1 -0
  78. package/dist/strategy/types.mjs +10 -0
  79. package/dist/strategy/types.mjs.map +1 -0
  80. package/dist/types.cjs.map +1 -1
  81. package/dist/types.d.cts +16 -4
  82. package/dist/types.d.cts.map +1 -1
  83. package/dist/types.d.mts +16 -4
  84. package/dist/types.d.mts.map +1 -1
  85. package/dist/types.mjs.map +1 -1
  86. package/dist/utils/bridge.cjs +5 -1
  87. package/dist/utils/bridge.cjs.map +1 -1
  88. package/dist/utils/bridge.d.cts +2 -2
  89. package/dist/utils/bridge.d.cts.map +1 -1
  90. package/dist/utils/bridge.d.mts +2 -2
  91. package/dist/utils/bridge.d.mts.map +1 -1
  92. package/dist/utils/bridge.mjs +3 -0
  93. package/dist/utils/bridge.mjs.map +1 -1
  94. package/dist/utils/history.cjs +72 -20
  95. package/dist/utils/history.cjs.map +1 -1
  96. package/dist/utils/history.d.cts +19 -5
  97. package/dist/utils/history.d.cts.map +1 -1
  98. package/dist/utils/history.d.mts +19 -5
  99. package/dist/utils/history.d.mts.map +1 -1
  100. package/dist/utils/history.mjs +69 -19
  101. package/dist/utils/history.mjs.map +1 -1
  102. package/dist/utils/metrics.cjs +10 -7
  103. package/dist/utils/metrics.cjs.map +1 -1
  104. package/dist/utils/metrics.d.cts +7 -6
  105. package/dist/utils/metrics.d.cts.map +1 -1
  106. package/dist/utils/metrics.d.mts +7 -6
  107. package/dist/utils/metrics.d.mts.map +1 -1
  108. package/dist/utils/metrics.mjs +10 -7
  109. package/dist/utils/metrics.mjs.map +1 -1
  110. package/dist/utils/trace.cjs +4 -4
  111. package/dist/utils/trace.cjs.map +1 -1
  112. package/dist/utils/trace.d.cts +2 -2
  113. package/dist/utils/trace.d.cts.map +1 -1
  114. package/dist/utils/trace.d.mts +2 -2
  115. package/dist/utils/trace.d.mts.map +1 -1
  116. package/dist/utils/trace.mjs +4 -4
  117. package/dist/utils/trace.mjs.map +1 -1
  118. package/dist/utils/transaction.cjs +80 -54
  119. package/dist/utils/transaction.cjs.map +1 -1
  120. package/dist/utils/transaction.d.cts +25 -31
  121. package/dist/utils/transaction.d.cts.map +1 -1
  122. package/dist/utils/transaction.d.mts +25 -31
  123. package/dist/utils/transaction.d.mts.map +1 -1
  124. package/dist/utils/transaction.mjs +76 -52
  125. package/dist/utils/transaction.mjs.map +1 -1
  126. package/package.json +2 -2
@@ -10,7 +10,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_intentManager, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_trace, _BridgeStatusController_onTransactionFailed, _BridgeStatusController_onTransactionConfirmed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_rekeyHistoryItem, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_handleOldHistoryItem, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_setAndGetSrcTxHash, _BridgeStatusController_updateHistoryItem, _BridgeStatusController_deleteHistoryItem, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_handleApprovalTx, _BridgeStatusController_handleEvmTransactionBatch, _BridgeStatusController_trackPollingStatusUpdatedEvent, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_intentManager, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_trace, _BridgeStatusController_onTransactionFailed, _BridgeStatusController_onTransactionConfirmed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_rekeyHistoryItem, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_handleOldHistoryItem, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_setAndGetSrcTxHash, _BridgeStatusController_updateHistoryItem, _BridgeStatusController_deleteHistoryItem, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_executeSubmitStrategy, _BridgeStatusController_trackPollingStatusUpdatedEvent, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
14
17
  Object.defineProperty(exports, "__esModule", { value: true });
15
18
  exports.BridgeStatusController = void 0;
16
19
  const bridge_controller_1 = require("@metamask/bridge-controller");
@@ -19,17 +22,16 @@ const transaction_controller_1 = require("@metamask/transaction-controller");
19
22
  const utils_1 = require("@metamask/utils");
20
23
  const bridge_status_controller_intent_1 = require("./bridge-status-controller.intent.cjs");
21
24
  const constants_1 = require("./constants.cjs");
22
- const types_1 = require("./types.cjs");
25
+ const strategy_1 = __importDefault(require("./strategy/index.cjs"));
26
+ const types_1 = require("./strategy/types.cjs");
27
+ const types_2 = require("./types.cjs");
23
28
  const accounts_1 = require("./utils/accounts.cjs");
24
29
  const authentication_1 = require("./utils/authentication.cjs");
25
30
  const bridge_1 = require("./utils/bridge.cjs");
26
31
  const bridge_status_1 = require("./utils/bridge-status.cjs");
27
32
  const history_1 = require("./utils/history.cjs");
28
- const intent_api_1 = require("./utils/intent-api.cjs");
29
- const keyring_1 = require("./utils/keyring.cjs");
30
33
  const metrics_1 = require("./utils/metrics.cjs");
31
34
  const network_1 = require("./utils/network.cjs");
32
- const snaps_1 = require("./utils/snaps.cjs");
33
35
  const trace_1 = require("./utils/trace.cjs");
34
36
  const transaction_1 = require("./utils/transaction.cjs");
35
37
  const metadata = {
@@ -48,6 +50,7 @@ const MESSENGER_EXPOSED_METHODS = [
48
50
  'resetState',
49
51
  'submitTx',
50
52
  'submitIntent',
53
+ 'submitBatchSell',
51
54
  'restartPollingForFailedAttempts',
52
55
  'getBridgeHistoryItemByTxMetaId',
53
56
  ];
@@ -79,6 +82,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
79
82
  historyKey,
80
83
  status: bridge_controller_1.StatusTypes.FAILED,
81
84
  txHash: isApprovalTxMeta ? undefined : txMeta.hash,
85
+ completionTime: Date.now(),
82
86
  });
83
87
  if (txMeta.status === transaction_controller_1.TransactionStatus.rejected) {
84
88
  return;
@@ -101,11 +105,13 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
101
105
  historyKey,
102
106
  txHash: txMeta.hash,
103
107
  });
104
- switch (txMeta.type) {
105
- case transaction_controller_1.TransactionType.swap:
108
+ const isSwap = txMeta.type === transaction_controller_1.TransactionType.swap || (0, transaction_1.hasNestedSwapTransactions)(txMeta);
109
+ switch (isSwap) {
110
+ case true:
106
111
  __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
107
112
  historyKey,
108
113
  status: bridge_controller_1.StatusTypes.COMPLETE,
114
+ completionTime: Date.now(),
109
115
  });
110
116
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, historyKey);
111
117
  break;
@@ -242,10 +248,9 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
242
248
  __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
243
249
  });
244
250
  });
245
- _BridgeStatusController_addTxToHistory.set(this, (...args) => {
246
- const { historyKey, txHistoryItem } = (0, history_1.getInitialHistoryItem)(...args);
251
+ _BridgeStatusController_addTxToHistory.set(this, (historyKey, ...args) => {
252
+ const txHistoryItem = (0, history_1.getInitialHistoryItem)(...args);
247
253
  this.update((state) => {
248
- // Use actionId as key for pre-submission, or txMeta.id for post-submission
249
254
  state.txHistory[historyKey] = txHistoryItem;
250
255
  });
251
256
  return historyKey;
@@ -254,14 +259,15 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
254
259
  * Rekeys a history item from actionId to txMeta.id after successful submission.
255
260
  * Also updates txMetaId and srcTxHash which weren't available pre-submission.
256
261
  *
257
- * @param actionId - The actionId used as the temporary key for the history item
262
+ * @param oldKey - The temporary key to use for the history item, usually the actionId
263
+ * @param newKey - The new key to use, typcally the txmeta.id
258
264
  * @param txMeta - The transaction meta from the successful submission
259
265
  * @param txMeta.id - The transaction meta id to use as the new key
260
266
  * @param txMeta.hash - The transaction hash to set on the history item
261
267
  */
262
- _BridgeStatusController_rekeyHistoryItem.set(this, (actionId, txMeta) => {
268
+ _BridgeStatusController_rekeyHistoryItem.set(this, (oldKey, newKey, txMeta) => {
263
269
  this.update((state) => {
264
- (0, history_1.rekeyHistoryItemInState)(state, actionId, txMeta);
270
+ (0, history_1.rekeyHistoryItemInState)(state, oldKey, newKey, txMeta);
265
271
  });
266
272
  });
267
273
  _BridgeStatusController_startPollingForTxId.set(this, (txId) => {
@@ -292,7 +298,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
292
298
  if (!bridgeTxMeta?.id) {
293
299
  throw new Error('Cannot start polling: bridgeTxMeta.id is required for polling');
294
300
  }
295
- const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, txHistoryMeta);
301
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, bridgeTxMeta.id, txHistoryMeta);
296
302
  __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
297
303
  };
298
304
  // This will be called after you call this.startPolling()
@@ -487,7 +493,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
487
493
  });
488
494
  return localTxHash;
489
495
  });
490
- _BridgeStatusController_updateHistoryItem.set(this, ({ historyKey, status, txHash, attempts, }) => {
496
+ _BridgeStatusController_updateHistoryItem.set(this, ({ historyKey, status, txHash, attempts, completionTime, }) => {
491
497
  if (!historyKey) {
492
498
  return;
493
499
  }
@@ -501,6 +507,9 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
501
507
  if (attempts) {
502
508
  currentState.txHistory[historyKey].attempts = attempts;
503
509
  }
510
+ if (completionTime) {
511
+ currentState.txHistory[historyKey].completionTime = completionTime;
512
+ }
504
513
  });
505
514
  });
506
515
  _BridgeStatusController_deleteHistoryItem.set(this, (historyKey) => {
@@ -536,249 +545,134 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
536
545
  * TX SUBMISSION HANDLING
537
546
  *******************************************************
538
547
  */
539
- _BridgeStatusController_handleApprovalTx.set(this, async (quoteResponse, isBridgeTx, srcChainId, approval, resetApproval, requireApproval) => {
540
- if (approval && (0, bridge_controller_1.isEvmTxData)(approval)) {
541
- const approveTx = async () => {
542
- if (resetApproval) {
543
- await (0, transaction_1.submitEvmTransaction)({
544
- messenger: this.messenger,
545
- transactionType: transaction_controller_1.TransactionType.bridgeApproval,
546
- trade: resetApproval,
547
- });
548
+ _BridgeStatusController_executeSubmitStrategy.set(this, async (params, sharedHistoryItemProperties) => {
549
+ let tradeTxMeta;
550
+ const steps = (0, strategy_1.default)(params);
551
+ // Each submission strategy determines when to execute step, which means these actions can happen in any order
552
+ for await (const { type, payload } of steps) {
553
+ try {
554
+ switch (type) {
555
+ case types_1.SubmitStep.RekeyHistoryItem:
556
+ __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, payload.oldHistoryKey, payload.newHistoryKey, payload.tradeMeta);
557
+ break;
558
+ case types_1.SubmitStep.UpdateBatchTransactions:
559
+ (0, transaction_1.updateTransactionsInBatch)({
560
+ messenger: this.messenger,
561
+ allTradesWithMetadata: payload.quoteAndTxMetas,
562
+ });
563
+ break;
564
+ case types_1.SubmitStep.SetTradeMeta:
565
+ tradeTxMeta = payload.tradeMeta;
566
+ break;
567
+ case types_1.SubmitStep.AddHistoryItem:
568
+ __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, payload.historyKey, {
569
+ ...payload,
570
+ ...sharedHistoryItemProperties,
571
+ quoteResponse: payload.quoteResponse,
572
+ accountAddress: params.selectedAccount.address,
573
+ isStxEnabled: params.isStxEnabled,
574
+ slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
575
+ });
576
+ break;
577
+ case types_1.SubmitStep.StartPolling:
578
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, payload.historyKey);
579
+ break;
580
+ case types_1.SubmitStep.PublishCompletedEvent:
581
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, payload.historyKey);
582
+ break;
583
+ /* c8 ignore start */
584
+ default:
585
+ throw new Error(`Unknown submit step type: ${String(type)}`);
586
+ /* c8 ignore end */
548
587
  }
549
- const approvalTxMeta = await (0, transaction_1.submitEvmTransaction)({
550
- messenger: this.messenger,
551
- transactionType: isBridgeTx
552
- ? transaction_controller_1.TransactionType.bridgeApproval
553
- : transaction_controller_1.TransactionType.swapApproval,
554
- trade: approval,
555
- requireApproval,
556
- });
557
- await (0, transaction_1.handleApprovalDelay)(srcChainId);
558
- return approvalTxMeta;
559
- };
560
- return await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getApprovalTraceParams)(quoteResponse, false), approveTx);
561
- }
562
- return undefined;
563
- });
564
- /**
565
- * Submits batched EVM transactions to the TransactionController
566
- *
567
- * @param args - The parameters for the transaction
568
- * @param args.isBridgeTx - Whether the transaction is a bridge transaction
569
- * @param args.quoteResponse - The quote response containing the approval and trade data
570
- * @param args.requireApproval - Whether to require approval for the transaction
571
- * @param args.isDelegatedAccount - Whether the account is a delegated account
572
- * @returns The approvalMeta and tradeMeta for the batched transaction
573
- */
574
- _BridgeStatusController_handleEvmTransactionBatch.set(this, async ({ requireApproval, isDelegatedAccount, isBridgeTx, quoteResponse, }) => {
575
- const tradeData = (0, transaction_1.toQuoteAndTxMetadata)({
576
- quoteResponse,
577
- isBridgeTx,
578
- });
579
- const transactionParams = await (0, transaction_1.getAddTransactionBatchParams)({
580
- tradeData,
581
- requireApproval,
582
- isDelegatedAccount,
583
- messenger: this.messenger,
584
- atomic: true,
585
- disable7702:
586
- // Enable 7702 batching when the quote includes gasless 7702 support,
587
- quoteResponse.quote.gasIncluded7702
588
- ? false
589
- : // or when the account is already delegated (to avoid the in-flight transaction limit for delegated accounts)
590
- !isDelegatedAccount ||
591
- // For gasless transactions with STX/sendBundle we keep disabling 7702.
592
- quoteResponse.quote.gasIncluded,
593
- isGasFeeSponsored: Boolean(quoteResponse.quote.gasSponsored),
594
- isGasFeeIncluded: Boolean(quoteResponse.quote.gasIncluded7702),
595
- });
596
- const { tradeMeta, approvalMeta } = await (0, transaction_1.addTransactionBatch)(this.messenger, __classPrivateFieldGet(this, _BridgeStatusController_addTransactionBatchFn, "f"), tradeData, transactionParams);
597
- if (!tradeMeta) {
598
- throw new Error('Failed to update cross-chain swap transaction batch: tradeMeta not found');
588
+ }
589
+ catch (error) {
590
+ console.error('Failed to add to bridge history and start polling.', error);
591
+ }
599
592
  }
600
- return { tradeMeta, approvalMeta };
593
+ return tradeTxMeta;
601
594
  });
602
595
  /**
603
596
  * Submits a cross-chain swap transaction
604
597
  *
605
598
  * @param accountAddress - The address of the account to submit the transaction for
606
- * @param quoteResponse - The quote response
607
- * @param isStxEnabledOnClient - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension
599
+ * @param maybeQuoteResponses - A single quote response or an array of quote responses
600
+ * @param isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension
608
601
  * @param quotesReceivedContext - The context for the QuotesReceived event
609
602
  * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore)
610
603
  * @param abTests - Legacy A/B test context for `ab_tests` (backward compatibility)
611
604
  * @param activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.
612
605
  * @param tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.
606
+ * @param batchSellTrades - Contains transaction data for the quotes, provided by the obtainGaslessBatch API
613
607
  * @returns The transaction meta
608
+ * @throws An error if transaction submission fails before it gets published
614
609
  */
615
- this.submitTx = async (accountAddress, quoteResponse, isStxEnabledOnClient, quotesReceivedContext, location = bridge_controller_1.MetaMetricsSwapsEventSource.MainView, abTests, activeAbTests, tokenSecurityTypeDestination) => {
616
- (0, bridge_1.stopPollingForQuotes)(this.messenger, quoteResponse.featureId, quotesReceivedContext);
610
+ this.submitTx = async (accountAddress, maybeQuoteResponses, isStxEnabled, quotesReceivedContext, location = bridge_controller_1.MetaMetricsSwapsEventSource.MainView, abTests, activeAbTests, tokenSecurityTypeDestination, batchSellTrades) => {
611
+ /**
612
+ * If there are multiple quote responses, we assume that they all originate from the same src chain
613
+ * and the same account. In this case its safe to use the first quote response's properties for
614
+ * metrics and other pre-submission logic
615
+ */
616
+ const quoteResponses = Array.isArray(maybeQuoteResponses)
617
+ ? maybeQuoteResponses
618
+ : [maybeQuoteResponses];
619
+ const quoteResponse = quoteResponses[0];
620
+ const { featureId, quote } = quoteResponse;
621
+ const startTime = Date.now();
622
+ (0, bridge_1.stopPollingForQuotes)(this.messenger, featureId, quotesReceivedContext);
617
623
  const selectedAccount = (0, accounts_1.getAccountByAddress)(this.messenger, accountAddress);
618
624
  if (!selectedAccount) {
619
625
  throw new Error('Failed to submit cross-chain swap transaction: undefined multichain account');
620
626
  }
621
627
  const accountHardwareType = (0, bridge_controller_1.getAccountHardwareType)(selectedAccount);
622
- const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabledOnClient, accountHardwareType, location, abTests, activeAbTests, tokenSecurityTypeDestination);
623
- let txMeta;
624
- let approvalTxId;
625
- let isDelegatedAccount = false;
626
- const startTime = Date.now();
627
- const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
628
- const isTronTx = (0, bridge_controller_1.isTronChainId)(quoteResponse.quote.srcChainId);
628
+ /**
629
+ * For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval.
630
+ * Extension does not have this issue
631
+ */
632
+ const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_2.BridgeClientId.MOBILE && accountHardwareType !== null;
633
+ const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quote.srcChainId, quote.destChainId);
634
+ const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabled, accountHardwareType, location, abTests, activeAbTests, tokenSecurityTypeDestination, batchSellTrades);
629
635
  try {
630
636
  // Emit Submitted event after submit button is clicked
631
- !quoteResponse.featureId &&
632
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Submitted, undefined, preConfirmationProperties);
633
- // Submit non-EVM tx (Solana, BTC, Tron)
634
- if ((0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId)) {
635
- // Handle non-EVM approval if present (e.g., Tron token approvals)
636
- if (quoteResponse.approval && (0, bridge_controller_1.isTronTrade)(quoteResponse.approval)) {
637
- const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getApprovalTraceParams)(quoteResponse, false), async () => {
638
- return quoteResponse.approval &&
639
- (0, bridge_controller_1.isTronTrade)(quoteResponse.approval)
640
- ? await (0, snaps_1.handleNonEvmTx)(this.messenger, quoteResponse.approval, quoteResponse, selectedAccount)
641
- : /* c8 ignore start */
642
- undefined;
643
- /* c8 ignore end */
644
- });
645
- approvalTxId = approvalTxMeta?.id;
646
- // Add delay after approval similar to EVM flow
647
- await (0, transaction_1.handleApprovalDelay)(quoteResponse.quote.srcChainId);
648
- }
649
- txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, false), async () => {
650
- if (!((0, bridge_controller_1.isTronTrade)(quoteResponse.trade) ||
651
- (0, bridge_controller_1.isBitcoinTrade)(quoteResponse.trade) ||
652
- typeof quoteResponse.trade === 'string')) {
653
- throw new Error('Failed to submit cross-chain swap transaction: trade is not a non-EVM transaction');
654
- }
655
- return await (0, snaps_1.handleNonEvmTx)(this.messenger, quoteResponse.trade, quoteResponse, selectedAccount);
656
- });
657
- }
658
- else {
659
- // Submit EVM tx
660
- // For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval
661
- // Extension does not have this issue
662
- const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE &&
663
- accountHardwareType !== null;
664
- // Handle smart transactions if enabled
665
- txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, isStxEnabledOnClient), async () => {
666
- if (!(0, bridge_controller_1.isEvmTxData)(quoteResponse.trade)) {
667
- throw new Error('Failed to submit cross-chain swap transaction: trade is not an EVM transaction');
668
- }
669
- // Check if the account is an EIP-7702 delegated account
670
- // Delegated accounts only allow 1 in-flight tx, so approve + swap
671
- // must be batched into a single transaction
672
- const hexChainId = (0, bridge_controller_1.formatChainIdToHex)(quoteResponse.quote.srcChainId);
673
- isDelegatedAccount = await (0, transaction_1.checkIsDelegatedAccount)(this.messenger, quoteResponse.trade.from, [hexChainId]);
674
- if (isStxEnabledOnClient ||
675
- quoteResponse.quote.gasIncluded7702 ||
676
- isDelegatedAccount) {
677
- const { tradeMeta, approvalMeta } = await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransactionBatch, "f").call(this, {
678
- isBridgeTx,
679
- quoteResponse,
680
- requireApproval,
681
- isDelegatedAccount,
682
- });
683
- approvalTxId = approvalMeta?.id;
684
- return tradeMeta;
685
- }
686
- // Set approval time and id if an approval tx is needed
687
- const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval)
688
- ? quoteResponse.approval
689
- : undefined, quoteResponse.resetApproval, requireApproval);
690
- approvalTxId = approvalTxMeta?.id;
691
- // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for
692
- // on-chain approval confirmation so swap gas estimation runs after allowance is set.
693
- if (requireApproval && approvalTxMeta) {
694
- await (0, transaction_1.handleMobileHardwareWalletDelay)(requireApproval);
695
- await (0, transaction_1.waitForTxConfirmation)(this.messenger, approvalTxMeta.id);
696
- }
697
- else {
698
- await (0, transaction_1.handleMobileHardwareWalletDelay)(requireApproval);
699
- }
700
- // Generate actionId for pre-submission history (non-batch EVM only)
701
- const actionId = (0, transaction_1.generateActionId)().toString();
702
- // Add pre-submission history keyed by actionId
703
- // This ensures we have quote data available if transaction fails during submission
704
- const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
705
- accountAddress: selectedAccount.address,
706
- quoteResponse,
707
- slippagePercentage: 0,
708
- isStxEnabled: isStxEnabledOnClient,
709
- startTime,
710
- approvalTxId,
711
- location,
712
- abTests,
713
- activeAbTests,
714
- actionId,
715
- tokenSecurityTypeDestination,
716
- });
717
- // Pass txFee when gasIncluded is true to use the quote's gas fees
718
- // instead of re-estimating (which would fail for max native token swaps)
719
- const tradeTxMeta = await (0, transaction_1.submitEvmTransaction)({
720
- messenger: this.messenger,
721
- transactionType: isBridgeTx
722
- ? transaction_controller_1.TransactionType.bridge
723
- : transaction_controller_1.TransactionType.swap,
724
- trade: quoteResponse.trade,
725
- requireApproval,
726
- txFee: quoteResponse.quote.gasIncluded
727
- ? quoteResponse.quote.feeData.txFee
728
- : undefined,
729
- actionId,
730
- });
731
- // On success, rekey from actionId to txMeta.id and update srcTxHash
732
- __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, historyKey, tradeTxMeta);
733
- return tradeTxMeta;
734
- });
735
- }
637
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Submitted, undefined, preConfirmationProperties, featureId);
638
+ /**
639
+ * Check if the account is an EIP-7702 delegated account.
640
+ * Delegated accounts only allow 1 in-flight tx, so approve + swap
641
+ * must be batched into a single transaction
642
+ */
643
+ const isDelegatedAccount = (0, bridge_controller_1.isNonEvmChainId)(quote.srcChainId)
644
+ ? false
645
+ : await (0, transaction_1.checkIsDelegatedAccount)(this.messenger, selectedAccount.address, [(0, bridge_controller_1.formatChainIdToHex)(quote.srcChainId)]);
646
+ const strategyParams = {
647
+ messenger: this.messenger,
648
+ quoteResponses,
649
+ batchSellTrades,
650
+ isStxEnabled,
651
+ isBridgeTx,
652
+ isDelegatedAccount,
653
+ selectedAccount,
654
+ requireApproval,
655
+ clientId: __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"),
656
+ bridgeApiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
657
+ addTransactionBatchFn: __classPrivateFieldGet(this, _BridgeStatusController_addTransactionBatchFn, "f"),
658
+ fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
659
+ traceFn: __classPrivateFieldGet(this, _BridgeStatusController_trace, "f"),
660
+ };
661
+ return await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, isStxEnabled), async () => await __classPrivateFieldGet(this, _BridgeStatusController_executeSubmitStrategy, "f").call(this, strategyParams, {
662
+ startTime,
663
+ location,
664
+ abTests,
665
+ activeAbTests,
666
+ tokenSecurityTypeDestination,
667
+ }));
736
668
  }
737
669
  catch (error) {
738
- !quoteResponse.featureId &&
739
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
740
- error_message: error?.message,
741
- ...preConfirmationProperties,
742
- });
670
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
671
+ error_message: error?.message,
672
+ ...preConfirmationProperties,
673
+ }, featureId);
743
674
  throw error;
744
675
  }
745
- try {
746
- // For non-batch EVM transactions, history was already added/rekeyed above
747
- // Only add history here for non-EVM and batch EVM transactions
748
- const isNonBatchEvm = !(0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId) &&
749
- !isStxEnabledOnClient &&
750
- !quoteResponse.quote.gasIncluded7702 &&
751
- !isDelegatedAccount;
752
- let historyKey = txMeta.id;
753
- if (!isNonBatchEvm) {
754
- // Add swap or bridge tx to history
755
- historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
756
- accountAddress: selectedAccount.address,
757
- bridgeTxMeta: txMeta, // Only the id and hash fields are used by the BridgeStatusController
758
- quoteResponse,
759
- slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
760
- isStxEnabled: isStxEnabledOnClient,
761
- startTime,
762
- approvalTxId,
763
- location,
764
- abTests,
765
- activeAbTests,
766
- tokenSecurityTypeDestination,
767
- });
768
- }
769
- if ((0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId)) {
770
- // Start polling for bridge tx status
771
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
772
- // Track non-EVM Swap completed event
773
- if (!(isBridgeTx || isTronTx)) {
774
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, historyKey);
775
- }
776
- }
777
- }
778
- catch {
779
- // Ignore errors here, we don't want to crash the app if this fails and tx submission succeeds
780
- }
781
- return txMeta;
782
676
  };
783
677
  /**
784
678
  * Submits an intent order and creates a synthetic history entry for UX.
@@ -791,135 +685,28 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
791
685
  * @param params.abTests - Legacy A/B test context for `ab_tests` (backward compatibility)
792
686
  * @param params.activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.
793
687
  * @param params.tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.
688
+ * @param params.isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension
689
+ * @param params.quotesReceivedContext - The context for the QuotesReceived event
794
690
  * @returns A lightweight TransactionMeta-like object for history linking
691
+ * @throws An error if intent or transaction submission fails before they get published
795
692
  */
796
693
  this.submitIntent = async (params) => {
797
- const { quoteResponse, accountAddress, location, abTests, activeAbTests, tokenSecurityTypeDestination, } = params;
694
+ const { quoteResponse, accountAddress, location, abTests, activeAbTests, tokenSecurityTypeDestination, isStxEnabled = false, quotesReceivedContext, } = params;
798
695
  // TODO add metrics context
799
- (0, bridge_1.stopPollingForQuotes)(this.messenger);
800
- const startTime = Date.now();
801
- // Build pre-confirmation properties for error tracking parity with submitTx
802
- const account = (0, accounts_1.getAccountByAddress)(this.messenger, accountAddress);
803
- const accountHardwareType = (0, bridge_controller_1.getAccountHardwareType)(account);
804
- const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, false, accountHardwareType, location, abTests, activeAbTests, tokenSecurityTypeDestination);
805
- try {
806
- const intent = (0, intent_api_1.getIntentFromQuote)(quoteResponse);
807
- // If backend provided an approval tx for this intent quote, submit it first (on-chain),
808
- // then proceed with off-chain intent submission.
809
- const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
810
- const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE &&
811
- accountHardwareType !== null;
812
- // Handle approval silently for better UX in intent flows
813
- const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval, quoteResponse.resetApproval, requireApproval);
814
- const approvalTxId = approvalTxMeta?.id;
815
- if (approvalTxId) {
816
- await (0, transaction_1.waitForTxConfirmation)(this.messenger, approvalTxId);
817
- }
818
- const { srcChainId, requestId } = quoteResponse.quote;
819
- const signature = await (0, keyring_1.signTypedMessage)({
820
- messenger: this.messenger,
821
- accountAddress,
822
- typedData: intent.typedData,
823
- });
824
- const submissionParams = {
825
- srcChainId,
826
- quoteId: requestId,
827
- signature,
828
- order: intent.order,
829
- userAddress: accountAddress,
830
- aggregatorId: intent.protocol,
831
- };
832
- const { id: orderUid, status } = await (0, intent_api_1.postSubmitOrder)({
833
- params: submissionParams,
834
- clientId: __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"),
835
- jwt: await (0, authentication_1.getJwt)(this.messenger),
836
- fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
837
- bridgeApiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
838
- });
839
- // Determine transaction type: swap for same-chain, bridge for cross-chain
840
- const transactionType = isBridgeTx
841
- ? /* c8 ignore start */
842
- transaction_controller_1.TransactionType.bridge
843
- : /* c8 ignore end */
844
- transaction_controller_1.TransactionType.swap;
845
- // Create actual transaction in Transaction Controller first
846
- const networkClientId = (0, network_1.getNetworkClientIdByChainId)(this.messenger, srcChainId);
847
- // This is a synthetic transaction whose purpose is to be able
848
- // to track the order status via the history
849
- const intentTransactionParams = {
850
- chainId: (0, bridge_controller_1.formatChainIdToHex)(srcChainId),
851
- from: accountAddress,
852
- to: intent.settlementContract ??
853
- '0x9008D19f58AAbd9eD0D60971565AA8510560ab41', // Default settlement contract
854
- data: `0x${orderUid.slice(-8)}`, // Use last 8 chars of orderUid to make each transaction unique
855
- value: '0x0',
856
- gas: '0x5208', // Minimal gas for display purposes
857
- gasPrice: '0x3b9aca00', // 1 Gwei - will be converted to EIP-1559 fees if network supports it
858
- };
859
- const initialTxMeta = await (0, transaction_1.addSyntheticTransaction)(this.messenger, intentTransactionParams, {
860
- requireApproval: false,
861
- networkClientId,
862
- type: transactionType,
863
- });
864
- // Update txHistory with actual transaction metadata
865
- const syntheticMeta = {
866
- ...initialTxMeta,
867
- // Map intent order status to TransactionController status
868
- status: (0, intent_api_1.mapIntentOrderStatusToTransactionStatus)(status),
869
- isIntentTx: true,
870
- orderUid,
871
- };
872
- // Record in bridge history with actual transaction metadata
873
- try {
874
- // Create a bridge transaction metadata keyed by orderUid for intent polling
875
- const bridgeTxMetaForHistory = {
876
- ...syntheticMeta,
877
- id: orderUid,
878
- };
879
- // Use orderId as the history key for intent transactions
880
- // IMPORTANT: pass originalTransactionId as a top-level argument so
881
- // `getInitialHistoryItem` reads it. Setting it on `bridgeTxMeta` is a no-op
882
- // because `getInitialHistoryItem` destructures `originalTransactionId` from
883
- // the top-level args, not from `bridgeTxMeta`. Without this, the field
884
- // falls back to `bridgeTxMeta.id` (the orderUid), severing the link between
885
- // the bridge history record and the synthetic TransactionController entry.
886
- const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
887
- accountAddress,
888
- bridgeTxMeta: bridgeTxMetaForHistory,
889
- originalTransactionId: syntheticMeta.id,
890
- quoteResponse,
891
- slippagePercentage: 0,
892
- isStxEnabled: false,
893
- approvalTxId,
894
- startTime,
895
- location,
896
- abTests,
897
- activeAbTests,
898
- tokenSecurityTypeDestination,
899
- });
900
- // Start polling using the orderId key to route to intent manager
901
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
902
- }
903
- catch (error) {
904
- console.error('📝 [submitIntent] Failed to add to bridge history', error);
905
- // non-fatal but log the error
906
- }
907
- return syntheticMeta;
908
- }
909
- catch (error) {
910
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
911
- error_message: error?.message,
912
- ...preConfirmationProperties,
913
- });
914
- throw error;
915
- }
696
+ return await this.submitTx(accountAddress, quoteResponse, isStxEnabled, quotesReceivedContext, location, abTests, activeAbTests, tokenSecurityTypeDestination);
697
+ };
698
+ this.submitBatchSell = async (params) => {
699
+ /**
700
+ * Retrieve the batch sell trades from the BridgeController's state to ensure we submit
701
+ * the original response data from the bridge-api
702
+ */
703
+ const batchSellTrades = (0, bridge_1.getBatchSellTrades)(this.messenger);
704
+ return await this.submitTx(params.accountAddress, params.quoteResponses.filter((quoteResponse) => quoteResponse !== null), params.isStxEnabled ?? false, params.quotesReceivedContext, params.location, params.abTests, params.activeAbTests, params.tokenSecurityTypeDestination, batchSellTrades);
916
705
  };
917
706
  _BridgeStatusController_trackPollingStatusUpdatedEvent.set(this, (historyKey, pollingStatus) => {
918
707
  // Track polling status updated event
919
708
  const historyItem = this.state.txHistory[historyKey];
920
- if (historyItem && !historyItem.featureId) {
921
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.PollingStatusUpdated, historyKey, (0, metrics_1.getPollingStatusUpdatedProperties)(this.messenger, pollingStatus, historyItem));
922
- }
709
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.PollingStatusUpdated, historyKey, (0, metrics_1.getPollingStatusUpdatedProperties)(this.messenger, pollingStatus, historyItem));
923
710
  });
924
711
  /**
925
712
  * Tracks post-submission events for a cross-chain swap based on the history item
@@ -927,8 +714,22 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
927
714
  * @param eventName - The name of the event to track
928
715
  * @param txMetaId - The txMetaId of the history item to track the event for
929
716
  * @param eventProperties - The properties for the event
717
+ * @param featureIdOverride - The featureId to use when the history item is not available. Should
718
+ * only be provided for events that are not associated with a history item yet, such as Submitted or Failed
930
719
  */
931
- _BridgeStatusController_trackUnifiedSwapBridgeEvent.set(this, (eventName, txMetaId, eventProperties) => {
720
+ _BridgeStatusController_trackUnifiedSwapBridgeEvent.set(this, (eventName, txMetaId, eventProperties, featureIdOverride) => {
721
+ const historyItem = txMetaId
722
+ ? this.state.txHistory[txMetaId]
723
+ : undefined;
724
+ const featureId = featureIdOverride ?? historyItem?.featureId;
725
+ const shouldSkipMetrics =
726
+ // Skip tracking all other events when featureId is set (i.e. PERPS)
727
+ featureId &&
728
+ // Always publish StatusValidationFailed event, regardless of featureId
729
+ eventName !== bridge_controller_1.UnifiedSwapBridgeEventName.StatusValidationFailed;
730
+ if (shouldSkipMetrics) {
731
+ return;
732
+ }
932
733
  // Legacy/new metrics fields are intentionally kept independent during migration.
933
734
  const historyAbTests = txMetaId
934
735
  ? this.state.txHistory?.[txMetaId]?.abTests
@@ -938,12 +739,12 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
938
739
  : undefined;
939
740
  const resolvedAbTests = eventProperties?.ab_tests ?? historyAbTests;
940
741
  const resolvedActiveAbTests = eventProperties?.active_ab_tests ?? historyActiveAbTests;
742
+ const location = (txMetaId ? this.state.txHistory?.[txMetaId]?.location : undefined) ??
743
+ bridge_controller_1.MetaMetricsSwapsEventSource.MainView;
941
744
  const baseProperties = {
942
745
  action_type: bridge_controller_1.MetricsActionType.SWAPBRIDGE_V1,
943
- location: eventProperties?.location ??
944
- (txMetaId ? this.state.txHistory?.[txMetaId]?.location : undefined) ??
945
- bridge_controller_1.MetaMetricsSwapsEventSource.MainView,
946
746
  ...(eventProperties ?? {}),
747
+ location,
947
748
  ...(resolvedAbTests &&
948
749
  Object.keys(resolvedAbTests).length > 0 && {
949
750
  ab_tests: resolvedAbTests,
@@ -954,15 +755,6 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
954
755
  }),
955
756
  };
956
757
  // This will publish events for PERPS dropped tx failures as well
957
- if (!txMetaId) {
958
- (0, bridge_1.trackMetricsEvent)({
959
- messenger: this.messenger,
960
- eventName,
961
- properties: baseProperties,
962
- });
963
- return;
964
- }
965
- const historyItem = this.state.txHistory[txMetaId];
966
758
  if (!historyItem) {
967
759
  (0, bridge_1.trackMetricsEvent)({
968
760
  messenger: this.messenger,
@@ -971,9 +763,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
971
763
  });
972
764
  return;
973
765
  }
974
- const { featureId, approvalTxId, quote } = historyItem;
766
+ const { approvalTxId, quote } = historyItem;
975
767
  const requestParamProperties = (0, metrics_1.getRequestParamFromHistory)(historyItem);
976
- // Always publish StatusValidationFailed event, regardless of featureId
977
768
  if (eventName === bridge_controller_1.UnifiedSwapBridgeEventName.StatusValidationFailed) {
978
769
  (0, bridge_1.trackMetricsEvent)({
979
770
  messenger: this.messenger,
@@ -990,10 +781,6 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
990
781
  });
991
782
  return;
992
783
  }
993
- // Skip tracking all other events when featureId is set (i.e. PERPS)
994
- if (featureId) {
995
- return;
996
- }
997
784
  const selectedAccount = (0, accounts_1.getAccountByAddress)(this.messenger, historyItem.account);
998
785
  const transactions = (0, transaction_1.getTransactions)(this.messenger);
999
786
  const txMeta = transactions.find((tx) => tx.id === txMetaId);
@@ -1074,5 +861,5 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
1074
861
  }
1075
862
  }
1076
863
  exports.BridgeStatusController = BridgeStatusController;
1077
- _BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_intentManager = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_addTransactionBatchFn = new WeakMap(), _BridgeStatusController_trace = new WeakMap(), _BridgeStatusController_onTransactionFailed = new WeakMap(), _BridgeStatusController_onTransactionConfirmed = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_addTxToHistory = new WeakMap(), _BridgeStatusController_rekeyHistoryItem = new WeakMap(), _BridgeStatusController_startPollingForTxId = new WeakMap(), _BridgeStatusController_handleFetchFailure = new WeakMap(), _BridgeStatusController_handleOldHistoryItem = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_setAndGetSrcTxHash = new WeakMap(), _BridgeStatusController_updateHistoryItem = new WeakMap(), _BridgeStatusController_deleteHistoryItem = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_handleApprovalTx = new WeakMap(), _BridgeStatusController_handleEvmTransactionBatch = new WeakMap(), _BridgeStatusController_trackPollingStatusUpdatedEvent = new WeakMap(), _BridgeStatusController_trackUnifiedSwapBridgeEvent = new WeakMap();
864
+ _BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_intentManager = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_addTransactionBatchFn = new WeakMap(), _BridgeStatusController_trace = new WeakMap(), _BridgeStatusController_onTransactionFailed = new WeakMap(), _BridgeStatusController_onTransactionConfirmed = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_addTxToHistory = new WeakMap(), _BridgeStatusController_rekeyHistoryItem = new WeakMap(), _BridgeStatusController_startPollingForTxId = new WeakMap(), _BridgeStatusController_handleFetchFailure = new WeakMap(), _BridgeStatusController_handleOldHistoryItem = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_setAndGetSrcTxHash = new WeakMap(), _BridgeStatusController_updateHistoryItem = new WeakMap(), _BridgeStatusController_deleteHistoryItem = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_executeSubmitStrategy = new WeakMap(), _BridgeStatusController_trackPollingStatusUpdatedEvent = new WeakMap(), _BridgeStatusController_trackUnifiedSwapBridgeEvent = new WeakMap();
1078
865
  //# sourceMappingURL=bridge-status-controller.cjs.map