@metamask-previews/bridge-status-controller 73.1.0-preview-e12e4a38f → 74.0.0-preview-4f9d41d

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 +9 -1
  2. package/dist/bridge-status-controller.cjs +167 -21
  3. package/dist/bridge-status-controller.cjs.map +1 -1
  4. package/dist/bridge-status-controller.d.cts +6 -1
  5. package/dist/bridge-status-controller.d.cts.map +1 -1
  6. package/dist/bridge-status-controller.d.mts +6 -1
  7. package/dist/bridge-status-controller.d.mts.map +1 -1
  8. package/dist/bridge-status-controller.mjs +167 -21
  9. package/dist/bridge-status-controller.mjs.map +1 -1
  10. package/dist/constants.cjs +1 -0
  11. package/dist/constants.cjs.map +1 -1
  12. package/dist/constants.d.cts.map +1 -1
  13. package/dist/constants.d.mts.map +1 -1
  14. package/dist/constants.mjs +1 -0
  15. package/dist/constants.mjs.map +1 -1
  16. package/dist/index.cjs +12 -6
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +3 -1
  19. package/dist/index.d.cts.map +1 -1
  20. package/dist/index.d.mts +3 -1
  21. package/dist/index.d.mts.map +1 -1
  22. package/dist/index.mjs +3 -0
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/quote-status-manager/constants.cjs +181 -0
  25. package/dist/quote-status-manager/constants.cjs.map +1 -0
  26. package/dist/quote-status-manager/constants.d.cts +137 -0
  27. package/dist/quote-status-manager/constants.d.cts.map +1 -0
  28. package/dist/quote-status-manager/constants.d.mts +137 -0
  29. package/dist/quote-status-manager/constants.d.mts.map +1 -0
  30. package/dist/quote-status-manager/constants.mjs +178 -0
  31. package/dist/quote-status-manager/constants.mjs.map +1 -0
  32. package/dist/quote-status-manager/errors.cjs +51 -0
  33. package/dist/quote-status-manager/errors.cjs.map +1 -0
  34. package/dist/quote-status-manager/errors.d.cts +45 -0
  35. package/dist/quote-status-manager/errors.d.cts.map +1 -0
  36. package/dist/quote-status-manager/errors.d.mts +45 -0
  37. package/dist/quote-status-manager/errors.d.mts.map +1 -0
  38. package/dist/quote-status-manager/errors.mjs +46 -0
  39. package/dist/quote-status-manager/errors.mjs.map +1 -0
  40. package/dist/quote-status-manager/quote-status-api-service.cjs +241 -0
  41. package/dist/quote-status-manager/quote-status-api-service.cjs.map +1 -0
  42. package/dist/quote-status-manager/quote-status-api-service.d.cts +93 -0
  43. package/dist/quote-status-manager/quote-status-api-service.d.cts.map +1 -0
  44. package/dist/quote-status-manager/quote-status-api-service.d.mts +93 -0
  45. package/dist/quote-status-manager/quote-status-api-service.d.mts.map +1 -0
  46. package/dist/quote-status-manager/quote-status-api-service.mjs +237 -0
  47. package/dist/quote-status-manager/quote-status-api-service.mjs.map +1 -0
  48. package/dist/quote-status-manager/quote-status-entry-store.cjs +271 -0
  49. package/dist/quote-status-manager/quote-status-entry-store.cjs.map +1 -0
  50. package/dist/quote-status-manager/quote-status-entry-store.d.cts +144 -0
  51. package/dist/quote-status-manager/quote-status-entry-store.d.cts.map +1 -0
  52. package/dist/quote-status-manager/quote-status-entry-store.d.mts +144 -0
  53. package/dist/quote-status-manager/quote-status-entry-store.d.mts.map +1 -0
  54. package/dist/quote-status-manager/quote-status-entry-store.mjs +267 -0
  55. package/dist/quote-status-manager/quote-status-entry-store.mjs.map +1 -0
  56. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.cjs +29 -0
  57. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.cjs.map +1 -0
  58. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.d.cts +32 -0
  59. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.d.cts.map +1 -0
  60. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.d.mts +32 -0
  61. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.d.mts.map +1 -0
  62. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.mjs +25 -0
  63. package/dist/quote-status-manager/quote-status-get-with-retry-outcome.mjs.map +1 -0
  64. package/dist/quote-status-manager/quote-status-state-fsm.cjs +107 -0
  65. package/dist/quote-status-manager/quote-status-state-fsm.cjs.map +1 -0
  66. package/dist/quote-status-manager/quote-status-state-fsm.d.cts +57 -0
  67. package/dist/quote-status-manager/quote-status-state-fsm.d.cts.map +1 -0
  68. package/dist/quote-status-manager/quote-status-state-fsm.d.mts +57 -0
  69. package/dist/quote-status-manager/quote-status-state-fsm.d.mts.map +1 -0
  70. package/dist/quote-status-manager/quote-status-state-fsm.mjs +103 -0
  71. package/dist/quote-status-manager/quote-status-state-fsm.mjs.map +1 -0
  72. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.cjs +27 -0
  73. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.cjs.map +1 -0
  74. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.d.cts +30 -0
  75. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.d.cts.map +1 -0
  76. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.d.mts +30 -0
  77. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.d.mts.map +1 -0
  78. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.mjs +23 -0
  79. package/dist/quote-status-manager/quote-status-update-with-retry-outcome.mjs.map +1 -0
  80. package/dist/quote-status-manager/quotes-status-manager.cjs +477 -0
  81. package/dist/quote-status-manager/quotes-status-manager.cjs.map +1 -0
  82. package/dist/quote-status-manager/quotes-status-manager.d.cts +124 -0
  83. package/dist/quote-status-manager/quotes-status-manager.d.cts.map +1 -0
  84. package/dist/quote-status-manager/quotes-status-manager.d.mts +124 -0
  85. package/dist/quote-status-manager/quotes-status-manager.d.mts.map +1 -0
  86. package/dist/quote-status-manager/quotes-status-manager.mjs +473 -0
  87. package/dist/quote-status-manager/quotes-status-manager.mjs.map +1 -0
  88. package/dist/quote-status-manager/types.cjs +8 -0
  89. package/dist/quote-status-manager/types.cjs.map +1 -0
  90. package/dist/quote-status-manager/types.d.cts +145 -0
  91. package/dist/quote-status-manager/types.d.cts.map +1 -0
  92. package/dist/quote-status-manager/types.d.mts +145 -0
  93. package/dist/quote-status-manager/types.d.mts.map +1 -0
  94. package/dist/quote-status-manager/types.mjs +6 -0
  95. package/dist/quote-status-manager/types.mjs.map +1 -0
  96. package/dist/quote-status-manager/utils.cjs +11 -0
  97. package/dist/quote-status-manager/utils.cjs.map +1 -0
  98. package/dist/quote-status-manager/utils.d.cts +7 -0
  99. package/dist/quote-status-manager/utils.d.cts.map +1 -0
  100. package/dist/quote-status-manager/utils.d.mts +7 -0
  101. package/dist/quote-status-manager/utils.d.mts.map +1 -0
  102. package/dist/quote-status-manager/utils.mjs +7 -0
  103. package/dist/quote-status-manager/utils.mjs.map +1 -0
  104. package/dist/quote-status-manager/validators.cjs +44 -0
  105. package/dist/quote-status-manager/validators.cjs.map +1 -0
  106. package/dist/quote-status-manager/validators.d.cts +172 -0
  107. package/dist/quote-status-manager/validators.d.cts.map +1 -0
  108. package/dist/quote-status-manager/validators.d.mts +172 -0
  109. package/dist/quote-status-manager/validators.d.mts.map +1 -0
  110. package/dist/quote-status-manager/validators.mjs +39 -0
  111. package/dist/quote-status-manager/validators.mjs.map +1 -0
  112. package/dist/types.cjs +2 -0
  113. package/dist/types.cjs.map +1 -1
  114. package/dist/types.d.cts +15 -3
  115. package/dist/types.d.cts.map +1 -1
  116. package/dist/types.d.mts +15 -3
  117. package/dist/types.d.mts.map +1 -1
  118. package/dist/types.mjs +2 -0
  119. package/dist/types.mjs.map +1 -1
  120. package/dist/utils/history.cjs +1 -0
  121. package/dist/utils/history.cjs.map +1 -1
  122. package/dist/utils/history.d.cts.map +1 -1
  123. package/dist/utils/history.d.mts.map +1 -1
  124. package/dist/utils/history.mjs +1 -0
  125. package/dist/utils/history.mjs.map +1 -1
  126. package/package.json +1 -1
@@ -9,7 +9,7 @@ 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_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;
12
+ var _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_intentManager, _BridgeStatusController_quoteStatusManager, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_trace, _BridgeStatusController_onTransactionFailed, _BridgeStatusController_onTransactionConfirmed, _BridgeStatusController_reportSubmittedForNonEvmTx, _BridgeStatusController_reportSubmittedOnce, _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;
13
13
  import { FeatureId } from "@metamask/bridge-controller";
14
14
  import { isNonEvmChainId, StatusTypes, getAccountHardwareType, UnifiedSwapBridgeEventName, isCrossChain, MetricsActionType, MetaMetricsSwapsEventSource, PollingStatus, formatChainIdToHex } from "@metamask/bridge-controller";
15
15
  import { StaticIntervalPollingController } from "@metamask/polling-controller";
@@ -17,6 +17,9 @@ import { TransactionStatus, TransactionType, TransactionController, generateBatc
17
17
  import { numberToHex } from "@metamask/utils";
18
18
  import { IntentManager } from "./bridge-status-controller.intent.mjs";
19
19
  import { ALLOWED_FEATURE_IDS_FOR_STATUS_EVENTS, BRIDGE_PROD_API_BASE_URL, BRIDGE_STATUS_CONTROLLER_NAME, DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE, MAX_ATTEMPTS, REFRESH_INTERVAL_MS } from "./constants.mjs";
20
+ import { QUOTE_STATUS_UPDATE_ENTRY_TTL, QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS } from "./quote-status-manager/constants.mjs";
21
+ import { QuoteStatusGetError, QuoteStatusUpdateError } from "./quote-status-manager/errors.mjs";
22
+ import { QuoteStatusManager } from "./quote-status-manager/quotes-status-manager.mjs";
20
23
  import executeSubmitStrategy from "./strategy/index.mjs";
21
24
  import { SubmitStep } from "./strategy/types.mjs";
22
25
  import { BridgeClientId } from "./types.mjs";
@@ -38,6 +41,13 @@ const metadata = {
38
41
  includeInDebugSnapshot: false,
39
42
  usedInUi: true,
40
43
  },
44
+ // Deferred status updates used by QuoteStatusUpdateManager
45
+ quoteUpdateStatusStore: {
46
+ includeInStateLogs: false,
47
+ persist: true,
48
+ includeInDebugSnapshot: false,
49
+ usedInUi: false,
50
+ },
41
51
  };
42
52
  const MESSENGER_EXPOSED_METHODS = [
43
53
  'startPollingForBridgeTxStatus',
@@ -50,7 +60,7 @@ const MESSENGER_EXPOSED_METHODS = [
50
60
  'getBridgeHistoryItemByTxMetaId',
51
61
  ];
52
62
  export class BridgeStatusController extends StaticIntervalPollingController() {
53
- constructor({ messenger, state, clientId, fetchFn, addTransactionBatchFn, config, traceFn, }) {
63
+ constructor({ messenger, state, clientId, clientProduct, clientVersion, fetchFn, addTransactionBatchFn, config, traceFn, onQuoteStatusManagerError, isQuoteStatusManagerEnabled, }) {
54
64
  super({
55
65
  name: BRIDGE_STATUS_CONTROLLER_NAME,
56
66
  metadata,
@@ -63,6 +73,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
63
73
  });
64
74
  _BridgeStatusController_pollingTokensByTxMetaId.set(this, {});
65
75
  _BridgeStatusController_intentManager.set(this, void 0);
76
+ _BridgeStatusController_quoteStatusManager.set(this, void 0);
66
77
  _BridgeStatusController_clientId.set(this, void 0);
67
78
  _BridgeStatusController_fetchFn.set(this, void 0);
68
79
  _BridgeStatusController_config.set(this, void 0);
@@ -87,6 +98,14 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
87
98
  if (isHistoryItemAlreadyFailed) {
88
99
  return;
89
100
  }
101
+ // Report finalized failure for swap/bridge transactions.
102
+ // Note: TransactionStatus.rejected means the user cancelled signing, so the tx was never broadcast.
103
+ // `hasNestedSwapTransactions` also covers batch/7702 swaps whose type may
104
+ // still read as `batch` rather than `swap`.
105
+ if ((txMeta.type && isCrossChainTx(txMeta.type)) ||
106
+ hasNestedSwapTransactions(txMeta)) {
107
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(txMeta.id, false);
108
+ }
90
109
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Failed, historyKey, getEVMTxPropertiesFromTransactionMeta(txMeta));
91
110
  });
92
111
  // Only EVM txs
@@ -101,25 +120,92 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
101
120
  txHash: txMeta.hash,
102
121
  });
103
122
  const isSwap = txMeta.type === TransactionType.swap || hasNestedSwapTransactions(txMeta);
104
- switch (isSwap) {
105
- case true:
106
- __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
107
- historyKey,
108
- status: StatusTypes.COMPLETE,
109
- completionTime: Date.now(),
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;
123
+ if (isSwap) {
124
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
125
+ historyKey,
126
+ status: StatusTypes.COMPLETE,
127
+ completionTime: Date.now(),
128
+ });
129
+ // For EVM intent-based swaps the synthetic tx transitions
130
+ // submitted→confirmed in a single update that carries the CoW
131
+ // settlement hash, so the submitted status handler never has a hash
132
+ // and reportSubmitted is never called. Call it here (before
133
+ // reportFinalised) so the deferred-queue entry is created.
134
+ const historyItem = historyKey
135
+ ? this.state.txHistory[historyKey]
136
+ : undefined;
137
+ if (historyKey &&
138
+ historyItem &&
139
+ txMeta.hash &&
140
+ !isNonEvmChainId(historyItem.quote.srcChainId)) {
141
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, historyKey, txMeta.hash, txMeta.id);
142
+ }
143
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(txMeta.id, true);
144
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, historyKey);
145
+ }
146
+ else if (historyKey) {
147
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
148
+ }
149
+ });
150
+ /**
151
+ * Reports the SUBMITTED quote status for non-EVM transactions.
152
+ *
153
+ * EVM transactions report SUBMITTED via the
154
+ * `TransactionController:transactionStatusUpdated` subscription, which also
155
+ * picks up hash replacements (speed-up/cancel) and the late hash assignment
156
+ * of smart/batch transactions. Non-EVM transactions (Solana, Bitcoin, Tron)
157
+ * are submitted through Snaps and never emit TransactionController lifecycle
158
+ * events, so they are reported here once the history item exists and the
159
+ * source tx hash is known.
160
+ *
161
+ * @param historyKey - The key of the history item in `txHistory`
162
+ * @param txMeta - The submitted trade transaction's id and hash
163
+ * @param txMeta.id - The transaction meta id, used for finalization matching
164
+ * @param txMeta.hash - The source chain transaction hash
165
+ */
166
+ _BridgeStatusController_reportSubmittedForNonEvmTx.set(this, (historyKey, txMeta) => {
167
+ if (!txMeta?.id || !txMeta.hash) {
168
+ return;
169
+ }
170
+ const historyItem = this.state.txHistory[historyKey];
171
+ if (!historyItem || !isNonEvmChainId(historyItem.quote.srcChainId)) {
172
+ return;
118
173
  }
174
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, historyKey, txMeta.hash, txMeta.id);
175
+ });
176
+ /**
177
+ * Reports a SUBMITTED quote status update exactly once per source tx hash.
178
+ *
179
+ * SUBMITTED can be triggered from several code paths (submission, the first
180
+ * poll where the hash is known, and the final-status branch) and the poll
181
+ * path runs on every interval.
182
+ *
183
+ * @param historyKey - The key of the history item in `txHistory`
184
+ * @param srcTxHash - The source chain transaction hash
185
+ * @param txMetaId - The transaction meta id, used for finalization matching
186
+ */
187
+ _BridgeStatusController_reportSubmittedOnce.set(this, (historyKey, srcTxHash, txMetaId) => {
188
+ const historyItem = this.state.txHistory[historyKey];
189
+ if (!historyItem?.quoteId) {
190
+ return;
191
+ }
192
+ if (historyItem.reportedSubmittedTxHash === srcTxHash) {
193
+ return;
194
+ }
195
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportSubmitted(historyItem.quoteId, srcTxHash, txMetaId);
196
+ this.update((state) => {
197
+ const item = state.txHistory[historyKey];
198
+ if (item) {
199
+ item.reportedSubmittedTxHash = srcTxHash;
200
+ }
201
+ });
119
202
  });
120
203
  this.resetState = () => {
204
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").destroy();
121
205
  this.update((state) => {
122
206
  state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;
207
+ state.quoteUpdateStatusStore =
208
+ DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.quoteUpdateStatusStore;
123
209
  });
124
210
  };
125
211
  this.wipeBridgeStatus = ({ address, ignoreNetwork, }) => {
@@ -344,7 +430,11 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
344
430
  this.stopPollingByPollingToken(pollingToken);
345
431
  delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
346
432
  }
347
- // Delete the history item so polling doesn't start over on the next restart
433
+ // Delete the history item so polling doesn't start over on the next restart.
434
+ // Report finalization as a failure here, this is the only place that
435
+ // permanently ends polling, so it's the correct and non-duplicative point
436
+ // to emit the final status.
437
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(bridgeTxMetaId, false);
348
438
  __classPrivateFieldGet(this, _BridgeStatusController_deleteHistoryItem, "f").call(this, bridgeTxMetaId);
349
439
  });
350
440
  _BridgeStatusController_fetchBridgeTxStatus.set(this, async ({ bridgeTxMetaId, }) => {
@@ -369,6 +459,12 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
369
459
  return;
370
460
  }
371
461
  status = intentTxStatus.bridgeStatus.status;
462
+ // Report SUBMITTED as soon as the intent's source/settlement hash is
463
+ // known at poll time, before the order reaches a terminal status.
464
+ const intentSrcTxHash = status.srcChain.txHash;
465
+ if (intentSrcTxHash) {
466
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, bridgeTxMetaId, intentSrcTxHash, bridgeTxMetaId);
467
+ }
372
468
  }
373
469
  else {
374
470
  // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx
@@ -378,6 +474,9 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
378
474
  if (!srcTxHash) {
379
475
  return;
380
476
  }
477
+ // Report SUBMITTED as soon as a srcTxHash is known at poll time, for
478
+ // every chain not just non-EVM sources.
479
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, bridgeTxMetaId, srcTxHash, bridgeTxMetaId);
381
480
  const statusRequest = getStatusRequestWithSrcTxHash(historyItem.quote, srcTxHash);
382
481
  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);
383
482
  status = response.status;
@@ -414,9 +513,17 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
414
513
  const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
415
514
  const isFinalStatus = status.status === StatusTypes.COMPLETE ||
416
515
  status.status === StatusTypes.FAILED;
417
- if (isFinalStatus && pollingToken) {
418
- this.stopPollingByPollingToken(pollingToken);
419
- delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
516
+ if (isFinalStatus) {
517
+ if (pollingToken) {
518
+ this.stopPollingByPollingToken(pollingToken);
519
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
520
+ }
521
+ // Ensure a deferred entry exists before reportFinalised is called.
522
+ const settlementTxHash = newBridgeHistoryItem.status.srcChain.txHash;
523
+ if (settlementTxHash) {
524
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, bridgeTxMetaId, settlementTxHash, bridgeTxMetaId);
525
+ }
526
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(bridgeTxMetaId, status.status === StatusTypes.COMPLETE);
420
527
  if (status.status === StatusTypes.COMPLETE) {
421
528
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, bridgeTxMetaId);
422
529
  this.messenger.publish('BridgeStatusController:destinationTransactionCompleted', historyItem.quote.destAsset.assetId);
@@ -531,6 +638,12 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
531
638
  switch (type) {
532
639
  case SubmitStep.RekeyHistoryItem:
533
640
  __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, payload.oldHistoryKey, payload.newHistoryKey, payload.tradeMeta);
641
+ // Report SUBMITTED as soon as the trade hash is known at submission
642
+ // time, instead of waiting for the delayed transactionStatusUpdated
643
+ // (submitted) event.
644
+ if (payload.tradeMeta.hash) {
645
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, payload.newHistoryKey, payload.tradeMeta.hash, payload.tradeMeta.id);
646
+ }
534
647
  break;
535
648
  case SubmitStep.UpdateBatchTransactions:
536
649
  updateTransactionsInBatch({
@@ -550,11 +663,13 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
550
663
  isStxEnabled: params.isStxEnabled,
551
664
  slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
552
665
  });
666
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedForNonEvmTx, "f").call(this, payload.historyKey, payload.bridgeTxMeta);
553
667
  break;
554
668
  case SubmitStep.StartPolling:
555
669
  __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, payload.historyKey);
556
670
  break;
557
671
  case SubmitStep.PublishCompletedEvent:
672
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(payload.historyKey, true);
558
673
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, UnifiedSwapBridgeEventName.Completed, payload.historyKey);
559
674
  break;
560
675
  /* c8 ignore start */
@@ -807,6 +922,23 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
807
922
  customBridgeApiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
808
923
  fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
809
924
  }), "f");
925
+ __classPrivateFieldSet(this, _BridgeStatusController_quoteStatusManager, new QuoteStatusManager({
926
+ messenger: this.messenger,
927
+ clientId: __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"),
928
+ clientProduct,
929
+ clientVersion,
930
+ apiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
931
+ initialData: this.state.quoteUpdateStatusStore,
932
+ onPersistUpdates: (updates) => {
933
+ this.update((draft) => {
934
+ draft.quoteUpdateStatusStore = updates;
935
+ });
936
+ },
937
+ entryTtlMs: QUOTE_STATUS_UPDATE_ENTRY_TTL,
938
+ updateIntervalMs: QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS,
939
+ onError: onQuoteStatusManagerError,
940
+ isEnabled: isQuoteStatusManagerEnabled,
941
+ }), "f");
810
942
  // Register action handlers
811
943
  this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
812
944
  // Set interval
@@ -823,6 +955,17 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
823
955
  return;
824
956
  }
825
957
  switch (status) {
958
+ case TransactionStatus.submitted:
959
+ // EVM txs report SUBMITTED here (not via transactionSubmitted) so hash
960
+ // replacements before confirmation still reach the Bridge API.
961
+ if (txMeta.hash &&
962
+ txMeta.type &&
963
+ isCrossChainTx(txMeta.type) &&
964
+ !isApprovalTxMeta &&
965
+ historyKey) {
966
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, historyKey, txMeta.hash, txMeta.id);
967
+ }
968
+ break;
826
969
  case TransactionStatus.confirmed:
827
970
  __classPrivateFieldGet(this, _BridgeStatusController_onTransactionConfirmed, "f").call(this, {
828
971
  txMeta,
@@ -849,11 +992,14 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
849
992
  isApprovalTxMeta: entryToUse?.[1]?.approvalTxId === transactionMeta.id,
850
993
  };
851
994
  });
995
+ // Replay swap/bridge finalizations that resolved while the client was
996
+ // closed, before resuming polling (which recovers in-flight bridges).
997
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").init();
852
998
  // If you close the extension, but keep the browser open, the polling continues
853
999
  // If you close the browser, the polling stops
854
1000
  // Check for historyItems that do not have a status of complete and restart polling
855
1001
  __classPrivateFieldGet(this, _BridgeStatusController_restartPollingForIncompleteHistoryItems, "f").call(this);
856
1002
  }
857
1003
  }
858
- _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();
1004
+ _BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_intentManager = new WeakMap(), _BridgeStatusController_quoteStatusManager = 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_reportSubmittedForNonEvmTx = new WeakMap(), _BridgeStatusController_reportSubmittedOnce = 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();
859
1005
  //# sourceMappingURL=bridge-status-controller.mjs.map