@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
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [74.0.0]
11
+
12
+ ### Added
13
+
14
+ - **BREAKING:** Add required `quoteId: string` and `reportedSubmittedTxHash: string` to `BridgeHistoryItem` ([#8462](https://github.com/MetaMask/core/pull/8462))
15
+ - **BREAKING:** Add `QuoteStatusUpdateManager` for resilient quote-status reporting to the Bridge API; reports `SUBMITTED`/`FINALIZED_SUCCESS`/`FINALIZED_FAILURE`, retries immediately on retryable errors, defers on network failures, and persists the queue to `quoteUpdateStatusStore` state across service-worker restarts ([#8462](https://github.com/MetaMask/core/pull/8462))
16
+
10
17
  ### Changed
11
18
 
12
19
  - Bump `@metamask/bridge-controller` from `^77.0.0` to `^77.1.0` ([#9301](https://github.com/MetaMask/core/pull/9301))
@@ -1340,7 +1347,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1340
1347
 
1341
1348
  - Initial release ([#5317](https://github.com/MetaMask/core/pull/5317))
1342
1349
 
1343
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@73.1.0...HEAD
1350
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@74.0.0...HEAD
1351
+ [74.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@73.1.0...@metamask/bridge-status-controller@74.0.0
1344
1352
  [73.1.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@73.0.0...@metamask/bridge-status-controller@73.1.0
1345
1353
  [73.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@72.3.0...@metamask/bridge-status-controller@73.0.0
1346
1354
  [72.3.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@72.2.0...@metamask/bridge-status-controller@72.3.0
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
- var _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_intentManager, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_trace, _BridgeStatusController_onTransactionFailed, _BridgeStatusController_onTransactionConfirmed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_rekeyHistoryItem, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_handleOldHistoryItem, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_setAndGetSrcTxHash, _BridgeStatusController_updateHistoryItem, _BridgeStatusController_deleteHistoryItem, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_executeSubmitStrategy, _BridgeStatusController_trackPollingStatusUpdatedEvent, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
16
+ 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;
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.BridgeStatusController = void 0;
19
19
  const bridge_controller_1 = require("@metamask/bridge-controller");
@@ -23,6 +23,9 @@ const transaction_controller_1 = require("@metamask/transaction-controller");
23
23
  const utils_1 = require("@metamask/utils");
24
24
  const bridge_status_controller_intent_1 = require("./bridge-status-controller.intent.cjs");
25
25
  const constants_1 = require("./constants.cjs");
26
+ const constants_2 = require("./quote-status-manager/constants.cjs");
27
+ const errors_1 = require("./quote-status-manager/errors.cjs");
28
+ const quotes_status_manager_1 = require("./quote-status-manager/quotes-status-manager.cjs");
26
29
  const strategy_1 = __importDefault(require("./strategy/index.cjs"));
27
30
  const types_1 = require("./strategy/types.cjs");
28
31
  const types_2 = require("./types.cjs");
@@ -44,6 +47,13 @@ const metadata = {
44
47
  includeInDebugSnapshot: false,
45
48
  usedInUi: true,
46
49
  },
50
+ // Deferred status updates used by QuoteStatusUpdateManager
51
+ quoteUpdateStatusStore: {
52
+ includeInStateLogs: false,
53
+ persist: true,
54
+ includeInDebugSnapshot: false,
55
+ usedInUi: false,
56
+ },
47
57
  };
48
58
  const MESSENGER_EXPOSED_METHODS = [
49
59
  'startPollingForBridgeTxStatus',
@@ -56,7 +66,7 @@ const MESSENGER_EXPOSED_METHODS = [
56
66
  'getBridgeHistoryItemByTxMetaId',
57
67
  ];
58
68
  class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPollingController)() {
59
- constructor({ messenger, state, clientId, fetchFn, addTransactionBatchFn, config, traceFn, }) {
69
+ constructor({ messenger, state, clientId, clientProduct, clientVersion, fetchFn, addTransactionBatchFn, config, traceFn, onQuoteStatusManagerError, isQuoteStatusManagerEnabled, }) {
60
70
  super({
61
71
  name: constants_1.BRIDGE_STATUS_CONTROLLER_NAME,
62
72
  metadata,
@@ -69,6 +79,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
69
79
  });
70
80
  _BridgeStatusController_pollingTokensByTxMetaId.set(this, {});
71
81
  _BridgeStatusController_intentManager.set(this, void 0);
82
+ _BridgeStatusController_quoteStatusManager.set(this, void 0);
72
83
  _BridgeStatusController_clientId.set(this, void 0);
73
84
  _BridgeStatusController_fetchFn.set(this, void 0);
74
85
  _BridgeStatusController_config.set(this, void 0);
@@ -93,6 +104,14 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
93
104
  if (isHistoryItemAlreadyFailed) {
94
105
  return;
95
106
  }
107
+ // Report finalized failure for swap/bridge transactions.
108
+ // Note: TransactionStatus.rejected means the user cancelled signing, so the tx was never broadcast.
109
+ // `hasNestedSwapTransactions` also covers batch/7702 swaps whose type may
110
+ // still read as `batch` rather than `swap`.
111
+ if ((txMeta.type && (0, transaction_1.isCrossChainTx)(txMeta.type)) ||
112
+ (0, transaction_1.hasNestedSwapTransactions)(txMeta)) {
113
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(txMeta.id, false);
114
+ }
96
115
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_2.UnifiedSwapBridgeEventName.Failed, historyKey, (0, metrics_1.getEVMTxPropertiesFromTransactionMeta)(txMeta));
97
116
  });
98
117
  // Only EVM txs
@@ -107,25 +126,92 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
107
126
  txHash: txMeta.hash,
108
127
  });
109
128
  const isSwap = txMeta.type === transaction_controller_1.TransactionType.swap || (0, transaction_1.hasNestedSwapTransactions)(txMeta);
110
- switch (isSwap) {
111
- case true:
112
- __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
113
- historyKey,
114
- status: bridge_controller_2.StatusTypes.COMPLETE,
115
- completionTime: Date.now(),
116
- });
117
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_2.UnifiedSwapBridgeEventName.Completed, historyKey);
118
- break;
119
- default:
120
- if (historyKey) {
121
- __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
122
- }
123
- break;
129
+ if (isSwap) {
130
+ __classPrivateFieldGet(this, _BridgeStatusController_updateHistoryItem, "f").call(this, {
131
+ historyKey,
132
+ status: bridge_controller_2.StatusTypes.COMPLETE,
133
+ completionTime: Date.now(),
134
+ });
135
+ // For EVM intent-based swaps the synthetic tx transitions
136
+ // submitted→confirmed in a single update that carries the CoW
137
+ // settlement hash, so the submitted status handler never has a hash
138
+ // and reportSubmitted is never called. Call it here (before
139
+ // reportFinalised) so the deferred-queue entry is created.
140
+ const historyItem = historyKey
141
+ ? this.state.txHistory[historyKey]
142
+ : undefined;
143
+ if (historyKey &&
144
+ historyItem &&
145
+ txMeta.hash &&
146
+ !(0, bridge_controller_2.isNonEvmChainId)(historyItem.quote.srcChainId)) {
147
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, historyKey, txMeta.hash, txMeta.id);
148
+ }
149
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(txMeta.id, true);
150
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_2.UnifiedSwapBridgeEventName.Completed, historyKey);
151
+ }
152
+ else if (historyKey) {
153
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, historyKey);
154
+ }
155
+ });
156
+ /**
157
+ * Reports the SUBMITTED quote status for non-EVM transactions.
158
+ *
159
+ * EVM transactions report SUBMITTED via the
160
+ * `TransactionController:transactionStatusUpdated` subscription, which also
161
+ * picks up hash replacements (speed-up/cancel) and the late hash assignment
162
+ * of smart/batch transactions. Non-EVM transactions (Solana, Bitcoin, Tron)
163
+ * are submitted through Snaps and never emit TransactionController lifecycle
164
+ * events, so they are reported here once the history item exists and the
165
+ * source tx hash is known.
166
+ *
167
+ * @param historyKey - The key of the history item in `txHistory`
168
+ * @param txMeta - The submitted trade transaction's id and hash
169
+ * @param txMeta.id - The transaction meta id, used for finalization matching
170
+ * @param txMeta.hash - The source chain transaction hash
171
+ */
172
+ _BridgeStatusController_reportSubmittedForNonEvmTx.set(this, (historyKey, txMeta) => {
173
+ if (!txMeta?.id || !txMeta.hash) {
174
+ return;
175
+ }
176
+ const historyItem = this.state.txHistory[historyKey];
177
+ if (!historyItem || !(0, bridge_controller_2.isNonEvmChainId)(historyItem.quote.srcChainId)) {
178
+ return;
124
179
  }
180
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, historyKey, txMeta.hash, txMeta.id);
181
+ });
182
+ /**
183
+ * Reports a SUBMITTED quote status update exactly once per source tx hash.
184
+ *
185
+ * SUBMITTED can be triggered from several code paths (submission, the first
186
+ * poll where the hash is known, and the final-status branch) and the poll
187
+ * path runs on every interval.
188
+ *
189
+ * @param historyKey - The key of the history item in `txHistory`
190
+ * @param srcTxHash - The source chain transaction hash
191
+ * @param txMetaId - The transaction meta id, used for finalization matching
192
+ */
193
+ _BridgeStatusController_reportSubmittedOnce.set(this, (historyKey, srcTxHash, txMetaId) => {
194
+ const historyItem = this.state.txHistory[historyKey];
195
+ if (!historyItem?.quoteId) {
196
+ return;
197
+ }
198
+ if (historyItem.reportedSubmittedTxHash === srcTxHash) {
199
+ return;
200
+ }
201
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportSubmitted(historyItem.quoteId, srcTxHash, txMetaId);
202
+ this.update((state) => {
203
+ const item = state.txHistory[historyKey];
204
+ if (item) {
205
+ item.reportedSubmittedTxHash = srcTxHash;
206
+ }
207
+ });
125
208
  });
126
209
  this.resetState = () => {
210
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").destroy();
127
211
  this.update((state) => {
128
212
  state.txHistory = constants_1.DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;
213
+ state.quoteUpdateStatusStore =
214
+ constants_1.DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.quoteUpdateStatusStore;
129
215
  });
130
216
  };
131
217
  this.wipeBridgeStatus = ({ address, ignoreNetwork, }) => {
@@ -350,7 +436,11 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
350
436
  this.stopPollingByPollingToken(pollingToken);
351
437
  delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
352
438
  }
353
- // Delete the history item so polling doesn't start over on the next restart
439
+ // Delete the history item so polling doesn't start over on the next restart.
440
+ // Report finalization as a failure here, this is the only place that
441
+ // permanently ends polling, so it's the correct and non-duplicative point
442
+ // to emit the final status.
443
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(bridgeTxMetaId, false);
354
444
  __classPrivateFieldGet(this, _BridgeStatusController_deleteHistoryItem, "f").call(this, bridgeTxMetaId);
355
445
  });
356
446
  _BridgeStatusController_fetchBridgeTxStatus.set(this, async ({ bridgeTxMetaId, }) => {
@@ -375,6 +465,12 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
375
465
  return;
376
466
  }
377
467
  status = intentTxStatus.bridgeStatus.status;
468
+ // Report SUBMITTED as soon as the intent's source/settlement hash is
469
+ // known at poll time, before the order reaches a terminal status.
470
+ const intentSrcTxHash = status.srcChain.txHash;
471
+ if (intentSrcTxHash) {
472
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, bridgeTxMetaId, intentSrcTxHash, bridgeTxMetaId);
473
+ }
378
474
  }
379
475
  else {
380
476
  // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx
@@ -384,6 +480,9 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
384
480
  if (!srcTxHash) {
385
481
  return;
386
482
  }
483
+ // Report SUBMITTED as soon as a srcTxHash is known at poll time, for
484
+ // every chain not just non-EVM sources.
485
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, bridgeTxMetaId, srcTxHash, bridgeTxMetaId);
387
486
  const statusRequest = (0, bridge_status_1.getStatusRequestWithSrcTxHash)(historyItem.quote, srcTxHash);
388
487
  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);
389
488
  status = response.status;
@@ -420,9 +519,17 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
420
519
  const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
421
520
  const isFinalStatus = status.status === bridge_controller_2.StatusTypes.COMPLETE ||
422
521
  status.status === bridge_controller_2.StatusTypes.FAILED;
423
- if (isFinalStatus && pollingToken) {
424
- this.stopPollingByPollingToken(pollingToken);
425
- delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
522
+ if (isFinalStatus) {
523
+ if (pollingToken) {
524
+ this.stopPollingByPollingToken(pollingToken);
525
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
526
+ }
527
+ // Ensure a deferred entry exists before reportFinalised is called.
528
+ const settlementTxHash = newBridgeHistoryItem.status.srcChain.txHash;
529
+ if (settlementTxHash) {
530
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, bridgeTxMetaId, settlementTxHash, bridgeTxMetaId);
531
+ }
532
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(bridgeTxMetaId, status.status === bridge_controller_2.StatusTypes.COMPLETE);
426
533
  if (status.status === bridge_controller_2.StatusTypes.COMPLETE) {
427
534
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_2.UnifiedSwapBridgeEventName.Completed, bridgeTxMetaId);
428
535
  this.messenger.publish('BridgeStatusController:destinationTransactionCompleted', historyItem.quote.destAsset.assetId);
@@ -537,6 +644,12 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
537
644
  switch (type) {
538
645
  case types_1.SubmitStep.RekeyHistoryItem:
539
646
  __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, payload.oldHistoryKey, payload.newHistoryKey, payload.tradeMeta);
647
+ // Report SUBMITTED as soon as the trade hash is known at submission
648
+ // time, instead of waiting for the delayed transactionStatusUpdated
649
+ // (submitted) event.
650
+ if (payload.tradeMeta.hash) {
651
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, payload.newHistoryKey, payload.tradeMeta.hash, payload.tradeMeta.id);
652
+ }
540
653
  break;
541
654
  case types_1.SubmitStep.UpdateBatchTransactions:
542
655
  (0, transaction_1.updateTransactionsInBatch)({
@@ -556,11 +669,13 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
556
669
  isStxEnabled: params.isStxEnabled,
557
670
  slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
558
671
  });
672
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedForNonEvmTx, "f").call(this, payload.historyKey, payload.bridgeTxMeta);
559
673
  break;
560
674
  case types_1.SubmitStep.StartPolling:
561
675
  __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, payload.historyKey);
562
676
  break;
563
677
  case types_1.SubmitStep.PublishCompletedEvent:
678
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportFinalised(payload.historyKey, true);
564
679
  __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_2.UnifiedSwapBridgeEventName.Completed, payload.historyKey);
565
680
  break;
566
681
  /* c8 ignore start */
@@ -813,6 +928,23 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
813
928
  customBridgeApiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
814
929
  fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
815
930
  }), "f");
931
+ __classPrivateFieldSet(this, _BridgeStatusController_quoteStatusManager, new quotes_status_manager_1.QuoteStatusManager({
932
+ messenger: this.messenger,
933
+ clientId: __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"),
934
+ clientProduct,
935
+ clientVersion,
936
+ apiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
937
+ initialData: this.state.quoteUpdateStatusStore,
938
+ onPersistUpdates: (updates) => {
939
+ this.update((draft) => {
940
+ draft.quoteUpdateStatusStore = updates;
941
+ });
942
+ },
943
+ entryTtlMs: constants_2.QUOTE_STATUS_UPDATE_ENTRY_TTL,
944
+ updateIntervalMs: constants_2.QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS,
945
+ onError: onQuoteStatusManagerError,
946
+ isEnabled: isQuoteStatusManagerEnabled,
947
+ }), "f");
816
948
  // Register action handlers
817
949
  this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
818
950
  // Set interval
@@ -829,6 +961,17 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
829
961
  return;
830
962
  }
831
963
  switch (status) {
964
+ case transaction_controller_1.TransactionStatus.submitted:
965
+ // EVM txs report SUBMITTED here (not via transactionSubmitted) so hash
966
+ // replacements before confirmation still reach the Bridge API.
967
+ if (txMeta.hash &&
968
+ txMeta.type &&
969
+ (0, transaction_1.isCrossChainTx)(txMeta.type) &&
970
+ !isApprovalTxMeta &&
971
+ historyKey) {
972
+ __classPrivateFieldGet(this, _BridgeStatusController_reportSubmittedOnce, "f").call(this, historyKey, txMeta.hash, txMeta.id);
973
+ }
974
+ break;
832
975
  case transaction_controller_1.TransactionStatus.confirmed:
833
976
  __classPrivateFieldGet(this, _BridgeStatusController_onTransactionConfirmed, "f").call(this, {
834
977
  txMeta,
@@ -855,6 +998,9 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
855
998
  isApprovalTxMeta: entryToUse?.[1]?.approvalTxId === transactionMeta.id,
856
999
  };
857
1000
  });
1001
+ // Replay swap/bridge finalizations that resolved while the client was
1002
+ // closed, before resuming polling (which recovers in-flight bridges).
1003
+ __classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").init();
858
1004
  // If you close the extension, but keep the browser open, the polling continues
859
1005
  // If you close the browser, the polling stops
860
1006
  // Check for historyItems that do not have a status of complete and restart polling
@@ -862,5 +1008,5 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
862
1008
  }
863
1009
  }
864
1010
  exports.BridgeStatusController = BridgeStatusController;
865
- _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();
1011
+ _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();
866
1012
  //# sourceMappingURL=bridge-status-controller.cjs.map