@metamask/bridge-status-controller 70.0.4 → 71.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +56 -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 +209 -121
  11. package/dist/bridge-status-controller.cjs.map +1 -1
  12. package/dist/bridge-status-controller.d.cts.map +1 -1
  13. package/dist/bridge-status-controller.d.mts.map +1 -1
  14. package/dist/bridge-status-controller.mjs +214 -126
  15. package/dist/bridge-status-controller.mjs.map +1 -1
  16. package/dist/constants.cjs +2 -1
  17. package/dist/constants.cjs.map +1 -1
  18. package/dist/constants.d.cts +1 -0
  19. package/dist/constants.d.cts.map +1 -1
  20. package/dist/constants.d.mts +1 -0
  21. package/dist/constants.d.mts.map +1 -1
  22. package/dist/constants.mjs +1 -0
  23. package/dist/constants.mjs.map +1 -1
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +2 -1
  26. package/dist/index.d.cts.map +1 -1
  27. package/dist/index.d.mts +2 -1
  28. package/dist/index.d.mts.map +1 -1
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/types.cjs +4 -0
  31. package/dist/types.cjs.map +1 -1
  32. package/dist/types.d.cts +12 -18
  33. package/dist/types.d.cts.map +1 -1
  34. package/dist/types.d.mts +12 -18
  35. package/dist/types.d.mts.map +1 -1
  36. package/dist/types.mjs +4 -0
  37. package/dist/types.mjs.map +1 -1
  38. package/dist/utils/accounts.d.cts +1 -1
  39. package/dist/utils/accounts.d.mts +1 -1
  40. package/dist/utils/bridge-status.cjs +49 -2
  41. package/dist/utils/bridge-status.cjs.map +1 -1
  42. package/dist/utils/bridge-status.d.cts +2 -1
  43. package/dist/utils/bridge-status.d.cts.map +1 -1
  44. package/dist/utils/bridge-status.d.mts +2 -1
  45. package/dist/utils/bridge-status.d.mts.map +1 -1
  46. package/dist/utils/bridge-status.mjs +48 -2
  47. package/dist/utils/bridge-status.mjs.map +1 -1
  48. package/dist/utils/feature-flags.cjs +12 -0
  49. package/dist/utils/feature-flags.cjs.map +1 -0
  50. package/dist/utils/feature-flags.d.cts +3 -0
  51. package/dist/utils/feature-flags.d.cts.map +1 -0
  52. package/dist/utils/feature-flags.d.mts +3 -0
  53. package/dist/utils/feature-flags.d.mts.map +1 -0
  54. package/dist/utils/feature-flags.mjs +8 -0
  55. package/dist/utils/feature-flags.mjs.map +1 -0
  56. package/dist/utils/history.cjs +44 -2
  57. package/dist/utils/history.cjs.map +1 -1
  58. package/dist/utils/history.d.cts +19 -1
  59. package/dist/utils/history.d.cts.map +1 -1
  60. package/dist/utils/history.d.mts +19 -1
  61. package/dist/utils/history.d.mts.map +1 -1
  62. package/dist/utils/history.mjs +41 -2
  63. package/dist/utils/history.mjs.map +1 -1
  64. package/dist/utils/intent-api.cjs.map +1 -1
  65. package/dist/utils/intent-api.d.cts +1 -1
  66. package/dist/utils/intent-api.d.cts.map +1 -1
  67. package/dist/utils/intent-api.d.mts +1 -1
  68. package/dist/utils/intent-api.d.mts.map +1 -1
  69. package/dist/utils/intent-api.mjs.map +1 -1
  70. package/dist/utils/metrics.cjs +39 -8
  71. package/dist/utils/metrics.cjs.map +1 -1
  72. package/dist/utils/metrics.d.cts +31 -5
  73. package/dist/utils/metrics.d.cts.map +1 -1
  74. package/dist/utils/metrics.d.mts +31 -5
  75. package/dist/utils/metrics.d.mts.map +1 -1
  76. package/dist/utils/metrics.mjs +38 -8
  77. package/dist/utils/metrics.mjs.map +1 -1
  78. package/dist/utils/network.cjs +7 -1
  79. package/dist/utils/network.cjs.map +1 -1
  80. package/dist/utils/network.d.cts +4 -2
  81. package/dist/utils/network.d.cts.map +1 -1
  82. package/dist/utils/network.d.mts +4 -2
  83. package/dist/utils/network.d.mts.map +1 -1
  84. package/dist/utils/network.mjs +5 -0
  85. package/dist/utils/network.mjs.map +1 -1
  86. package/dist/utils/transaction.cjs +10 -9
  87. package/dist/utils/transaction.cjs.map +1 -1
  88. package/dist/utils/transaction.d.cts +3 -0
  89. package/dist/utils/transaction.d.cts.map +1 -1
  90. package/dist/utils/transaction.d.mts +3 -0
  91. package/dist/utils/transaction.d.mts.map +1 -1
  92. package/dist/utils/transaction.mjs +8 -8
  93. package/dist/utils/transaction.mjs.map +1 -1
  94. package/dist/utils/validators.d.cts +2 -2
  95. package/dist/utils/validators.d.mts +2 -2
  96. package/package.json +23 -20
@@ -10,7 +10,7 @@ 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_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
+ 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;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BridgeStatusController = void 0;
16
16
  const bridge_controller_1 = require("@metamask/bridge-controller");
@@ -42,6 +42,15 @@ const metadata = {
42
42
  usedInUi: true,
43
43
  },
44
44
  };
45
+ const MESSENGER_EXPOSED_METHODS = [
46
+ 'startPollingForBridgeTxStatus',
47
+ 'wipeBridgeStatus',
48
+ 'resetState',
49
+ 'submitTx',
50
+ 'submitIntent',
51
+ 'restartPollingForFailedAttempts',
52
+ 'getBridgeHistoryItemByTxMetaId',
53
+ ];
45
54
  class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPollingController)() {
46
55
  constructor({ messenger, state, clientId, fetchFn, addTransactionBatchFn, config, traceFn, }) {
47
56
  super({
@@ -61,25 +70,55 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
61
70
  _BridgeStatusController_config.set(this, void 0);
62
71
  _BridgeStatusController_addTransactionBatchFn.set(this, void 0);
63
72
  _BridgeStatusController_trace.set(this, void 0);
64
- // Mark tx as failed in txHistory if either the approval or trade fails
65
- _BridgeStatusController_markTxAsFailed.set(this, ({ id: txMetaId, actionId, }) => {
66
- // Look up by txMetaId first
67
- let txHistoryKey = this.state.txHistory[txMetaId]
68
- ? txMetaId
69
- : undefined;
70
- // If not found by txMetaId, try looking up by actionId (for pre-submission failures)
71
- if (!txHistoryKey && actionId && this.state.txHistory[actionId]) {
72
- txHistoryKey = actionId;
73
+ _BridgeStatusController_onTransactionFailed.set(this, ({ txMeta, historyKey, isApprovalTxMeta, }) => {
74
+ // Check if the history item is already marked as a failure
75
+ const isHistoryItemAlreadyFailed = historyKey
76
+ ? this.state.txHistory[historyKey]?.status.status === bridge_controller_1.StatusTypes.FAILED
77
+ : false;
78
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
79
+ historyKey,
80
+ status: bridge_controller_1.StatusTypes.FAILED,
81
+ txHash: isApprovalTxMeta ? undefined : txMeta.hash,
82
+ });
83
+ if (txMeta.status === transaction_controller_1.TransactionStatus.rejected) {
84
+ return;
85
+ }
86
+ // Skip account lookup and tracking when featureId is set (e.g. PERPS)
87
+ if (historyKey && this.state.txHistory[historyKey]?.featureId) {
88
+ return;
89
+ }
90
+ // Skip tracking if this is a duplicate failed event for the same history item
91
+ // This can happen if the transaction includes an approval tx that fails
92
+ if (isHistoryItemAlreadyFailed) {
93
+ return;
73
94
  }
74
- // If still not found, try looking up by approvalTxId
75
- txHistoryKey ?? (txHistoryKey = Object.keys(this.state.txHistory).find((key) => this.state.txHistory[key].approvalTxId === txMetaId));
76
- if (!txHistoryKey) {
95
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, historyKey, (0, metrics_1.getEVMTxPropertiesFromTransactionMeta)(txMeta));
96
+ });
97
+ // Only EVM txs
98
+ _BridgeStatusController_onTransactionConfirmed.set(this, ({ txMeta, historyKey, isApprovalTxMeta, }) => {
99
+ // Return early if the confirmed txMeta is for an approval since we
100
+ // still need to wait for the trade to be confirmed
101
+ if (isApprovalTxMeta) {
77
102
  return;
78
103
  }
79
- const key = txHistoryKey;
80
- this.update((statusState) => {
81
- statusState.txHistory[key].status.status = bridge_controller_1.StatusTypes.FAILED;
104
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
105
+ historyKey,
106
+ txHash: txMeta.hash,
82
107
  });
108
+ switch (txMeta.type) {
109
+ case transaction_controller_1.TransactionType.swap:
110
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
111
+ historyKey,
112
+ status: bridge_controller_1.StatusTypes.COMPLETE,
113
+ });
114
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, historyKey);
115
+ break;
116
+ default:
117
+ if (historyKey) {
118
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
119
+ }
120
+ break;
121
+ }
83
122
  });
84
123
  this.resetState = () => {
85
124
  this.update((state) => {
@@ -180,30 +219,31 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
180
219
  _BridgeStatusController_restartPollingForIncompleteHistoryItems.set(this, () => {
181
220
  // Check for historyItems that do not have a status of complete and restart polling
182
221
  const { txHistory } = this.state;
183
- const historyItems = Object.values(txHistory);
222
+ const historyItems = Object.entries(txHistory);
184
223
  const incompleteHistoryItems = historyItems
185
- .filter((historyItem) => historyItem.status.status === bridge_controller_1.StatusTypes.PENDING ||
224
+ .filter(([_, historyItem]) => historyItem.status.status === bridge_controller_1.StatusTypes.PENDING ||
186
225
  historyItem.status.status === bridge_controller_1.StatusTypes.UNKNOWN)
187
226
  // Only poll items with txMetaId (post-submission items)
188
- .filter((historyItem) => Boolean(historyItem.txMetaId))
189
- .filter((historyItem) => {
227
+ .filter(([_, historyItem]) => {
228
+ if (!historyItem.txMetaId) {
229
+ return false;
230
+ }
190
231
  // Check if we are already polling this tx, if so, skip restarting polling for that
191
232
  const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[historyItem.txMetaId];
192
233
  return !pollingToken;
193
234
  })
194
235
  // Only restart polling for items that still require status updates
195
- .filter((historyItem) => {
236
+ .filter(([_, historyItem]) => {
196
237
  return (0, history_1.shouldPollHistoryItem)(historyItem);
197
238
  });
198
- incompleteHistoryItems.forEach((historyItem) => {
199
- const bridgeTxMetaId = historyItem.txMetaId;
239
+ incompleteHistoryItems.forEach(([historyKey, historyItem]) => {
200
240
  const shouldSkipFetch = (0, bridge_status_1.shouldSkipFetchDueToFetchFailures)(historyItem.attempts);
201
241
  if (shouldSkipFetch) {
202
242
  return;
203
243
  }
204
244
  // We manually call startPolling() here rather than go through startPollingForBridgeTxStatus()
205
245
  // because we don't want to overwrite the existing historyItem in state
206
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeTxMetaId);
246
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
207
247
  });
208
248
  });
209
249
  _BridgeStatusController_addTxToHistory.set(this, (...args) => {
@@ -212,6 +252,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
212
252
  // Use actionId as key for pre-submission, or txMeta.id for post-submission
213
253
  state.txHistory[historyKey] = txHistoryItem;
214
254
  });
255
+ return historyKey;
215
256
  });
216
257
  /**
217
258
  * Rekeys a history item from actionId to txMeta.id after successful submission.
@@ -234,10 +275,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
234
275
  this.stopPollingByPollingToken(existingPollingToken);
235
276
  }
236
277
  const txHistoryItem = this.state.txHistory[txId];
237
- if (!txHistoryItem) {
238
- return;
239
- }
240
- if ((0, history_1.shouldPollHistoryItem)(txHistoryItem)) {
278
+ if (txHistoryItem && (0, history_1.shouldPollHistoryItem)(txHistoryItem)) {
241
279
  __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[txId] = this.startPolling({
242
280
  bridgeTxMetaId: txId,
243
281
  });
@@ -258,8 +296,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
258
296
  if (!bridgeTxMeta?.id) {
259
297
  throw new Error('Cannot start polling: bridgeTxMeta.id is required for polling');
260
298
  }
261
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, txHistoryMeta);
262
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeTxMeta.id);
299
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, txHistoryMeta);
300
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
263
301
  };
264
302
  // This will be called after you call this.startPolling()
265
303
  // The args passed in are the args you passed in to startPolling()
@@ -294,29 +332,38 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
294
332
  // Track max polling reached event
295
333
  const historyItem = this.state.txHistory[bridgeTxMetaId];
296
334
  if (historyItem && !historyItem.featureId) {
297
- const selectedAccount = (0, accounts_1.getAccountByAddress)(this.messenger, historyItem.account);
298
- const requestParams = (0, metrics_1.getRequestParamFromHistory)(historyItem);
299
- const requestMetadata = (0, metrics_1.getRequestMetadataFromHistory)(historyItem, selectedAccount);
300
- const { security_warnings: _, ...metadataWithoutWarnings } = requestMetadata;
301
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.PollingStatusUpdated, bridgeTxMetaId, {
302
- ...(0, metrics_1.getTradeDataFromHistory)(historyItem),
303
- ...(0, metrics_1.getPriceImpactFromQuote)(historyItem.quote),
304
- ...metadataWithoutWarnings,
305
- chain_id_source: requestParams.chain_id_source,
306
- chain_id_destination: requestParams.chain_id_destination,
307
- token_symbol_source: requestParams.token_symbol_source,
308
- token_symbol_destination: requestParams.token_symbol_destination,
309
- action_type: bridge_controller_1.MetricsActionType.SWAPBRIDGE_V1,
310
- polling_status: bridge_controller_1.PollingStatus.MaxPollingReached,
311
- retry_attempts: newAttempts.counter,
312
- });
335
+ // Track polling status updated event
336
+ __classPrivateFieldGet(this, _BridgeStatusController_trackPollingStatusUpdatedEvent, "f").call(this, bridgeTxMetaId, bridge_controller_1.PollingStatus.MaxPollingReached);
313
337
  }
314
338
  }
315
339
  // Update the attempts counter
316
- this.update((state) => {
317
- state.txHistory[bridgeTxMetaId].attempts = newAttempts;
340
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
341
+ historyKey: bridgeTxMetaId,
342
+ attempts: newAttempts,
318
343
  });
319
344
  });
345
+ /**
346
+ * Checks if the history item should be preserved so its status can be fetched.
347
+ *
348
+ * @param bridgeTxMetaId - The txMetaId of the bridge tx
349
+ */
350
+ _BridgeStatusController_handleOldHistoryItem.set(this, async (bridgeTxMetaId) => {
351
+ // Continue polling on next restart if the history item is valid
352
+ if (this.state.txHistory[bridgeTxMetaId] &&
353
+ (await (0, bridge_status_1.shouldWaitForFinalBridgeStatus)(this.messenger, this.state.txHistory[bridgeTxMetaId]))) {
354
+ return;
355
+ }
356
+ const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
357
+ // Track polling status updated event
358
+ __classPrivateFieldGet(this, _BridgeStatusController_trackPollingStatusUpdatedEvent, "f").call(this, bridgeTxMetaId, bridge_controller_1.PollingStatus.InvalidTransactionHash);
359
+ // If we've failed too many times, stop polling for the tx
360
+ if (pollingToken) {
361
+ this.stopPollingByPollingToken(pollingToken);
362
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
363
+ }
364
+ // Delete the history item so polling doesn't start over on the next restart
365
+ __classPrivateFieldGet(this, _BridgeStatusController_deleteHistoryItem, "f").call(this, bridgeTxMetaId);
366
+ });
320
367
  _BridgeStatusController_fetchBridgeTxStatus.set(this, async ({ bridgeTxMetaId, }) => {
321
368
  // 1. Check for history item
322
369
  const { txHistory } = this.state;
@@ -328,7 +375,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
328
375
  if ((0, bridge_status_1.shouldSkipFetchDueToFetchFailures)(historyItem.attempts)) {
329
376
  return;
330
377
  }
331
- // 3. Fetch transcation status
378
+ // 3. Fetch transaction status
332
379
  try {
333
380
  let status;
334
381
  let validationFailures = [];
@@ -344,11 +391,10 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
344
391
  // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx
345
392
  // Oddly mostly happens on Optimism, never on Arbitrum. By the 2nd fetch, the Bridge API responds properly.
346
393
  // Also srcTxHash may not be available immediately for STX, so we don't want to fetch in those cases
347
- const srcTxHash = __classPrivateFieldGet(this, _BridgeStatusController_getSrcTxHash, "f").call(this, bridgeTxMetaId);
394
+ const srcTxHash = __classPrivateFieldGet(this, _BridgeStatusController_setAndGetSrcTxHash, "f").call(this, bridgeTxMetaId);
348
395
  if (!srcTxHash) {
349
396
  return;
350
397
  }
351
- __classPrivateFieldGet(this, _BridgeStatusController_updateSrcTxHash, "f").call(this, bridgeTxMetaId, srcTxHash);
352
398
  const statusRequest = (0, bridge_status_1.getStatusRequestWithSrcTxHash)(historyItem.quote, srcTxHash);
353
399
  const response = await (0, bridge_status_1.fetchBridgeTxStatus)(statusRequest, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"), await (0, authentication_1.getJwt)(this.messenger), __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"), __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl);
354
400
  status = response.status;
@@ -405,26 +451,65 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
405
451
  console.warn('Failed to fetch bridge tx status', error);
406
452
  __classPrivateFieldGet(this, _BridgeStatusController_handleFetchFailure, "f").call(this, bridgeTxMetaId);
407
453
  }
454
+ finally {
455
+ await __classPrivateFieldGet(this, _BridgeStatusController_handleOldHistoryItem, "f").call(this, bridgeTxMetaId);
456
+ }
408
457
  });
409
- _BridgeStatusController_getSrcTxHash.set(this, (bridgeTxMetaId) => {
458
+ /**
459
+ * Returns the srcTxHash for a non-STX EVM tx, the hash from the bridge status api,
460
+ * or the local hash from the TransactionController if the tx is in a finalized state
461
+ *
462
+ * @param bridgeTxMetaId - The bridge tx meta id
463
+ * @returns The srcTxHash
464
+ */
465
+ _BridgeStatusController_setAndGetSrcTxHash.set(this, (bridgeTxMetaId) => {
410
466
  const { txHistory } = this.state;
411
- // Prefer the srcTxHash from bridgeStatusState so we don't have to l ook up in TransactionController
467
+ // Prefer the srcTxHash from bridgeStatusState so we don't have to look up in TransactionController
412
468
  // But it is possible to have bridgeHistoryItem in state without the srcTxHash yet when it is an STX
413
469
  const srcTxHash = txHistory[bridgeTxMetaId].status.srcChain.txHash;
414
- if (srcTxHash) {
470
+ if (srcTxHash ||
471
+ (0, bridge_controller_1.isNonEvmChainId)(txHistory[bridgeTxMetaId].quote.srcChainId)) {
415
472
  return srcTxHash;
416
473
  }
417
- // Look up in TransactionController if txMeta has been updated with the srcTxHash
474
+ // Update history with TransactionController's hash if it has been updated
418
475
  const txMeta = (0, transaction_1.getTransactionMetaById)(this.messenger, bridgeTxMetaId);
419
- return txMeta?.hash;
476
+ if (!txMeta) {
477
+ return undefined;
478
+ }
479
+ // Wait for finalized status before updating the history item
480
+ const localTxHash = [
481
+ transaction_controller_1.TransactionStatus.confirmed,
482
+ transaction_controller_1.TransactionStatus.dropped,
483
+ transaction_controller_1.TransactionStatus.rejected,
484
+ transaction_controller_1.TransactionStatus.failed,
485
+ ].includes(txMeta.status)
486
+ ? txMeta.hash
487
+ : undefined;
488
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
489
+ historyKey: bridgeTxMetaId,
490
+ txHash: localTxHash,
491
+ });
492
+ return localTxHash;
420
493
  });
421
- _BridgeStatusController_updateSrcTxHash.set(this, (bridgeTxMetaId, srcTxHash) => {
422
- const { txHistory } = this.state;
423
- if (txHistory[bridgeTxMetaId].status.srcChain.txHash) {
494
+ _BridgeStatusController_updateHistoryItem.set(this, ({ historyKey, status, txHash, attempts, }) => {
495
+ if (!historyKey) {
424
496
  return;
425
497
  }
426
- this.update((state) => {
427
- state.txHistory[bridgeTxMetaId].status.srcChain.txHash = srcTxHash;
498
+ this.update((currentState) => {
499
+ if (status) {
500
+ currentState.txHistory[historyKey].status.status = status;
501
+ }
502
+ if (txHash) {
503
+ currentState.txHistory[historyKey].status.srcChain.txHash = txHash;
504
+ }
505
+ if (attempts) {
506
+ currentState.txHistory[historyKey].attempts = attempts;
507
+ }
508
+ });
509
+ });
510
+ _BridgeStatusController_deleteHistoryItem.set(this, (historyKey) => {
511
+ this.update((currentState) => {
512
+ delete currentState.txHistory[historyKey];
428
513
  });
429
514
  });
430
515
  // Wipes the bridge status for the given address and chainId
@@ -440,6 +525,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
440
525
  const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[sourceTxMetaId];
441
526
  if (pollingToken) {
442
527
  this.stopPollingByPollingToken(__classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[sourceTxMetaId]);
528
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[sourceTxMetaId];
443
529
  }
444
530
  });
445
531
  this.update((state) => {
@@ -517,8 +603,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
517
603
  if (!selectedAccount) {
518
604
  throw new Error('Failed to submit cross-chain swap transaction: undefined multichain account');
519
605
  }
520
- const isHardwareAccount = (0, bridge_controller_1.isHardwareWallet)(selectedAccount);
521
- const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabledOnClient, isHardwareAccount, location, abTests, activeAbTests);
606
+ const accountHardwareType = (0, bridge_controller_1.getAccountHardwareType)(selectedAccount);
607
+ const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabledOnClient, accountHardwareType, location, abTests, activeAbTests);
522
608
  let txMeta;
523
609
  let approvalTxId;
524
610
  let isDelegatedAccount = false;
@@ -558,7 +644,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
558
644
  // Submit EVM tx
559
645
  // For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval
560
646
  // Extension does not have this issue
561
- const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE && isHardwareAccount;
647
+ const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE &&
648
+ accountHardwareType !== null;
562
649
  // Handle smart transactions if enabled
563
650
  txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, isStxEnabledOnClient), async () => {
564
651
  if (!(0, bridge_controller_1.isEvmTxData)(quoteResponse.trade)) {
@@ -605,7 +692,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
605
692
  const actionId = (0, transaction_1.generateActionId)().toString();
606
693
  // Add pre-submission history keyed by actionId
607
694
  // This ensures we have quote data available if transaction fails during submission
608
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
695
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
609
696
  accountAddress: selectedAccount.address,
610
697
  quoteResponse,
611
698
  slippagePercentage: 0,
@@ -632,7 +719,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
632
719
  actionId,
633
720
  });
634
721
  // On success, rekey from actionId to txMeta.id and update srcTxHash
635
- __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, actionId, tradeTxMeta);
722
+ __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, historyKey, tradeTxMeta);
636
723
  return tradeTxMeta;
637
724
  });
638
725
  }
@@ -652,11 +739,12 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
652
739
  !isStxEnabledOnClient &&
653
740
  !quoteResponse.quote.gasIncluded7702 &&
654
741
  !isDelegatedAccount;
742
+ let historyKey = txMeta.id;
655
743
  if (!isNonBatchEvm) {
656
744
  // Add swap or bridge tx to history
657
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
745
+ historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
658
746
  accountAddress: selectedAccount.address,
659
- bridgeTxMeta: txMeta, // Only the id field is used by the BridgeStatusController
747
+ bridgeTxMeta: txMeta, // Only the id and hash fields are used by the BridgeStatusController
660
748
  quoteResponse,
661
749
  slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
662
750
  isStxEnabled: isStxEnabledOnClient,
@@ -669,10 +757,10 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
669
757
  }
670
758
  if ((0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId)) {
671
759
  // Start polling for bridge tx status
672
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, txMeta.id);
760
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
673
761
  // Track non-EVM Swap completed event
674
762
  if (!(isBridgeTx || isTronTx)) {
675
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, txMeta.id);
763
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, historyKey);
676
764
  }
677
765
  }
678
766
  }
@@ -700,14 +788,15 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
700
788
  const startTime = Date.now();
701
789
  // Build pre-confirmation properties for error tracking parity with submitTx
702
790
  const account = (0, accounts_1.getAccountByAddress)(this.messenger, accountAddress);
703
- const isHardwareAccount = Boolean(account) && (0, bridge_controller_1.isHardwareWallet)(account);
704
- const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, false, isHardwareAccount, location, abTests, activeAbTests);
791
+ const accountHardwareType = (0, bridge_controller_1.getAccountHardwareType)(account);
792
+ const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, false, accountHardwareType, location, abTests, activeAbTests);
705
793
  try {
706
794
  const intent = (0, intent_api_1.getIntentFromQuote)(quoteResponse);
707
795
  // If backend provided an approval tx for this intent quote, submit it first (on-chain),
708
796
  // then proceed with off-chain intent submission.
709
797
  const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
710
- const requireApproval = isHardwareAccount && __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE;
798
+ const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE &&
799
+ accountHardwareType !== null;
711
800
  // Handle approval silently for better UX in intent flows
712
801
  const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval, quoteResponse.resetApproval, requireApproval);
713
802
  const approvalTxId = approvalTxMeta?.id;
@@ -770,15 +859,14 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
770
859
  };
771
860
  // Record in bridge history with actual transaction metadata
772
861
  try {
773
- // Use orderId as the history key for intent transactions
774
- const bridgeHistoryKey = orderUid;
775
862
  // Create a bridge transaction metadata that includes the original txId
776
863
  const bridgeTxMetaForHistory = {
777
864
  ...syntheticMeta,
778
- id: bridgeHistoryKey,
865
+ id: orderUid,
779
866
  originalTransactionId: syntheticMeta.id, // Keep original txId for TransactionController updates
780
867
  };
781
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
868
+ // Use orderId as the history key for intent transactions
869
+ const historyKey = __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
782
870
  accountAddress,
783
871
  bridgeTxMeta: bridgeTxMetaForHistory,
784
872
  quoteResponse,
@@ -791,7 +879,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
791
879
  activeAbTests,
792
880
  });
793
881
  // Start polling using the orderId key to route to intent manager
794
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeHistoryKey);
882
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
795
883
  }
796
884
  catch (error) {
797
885
  console.error('📝 [submitIntent] Failed to add to bridge history', error);
@@ -807,6 +895,13 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
807
895
  throw error;
808
896
  }
809
897
  };
898
+ _BridgeStatusController_trackPollingStatusUpdatedEvent.set(this, (historyKey, pollingStatus) => {
899
+ // Track polling status updated event
900
+ const historyItem = this.state.txHistory[historyKey];
901
+ if (historyItem && !historyItem.featureId) {
902
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.PollingStatusUpdated, historyKey, (0, metrics_1.getPollingStatusUpdatedProperties)(this.messenger, pollingStatus, historyItem));
903
+ }
904
+ });
810
905
  /**
811
906
  * Tracks post-submission events for a cross-chain swap based on the history item
812
907
  *
@@ -911,53 +1006,46 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
911
1006
  fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
912
1007
  }), "f");
913
1008
  // Register action handlers
914
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`, this.startPollingForBridgeTxStatus.bind(this));
915
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`, this.wipeBridgeStatus.bind(this));
916
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:resetState`, this.resetState.bind(this));
917
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:submitTx`, this.submitTx.bind(this));
918
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:submitIntent`, this.submitIntent.bind(this));
919
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:restartPollingForFailedAttempts`, this.restartPollingForFailedAttempts.bind(this));
920
- this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:getBridgeHistoryItemByTxMetaId`, this.getBridgeHistoryItemByTxMetaId.bind(this));
1009
+ this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
921
1010
  // Set interval
922
1011
  this.setIntervalLength(constants_1.REFRESH_INTERVAL_MS);
923
- this.messenger.subscribe('TransactionController:transactionFailed', ({ transactionMeta }) => {
924
- const { type, status, id: txMetaId, actionId } = transactionMeta;
925
- if (type &&
926
- [
927
- transaction_controller_1.TransactionType.bridge,
928
- transaction_controller_1.TransactionType.swap,
929
- transaction_controller_1.TransactionType.bridgeApproval,
930
- transaction_controller_1.TransactionType.swapApproval,
931
- ].includes(type) &&
932
- [
933
- transaction_controller_1.TransactionStatus.failed,
934
- transaction_controller_1.TransactionStatus.dropped,
935
- transaction_controller_1.TransactionStatus.rejected,
936
- ].includes(status)) {
937
- // Mark tx as failed in txHistory
938
- __classPrivateFieldGet(this, _BridgeStatusController_markTxAsFailed, "f").call(this, transactionMeta);
939
- // Track failed event
940
- if (status !== transaction_controller_1.TransactionStatus.rejected) {
941
- // Look up history by txMetaId first, then by actionId (for pre-submission failures)
942
- let historyKey;
943
- if (this.state.txHistory[txMetaId]) {
944
- historyKey = txMetaId;
945
- }
946
- else if (actionId && this.state.txHistory[actionId]) {
947
- historyKey = actionId;
948
- }
949
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, historyKey ?? txMetaId, (0, metrics_1.getEVMTxPropertiesFromTransactionMeta)(transactionMeta));
950
- }
1012
+ this.messenger.subscribe('TransactionController:transactionStatusUpdated', ({ txMeta, historyKey, historyItem, isApprovalTxMeta }) => {
1013
+ if (!txMeta) {
1014
+ return;
951
1015
  }
952
- });
953
- this.messenger.subscribe('TransactionController:transactionConfirmed', (transactionMeta) => {
954
- const { type, id: txMetaId, chainId } = transactionMeta;
955
- if (type === transaction_controller_1.TransactionType.swap) {
956
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, txMetaId);
1016
+ const { type, status } = txMeta;
1017
+ // Allow event publishing if the txMeta is a swap/bridge OR if the
1018
+ // corresponding history item exists
1019
+ const isSwapOrBridgeTransaction = type && (0, transaction_1.isCrossChainTx)(type);
1020
+ if (!isSwapOrBridgeTransaction && !historyKey && !historyItem) {
1021
+ return;
957
1022
  }
958
- if (type === transaction_controller_1.TransactionType.bridge && !(0, bridge_controller_1.isNonEvmChainId)(chainId)) {
959
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, txMetaId);
1023
+ switch (status) {
1024
+ case transaction_controller_1.TransactionStatus.confirmed:
1025
+ __classPrivateFieldGet(this, _BridgeStatusController_onTransactionConfirmed, "f").call(this, {
1026
+ txMeta,
1027
+ historyKey,
1028
+ isApprovalTxMeta,
1029
+ });
1030
+ break;
1031
+ case transaction_controller_1.TransactionStatus.failed:
1032
+ case transaction_controller_1.TransactionStatus.dropped:
1033
+ case transaction_controller_1.TransactionStatus.rejected:
1034
+ __classPrivateFieldGet(this, _BridgeStatusController_onTransactionFailed, "f").call(this, { txMeta, historyKey, isApprovalTxMeta });
1035
+ break;
1036
+ default:
1037
+ break;
960
1038
  }
1039
+ }, ({ transactionMeta }) => {
1040
+ const entry = (0, history_1.getMatchingHistoryEntryForTxMeta)(this.state.txHistory, transactionMeta);
1041
+ const approvalEntry = (0, history_1.getMatchingHistoryEntryForApprovalTxMeta)(this.state.txHistory, transactionMeta);
1042
+ const entryToUse = entry ?? approvalEntry;
1043
+ return {
1044
+ historyKey: entryToUse?.[0],
1045
+ historyItem: entryToUse?.[1],
1046
+ txMeta: transactionMeta,
1047
+ isApprovalTxMeta: entryToUse?.[1]?.approvalTxId === transactionMeta.id,
1048
+ };
961
1049
  });
962
1050
  // If you close the extension, but keep the browser open, the polling continues
963
1051
  // If you close the browser, the polling stops
@@ -966,5 +1054,5 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
966
1054
  }
967
1055
  }
968
1056
  exports.BridgeStatusController = BridgeStatusController;
969
- _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();
1057
+ _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();
970
1058
  //# sourceMappingURL=bridge-status-controller.cjs.map