@metamask/bridge-status-controller 70.0.5 → 71.1.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 (98) hide show
  1. package/CHANGELOG.md +58 -8
  2. package/dist/bridge-status-controller-method-action-types.cjs +7 -0
  3. package/dist/bridge-status-controller-method-action-types.cjs.map +1 -0
  4. package/dist/bridge-status-controller-method-action-types.d.cts +38 -0
  5. package/dist/bridge-status-controller-method-action-types.d.cts.map +1 -0
  6. package/dist/bridge-status-controller-method-action-types.d.mts +38 -0
  7. package/dist/bridge-status-controller-method-action-types.d.mts.map +1 -0
  8. package/dist/bridge-status-controller-method-action-types.mjs +6 -0
  9. package/dist/bridge-status-controller-method-action-types.mjs.map +1 -0
  10. package/dist/bridge-status-controller.cjs +217 -123
  11. package/dist/bridge-status-controller.cjs.map +1 -1
  12. package/dist/bridge-status-controller.d.cts +4 -1
  13. package/dist/bridge-status-controller.d.cts.map +1 -1
  14. package/dist/bridge-status-controller.d.mts +4 -1
  15. package/dist/bridge-status-controller.d.mts.map +1 -1
  16. package/dist/bridge-status-controller.mjs +222 -128
  17. package/dist/bridge-status-controller.mjs.map +1 -1
  18. package/dist/constants.cjs +2 -1
  19. package/dist/constants.cjs.map +1 -1
  20. package/dist/constants.d.cts +1 -0
  21. package/dist/constants.d.cts.map +1 -1
  22. package/dist/constants.d.mts +1 -0
  23. package/dist/constants.d.mts.map +1 -1
  24. package/dist/constants.mjs +1 -0
  25. package/dist/constants.mjs.map +1 -1
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +2 -1
  28. package/dist/index.d.cts.map +1 -1
  29. package/dist/index.d.mts +2 -1
  30. package/dist/index.d.mts.map +1 -1
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/types.cjs +4 -0
  33. package/dist/types.cjs.map +1 -1
  34. package/dist/types.d.cts +21 -18
  35. package/dist/types.d.cts.map +1 -1
  36. package/dist/types.d.mts +21 -18
  37. package/dist/types.d.mts.map +1 -1
  38. package/dist/types.mjs +4 -0
  39. package/dist/types.mjs.map +1 -1
  40. package/dist/utils/accounts.d.cts +1 -1
  41. package/dist/utils/accounts.d.mts +1 -1
  42. package/dist/utils/bridge-status.cjs +49 -2
  43. package/dist/utils/bridge-status.cjs.map +1 -1
  44. package/dist/utils/bridge-status.d.cts +2 -1
  45. package/dist/utils/bridge-status.d.cts.map +1 -1
  46. package/dist/utils/bridge-status.d.mts +2 -1
  47. package/dist/utils/bridge-status.d.mts.map +1 -1
  48. package/dist/utils/bridge-status.mjs +48 -2
  49. package/dist/utils/bridge-status.mjs.map +1 -1
  50. package/dist/utils/feature-flags.cjs +12 -0
  51. package/dist/utils/feature-flags.cjs.map +1 -0
  52. package/dist/utils/feature-flags.d.cts +3 -0
  53. package/dist/utils/feature-flags.d.cts.map +1 -0
  54. package/dist/utils/feature-flags.d.mts +3 -0
  55. package/dist/utils/feature-flags.d.mts.map +1 -0
  56. package/dist/utils/feature-flags.mjs +8 -0
  57. package/dist/utils/feature-flags.mjs.map +1 -0
  58. package/dist/utils/history.cjs +48 -3
  59. package/dist/utils/history.cjs.map +1 -1
  60. package/dist/utils/history.d.cts +19 -1
  61. package/dist/utils/history.d.cts.map +1 -1
  62. package/dist/utils/history.d.mts +19 -1
  63. package/dist/utils/history.d.mts.map +1 -1
  64. package/dist/utils/history.mjs +45 -3
  65. package/dist/utils/history.mjs.map +1 -1
  66. package/dist/utils/intent-api.cjs.map +1 -1
  67. package/dist/utils/intent-api.d.cts +1 -1
  68. package/dist/utils/intent-api.d.cts.map +1 -1
  69. package/dist/utils/intent-api.d.mts +1 -1
  70. package/dist/utils/intent-api.d.mts.map +1 -1
  71. package/dist/utils/intent-api.mjs.map +1 -1
  72. package/dist/utils/metrics.cjs +45 -8
  73. package/dist/utils/metrics.cjs.map +1 -1
  74. package/dist/utils/metrics.d.cts +37 -6
  75. package/dist/utils/metrics.d.cts.map +1 -1
  76. package/dist/utils/metrics.d.mts +37 -6
  77. package/dist/utils/metrics.d.mts.map +1 -1
  78. package/dist/utils/metrics.mjs +44 -8
  79. package/dist/utils/metrics.mjs.map +1 -1
  80. package/dist/utils/network.cjs +7 -1
  81. package/dist/utils/network.cjs.map +1 -1
  82. package/dist/utils/network.d.cts +4 -2
  83. package/dist/utils/network.d.cts.map +1 -1
  84. package/dist/utils/network.d.mts +4 -2
  85. package/dist/utils/network.d.mts.map +1 -1
  86. package/dist/utils/network.mjs +5 -0
  87. package/dist/utils/network.mjs.map +1 -1
  88. package/dist/utils/transaction.cjs +10 -9
  89. package/dist/utils/transaction.cjs.map +1 -1
  90. package/dist/utils/transaction.d.cts +3 -0
  91. package/dist/utils/transaction.d.cts.map +1 -1
  92. package/dist/utils/transaction.d.mts +3 -0
  93. package/dist/utils/transaction.d.mts.map +1 -1
  94. package/dist/utils/transaction.mjs +8 -8
  95. package/dist/utils/transaction.mjs.map +1 -1
  96. package/dist/utils/validators.d.cts +2 -2
  97. package/dist/utils/validators.d.mts +2 -2
  98. package/package.json +22 -20
@@ -9,8 +9,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  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");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_intentManager, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_trace, _BridgeStatusController_markTxAsFailed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_rekeyHistoryItem, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_getSrcTxHash, _BridgeStatusController_updateSrcTxHash, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_handleApprovalTx, _BridgeStatusController_handleEvmTransactionBatch, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
13
- import { formatChainIdToHex, isNonEvmChainId, StatusTypes, UnifiedSwapBridgeEventName, isCrossChain, isTronChainId, isEvmTxData, isHardwareWallet, MetricsActionType, MetaMetricsSwapsEventSource, isBitcoinTrade, isTronTrade, PollingStatus } from "@metamask/bridge-controller";
12
+ 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
+ import { formatChainIdToHex, isNonEvmChainId, StatusTypes, getAccountHardwareType, UnifiedSwapBridgeEventName, isCrossChain, isTronChainId, isEvmTxData, MetricsActionType, MetaMetricsSwapsEventSource, isBitcoinTrade, isTronTrade, PollingStatus } from "@metamask/bridge-controller";
14
14
  import { StaticIntervalPollingController } from "@metamask/polling-controller";
15
15
  import { TransactionStatus, TransactionType, TransactionController } from "@metamask/transaction-controller";
16
16
  import { numberToHex } from "@metamask/utils";
@@ -20,15 +20,15 @@ import { BridgeClientId } from "./types.mjs";
20
20
  import { getAccountByAddress } from "./utils/accounts.mjs";
21
21
  import { getJwt } from "./utils/authentication.mjs";
22
22
  import { stopPollingForQuotes, trackMetricsEvent } from "./utils/bridge.mjs";
23
- import { fetchBridgeTxStatus, getStatusRequestWithSrcTxHash, shouldSkipFetchDueToFetchFailures } from "./utils/bridge-status.mjs";
24
- import { getInitialHistoryItem, rekeyHistoryItemInState, shouldPollHistoryItem } from "./utils/history.mjs";
23
+ import { fetchBridgeTxStatus, getStatusRequestWithSrcTxHash, shouldSkipFetchDueToFetchFailures, shouldWaitForFinalBridgeStatus } from "./utils/bridge-status.mjs";
24
+ import { getInitialHistoryItem, getMatchingHistoryEntryForTxMeta, rekeyHistoryItemInState, shouldPollHistoryItem, getMatchingHistoryEntryForApprovalTxMeta } from "./utils/history.mjs";
25
25
  import { getIntentFromQuote, mapIntentOrderStatusToTransactionStatus, postSubmitOrder } from "./utils/intent-api.mjs";
26
26
  import { signTypedMessage } from "./utils/keyring.mjs";
27
- import { getFinalizedTxProperties, getPriceImpactFromQuote, getRequestMetadataFromHistory, getRequestParamFromHistory, getTradeDataFromHistory, getEVMTxPropertiesFromTransactionMeta, getTxStatusesFromHistory, getPreConfirmationPropertiesFromQuote } from "./utils/metrics.mjs";
27
+ import { getFinalizedTxProperties, getPriceImpactFromQuote, getRequestMetadataFromHistory, getRequestParamFromHistory, getTradeDataFromHistory, getEVMTxPropertiesFromTransactionMeta, getTxStatusesFromHistory, getPreConfirmationPropertiesFromQuote, getPollingStatusUpdatedProperties } from "./utils/metrics.mjs";
28
28
  import { getNetworkClientIdByChainId, getSelectedChainId } from "./utils/network.mjs";
29
29
  import { handleNonEvmTx } from "./utils/snaps.mjs";
30
30
  import { getApprovalTraceParams, getTraceParams } from "./utils/trace.mjs";
31
- import { getAddTransactionBatchParams, handleApprovalDelay, handleMobileHardwareWalletDelay, generateActionId, waitForTxConfirmation, getTransactionMetaById, addTransactionBatch, addSyntheticTransaction, getTransactions, submitEvmTransaction, checkIsDelegatedAccount } from "./utils/transaction.mjs";
31
+ import { getAddTransactionBatchParams, handleApprovalDelay, handleMobileHardwareWalletDelay, generateActionId, waitForTxConfirmation, getTransactionMetaById, addTransactionBatch, addSyntheticTransaction, getTransactions, submitEvmTransaction, checkIsDelegatedAccount, isCrossChainTx } from "./utils/transaction.mjs";
32
32
  const metadata = {
33
33
  // We want to persist the bridge status state so that we can show the proper data for the Activity list
34
34
  // basically match the behavior of TransactionController
@@ -39,6 +39,15 @@ const metadata = {
39
39
  usedInUi: true,
40
40
  },
41
41
  };
42
+ const MESSENGER_EXPOSED_METHODS = [
43
+ 'startPollingForBridgeTxStatus',
44
+ 'wipeBridgeStatus',
45
+ 'resetState',
46
+ 'submitTx',
47
+ 'submitIntent',
48
+ 'restartPollingForFailedAttempts',
49
+ 'getBridgeHistoryItemByTxMetaId',
50
+ ];
42
51
  export class BridgeStatusController extends StaticIntervalPollingController() {
43
52
  constructor({ messenger, state, clientId, fetchFn, addTransactionBatchFn, config, traceFn, }) {
44
53
  super({
@@ -58,25 +67,55 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
58
67
  _BridgeStatusController_config.set(this, void 0);
59
68
  _BridgeStatusController_addTransactionBatchFn.set(this, void 0);
60
69
  _BridgeStatusController_trace.set(this, void 0);
61
- // Mark tx as failed in txHistory if either the approval or trade fails
62
- _BridgeStatusController_markTxAsFailed.set(this, ({ id: txMetaId, actionId, }) => {
63
- // Look up by txMetaId first
64
- let txHistoryKey = this.state.txHistory[txMetaId]
65
- ? txMetaId
66
- : undefined;
67
- // If not found by txMetaId, try looking up by actionId (for pre-submission failures)
68
- if (!txHistoryKey && actionId && this.state.txHistory[actionId]) {
69
- txHistoryKey = actionId;
70
+ _BridgeStatusController_onTransactionFailed.set(this, ({ txMeta, historyKey, isApprovalTxMeta, }) => {
71
+ // Check if the history item is already marked as a failure
72
+ const isHistoryItemAlreadyFailed = historyKey
73
+ ? this.state.txHistory[historyKey]?.status.status === StatusTypes.FAILED
74
+ : false;
75
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
76
+ historyKey,
77
+ status: StatusTypes.FAILED,
78
+ txHash: isApprovalTxMeta ? undefined : txMeta.hash,
79
+ });
80
+ if (txMeta.status === TransactionStatus.rejected) {
81
+ return;
82
+ }
83
+ // Skip account lookup and tracking when featureId is set (e.g. PERPS)
84
+ if (historyKey && this.state.txHistory[historyKey]?.featureId) {
85
+ return;
86
+ }
87
+ // Skip tracking if this is a duplicate failed event for the same history item
88
+ // This can happen if the transaction includes an approval tx that fails
89
+ if (isHistoryItemAlreadyFailed) {
90
+ return;
70
91
  }
71
- // If still not found, try looking up by approvalTxId
72
- txHistoryKey ?? (txHistoryKey = Object.keys(this.state.txHistory).find((key) => this.state.txHistory[key].approvalTxId === txMetaId));
73
- if (!txHistoryKey) {
92
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Failed, historyKey, getEVMTxPropertiesFromTransactionMeta(txMeta));
93
+ });
94
+ // Only EVM txs
95
+ _BridgeStatusController_onTransactionConfirmed.set(this, ({ txMeta, historyKey, isApprovalTxMeta, }) => {
96
+ // Return early if the confirmed txMeta is for an approval since we
97
+ // still need to wait for the trade to be confirmed
98
+ if (isApprovalTxMeta) {
74
99
  return;
75
100
  }
76
- const key = txHistoryKey;
77
- this.update((statusState) => {
78
- statusState.txHistory[key].status.status = StatusTypes.FAILED;
101
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
102
+ historyKey,
103
+ txHash: txMeta.hash,
79
104
  });
105
+ switch (txMeta.type) {
106
+ case TransactionType.swap:
107
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
108
+ historyKey,
109
+ status: StatusTypes.COMPLETE,
110
+ });
111
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, historyKey);
112
+ break;
113
+ default:
114
+ if (historyKey) {
115
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
116
+ }
117
+ break;
118
+ }
80
119
  });
81
120
  this.resetState = () => {
82
121
  this.update((state) => {
@@ -177,30 +216,31 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
177
216
  _BridgeStatusController_restartPollingForIncompleteHistoryItems.set(this, () => {
178
217
  // Check for historyItems that do not have a status of complete and restart polling
179
218
  const { txHistory } = this.state;
180
- const historyItems = Object.values(txHistory);
219
+ const historyItems = Object.entries(txHistory);
181
220
  const incompleteHistoryItems = historyItems
182
- .filter((historyItem) => historyItem.status.status === StatusTypes.PENDING ||
221
+ .filter(([_, historyItem]) => historyItem.status.status === StatusTypes.PENDING ||
183
222
  historyItem.status.status === StatusTypes.UNKNOWN)
184
223
  // Only poll items with txMetaId (post-submission items)
185
- .filter((historyItem) => Boolean(historyItem.txMetaId))
186
- .filter((historyItem) => {
224
+ .filter(([_, historyItem]) => {
225
+ if (!historyItem.txMetaId) {
226
+ return false;
227
+ }
187
228
  // Check if we are already polling this tx, if so, skip restarting polling for that
188
229
  const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[historyItem.txMetaId];
189
230
  return !pollingToken;
190
231
  })
191
232
  // Only restart polling for items that still require status updates
192
- .filter((historyItem) => {
233
+ .filter(([_, historyItem]) => {
193
234
  return shouldPollHistoryItem(historyItem);
194
235
  });
195
- incompleteHistoryItems.forEach((historyItem) => {
196
- const bridgeTxMetaId = historyItem.txMetaId;
236
+ incompleteHistoryItems.forEach(([historyKey, historyItem]) => {
197
237
  const shouldSkipFetch = shouldSkipFetchDueToFetchFailures(historyItem.attempts);
198
238
  if (shouldSkipFetch) {
199
239
  return;
200
240
  }
201
241
  // We manually call startPolling() here rather than go through startPollingForBridgeTxStatus()
202
242
  // because we don't want to overwrite the existing historyItem in state
203
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeTxMetaId);
243
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
204
244
  });
205
245
  });
206
246
  _BridgeStatusController_addTxToHistory.set(this, (...args) => {
@@ -209,6 +249,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
209
249
  // Use actionId as key for pre-submission, or txMeta.id for post-submission
210
250
  state.txHistory[historyKey] = txHistoryItem;
211
251
  });
252
+ return historyKey;
212
253
  });
213
254
  /**
214
255
  * Rekeys a history item from actionId to txMeta.id after successful submission.
@@ -231,10 +272,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
231
272
  this.stopPollingByPollingToken(existingPollingToken);
232
273
  }
233
274
  const txHistoryItem = this.state.txHistory[txId];
234
- if (!txHistoryItem) {
235
- return;
236
- }
237
- if (shouldPollHistoryItem(txHistoryItem)) {
275
+ if (txHistoryItem && shouldPollHistoryItem(txHistoryItem)) {
238
276
  __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[txId] = this.startPolling({
239
277
  bridgeTxMetaId: txId,
240
278
  });
@@ -255,8 +293,8 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
255
293
  if (!bridgeTxMeta?.id) {
256
294
  throw new Error('Cannot start polling: bridgeTxMeta.id is required for polling');
257
295
  }
258
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, txHistoryMeta);
259
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeTxMeta.id);
296
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, txHistoryMeta);
297
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
260
298
  };
261
299
  // This will be called after you call this.startPolling()
262
300
  // The args passed in are the args you passed in to startPolling()
@@ -291,29 +329,38 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
291
329
  // Track max polling reached event
292
330
  const historyItem = this.state.txHistory[bridgeTxMetaId];
293
331
  if (historyItem && !historyItem.featureId) {
294
- const selectedAccount = getAccountByAddress(this.messenger, historyItem.account);
295
- const requestParams = getRequestParamFromHistory(historyItem);
296
- const requestMetadata = getRequestMetadataFromHistory(historyItem, selectedAccount);
297
- const { security_warnings: _, ...metadataWithoutWarnings } = requestMetadata;
298
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.PollingStatusUpdated, bridgeTxMetaId, {
299
- ...getTradeDataFromHistory(historyItem),
300
- ...getPriceImpactFromQuote(historyItem.quote),
301
- ...metadataWithoutWarnings,
302
- chain_id_source: requestParams.chain_id_source,
303
- chain_id_destination: requestParams.chain_id_destination,
304
- token_symbol_source: requestParams.token_symbol_source,
305
- token_symbol_destination: requestParams.token_symbol_destination,
306
- action_type: MetricsActionType.SWAPBRIDGE_V1,
307
- polling_status: PollingStatus.MaxPollingReached,
308
- retry_attempts: newAttempts.counter,
309
- });
332
+ // Track polling status updated event
333
+ __classPrivateFieldGet(this, _BridgeStatusController_trackPollingStatusUpdatedEvent, "f").call(this, bridgeTxMetaId, PollingStatus.MaxPollingReached);
310
334
  }
311
335
  }
312
336
  // Update the attempts counter
313
- this.update((state) => {
314
- state.txHistory[bridgeTxMetaId].attempts = newAttempts;
337
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
338
+ historyKey: bridgeTxMetaId,
339
+ attempts: newAttempts,
315
340
  });
316
341
  });
342
+ /**
343
+ * Checks if the history item should be preserved so its status can be fetched.
344
+ *
345
+ * @param bridgeTxMetaId - The txMetaId of the bridge tx
346
+ */
347
+ _BridgeStatusController_handleOldHistoryItem.set(this, async (bridgeTxMetaId) => {
348
+ // Continue polling on next restart if the history item is valid
349
+ if (this.state.txHistory[bridgeTxMetaId] &&
350
+ (await shouldWaitForFinalBridgeStatus(this.messenger, this.state.txHistory[bridgeTxMetaId]))) {
351
+ return;
352
+ }
353
+ const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
354
+ // Track polling status updated event
355
+ __classPrivateFieldGet(this, _BridgeStatusController_trackPollingStatusUpdatedEvent, "f").call(this, bridgeTxMetaId, PollingStatus.InvalidTransactionHash);
356
+ // If we've failed too many times, stop polling for the tx
357
+ if (pollingToken) {
358
+ this.stopPollingByPollingToken(pollingToken);
359
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
360
+ }
361
+ // Delete the history item so polling doesn't start over on the next restart
362
+ __classPrivateFieldGet(this, _BridgeStatusController_deleteHistoryItem, "f").call(this, bridgeTxMetaId);
363
+ });
317
364
  _BridgeStatusController_fetchBridgeTxStatus.set(this, async ({ bridgeTxMetaId, }) => {
318
365
  // 1. Check for history item
319
366
  const { txHistory } = this.state;
@@ -325,7 +372,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
325
372
  if (shouldSkipFetchDueToFetchFailures(historyItem.attempts)) {
326
373
  return;
327
374
  }
328
- // 3. Fetch transcation status
375
+ // 3. Fetch transaction status
329
376
  try {
330
377
  let status;
331
378
  let validationFailures = [];
@@ -341,11 +388,10 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
341
388
  // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx
342
389
  // Oddly mostly happens on Optimism, never on Arbitrum. By the 2nd fetch, the Bridge API responds properly.
343
390
  // Also srcTxHash may not be available immediately for STX, so we don't want to fetch in those cases
344
- const srcTxHash = __classPrivateFieldGet(this, _BridgeStatusController_getSrcTxHash, "f").call(this, bridgeTxMetaId);
391
+ const srcTxHash = __classPrivateFieldGet(this, _BridgeStatusController_setAndGetSrcTxHash, "f").call(this, bridgeTxMetaId);
345
392
  if (!srcTxHash) {
346
393
  return;
347
394
  }
348
- __classPrivateFieldGet(this, _BridgeStatusController_updateSrcTxHash, "f").call(this, bridgeTxMetaId, srcTxHash);
349
395
  const statusRequest = getStatusRequestWithSrcTxHash(historyItem.quote, srcTxHash);
350
396
  const response = await fetchBridgeTxStatus(statusRequest, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"), await getJwt(this.messenger), __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"), __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl);
351
397
  status = response.status;
@@ -402,26 +448,65 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
402
448
  console.warn('Failed to fetch bridge tx status', error);
403
449
  __classPrivateFieldGet(this, _BridgeStatusController_handleFetchFailure, "f").call(this, bridgeTxMetaId);
404
450
  }
451
+ finally {
452
+ await __classPrivateFieldGet(this, _BridgeStatusController_handleOldHistoryItem, "f").call(this, bridgeTxMetaId);
453
+ }
405
454
  });
406
- _BridgeStatusController_getSrcTxHash.set(this, (bridgeTxMetaId) => {
455
+ /**
456
+ * Returns the srcTxHash for a non-STX EVM tx, the hash from the bridge status api,
457
+ * or the local hash from the TransactionController if the tx is in a finalized state
458
+ *
459
+ * @param bridgeTxMetaId - The bridge tx meta id
460
+ * @returns The srcTxHash
461
+ */
462
+ _BridgeStatusController_setAndGetSrcTxHash.set(this, (bridgeTxMetaId) => {
407
463
  const { txHistory } = this.state;
408
- // Prefer the srcTxHash from bridgeStatusState so we don't have to l ook up in TransactionController
464
+ // Prefer the srcTxHash from bridgeStatusState so we don't have to look up in TransactionController
409
465
  // But it is possible to have bridgeHistoryItem in state without the srcTxHash yet when it is an STX
410
466
  const srcTxHash = txHistory[bridgeTxMetaId].status.srcChain.txHash;
411
- if (srcTxHash) {
467
+ if (srcTxHash ||
468
+ isNonEvmChainId(txHistory[bridgeTxMetaId].quote.srcChainId)) {
412
469
  return srcTxHash;
413
470
  }
414
- // Look up in TransactionController if txMeta has been updated with the srcTxHash
471
+ // Update history with TransactionController's hash if it has been updated
415
472
  const txMeta = getTransactionMetaById(this.messenger, bridgeTxMetaId);
416
- return txMeta?.hash;
473
+ if (!txMeta) {
474
+ return undefined;
475
+ }
476
+ // Wait for finalized status before updating the history item
477
+ const localTxHash = [
478
+ TransactionStatus.confirmed,
479
+ TransactionStatus.dropped,
480
+ TransactionStatus.rejected,
481
+ TransactionStatus.failed,
482
+ ].includes(txMeta.status)
483
+ ? txMeta.hash
484
+ : undefined;
485
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
486
+ historyKey: bridgeTxMetaId,
487
+ txHash: localTxHash,
488
+ });
489
+ return localTxHash;
417
490
  });
418
- _BridgeStatusController_updateSrcTxHash.set(this, (bridgeTxMetaId, srcTxHash) => {
419
- const { txHistory } = this.state;
420
- if (txHistory[bridgeTxMetaId].status.srcChain.txHash) {
491
+ _BridgeStatusController_updateHistoryItem.set(this, ({ historyKey, status, txHash, attempts, }) => {
492
+ if (!historyKey) {
421
493
  return;
422
494
  }
423
- this.update((state) => {
424
- state.txHistory[bridgeTxMetaId].status.srcChain.txHash = srcTxHash;
495
+ this.update((currentState) => {
496
+ if (status) {
497
+ currentState.txHistory[historyKey].status.status = status;
498
+ }
499
+ if (txHash) {
500
+ currentState.txHistory[historyKey].status.srcChain.txHash = txHash;
501
+ }
502
+ if (attempts) {
503
+ currentState.txHistory[historyKey].attempts = attempts;
504
+ }
505
+ });
506
+ });
507
+ _BridgeStatusController_deleteHistoryItem.set(this, (historyKey) => {
508
+ this.update((currentState) => {
509
+ delete currentState.txHistory[historyKey];
425
510
  });
426
511
  });
427
512
  // Wipes the bridge status for the given address and chainId
@@ -437,6 +522,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
437
522
  const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[sourceTxMetaId];
438
523
  if (pollingToken) {
439
524
  this.stopPollingByPollingToken(__classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[sourceTxMetaId]);
525
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[sourceTxMetaId];
440
526
  }
441
527
  });
442
528
  this.update((state) => {
@@ -506,16 +592,17 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
506
592
  * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore)
507
593
  * @param abTests - Legacy A/B test context for `ab_tests` (backward compatibility)
508
594
  * @param activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.
595
+ * @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.
509
596
  * @returns The transaction meta
510
597
  */
511
- this.submitTx = async (accountAddress, quoteResponse, isStxEnabledOnClient, quotesReceivedContext, location = MetaMetricsSwapsEventSource.MainView, abTests, activeAbTests) => {
598
+ this.submitTx = async (accountAddress, quoteResponse, isStxEnabledOnClient, quotesReceivedContext, location = MetaMetricsSwapsEventSource.MainView, abTests, activeAbTests, tokenSecurityTypeDestination) => {
512
599
  stopPollingForQuotes(this.messenger, quoteResponse.featureId, quotesReceivedContext);
513
600
  const selectedAccount = getAccountByAddress(this.messenger, accountAddress);
514
601
  if (!selectedAccount) {
515
602
  throw new Error('Failed to submit cross-chain swap transaction: undefined multichain account');
516
603
  }
517
- const isHardwareAccount = isHardwareWallet(selectedAccount);
518
- const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(quoteResponse, isStxEnabledOnClient, isHardwareAccount, location, abTests, activeAbTests);
604
+ const accountHardwareType = getAccountHardwareType(selectedAccount);
605
+ const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(quoteResponse, isStxEnabledOnClient, accountHardwareType, location, abTests, activeAbTests, tokenSecurityTypeDestination);
519
606
  let txMeta;
520
607
  let approvalTxId;
521
608
  let isDelegatedAccount = false;
@@ -555,7 +642,8 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
555
642
  // Submit EVM tx
556
643
  // For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval
557
644
  // Extension does not have this issue
558
- const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === BridgeClientId.MOBILE && isHardwareAccount;
645
+ const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === BridgeClientId.MOBILE &&
646
+ accountHardwareType !== null;
559
647
  // Handle smart transactions if enabled
560
648
  txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, getTraceParams(quoteResponse, isStxEnabledOnClient), async () => {
561
649
  if (!isEvmTxData(quoteResponse.trade)) {
@@ -602,7 +690,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
602
690
  const actionId = generateActionId().toString();
603
691
  // Add pre-submission history keyed by actionId
604
692
  // This ensures we have quote data available if transaction fails during submission
605
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
693
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
606
694
  accountAddress: selectedAccount.address,
607
695
  quoteResponse,
608
696
  slippagePercentage: 0,
@@ -613,6 +701,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
613
701
  abTests,
614
702
  activeAbTests,
615
703
  actionId,
704
+ tokenSecurityTypeDestination,
616
705
  });
617
706
  // Pass txFee when gasIncluded is true to use the quote's gas fees
618
707
  // instead of re-estimating (which would fail for max native token swaps)
@@ -629,7 +718,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
629
718
  actionId,
630
719
  });
631
720
  // On success, rekey from actionId to txMeta.id and update srcTxHash
632
- __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, actionId, tradeTxMeta);
721
+ __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, historyKey, tradeTxMeta);
633
722
  return tradeTxMeta;
634
723
  });
635
724
  }
@@ -649,11 +738,12 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
649
738
  !isStxEnabledOnClient &&
650
739
  !quoteResponse.quote.gasIncluded7702 &&
651
740
  !isDelegatedAccount;
741
+ let historyKey = txMeta.id;
652
742
  if (!isNonBatchEvm) {
653
743
  // Add swap or bridge tx to history
654
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
744
+ historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
655
745
  accountAddress: selectedAccount.address,
656
- bridgeTxMeta: txMeta, // Only the id field is used by the BridgeStatusController
746
+ bridgeTxMeta: txMeta, // Only the id and hash fields are used by the BridgeStatusController
657
747
  quoteResponse,
658
748
  slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
659
749
  isStxEnabled: isStxEnabledOnClient,
@@ -662,14 +752,15 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
662
752
  location,
663
753
  abTests,
664
754
  activeAbTests,
755
+ tokenSecurityTypeDestination,
665
756
  });
666
757
  }
667
758
  if (isNonEvmChainId(quoteResponse.quote.srcChainId)) {
668
759
  // Start polling for bridge tx status
669
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, txMeta.id);
760
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
670
761
  // Track non-EVM Swap completed event
671
762
  if (!(isBridgeTx || isTronTx)) {
672
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, txMeta.id);
763
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, historyKey);
673
764
  }
674
765
  }
675
766
  }
@@ -688,23 +779,25 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
688
779
  * @param params.location - The entry point from which the user initiated the swap or bridge
689
780
  * @param params.abTests - Legacy A/B test context for `ab_tests` (backward compatibility)
690
781
  * @param params.activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.
782
+ * @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.
691
783
  * @returns A lightweight TransactionMeta-like object for history linking
692
784
  */
693
785
  this.submitIntent = async (params) => {
694
- const { quoteResponse, accountAddress, location, abTests, activeAbTests } = params;
786
+ const { quoteResponse, accountAddress, location, abTests, activeAbTests, tokenSecurityTypeDestination, } = params;
695
787
  // TODO add metrics context
696
788
  stopPollingForQuotes(this.messenger);
697
789
  const startTime = Date.now();
698
790
  // Build pre-confirmation properties for error tracking parity with submitTx
699
791
  const account = getAccountByAddress(this.messenger, accountAddress);
700
- const isHardwareAccount = Boolean(account) && isHardwareWallet(account);
701
- const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(quoteResponse, false, isHardwareAccount, location, abTests, activeAbTests);
792
+ const accountHardwareType = getAccountHardwareType(account);
793
+ const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(quoteResponse, false, accountHardwareType, location, abTests, activeAbTests, tokenSecurityTypeDestination);
702
794
  try {
703
795
  const intent = getIntentFromQuote(quoteResponse);
704
796
  // If backend provided an approval tx for this intent quote, submit it first (on-chain),
705
797
  // then proceed with off-chain intent submission.
706
798
  const isBridgeTx = isCrossChain(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
707
- const requireApproval = isHardwareAccount && __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === BridgeClientId.MOBILE;
799
+ const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === BridgeClientId.MOBILE &&
800
+ accountHardwareType !== null;
708
801
  // Handle approval silently for better UX in intent flows
709
802
  const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval, quoteResponse.resetApproval, requireApproval);
710
803
  const approvalTxId = approvalTxMeta?.id;
@@ -767,15 +860,14 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
767
860
  };
768
861
  // Record in bridge history with actual transaction metadata
769
862
  try {
770
- // Use orderId as the history key for intent transactions
771
- const bridgeHistoryKey = orderUid;
772
863
  // Create a bridge transaction metadata that includes the original txId
773
864
  const bridgeTxMetaForHistory = {
774
865
  ...syntheticMeta,
775
- id: bridgeHistoryKey,
866
+ id: orderUid,
776
867
  originalTransactionId: syntheticMeta.id, // Keep original txId for TransactionController updates
777
868
  };
778
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
869
+ // Use orderId as the history key for intent transactions
870
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
779
871
  accountAddress,
780
872
  bridgeTxMeta: bridgeTxMetaForHistory,
781
873
  quoteResponse,
@@ -786,9 +878,10 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
786
878
  location,
787
879
  abTests,
788
880
  activeAbTests,
881
+ tokenSecurityTypeDestination,
789
882
  });
790
883
  // Start polling using the orderId key to route to intent manager
791
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeHistoryKey);
884
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
792
885
  }
793
886
  catch (error) {
794
887
  console.error('📝 [submitIntent] Failed to add to bridge history', error);
@@ -804,6 +897,13 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
804
897
  throw error;
805
898
  }
806
899
  };
900
+ _BridgeStatusController_trackPollingStatusUpdatedEvent.set(this, (historyKey, pollingStatus) => {
901
+ // Track polling status updated event
902
+ const historyItem = this.state.txHistory[historyKey];
903
+ if (historyItem && !historyItem.featureId) {
904
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.PollingStatusUpdated, historyKey, getPollingStatusUpdatedProperties(this.messenger, pollingStatus, historyItem));
905
+ }
906
+ });
807
907
  /**
808
908
  * Tracks post-submission events for a cross-chain swap based on the history item
809
909
  *
@@ -867,6 +967,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
867
967
  chain_id_destination: requestParamProperties.chain_id_destination,
868
968
  token_address_source: requestParamProperties.token_address_source,
869
969
  token_address_destination: requestParamProperties.token_address_destination,
970
+ token_security_type_destination: requestParamProperties.token_security_type_destination,
870
971
  refresh_count: historyItem.attempts?.counter ?? 0,
871
972
  },
872
973
  });
@@ -908,53 +1009,46 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
908
1009
  fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
909
1010
  }), "f");
910
1011
  // Register action handlers
911
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`, this.startPollingForBridgeTxStatus.bind(this));
912
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`, this.wipeBridgeStatus.bind(this));
913
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:resetState`, this.resetState.bind(this));
914
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:submitTx`, this.submitTx.bind(this));
915
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:submitIntent`, this.submitIntent.bind(this));
916
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:restartPollingForFailedAttempts`, this.restartPollingForFailedAttempts.bind(this));
917
- this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:getBridgeHistoryItemByTxMetaId`, this.getBridgeHistoryItemByTxMetaId.bind(this));
1012
+ this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
918
1013
  // Set interval
919
1014
  this.setIntervalLength(REFRESH_INTERVAL_MS);
920
- this.messenger.subscribe('TransactionController:transactionFailed', ({ transactionMeta }) => {
921
- const { type, status, id: txMetaId, actionId } = transactionMeta;
922
- if (type &&
923
- [
924
- TransactionType.bridge,
925
- TransactionType.swap,
926
- TransactionType.bridgeApproval,
927
- TransactionType.swapApproval,
928
- ].includes(type) &&
929
- [
930
- TransactionStatus.failed,
931
- TransactionStatus.dropped,
932
- TransactionStatus.rejected,
933
- ].includes(status)) {
934
- // Mark tx as failed in txHistory
935
- __classPrivateFieldGet(this, _BridgeStatusController_markTxAsFailed, "f").call(this, transactionMeta);
936
- // Track failed event
937
- if (status !== TransactionStatus.rejected) {
938
- // Look up history by txMetaId first, then by actionId (for pre-submission failures)
939
- let historyKey;
940
- if (this.state.txHistory[txMetaId]) {
941
- historyKey = txMetaId;
942
- }
943
- else if (actionId && this.state.txHistory[actionId]) {
944
- historyKey = actionId;
945
- }
946
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Failed, historyKey ?? txMetaId, getEVMTxPropertiesFromTransactionMeta(transactionMeta));
947
- }
1015
+ this.messenger.subscribe('TransactionController:transactionStatusUpdated', ({ txMeta, historyKey, historyItem, isApprovalTxMeta }) => {
1016
+ if (!txMeta) {
1017
+ return;
948
1018
  }
949
- });
950
- this.messenger.subscribe('TransactionController:transactionConfirmed', (transactionMeta) => {
951
- const { type, id: txMetaId, chainId } = transactionMeta;
952
- if (type === TransactionType.swap) {
953
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, txMetaId);
1019
+ const { type, status } = txMeta;
1020
+ // Allow event publishing if the txMeta is a swap/bridge OR if the
1021
+ // corresponding history item exists
1022
+ const isSwapOrBridgeTransaction = type && isCrossChainTx(type);
1023
+ if (!isSwapOrBridgeTransaction && !historyKey && !historyItem) {
1024
+ return;
954
1025
  }
955
- if (type === TransactionType.bridge && !isNonEvmChainId(chainId)) {
956
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, txMetaId);
1026
+ switch (status) {
1027
+ case TransactionStatus.confirmed:
1028
+ __classPrivateFieldGet(this, _BridgeStatusController_onTransactionConfirmed, "f").call(this, {
1029
+ txMeta,
1030
+ historyKey,
1031
+ isApprovalTxMeta,
1032
+ });
1033
+ break;
1034
+ case TransactionStatus.failed:
1035
+ case TransactionStatus.dropped:
1036
+ case TransactionStatus.rejected:
1037
+ __classPrivateFieldGet(this, _BridgeStatusController_onTransactionFailed, "f").call(this, { txMeta, historyKey, isApprovalTxMeta });
1038
+ break;
1039
+ default:
1040
+ break;
957
1041
  }
1042
+ }, ({ transactionMeta }) => {
1043
+ const entry = getMatchingHistoryEntryForTxMeta(this.state.txHistory, transactionMeta);
1044
+ const approvalEntry = getMatchingHistoryEntryForApprovalTxMeta(this.state.txHistory, transactionMeta);
1045
+ const entryToUse = entry ?? approvalEntry;
1046
+ return {
1047
+ historyKey: entryToUse?.[0],
1048
+ historyItem: entryToUse?.[1],
1049
+ txMeta: transactionMeta,
1050
+ isApprovalTxMeta: entryToUse?.[1]?.approvalTxId === transactionMeta.id,
1051
+ };
958
1052
  });
959
1053
  // If you close the extension, but keep the browser open, the polling continues
960
1054
  // If you close the browser, the polling stops
@@ -962,5 +1056,5 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
962
1056
  __classPrivateFieldGet(this, _BridgeStatusController_restartPollingForIncompleteHistoryItems, "f").call(this);
963
1057
  }
964
1058
  }
965
- _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_markTxAsFailed = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_addTxToHistory = new WeakMap(), _BridgeStatusController_rekeyHistoryItem = new WeakMap(), _BridgeStatusController_startPollingForTxId = new WeakMap(), _BridgeStatusController_handleFetchFailure = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_getSrcTxHash = new WeakMap(), _BridgeStatusController_updateSrcTxHash = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_handleApprovalTx = new WeakMap(), _BridgeStatusController_handleEvmTransactionBatch = new WeakMap(), _BridgeStatusController_trackUnifiedSwapBridgeEvent = new WeakMap();
1059
+ _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();
966
1060
  //# sourceMappingURL=bridge-status-controller.mjs.map