@metamask/bridge-status-controller 74.2.0 → 74.3.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.
- package/CHANGELOG.md +12 -1
- package/dist/bridge-status-controller.cjs +32 -4
- package/dist/bridge-status-controller.cjs.map +1 -1
- package/dist/bridge-status-controller.d.cts.map +1 -1
- package/dist/bridge-status-controller.d.mts.map +1 -1
- package/dist/bridge-status-controller.mjs +32 -4
- package/dist/bridge-status-controller.mjs.map +1 -1
- package/dist/quote-status-manager/quote-status-entry-store.cjs +22 -0
- package/dist/quote-status-manager/quote-status-entry-store.cjs.map +1 -1
- package/dist/quote-status-manager/quote-status-entry-store.d.cts +13 -0
- package/dist/quote-status-manager/quote-status-entry-store.d.cts.map +1 -1
- package/dist/quote-status-manager/quote-status-entry-store.d.mts +13 -0
- package/dist/quote-status-manager/quote-status-entry-store.d.mts.map +1 -1
- package/dist/quote-status-manager/quote-status-entry-store.mjs +22 -0
- package/dist/quote-status-manager/quote-status-entry-store.mjs.map +1 -1
- package/dist/quote-status-manager/quotes-status-manager.cjs +26 -12
- package/dist/quote-status-manager/quotes-status-manager.cjs.map +1 -1
- package/dist/quote-status-manager/quotes-status-manager.d.cts +4 -1
- package/dist/quote-status-manager/quotes-status-manager.d.cts.map +1 -1
- package/dist/quote-status-manager/quotes-status-manager.d.mts +4 -1
- package/dist/quote-status-manager/quotes-status-manager.d.mts.map +1 -1
- package/dist/quote-status-manager/quotes-status-manager.mjs +26 -12
- package/dist/quote-status-manager/quotes-status-manager.mjs.map +1 -1
- package/dist/strategy/batch-sell-strategy.cjs +10 -1
- package/dist/strategy/batch-sell-strategy.cjs.map +1 -1
- package/dist/strategy/batch-sell-strategy.d.cts.map +1 -1
- package/dist/strategy/batch-sell-strategy.d.mts.map +1 -1
- package/dist/strategy/batch-sell-strategy.mjs +10 -1
- package/dist/strategy/batch-sell-strategy.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +9 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +9 -0
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +3 -1
|
@@ -180,13 +180,36 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
180
180
|
* poll where the hash is known, and the final-status branch) and the poll
|
|
181
181
|
* path runs on every interval.
|
|
182
182
|
*
|
|
183
|
+
* For 7702/nested batch sells a single source transaction carries multiple
|
|
184
|
+
* quotes: the parent history item lists all of them in `quoteIds` (each a key
|
|
185
|
+
* into `txHistory`). In that case every quote is reported under the shared
|
|
186
|
+
* source tx hash and `txMetaId`.
|
|
187
|
+
*
|
|
183
188
|
* @param historyKey - The key of the history item in `txHistory`
|
|
184
189
|
* @param srcTxHash - The source chain transaction hash
|
|
185
190
|
* @param txMetaId - The transaction meta id, used for finalization matching
|
|
186
191
|
*/
|
|
187
192
|
_BridgeStatusController_reportSubmittedOnce.set(this, (historyKey, srcTxHash, txMetaId) => {
|
|
188
193
|
const historyItem = this.state.txHistory[historyKey];
|
|
189
|
-
if (!historyItem
|
|
194
|
+
if (!historyItem) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
// For a 7702/nested batch the parent item lists every quote in `quoteIds`
|
|
198
|
+
// (keys into `txHistory`); resolve each to its real quote id. Otherwise fall
|
|
199
|
+
// back to the item's own single quote id.
|
|
200
|
+
let quoteIds;
|
|
201
|
+
if (historyItem.quoteIds?.length) {
|
|
202
|
+
quoteIds = historyItem.quoteIds
|
|
203
|
+
.map((quoteKey) => this.state.txHistory[quoteKey]?.quoteId)
|
|
204
|
+
.filter((quoteId) => Boolean(quoteId));
|
|
205
|
+
}
|
|
206
|
+
else if (historyItem.quoteId) {
|
|
207
|
+
quoteIds = [historyItem.quoteId];
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
quoteIds = [];
|
|
211
|
+
}
|
|
212
|
+
if (quoteIds.length === 0) {
|
|
190
213
|
return;
|
|
191
214
|
}
|
|
192
215
|
// `reportedSubmittedTxHash` is set once `reportSubmitted` is called.
|
|
@@ -195,7 +218,9 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
195
218
|
if (historyItem.reportedSubmittedTxHash === srcTxHash) {
|
|
196
219
|
return;
|
|
197
220
|
}
|
|
198
|
-
|
|
221
|
+
for (const quoteId of quoteIds) {
|
|
222
|
+
__classPrivateFieldGet(this, _BridgeStatusController_quoteStatusManager, "f").reportSubmitted(quoteId, srcTxHash, txMetaId);
|
|
223
|
+
}
|
|
199
224
|
this.update((state) => {
|
|
200
225
|
const item = state.txHistory[historyKey];
|
|
201
226
|
if (item) {
|
|
@@ -303,8 +328,11 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
303
328
|
return;
|
|
304
329
|
}
|
|
305
330
|
for (const [historyKey, historyItem] of Object.entries(this.state.txHistory)) {
|
|
306
|
-
const { quoteId, txMetaId } = historyItem;
|
|
307
|
-
|
|
331
|
+
const { quoteId, quoteIds, txMetaId } = historyItem;
|
|
332
|
+
// A 7702/nested batch parent reports its quotes via `quoteIds` rather than
|
|
333
|
+
// its own single `quoteId`, so accept either. `#reportSubmittedOnce`
|
|
334
|
+
// resolves the actual set of quotes to report.
|
|
335
|
+
if ((!quoteId && !quoteIds?.length) || !txMetaId) {
|
|
308
336
|
continue;
|
|
309
337
|
}
|
|
310
338
|
// Skip items older than the backfill window: the backend would reject
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-status-controller.mjs","sourceRoot":"","sources":["../src/bridge-status-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport {\n QuoteMetadata,\n RequiredEventContextFromClient,\n QuoteResponse,\n Trade,\n FeatureId,\n BatchSellTradesResponse,\n InputPrimaryDenomination,\n} from '@metamask/bridge-controller';\nimport {\n isNonEvmChainId,\n StatusTypes,\n getAccountHardwareType,\n UnifiedSwapBridgeEventName,\n isCrossChain,\n MetricsActionType,\n MetaMetricsSwapsEventSource,\n PollingStatus,\n formatChainIdToHex,\n} from '@metamask/bridge-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport {\n TransactionStatus,\n TransactionType,\n TransactionController,\n generateBatchId,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { IntentManager } from './bridge-status-controller.intent';\nimport {\n ALLOWED_FEATURE_IDS_FOR_STATUS_EVENTS,\n BRIDGE_PROD_API_BASE_URL,\n BRIDGE_STATUS_CONTROLLER_NAME,\n DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n MAX_ATTEMPTS,\n REFRESH_INTERVAL_MS,\n} from './constants';\nimport {\n QUOTE_STATUS_BACKFILL_WINDOW_MS,\n QUOTE_STATUS_UPDATE_ENTRY_TTL,\n QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS,\n} from './quote-status-manager/constants';\nimport {\n QuoteStatusGetError,\n QuoteStatusUpdateError,\n} from './quote-status-manager/errors';\nimport { QuoteStatusManager } from './quote-status-manager/quotes-status-manager';\nimport executeSubmitStrategy from './strategy';\nimport { SubmitStep } from './strategy/types';\nimport type { SubmitStrategyParams } from './strategy/types';\nimport type {\n BridgeStatusControllerState,\n StartPollingForBridgeTxStatusArgsSerialized,\n FetchFunction,\n BridgeHistoryItem,\n} from './types';\nimport type { BridgeStatusControllerMessenger } from './types';\nimport { BridgeClientId } from './types';\nimport { getAccountByAddress } from './utils/accounts';\nimport { getJwt } from './utils/authentication';\nimport {\n getBatchSellTrades,\n stopPollingForQuotes,\n trackMetricsEvent,\n} from './utils/bridge';\nimport {\n fetchBridgeTxStatus,\n fetchBridgeQuoteStatus,\n getStatusRequestWithSrcTxHash,\n shouldSkipFetchDueToFetchFailures,\n shouldWaitForFinalBridgeStatus,\n} from './utils/bridge-status';\nimport {\n getInitialHistoryItem,\n getMatchingHistoryEntryForTxMeta,\n rekeyHistoryItemInState,\n shouldPollHistoryItem,\n getMatchingHistoryEntryForApprovalTxMeta,\n} from './utils/history';\nimport {\n getFinalizedTxProperties,\n getPriceImpactFromQuote,\n getRequestMetadataFromHistory,\n getRequestParamFromHistory,\n getTradeDataFromHistory,\n getEVMTxPropertiesFromTransactionMeta,\n getTxStatusesFromHistory,\n getPreConfirmationPropertiesFromQuote,\n} from './utils/metrics';\nimport { getSelectedChainId } from './utils/network';\nimport { getTraceParams } from './utils/trace';\nimport {\n getTransactionMetaById,\n getTransactions,\n checkIsDelegatedAccount,\n isCrossChainTx,\n updateTransactionsInBatch,\n hasNestedSwapTransactions,\n} from './utils/transaction';\n\nconst metadata: StateMetadata<BridgeStatusControllerState> = {\n // We want to persist the bridge status state so that we can show the proper data for the Activity list\n // basically match the behavior of TransactionController\n txHistory: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n // Deferred status updates used by QuoteStatusUpdateManager\n quoteUpdateStatusStore: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n};\n\n/** The input to start polling for the {@link BridgeStatusController} */\ntype BridgeStatusPollingInput = FetchBridgeTxStatusArgs;\n\ntype SrcTxMetaId = string;\nexport type FetchBridgeTxStatusArgs = {\n bridgeTxMetaId: string;\n};\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'startPollingForBridgeTxStatus',\n 'wipeBridgeStatus',\n 'resetState',\n 'submitTx',\n 'submitIntent',\n 'submitBatchSell',\n 'restartPollingForFailedAttempts',\n 'getBridgeHistoryItemByTxMetaId',\n] as const;\n\nexport class BridgeStatusController extends StaticIntervalPollingController<BridgeStatusPollingInput>()<\n typeof BRIDGE_STATUS_CONTROLLER_NAME,\n BridgeStatusControllerState,\n BridgeStatusControllerMessenger\n> {\n #pollingTokensByTxMetaId: Record<SrcTxMetaId, string> = {};\n\n readonly #intentManager: IntentManager;\n\n readonly #quoteStatusManager: QuoteStatusManager;\n\n readonly #clientId: BridgeClientId;\n\n readonly #fetchFn: FetchFunction;\n\n readonly #config: {\n customBridgeApiBaseUrl: string;\n };\n\n readonly #addTransactionBatchFn: typeof TransactionController.prototype.addTransactionBatch;\n\n readonly #trace: TraceCallback;\n\n constructor({\n messenger,\n state,\n clientId,\n clientProduct,\n clientVersion,\n fetchFn,\n addTransactionBatchFn,\n config,\n traceFn,\n onQuoteStatusManagerError,\n isQuoteStatusManagerEnabled,\n }: {\n messenger: BridgeStatusControllerMessenger;\n state?: Partial<BridgeStatusControllerState>;\n clientId: BridgeClientId;\n clientProduct: string;\n clientVersion?: string;\n fetchFn: FetchFunction;\n addTransactionBatchFn: typeof TransactionController.prototype.addTransactionBatch;\n config?: {\n customBridgeApiBaseUrl?: string;\n };\n traceFn?: TraceCallback;\n onQuoteStatusManagerError?: (\n error: QuoteStatusUpdateError | QuoteStatusGetError,\n ) => void;\n isQuoteStatusManagerEnabled?: () => boolean;\n }) {\n super({\n name: BRIDGE_STATUS_CONTROLLER_NAME,\n metadata,\n messenger,\n // Restore the persisted state\n state: {\n ...DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n ...state,\n },\n });\n\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n this.#addTransactionBatchFn = addTransactionBatchFn;\n this.#config = {\n customBridgeApiBaseUrl:\n config?.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n };\n this.#trace = traceFn ?? (((_request, fn) => fn?.()) as TraceCallback);\n this.#intentManager = new IntentManager({\n messenger: this.messenger,\n customBridgeApiBaseUrl: this.#config.customBridgeApiBaseUrl,\n fetchFn: this.#fetchFn,\n });\n this.#quoteStatusManager = new QuoteStatusManager({\n messenger: this.messenger,\n clientId: this.#clientId,\n clientProduct,\n clientVersion,\n apiBaseUrl: this.#config.customBridgeApiBaseUrl,\n initialData: this.state.quoteUpdateStatusStore,\n onPersistUpdates: (updates): void => {\n this.update((draft) => {\n draft.quoteUpdateStatusStore = updates;\n });\n },\n entryTtlMs: QUOTE_STATUS_UPDATE_ENTRY_TTL,\n updateIntervalMs: QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS,\n onError: onQuoteStatusManagerError,\n isEnabled: isQuoteStatusManagerEnabled,\n });\n\n // Register action handlers\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n // Set interval\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.messenger.subscribe<\n 'TransactionController:transactionStatusUpdated',\n {\n historyKey?: string;\n historyItem?: BridgeHistoryItem;\n txMeta: TransactionMeta;\n isApprovalTxMeta: boolean;\n }\n >(\n 'TransactionController:transactionStatusUpdated',\n ({ txMeta, historyKey, historyItem, isApprovalTxMeta }) => {\n if (!txMeta) {\n return;\n }\n const { type, status } = txMeta;\n\n // Allow event publishing if the txMeta is a swap/bridge OR if the\n // corresponding history item exists\n const isSwapOrBridgeTransaction = type && isCrossChainTx(type);\n if (!isSwapOrBridgeTransaction && !historyKey && !historyItem) {\n return;\n }\n\n switch (status) {\n case TransactionStatus.submitted:\n // EVM txs report SUBMITTED here (not via transactionSubmitted) so hash\n // replacements before confirmation still reach the Bridge API.\n if (\n txMeta.hash &&\n txMeta.type &&\n isCrossChainTx(txMeta.type) &&\n !isApprovalTxMeta &&\n historyKey\n ) {\n this.#reportSubmittedOnce(historyKey, txMeta.hash, txMeta.id);\n }\n break;\n case TransactionStatus.confirmed:\n this.#onTransactionConfirmed({\n txMeta,\n historyKey,\n isApprovalTxMeta,\n });\n break;\n case TransactionStatus.failed:\n case TransactionStatus.dropped:\n case TransactionStatus.rejected:\n this.#onTransactionFailed({ txMeta, historyKey, isApprovalTxMeta });\n break;\n default:\n break;\n }\n },\n ({ transactionMeta }) => {\n const entry = getMatchingHistoryEntryForTxMeta(\n this.state.txHistory,\n transactionMeta,\n );\n const approvalEntry = getMatchingHistoryEntryForApprovalTxMeta(\n this.state.txHistory,\n transactionMeta,\n );\n const entryToUse = entry ?? approvalEntry;\n\n return {\n historyKey: entryToUse?.[0],\n historyItem: entryToUse?.[1],\n txMeta: transactionMeta,\n isApprovalTxMeta:\n entryToUse?.[1]?.approvalTxId === transactionMeta.id,\n };\n },\n );\n\n // Seed any missing quote-status entries from persisted history before\n // init(), so init()'s reconciliation loop can finalize quotes whose\n // deferred entry was never created (e.g. the client closed before\n // reportSubmitted ran).\n this.#seedQuoteStatusEntriesFromHistory();\n\n // Replay swap/bridge finalizations that resolved while the client was\n // closed, before resuming polling (which recovers in-flight bridges).\n this.#quoteStatusManager.init();\n\n // If you close the extension, but keep the browser open, the polling continues\n // If you close the browser, the polling stops\n // Check for historyItems that do not have a status of complete and restart polling\n this.#restartPollingForIncompleteHistoryItems();\n }\n\n readonly #onTransactionFailed = ({\n txMeta,\n historyKey,\n isApprovalTxMeta,\n }: {\n txMeta: TransactionMeta;\n historyKey?: string;\n isApprovalTxMeta: boolean;\n }): void => {\n // Check if the history item is already marked as a failure\n const isHistoryItemAlreadyFailed = historyKey\n ? this.state.txHistory[historyKey]?.status.status === StatusTypes.FAILED\n : false;\n\n this.#updateHistoryItem({\n historyKey,\n status: StatusTypes.FAILED,\n txHash: isApprovalTxMeta ? undefined : txMeta.hash,\n completionTime: Date.now(),\n });\n\n if (txMeta.status === TransactionStatus.rejected) {\n return;\n }\n\n // Skip tracking if this is a duplicate failed event for the same history item\n // This can happen if the transaction includes an approval tx that fails\n if (isHistoryItemAlreadyFailed) {\n return;\n }\n\n // Report finalized failure for swap/bridge transactions.\n // Note: TransactionStatus.rejected means the user cancelled signing, so the tx was never broadcast.\n // `hasNestedSwapTransactions` also covers batch/7702 swaps whose type may\n // still read as `batch` rather than `swap`.\n if (\n (txMeta.type && isCrossChainTx(txMeta.type)) ||\n hasNestedSwapTransactions(txMeta)\n ) {\n this.#quoteStatusManager.reportFinalised(txMeta.id, false);\n }\n\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Failed,\n historyKey,\n getEVMTxPropertiesFromTransactionMeta(txMeta),\n );\n };\n\n // Only EVM txs\n readonly #onTransactionConfirmed = ({\n txMeta,\n historyKey,\n isApprovalTxMeta,\n }: {\n txMeta: TransactionMeta;\n historyKey?: string;\n isApprovalTxMeta: boolean;\n }): void => {\n // Return early if the confirmed txMeta is for an approval since we\n // still need to wait for the trade to be confirmed\n if (isApprovalTxMeta) {\n return;\n }\n\n this.#updateHistoryItem({\n historyKey,\n txHash: txMeta.hash,\n });\n\n const isSwap =\n txMeta.type === TransactionType.swap || hasNestedSwapTransactions(txMeta);\n\n if (isSwap) {\n this.#updateHistoryItem({\n historyKey,\n status: StatusTypes.COMPLETE,\n completionTime: Date.now(),\n });\n\n // For EVM intent-based swaps the synthetic tx transitions\n // submitted→confirmed in a single update that carries the CoW\n // settlement hash, so the submitted status handler never has a hash\n // and reportSubmitted is never called. Call it here (before\n // reportFinalised) so the deferred-queue entry is created.\n const historyItem = historyKey\n ? this.state.txHistory[historyKey]\n : undefined;\n if (\n historyKey &&\n historyItem &&\n txMeta.hash &&\n !isNonEvmChainId(historyItem.quote.srcChainId)\n ) {\n this.#reportSubmittedOnce(historyKey, txMeta.hash, txMeta.id);\n }\n this.#quoteStatusManager.reportFinalised(txMeta.id, true);\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Completed,\n historyKey,\n );\n } else if (historyKey) {\n this.#startPollingForTxId(historyKey);\n }\n };\n\n /**\n * Reports the SUBMITTED quote status for non-EVM transactions.\n *\n * EVM transactions report SUBMITTED via the\n * `TransactionController:transactionStatusUpdated` subscription, which also\n * picks up hash replacements (speed-up/cancel) and the late hash assignment\n * of smart/batch transactions. Non-EVM transactions (Solana, Bitcoin, Tron)\n * are submitted through Snaps and never emit TransactionController lifecycle\n * events, so they are reported here once the history item exists and the\n * source tx hash is known.\n *\n * @param historyKey - The key of the history item in `txHistory`\n * @param txMeta - The submitted trade transaction's id and hash\n * @param txMeta.id - The transaction meta id, used for finalization matching\n * @param txMeta.hash - The source chain transaction hash\n */\n readonly #reportSubmittedForNonEvmTx = (\n historyKey: string,\n txMeta?: { id?: string; hash?: string },\n ): void => {\n if (!txMeta?.id || !txMeta.hash) {\n return;\n }\n const historyItem = this.state.txHistory[historyKey];\n if (!historyItem || !isNonEvmChainId(historyItem.quote.srcChainId)) {\n return;\n }\n this.#reportSubmittedOnce(historyKey, txMeta.hash, txMeta.id);\n };\n\n /**\n * Reports a SUBMITTED quote status update exactly once per source tx hash.\n *\n * SUBMITTED can be triggered from several code paths (submission, the first\n * poll where the hash is known, and the final-status branch) and the poll\n * path runs on every interval.\n *\n * @param historyKey - The key of the history item in `txHistory`\n * @param srcTxHash - The source chain transaction hash\n * @param txMetaId - The transaction meta id, used for finalization matching\n */\n readonly #reportSubmittedOnce = (\n historyKey: string,\n srcTxHash: string,\n txMetaId: string,\n ): void => {\n const historyItem = this.state.txHistory[historyKey];\n if (!historyItem?.quoteId) {\n return;\n }\n // `reportedSubmittedTxHash` is set once `reportSubmitted` is called.\n // This avoids processing multiple `eportSubmitted` for the\n // same swap/bridge.\n if (historyItem.reportedSubmittedTxHash === srcTxHash) {\n return;\n }\n this.#quoteStatusManager.reportSubmitted(\n historyItem.quoteId,\n srcTxHash,\n txMetaId,\n );\n this.update((state) => {\n const item = state.txHistory[historyKey];\n if (item) {\n item.reportedSubmittedTxHash = srcTxHash;\n }\n });\n };\n\n resetState = (): void => {\n this.#quoteStatusManager.destroy();\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n state.quoteUpdateStatusStore =\n DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.quoteUpdateStatusStore;\n });\n };\n\n wipeBridgeStatus = ({\n address,\n ignoreNetwork,\n }: {\n address: string;\n ignoreNetwork: boolean;\n }): void => {\n // Wipe all networks for this address\n if (ignoreNetwork) {\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n });\n } else {\n const selectedChainId = getSelectedChainId(this.messenger);\n\n this.#wipeBridgeStatusByChainId(address, selectedChainId);\n }\n };\n\n /**\n * Resets the attempts counter for a bridge transaction history item\n * and restarts polling if it was previously stopped due to max attempts\n *\n * @param identifier - Object containing either txMetaId or txHash to identify the history item\n * @param identifier.txMetaId - The transaction meta ID\n * @param identifier.txHash - The transaction hash\n */\n restartPollingForFailedAttempts = (identifier: {\n txMetaId?: string;\n txHash?: string;\n }): void => {\n const { txMetaId, txHash } = identifier;\n\n if (!txMetaId && !txHash) {\n throw new Error('Either txMetaId or txHash must be provided');\n }\n\n // Find the history item by txMetaId or txHash\n let targetTxMetaId: string | undefined;\n\n if (txMetaId) {\n // Direct lookup by txMetaId\n if (this.state.txHistory[txMetaId]) {\n targetTxMetaId = txMetaId;\n }\n } else if (txHash) {\n // Search by txHash in status.srcChain.txHash\n targetTxMetaId = Object.keys(this.state.txHistory).find(\n (id) => this.state.txHistory[id].status.srcChain.txHash === txHash,\n );\n }\n\n if (!targetTxMetaId) {\n throw new Error(\n `No bridge transaction history found for ${\n txMetaId ? `txMetaId: ${txMetaId}` : `txHash: ${txHash}`\n }`,\n );\n }\n\n const historyItem = this.state.txHistory[targetTxMetaId];\n\n // Capture attempts count before resetting for metrics\n const previousAttempts = historyItem.attempts?.counter ?? 0;\n\n // Reset the attempts counter\n this.update((state) => {\n if (targetTxMetaId) {\n state.txHistory[targetTxMetaId].attempts = undefined;\n }\n });\n\n // Restart polling if it was stopped and this tx still needs status updates\n if (shouldPollHistoryItem(historyItem)) {\n // Check if polling was stopped (no active polling token)\n const existingPollingToken =\n this.#pollingTokensByTxMetaId[targetTxMetaId];\n\n if (!existingPollingToken) {\n // Restart polling\n this.#startPollingForTxId(targetTxMetaId);\n\n // Track polling manually restarted event\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.PollingStatusUpdated,\n targetTxMetaId,\n {\n polling_status: PollingStatus.ManuallyRestarted,\n retry_attempts: previousAttempts,\n },\n );\n }\n }\n };\n\n /**\n * Gets a bridge history item from the history by its transaction meta ID\n *\n * @param txMetaId - The transaction meta ID to look up\n * @returns The bridge history item if found, undefined otherwise\n */\n getBridgeHistoryItemByTxMetaId = (\n txMetaId: string,\n ): BridgeHistoryItem | undefined => {\n return this.state.txHistory[txMetaId];\n };\n\n /**\n * Seeds missing quote-status entries from persisted history on startup.\n *\n * The deferred quote-status entry (keyed by `${quoteId}:${srcTxHash}`) is only\n * created when `reportSubmitted` runs. If the client closes after a swap/bridge\n * is submitted but before that happens, the entry is never created and\n * `QuoteStatusManager.init()` has nothing to reconcile. The persisted history\n * item carries the `quoteId`, source tx hash, and `txMetaId` needed to rebuild\n * the entry, so we replay `reportSubmitted` here (idempotent via\n * `#reportSubmittedOnce`) before `init()` runs.\n */\n readonly #seedQuoteStatusEntriesFromHistory = (): void => {\n if (!this.#quoteStatusManager.enabled) {\n // Skip seeding to prevent `#reportSubmittedOnce` from persisting\n // `reportedSubmittedTxHash` so recent bridge history cannot be marked as\n // already reported with no store entry or backend update.\n return;\n }\n\n for (const [historyKey, historyItem] of Object.entries(\n this.state.txHistory,\n )) {\n const { quoteId, txMetaId } = historyItem;\n if (!quoteId || !txMetaId) {\n continue;\n }\n\n // Skip items older than the backfill window: the backend would reject\n // a status report for a quote that old, so there is no point creating\n // an entry or making a request.\n if (\n Date.now() - historyItem.startTime >\n QUOTE_STATUS_BACKFILL_WINDOW_MS\n ) {\n continue;\n }\n\n // Prefer the history hash; fall back to the tx hash (covers STX swaps\n // confirmed while closed, where the history hash was never written).\n const srcTxHash =\n historyItem.status.srcChain.txHash ??\n getTransactionMetaById(this.messenger, txMetaId)?.hash;\n if (!srcTxHash) {\n continue;\n }\n\n // Call `reportSubmittedOnce` for each history item that satisfies\n // the above criteria. The method will then take care the rest\n // (ie. if it actually needs to be reported or not because it already has been).\n this.#reportSubmittedOnce(historyKey, srcTxHash, txMetaId);\n }\n };\n\n /**\n * Restart polling for txs that are not in a final state\n * This is called during initialization\n */\n readonly #restartPollingForIncompleteHistoryItems = (): void => {\n // Check for historyItems that do not have a status of complete and restart polling\n const { txHistory } = this.state;\n const historyItems = Object.entries(txHistory);\n const incompleteHistoryItems = historyItems\n .filter(\n ([_, historyItem]) =>\n historyItem.status.status === StatusTypes.PENDING ||\n historyItem.status.status === StatusTypes.UNKNOWN,\n )\n // Only poll items with txMetaId (post-submission items)\n .filter(([_, historyItem]: [string, BridgeHistoryItem]) => {\n if (!historyItem.txMetaId) {\n return false;\n }\n // Check if we are already polling this tx, if so, skip restarting polling for that\n const pollingToken =\n this.#pollingTokensByTxMetaId[historyItem.txMetaId];\n return !pollingToken;\n })\n // Only restart polling for items that still require status updates\n .filter(([_, historyItem]: [string, BridgeHistoryItem]) => {\n return shouldPollHistoryItem(historyItem);\n });\n\n incompleteHistoryItems.forEach(\n ([historyKey, historyItem]: [string, BridgeHistoryItem]) => {\n const shouldSkipFetch = shouldSkipFetchDueToFetchFailures(\n historyItem.attempts,\n );\n if (shouldSkipFetch) {\n return;\n }\n\n // We manually call startPolling() here rather than go through startPollingForBridgeTxStatus()\n // because we don't want to overwrite the existing historyItem in state\n this.#startPollingForTxId(historyKey);\n },\n );\n };\n\n readonly #addTxToHistory = (\n historyKey: string,\n ...args: Parameters<typeof getInitialHistoryItem>\n ): string => {\n const txHistoryItem = getInitialHistoryItem(...args);\n this.update((state) => {\n state.txHistory[historyKey] = txHistoryItem;\n });\n return historyKey;\n };\n\n /**\n * Rekeys a history item from actionId to txMeta.id after successful submission.\n * Also updates txMetaId and srcTxHash which weren't available pre-submission.\n *\n * @param oldKey - The temporary key to use for the history item, usually the actionId\n * @param newKey - The new key to use, typcally the txmeta.id\n * @param txMeta - The transaction meta from the successful submission\n * @param txMeta.id - The transaction meta id to use as the new key\n * @param txMeta.hash - The transaction hash to set on the history item\n */\n readonly #rekeyHistoryItem = (\n oldKey: string,\n newKey: string,\n txMeta: { id: string; hash?: string },\n ): void => {\n this.update((state) => {\n rekeyHistoryItemInState(state, oldKey, newKey, txMeta);\n });\n };\n\n readonly #startPollingForTxId = (txId: string): void => {\n // If we are already polling for this tx, stop polling for it before restarting\n const existingPollingToken = this.#pollingTokensByTxMetaId[txId];\n if (existingPollingToken) {\n this.stopPollingByPollingToken(existingPollingToken);\n }\n\n const txHistoryItem = this.state.txHistory[txId];\n if (txHistoryItem && shouldPollHistoryItem(txHistoryItem)) {\n this.#pollingTokensByTxMetaId[txId] = this.startPolling({\n bridgeTxMetaId: txId,\n });\n }\n };\n\n /**\n * @deprecated For EVM/Solana swap/bridge txs we add tx to history in submitTx()\n * For Solana swap/bridge we start polling in submitTx()\n * For EVM bridge we listen for 'TransactionController:transactionConfirmed' and start polling there\n * No clients currently call this, safe to remove in future versions\n *\n * Adds tx to history and starts polling for the bridge tx status\n *\n * @param txHistoryMeta - The parameters for creating the history item\n */\n startPollingForBridgeTxStatus = (\n txHistoryMeta: StartPollingForBridgeTxStatusArgsSerialized,\n ): void => {\n const { bridgeTxMeta } = txHistoryMeta;\n\n if (!bridgeTxMeta?.id) {\n throw new Error(\n 'Cannot start polling: bridgeTxMeta.id is required for polling',\n );\n }\n\n const historyKey = this.#addTxToHistory(bridgeTxMeta.id, txHistoryMeta);\n this.#startPollingForTxId(historyKey);\n };\n\n // This will be called after you call this.startPolling()\n // The args passed in are the args you passed in to startPolling()\n _executePoll = async (\n pollingInput: BridgeStatusPollingInput,\n ): Promise<void> => {\n await this.#fetchBridgeTxStatus(pollingInput);\n };\n\n /**\n * Handles the failure to fetch the bridge tx status\n * We eventually stop polling for the tx if we fail too many times\n * Failures (500 errors) can be due to:\n * - The srcTxHash not being available immediately for STX\n * - The srcTxHash being invalid for the chain. This case will never resolve so we stop polling for it to avoid hammering the Bridge API forever.\n *\n * @param bridgeTxMetaId - The txMetaId of the bridge tx\n */\n readonly #handleFetchFailure = (bridgeTxMetaId: string): void => {\n const { attempts } = this.state.txHistory[bridgeTxMetaId];\n\n const newAttempts = attempts\n ? {\n counter: attempts.counter + 1,\n lastAttemptTime: Date.now(),\n }\n : {\n counter: 1,\n lastAttemptTime: Date.now(),\n };\n\n // If we've failed too many times, stop polling for the tx\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n if (newAttempts.counter >= MAX_ATTEMPTS && pollingToken) {\n this.stopPollingByPollingToken(pollingToken);\n delete this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n // Track max polling reached event\n const historyItem = this.state.txHistory[bridgeTxMetaId];\n if (historyItem) {\n // Track polling status updated event\n this.#trackPollingStatusUpdatedEvent(\n bridgeTxMetaId,\n PollingStatus.MaxPollingReached,\n );\n }\n }\n\n // Update the attempts counter\n this.#updateHistoryItem({\n historyKey: bridgeTxMetaId,\n attempts: newAttempts,\n });\n };\n\n /**\n * Checks if the history item should be preserved so its status can be fetched.\n *\n * @param bridgeTxMetaId - The txMetaId of the bridge tx\n */\n readonly #handleOldHistoryItem = async (\n bridgeTxMetaId: string,\n ): Promise<void> => {\n // Continue polling on next restart if the history item is valid\n if (\n this.state.txHistory[bridgeTxMetaId] &&\n (await shouldWaitForFinalBridgeStatus(\n this.messenger,\n this.state.txHistory[bridgeTxMetaId],\n ))\n ) {\n return;\n }\n\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n // Track polling status updated event\n this.#trackPollingStatusUpdatedEvent(\n bridgeTxMetaId,\n PollingStatus.InvalidTransactionHash,\n );\n\n // If we've failed too many times, stop polling for the tx\n if (pollingToken) {\n this.stopPollingByPollingToken(pollingToken);\n delete this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n }\n\n // Delete the history item so polling doesn't start over on the next restart.\n // Report finalization as a failure here, this is the only place that\n // permanently ends polling, so it's the correct and non-duplicative point\n // to emit the final status.\n this.#quoteStatusManager.reportFinalised(bridgeTxMetaId, false);\n this.#deleteHistoryItem(bridgeTxMetaId);\n };\n\n readonly #fetchBridgeTxStatus = async ({\n bridgeTxMetaId,\n }: FetchBridgeTxStatusArgs): Promise<void> => {\n // 1. Check for history item\n\n const { txHistory } = this.state;\n const historyItem = txHistory[bridgeTxMetaId];\n if (!historyItem) {\n return;\n }\n\n // 2. Check for previous failures\n\n if (shouldSkipFetchDueToFetchFailures(historyItem.attempts)) {\n return;\n }\n\n // 3. Fetch transaction status\n\n try {\n let status: BridgeHistoryItem['status'];\n let validationFailures: string[] = [];\n\n if (historyItem.quote.intent) {\n const intentTxStatus =\n await this.#intentManager.getIntentTransactionStatus(\n bridgeTxMetaId,\n historyItem.quote.srcChainId,\n historyItem.quote.intent.protocol,\n this.#clientId,\n historyItem.status.srcChain.txHash,\n );\n\n if (\n intentTxStatus?.bridgeStatus === null ||\n intentTxStatus?.bridgeStatus === undefined\n ) {\n return;\n }\n status = intentTxStatus.bridgeStatus.status;\n\n // Report SUBMITTED as soon as the intent's source/settlement hash is\n // known at poll time, before the order reaches a terminal status.\n const intentSrcTxHash = status.srcChain.txHash;\n if (intentSrcTxHash) {\n this.#reportSubmittedOnce(\n bridgeTxMetaId,\n intentSrcTxHash,\n bridgeTxMetaId,\n );\n }\n } else {\n // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx\n // Oddly mostly happens on Optimism, never on Arbitrum. By the 2nd fetch, the Bridge API responds properly.\n // Also srcTxHash may not be available immediately for STX, so we don't want to fetch in those cases\n const srcTxHash = this.#setAndGetSrcTxHash(bridgeTxMetaId);\n\n if (!srcTxHash) {\n return;\n }\n\n // Report SUBMITTED as soon as a srcTxHash is known at poll time, for\n // every chain not just non-EVM sources.\n this.#reportSubmittedOnce(bridgeTxMetaId, srcTxHash, bridgeTxMetaId);\n\n const statusRequest = getStatusRequestWithSrcTxHash(\n historyItem.quote,\n srcTxHash,\n );\n const response =\n (historyItem.quoteId\n ? await fetchBridgeQuoteStatus(\n this.#quoteStatusManager,\n historyItem.quoteId,\n )\n : null) ??\n (await fetchBridgeTxStatus(\n statusRequest,\n this.#clientId,\n await getJwt(this.messenger),\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl,\n ));\n status = response.status;\n validationFailures = response.validationFailures;\n }\n\n if (validationFailures.length > 0) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.StatusValidationFailed,\n bridgeTxMetaId,\n {\n failures: validationFailures,\n refresh_count: historyItem.attempts?.counter ?? 0,\n },\n );\n throw new Error(\n `Bridge status validation failed: ${validationFailures.join(', ')}`,\n );\n }\n\n // 4. Create bridge history item\n\n const newBridgeHistoryItem = {\n ...historyItem,\n status,\n completionTime:\n status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED\n ? Date.now()\n : undefined, // TODO make this more accurate by looking up dest txHash block time\n attempts: undefined,\n };\n\n // No need to purge these on network change or account change, TransactionController does not purge either.\n // TODO In theory we can skip checking status if it's not the current account/network\n // we need to keep track of the account that this is associated with as well so that we don't show it in Activity list for other accounts\n // First stab at this will not stop polling when you are on a different account\n this.update((state) => {\n state.txHistory[bridgeTxMetaId] = newBridgeHistoryItem;\n });\n\n if (historyItem.quote.intent) {\n this.#intentManager.syncTransactionFromIntentStatus(\n bridgeTxMetaId,\n historyItem,\n );\n }\n\n // 5. After effects\n\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n const isFinalStatus =\n status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED;\n\n if (isFinalStatus) {\n if (pollingToken) {\n this.stopPollingByPollingToken(pollingToken);\n delete this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n }\n\n // Ensure a deferred entry exists before reportFinalised is called.\n const settlementTxHash = newBridgeHistoryItem.status.srcChain.txHash;\n if (settlementTxHash) {\n this.#reportSubmittedOnce(\n bridgeTxMetaId,\n settlementTxHash,\n bridgeTxMetaId,\n );\n }\n\n this.#quoteStatusManager.reportFinalised(\n bridgeTxMetaId,\n status.status === StatusTypes.COMPLETE,\n );\n\n if (status.status === StatusTypes.COMPLETE) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Completed,\n bridgeTxMetaId,\n );\n this.messenger.publish(\n 'BridgeStatusController:destinationTransactionCompleted',\n historyItem.quote.destAsset.assetId,\n );\n }\n if (status.status === StatusTypes.FAILED) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Failed,\n bridgeTxMetaId,\n );\n }\n }\n } catch (error) {\n console.warn('Failed to fetch bridge tx status', error);\n this.#handleFetchFailure(bridgeTxMetaId);\n } finally {\n await this.#handleOldHistoryItem(bridgeTxMetaId);\n }\n };\n\n /**\n * Returns the srcTxHash for a non-STX EVM tx, the hash from the bridge status api,\n * or the local hash from the TransactionController if the tx is in a finalized state\n *\n * @param bridgeTxMetaId - The bridge tx meta id\n * @returns The srcTxHash\n */\n readonly #setAndGetSrcTxHash = (\n bridgeTxMetaId: string,\n ): string | undefined => {\n const { txHistory } = this.state;\n // Prefer the srcTxHash from bridgeStatusState so we don't have to look up in TransactionController\n // But it is possible to have bridgeHistoryItem in state without the srcTxHash yet when it is an STX\n const srcTxHash = txHistory[bridgeTxMetaId].status.srcChain.txHash;\n\n if (\n srcTxHash ||\n isNonEvmChainId(txHistory[bridgeTxMetaId].quote.srcChainId)\n ) {\n return srcTxHash;\n }\n\n // Update history with TransactionController's hash if it has been updated\n const txMeta = getTransactionMetaById(this.messenger, bridgeTxMetaId);\n\n if (!txMeta) {\n return undefined;\n }\n\n // Wait for finalized status before updating the history item\n const localTxHash = [\n TransactionStatus.confirmed,\n TransactionStatus.dropped,\n TransactionStatus.rejected,\n TransactionStatus.failed,\n ].includes(txMeta.status)\n ? txMeta.hash\n : undefined;\n this.#updateHistoryItem({\n historyKey: bridgeTxMetaId,\n txHash: localTxHash,\n });\n\n return localTxHash;\n };\n\n readonly #updateHistoryItem = ({\n historyKey,\n status,\n txHash,\n attempts,\n completionTime,\n }: {\n historyKey?: string;\n status?: StatusTypes;\n txHash?: string;\n attempts?: BridgeHistoryItem['attempts'];\n completionTime?: BridgeHistoryItem['completionTime'];\n }): void => {\n if (!historyKey) {\n return;\n }\n this.update((currentState) => {\n if (status) {\n currentState.txHistory[historyKey].status.status = status;\n }\n if (txHash) {\n currentState.txHistory[historyKey].status.srcChain.txHash = txHash;\n }\n if (attempts) {\n currentState.txHistory[historyKey].attempts = attempts;\n }\n if (completionTime) {\n currentState.txHistory[historyKey].completionTime = completionTime;\n }\n });\n };\n\n readonly #deleteHistoryItem = (historyKey: string): void => {\n this.update((currentState) => {\n delete currentState.txHistory[historyKey];\n });\n };\n\n // Wipes the bridge status for the given address and chainId\n // Will match only source chainId to the selectedChainId\n readonly #wipeBridgeStatusByChainId = (\n address: string,\n selectedChainId: Hex,\n ): void => {\n const sourceTxMetaIdsToDelete = Object.keys(this.state.txHistory).filter(\n (txMetaId) => {\n const bridgeHistoryItem = this.state.txHistory[txMetaId];\n\n const hexSourceChainId = numberToHex(\n bridgeHistoryItem.quote.srcChainId,\n );\n\n return (\n bridgeHistoryItem.account === address &&\n hexSourceChainId === selectedChainId\n );\n },\n );\n\n sourceTxMetaIdsToDelete.forEach((sourceTxMetaId) => {\n const pollingToken = this.#pollingTokensByTxMetaId[sourceTxMetaId];\n\n if (pollingToken) {\n this.stopPollingByPollingToken(\n this.#pollingTokensByTxMetaId[sourceTxMetaId],\n );\n delete this.#pollingTokensByTxMetaId[sourceTxMetaId];\n }\n });\n\n this.update((state) => {\n state.txHistory = sourceTxMetaIdsToDelete.reduce(\n (acc, sourceTxMetaId) => {\n delete acc[sourceTxMetaId];\n return acc;\n },\n state.txHistory,\n );\n });\n };\n\n /**\n * ******************************************************\n * TX SUBMISSION HANDLING\n *******************************************************\n */\n\n readonly #executeSubmitStrategy = async (\n params: SubmitStrategyParams<Trade>,\n sharedHistoryItemProperties: {\n startTime: number;\n location: MetaMetricsSwapsEventSource;\n abTests?: Record<string, string>;\n activeAbTests?: { key: string; value: string }[];\n tokenSecurityTypeDestination?: string | null;\n inputPrimaryDenomination?: InputPrimaryDenomination;\n },\n ): Promise<TransactionMeta> => {\n let tradeTxMeta!: TransactionMeta;\n\n const steps = executeSubmitStrategy(params);\n\n // Each submission strategy determines when to execute step, which means these actions can happen in any order\n for await (const { type, payload } of steps) {\n try {\n switch (type) {\n case SubmitStep.RekeyHistoryItem:\n this.#rekeyHistoryItem(\n payload.oldHistoryKey,\n payload.newHistoryKey,\n payload.tradeMeta,\n );\n // Report SUBMITTED as soon as the trade hash is known at submission\n // time, instead of waiting for the delayed transactionStatusUpdated\n // (submitted) event.\n if (payload.tradeMeta.hash) {\n this.#reportSubmittedOnce(\n payload.newHistoryKey,\n payload.tradeMeta.hash,\n payload.tradeMeta.id,\n );\n }\n break;\n\n case SubmitStep.UpdateBatchTransactions:\n updateTransactionsInBatch({\n messenger: this.messenger,\n allTradesWithMetadata: payload.quoteAndTxMetas,\n });\n break;\n\n case SubmitStep.SetTradeMeta:\n tradeTxMeta = payload.tradeMeta;\n break;\n\n case SubmitStep.AddHistoryItem:\n this.#addTxToHistory(payload.historyKey, {\n ...payload,\n ...sharedHistoryItemProperties,\n quoteResponse: payload.quoteResponse,\n accountAddress: params.selectedAccount.address,\n isStxEnabled: params.isStxEnabled,\n slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request\n });\n this.#reportSubmittedForNonEvmTx(\n payload.historyKey,\n payload.bridgeTxMeta,\n );\n break;\n\n case SubmitStep.StartPolling:\n this.#startPollingForTxId(payload.historyKey);\n break;\n\n case SubmitStep.PublishCompletedEvent:\n this.#quoteStatusManager.reportFinalised(payload.historyKey, true);\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Completed,\n payload.historyKey,\n );\n break;\n\n /* c8 ignore start */\n default:\n throw new Error(`Unknown submit step type: ${String(type)}`);\n /* c8 ignore end */\n }\n } catch (error) {\n console.error(\n 'Failed to add to bridge history and start polling.',\n error,\n );\n }\n }\n\n return tradeTxMeta;\n };\n\n /**\n * Submits a cross-chain swap transaction\n *\n * @param accountAddress - The address of the account to submit the transaction for\n * @param maybeQuoteResponses - A single quote response or an array of quote responses\n * @param isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension\n * @param quotesReceivedContext - The context for the QuotesReceived event\n * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore)\n * @param abTests - Legacy A/B test context for `ab_tests` (backward compatibility)\n * @param activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.\n * @param tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.\n * @param batchSellTrades - Contains transaction data for the quotes, provided by the obtainGaslessBatch API\n * @param inputPrimaryDenomination - The denomination shown as the primary source amount input at submission time.\n * @returns The transaction meta\n * @throws An error if transaction submission fails before it gets published\n */\n submitTx = async (\n accountAddress: string,\n maybeQuoteResponses:\n | (QuoteResponse<Trade, Trade> & QuoteMetadata)\n | (QuoteResponse<Trade, Trade> & QuoteMetadata)[],\n isStxEnabled: boolean,\n quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived],\n location: MetaMetricsSwapsEventSource = MetaMetricsSwapsEventSource.Unknown,\n abTests?: Record<string, string>,\n activeAbTests?: { key: string; value: string }[],\n tokenSecurityTypeDestination?: string | null,\n batchSellTrades?: BatchSellTradesResponse | null,\n inputPrimaryDenomination?: InputPrimaryDenomination,\n ): Promise<TransactionMeta> => {\n /**\n * If there are multiple quote responses, we assume that they all originate from the same src chain\n * and the same account. In this case its safe to use the first quote response's properties for\n * metrics and other pre-submission logic\n */\n const quoteResponses = Array.isArray(maybeQuoteResponses)\n ? maybeQuoteResponses\n : [maybeQuoteResponses];\n const quoteResponse = quoteResponses[0];\n\n const { quote } = quoteResponse;\n const startTime = Date.now();\n\n stopPollingForQuotes(this.messenger, quotesReceivedContext);\n\n const selectedAccount = getAccountByAddress(this.messenger, accountAddress);\n if (!selectedAccount) {\n throw new Error(\n 'Failed to submit cross-chain swap transaction: undefined multichain account',\n );\n }\n const accountHardwareType = getAccountHardwareType(selectedAccount);\n\n /**\n * For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval.\n * Extension does not have this issue\n */\n const requireApproval =\n this.#clientId === BridgeClientId.MOBILE && accountHardwareType !== null;\n const isBridgeTx = isCrossChain(quote.srcChainId, quote.destChainId);\n\n const batchId = quoteResponses.some(\n ({ featureId: quoteFeatureId }) =>\n quoteFeatureId === FeatureId.BATCH_SELL,\n )\n ? generateBatchId()\n : undefined;\n\n const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(\n quoteResponse,\n isStxEnabled,\n accountHardwareType,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n batchSellTrades,\n batchId,\n );\n\n try {\n // Emit Submitted event after submit button is clicked\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Submitted,\n undefined,\n {\n ...preConfirmationProperties,\n ...(inputPrimaryDenomination && {\n input_primary_denomination: inputPrimaryDenomination,\n }),\n },\n );\n\n /**\n * Check if the account is an EIP-7702 delegated account.\n * Delegated accounts only allow 1 in-flight tx, so approve + swap\n * must be batched into a single transaction\n */\n const isDelegatedAccount = isNonEvmChainId(quote.srcChainId)\n ? false\n : await checkIsDelegatedAccount(\n this.messenger,\n selectedAccount.address as Hex,\n [formatChainIdToHex(quote.srcChainId)],\n );\n\n const strategyParams: SubmitStrategyParams<Trade> = {\n messenger: this.messenger,\n quoteResponses,\n batchSellTrades,\n isStxEnabled,\n isBridgeTx,\n isDelegatedAccount,\n selectedAccount,\n requireApproval,\n clientId: this.#clientId,\n bridgeApiBaseUrl: this.#config.customBridgeApiBaseUrl,\n addTransactionBatchFn: this.#addTransactionBatchFn,\n fetchFn: this.#fetchFn,\n traceFn: this.#trace,\n batchId,\n };\n\n return await this.#trace(\n getTraceParams(quoteResponse, isStxEnabled),\n async () =>\n await this.#executeSubmitStrategy(strategyParams, {\n startTime,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n inputPrimaryDenomination,\n }),\n );\n } catch (error) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Failed,\n undefined,\n {\n error_message: (error as Error)?.message,\n ...preConfirmationProperties,\n },\n );\n throw error;\n }\n };\n\n /**\n * Submits an intent order and creates a synthetic history entry for UX.\n * The EIP-712 payload is always signed inside this controller via KeyringController.\n *\n * @param params - Object containing intent submission parameters\n * @param params.quoteResponse - Quote carrying intent data\n * @param params.accountAddress - The EOA submitting the order\n * @param params.location - The entry point from which the user initiated the swap or bridge\n * @param params.abTests - Legacy A/B test context for `ab_tests` (backward compatibility)\n * @param params.activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.\n * @param params.tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.\n * @param params.inputPrimaryDenomination - The denomination shown as the primary source amount input at submission time.\n * @param params.isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension\n * @param params.quotesReceivedContext - The context for the QuotesReceived event\n * @returns A lightweight TransactionMeta-like object for history linking\n * @throws An error if intent or transaction submission fails before they get published\n */\n submitIntent = async (params: {\n quoteResponse: QuoteResponse<Trade, Trade> & QuoteMetadata;\n accountAddress: string;\n location?: MetaMetricsSwapsEventSource;\n abTests?: Record<string, string>;\n activeAbTests?: { key: string; value: string }[];\n tokenSecurityTypeDestination?: string | null;\n inputPrimaryDenomination?: InputPrimaryDenomination;\n isStxEnabled?: boolean;\n quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived];\n }): Promise<TransactionMeta> => {\n const {\n quoteResponse,\n accountAddress,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n inputPrimaryDenomination,\n isStxEnabled = false,\n quotesReceivedContext,\n } = params;\n\n // TODO add metrics context\n return await this.submitTx(\n accountAddress,\n quoteResponse,\n isStxEnabled,\n quotesReceivedContext,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n undefined,\n inputPrimaryDenomination,\n );\n };\n\n submitBatchSell = async (params: {\n quoteResponses: ((QuoteResponse<Trade, Trade> & QuoteMetadata) | null)[];\n accountAddress: string;\n location?: MetaMetricsSwapsEventSource;\n abTests?: Record<string, string>;\n activeAbTests?: { key: string; value: string }[];\n isStxEnabled?: boolean;\n quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived];\n tokenSecurityTypeDestination?: string | null;\n }): Promise<TransactionMeta> => {\n /**\n * Retrieve the batch sell trades from the BridgeController's state to ensure we submit\n * the original response data from the bridge-api\n */\n const batchSellTrades = getBatchSellTrades(this.messenger);\n return await this.submitTx(\n params.accountAddress,\n params.quoteResponses.filter(\n (\n quoteResponse,\n ): quoteResponse is QuoteResponse<Trade, Trade> & QuoteMetadata =>\n quoteResponse !== null,\n ),\n params.isStxEnabled ?? false,\n params.quotesReceivedContext,\n params.location,\n params.abTests,\n params.activeAbTests,\n params.tokenSecurityTypeDestination,\n batchSellTrades,\n );\n };\n\n readonly #trackPollingStatusUpdatedEvent = (\n historyKey: string,\n pollingStatus: PollingStatus,\n ): void => {\n // Track polling status updated event\n const historyItem = this.state.txHistory[historyKey];\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.PollingStatusUpdated,\n historyKey,\n {\n polling_status: pollingStatus,\n retry_attempts: historyItem.attempts?.counter ?? 0,\n },\n );\n };\n\n /**\n * Tracks post-submission events for a cross-chain swap based on the history item\n *\n * @param eventName - The name of the event to track\n * @param txHistoryKey - The txMetaId, actionId or intentUid of the history item to track the event for\n * @param eventProperties - The properties for the event\n */\n readonly #trackUnifiedSwapBridgeEvent = <\n EventName extends\n | typeof UnifiedSwapBridgeEventName.Submitted\n | typeof UnifiedSwapBridgeEventName.Failed\n | typeof UnifiedSwapBridgeEventName.Completed\n | typeof UnifiedSwapBridgeEventName.StatusValidationFailed\n | typeof UnifiedSwapBridgeEventName.PollingStatusUpdated,\n EventProperties extends Omit<\n RequiredEventContextFromClient[EventName],\n 'feature_id'\n > & {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n feature_id?: FeatureId;\n },\n >(\n eventName: EventName,\n txHistoryKey?: string,\n eventProperties?: EventProperties,\n ): void => {\n const historyItem: BridgeHistoryItem | undefined = txHistoryKey\n ? this.state.txHistory[txHistoryKey]\n : undefined;\n\n const featureId =\n eventProperties?.feature_id ??\n historyItem?.featureId ??\n FeatureId.UNIFIED_SWAP_BRIDGE;\n\n if (\n !(\n ALLOWED_FEATURE_IDS_FOR_STATUS_EVENTS.includes(featureId) ||\n eventName === UnifiedSwapBridgeEventName.StatusValidationFailed\n )\n ) {\n return;\n }\n\n // Legacy/new metrics fields are intentionally kept independent during migration.\n const historyAbTests = txHistoryKey\n ? this.state.txHistory?.[txHistoryKey]?.abTests\n : undefined;\n const historyActiveAbTests = txHistoryKey\n ? this.state.txHistory?.[txHistoryKey]?.activeAbTests\n : undefined;\n const resolvedAbTests = eventProperties?.ab_tests ?? historyAbTests;\n const resolvedActiveAbTests =\n eventProperties?.active_ab_tests ?? historyActiveAbTests;\n\n const location =\n historyItem?.location ??\n eventProperties?.location ??\n MetaMetricsSwapsEventSource.Unknown;\n\n const baseProperties = {\n action_type: MetricsActionType.SWAPBRIDGE_V1,\n feature_id: featureId ?? FeatureId.UNIFIED_SWAP_BRIDGE,\n ...(historyItem?.batchId ? { batch_id: historyItem.batchId } : {}),\n ...(eventProperties ?? {}),\n location,\n ...(resolvedAbTests &&\n Object.keys(resolvedAbTests).length > 0 && {\n ab_tests: resolvedAbTests,\n }),\n ...(resolvedActiveAbTests &&\n resolvedActiveAbTests.length > 0 && {\n active_ab_tests: resolvedActiveAbTests,\n }),\n };\n\n // This will publish events for PERPS dropped tx failures as well\n if (!historyItem) {\n trackMetricsEvent({\n messenger: this.messenger,\n eventName,\n properties: baseProperties,\n });\n return;\n }\n\n const { approvalTxId, quote } = historyItem;\n const requestParamProperties = getRequestParamFromHistory(historyItem);\n\n if (eventName === UnifiedSwapBridgeEventName.StatusValidationFailed) {\n trackMetricsEvent({\n messenger: this.messenger,\n eventName,\n properties: {\n ...baseProperties,\n chain_id_source: requestParamProperties.chain_id_source,\n chain_id_destination: requestParamProperties.chain_id_destination,\n token_address_source: requestParamProperties.token_address_source,\n token_address_destination:\n requestParamProperties.token_address_destination,\n token_security_type_destination:\n requestParamProperties.token_security_type_destination,\n refresh_count: historyItem.attempts?.counter ?? 0,\n },\n });\n return;\n }\n\n const selectedAccount = getAccountByAddress(\n this.messenger,\n historyItem.account,\n );\n\n const transactions = getTransactions(this.messenger);\n const txMeta = transactions.find(\n (tx: TransactionMeta) => tx.id === txHistoryKey,\n );\n const approvalTxMeta = transactions.find(\n (tx: TransactionMeta) => tx.id === approvalTxId,\n );\n\n const requiredEventProperties = {\n ...baseProperties,\n ...requestParamProperties,\n ...getRequestMetadataFromHistory(historyItem, selectedAccount),\n ...getTradeDataFromHistory(historyItem),\n ...getTxStatusesFromHistory(historyItem),\n ...getFinalizedTxProperties(historyItem, txMeta, approvalTxMeta),\n ...getPriceImpactFromQuote(quote),\n ...(eventName === UnifiedSwapBridgeEventName.Completed && {\n ...(!isNonEvmChainId(historyItem.quote.srcChainId) &&\n historyItem.txMetaId && {\n transaction_internal_id: historyItem.txMetaId,\n }),\n ...(historyItem.inputPrimaryDenomination && {\n input_primary_denomination: historyItem.inputPrimaryDenomination,\n }),\n }),\n };\n\n trackMetricsEvent({\n messenger: this.messenger,\n eventName,\n properties: requiredEventProperties,\n });\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bridge-status-controller.mjs","sourceRoot":"","sources":["../src/bridge-status-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport {\n QuoteMetadata,\n RequiredEventContextFromClient,\n QuoteResponse,\n Trade,\n FeatureId,\n BatchSellTradesResponse,\n InputPrimaryDenomination,\n} from '@metamask/bridge-controller';\nimport {\n isNonEvmChainId,\n StatusTypes,\n getAccountHardwareType,\n UnifiedSwapBridgeEventName,\n isCrossChain,\n MetricsActionType,\n MetaMetricsSwapsEventSource,\n PollingStatus,\n formatChainIdToHex,\n} from '@metamask/bridge-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport {\n TransactionStatus,\n TransactionType,\n TransactionController,\n generateBatchId,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { IntentManager } from './bridge-status-controller.intent';\nimport {\n ALLOWED_FEATURE_IDS_FOR_STATUS_EVENTS,\n BRIDGE_PROD_API_BASE_URL,\n BRIDGE_STATUS_CONTROLLER_NAME,\n DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n MAX_ATTEMPTS,\n REFRESH_INTERVAL_MS,\n} from './constants';\nimport {\n QUOTE_STATUS_BACKFILL_WINDOW_MS,\n QUOTE_STATUS_UPDATE_ENTRY_TTL,\n QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS,\n} from './quote-status-manager/constants';\nimport {\n QuoteStatusGetError,\n QuoteStatusUpdateError,\n} from './quote-status-manager/errors';\nimport { QuoteStatusManager } from './quote-status-manager/quotes-status-manager';\nimport executeSubmitStrategy from './strategy';\nimport { SubmitStep } from './strategy/types';\nimport type { SubmitStrategyParams } from './strategy/types';\nimport type {\n BridgeStatusControllerState,\n StartPollingForBridgeTxStatusArgsSerialized,\n FetchFunction,\n BridgeHistoryItem,\n} from './types';\nimport type { BridgeStatusControllerMessenger } from './types';\nimport { BridgeClientId } from './types';\nimport { getAccountByAddress } from './utils/accounts';\nimport { getJwt } from './utils/authentication';\nimport {\n getBatchSellTrades,\n stopPollingForQuotes,\n trackMetricsEvent,\n} from './utils/bridge';\nimport {\n fetchBridgeTxStatus,\n fetchBridgeQuoteStatus,\n getStatusRequestWithSrcTxHash,\n shouldSkipFetchDueToFetchFailures,\n shouldWaitForFinalBridgeStatus,\n} from './utils/bridge-status';\nimport {\n getInitialHistoryItem,\n getMatchingHistoryEntryForTxMeta,\n rekeyHistoryItemInState,\n shouldPollHistoryItem,\n getMatchingHistoryEntryForApprovalTxMeta,\n} from './utils/history';\nimport {\n getFinalizedTxProperties,\n getPriceImpactFromQuote,\n getRequestMetadataFromHistory,\n getRequestParamFromHistory,\n getTradeDataFromHistory,\n getEVMTxPropertiesFromTransactionMeta,\n getTxStatusesFromHistory,\n getPreConfirmationPropertiesFromQuote,\n} from './utils/metrics';\nimport { getSelectedChainId } from './utils/network';\nimport { getTraceParams } from './utils/trace';\nimport {\n getTransactionMetaById,\n getTransactions,\n checkIsDelegatedAccount,\n isCrossChainTx,\n updateTransactionsInBatch,\n hasNestedSwapTransactions,\n} from './utils/transaction';\n\nconst metadata: StateMetadata<BridgeStatusControllerState> = {\n // We want to persist the bridge status state so that we can show the proper data for the Activity list\n // basically match the behavior of TransactionController\n txHistory: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n // Deferred status updates used by QuoteStatusUpdateManager\n quoteUpdateStatusStore: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n};\n\n/** The input to start polling for the {@link BridgeStatusController} */\ntype BridgeStatusPollingInput = FetchBridgeTxStatusArgs;\n\ntype SrcTxMetaId = string;\nexport type FetchBridgeTxStatusArgs = {\n bridgeTxMetaId: string;\n};\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'startPollingForBridgeTxStatus',\n 'wipeBridgeStatus',\n 'resetState',\n 'submitTx',\n 'submitIntent',\n 'submitBatchSell',\n 'restartPollingForFailedAttempts',\n 'getBridgeHistoryItemByTxMetaId',\n] as const;\n\nexport class BridgeStatusController extends StaticIntervalPollingController<BridgeStatusPollingInput>()<\n typeof BRIDGE_STATUS_CONTROLLER_NAME,\n BridgeStatusControllerState,\n BridgeStatusControllerMessenger\n> {\n #pollingTokensByTxMetaId: Record<SrcTxMetaId, string> = {};\n\n readonly #intentManager: IntentManager;\n\n readonly #quoteStatusManager: QuoteStatusManager;\n\n readonly #clientId: BridgeClientId;\n\n readonly #fetchFn: FetchFunction;\n\n readonly #config: {\n customBridgeApiBaseUrl: string;\n };\n\n readonly #addTransactionBatchFn: typeof TransactionController.prototype.addTransactionBatch;\n\n readonly #trace: TraceCallback;\n\n constructor({\n messenger,\n state,\n clientId,\n clientProduct,\n clientVersion,\n fetchFn,\n addTransactionBatchFn,\n config,\n traceFn,\n onQuoteStatusManagerError,\n isQuoteStatusManagerEnabled,\n }: {\n messenger: BridgeStatusControllerMessenger;\n state?: Partial<BridgeStatusControllerState>;\n clientId: BridgeClientId;\n clientProduct: string;\n clientVersion?: string;\n fetchFn: FetchFunction;\n addTransactionBatchFn: typeof TransactionController.prototype.addTransactionBatch;\n config?: {\n customBridgeApiBaseUrl?: string;\n };\n traceFn?: TraceCallback;\n onQuoteStatusManagerError?: (\n error: QuoteStatusUpdateError | QuoteStatusGetError,\n ) => void;\n isQuoteStatusManagerEnabled?: () => boolean;\n }) {\n super({\n name: BRIDGE_STATUS_CONTROLLER_NAME,\n metadata,\n messenger,\n // Restore the persisted state\n state: {\n ...DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n ...state,\n },\n });\n\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n this.#addTransactionBatchFn = addTransactionBatchFn;\n this.#config = {\n customBridgeApiBaseUrl:\n config?.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n };\n this.#trace = traceFn ?? (((_request, fn) => fn?.()) as TraceCallback);\n this.#intentManager = new IntentManager({\n messenger: this.messenger,\n customBridgeApiBaseUrl: this.#config.customBridgeApiBaseUrl,\n fetchFn: this.#fetchFn,\n });\n this.#quoteStatusManager = new QuoteStatusManager({\n messenger: this.messenger,\n clientId: this.#clientId,\n clientProduct,\n clientVersion,\n apiBaseUrl: this.#config.customBridgeApiBaseUrl,\n initialData: this.state.quoteUpdateStatusStore,\n onPersistUpdates: (updates): void => {\n this.update((draft) => {\n draft.quoteUpdateStatusStore = updates;\n });\n },\n entryTtlMs: QUOTE_STATUS_UPDATE_ENTRY_TTL,\n updateIntervalMs: QUOTE_STATUS_UPDATE_RETRY_INTERVAL_MS,\n onError: onQuoteStatusManagerError,\n isEnabled: isQuoteStatusManagerEnabled,\n });\n\n // Register action handlers\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n // Set interval\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.messenger.subscribe<\n 'TransactionController:transactionStatusUpdated',\n {\n historyKey?: string;\n historyItem?: BridgeHistoryItem;\n txMeta: TransactionMeta;\n isApprovalTxMeta: boolean;\n }\n >(\n 'TransactionController:transactionStatusUpdated',\n ({ txMeta, historyKey, historyItem, isApprovalTxMeta }) => {\n if (!txMeta) {\n return;\n }\n const { type, status } = txMeta;\n\n // Allow event publishing if the txMeta is a swap/bridge OR if the\n // corresponding history item exists\n const isSwapOrBridgeTransaction = type && isCrossChainTx(type);\n if (!isSwapOrBridgeTransaction && !historyKey && !historyItem) {\n return;\n }\n\n switch (status) {\n case TransactionStatus.submitted:\n // EVM txs report SUBMITTED here (not via transactionSubmitted) so hash\n // replacements before confirmation still reach the Bridge API.\n if (\n txMeta.hash &&\n txMeta.type &&\n isCrossChainTx(txMeta.type) &&\n !isApprovalTxMeta &&\n historyKey\n ) {\n this.#reportSubmittedOnce(historyKey, txMeta.hash, txMeta.id);\n }\n break;\n case TransactionStatus.confirmed:\n this.#onTransactionConfirmed({\n txMeta,\n historyKey,\n isApprovalTxMeta,\n });\n break;\n case TransactionStatus.failed:\n case TransactionStatus.dropped:\n case TransactionStatus.rejected:\n this.#onTransactionFailed({ txMeta, historyKey, isApprovalTxMeta });\n break;\n default:\n break;\n }\n },\n ({ transactionMeta }) => {\n const entry = getMatchingHistoryEntryForTxMeta(\n this.state.txHistory,\n transactionMeta,\n );\n const approvalEntry = getMatchingHistoryEntryForApprovalTxMeta(\n this.state.txHistory,\n transactionMeta,\n );\n const entryToUse = entry ?? approvalEntry;\n\n return {\n historyKey: entryToUse?.[0],\n historyItem: entryToUse?.[1],\n txMeta: transactionMeta,\n isApprovalTxMeta:\n entryToUse?.[1]?.approvalTxId === transactionMeta.id,\n };\n },\n );\n\n // Seed any missing quote-status entries from persisted history before\n // init(), so init()'s reconciliation loop can finalize quotes whose\n // deferred entry was never created (e.g. the client closed before\n // reportSubmitted ran).\n this.#seedQuoteStatusEntriesFromHistory();\n\n // Replay swap/bridge finalizations that resolved while the client was\n // closed, before resuming polling (which recovers in-flight bridges).\n this.#quoteStatusManager.init();\n\n // If you close the extension, but keep the browser open, the polling continues\n // If you close the browser, the polling stops\n // Check for historyItems that do not have a status of complete and restart polling\n this.#restartPollingForIncompleteHistoryItems();\n }\n\n readonly #onTransactionFailed = ({\n txMeta,\n historyKey,\n isApprovalTxMeta,\n }: {\n txMeta: TransactionMeta;\n historyKey?: string;\n isApprovalTxMeta: boolean;\n }): void => {\n // Check if the history item is already marked as a failure\n const isHistoryItemAlreadyFailed = historyKey\n ? this.state.txHistory[historyKey]?.status.status === StatusTypes.FAILED\n : false;\n\n this.#updateHistoryItem({\n historyKey,\n status: StatusTypes.FAILED,\n txHash: isApprovalTxMeta ? undefined : txMeta.hash,\n completionTime: Date.now(),\n });\n\n if (txMeta.status === TransactionStatus.rejected) {\n return;\n }\n\n // Skip tracking if this is a duplicate failed event for the same history item\n // This can happen if the transaction includes an approval tx that fails\n if (isHistoryItemAlreadyFailed) {\n return;\n }\n\n // Report finalized failure for swap/bridge transactions.\n // Note: TransactionStatus.rejected means the user cancelled signing, so the tx was never broadcast.\n // `hasNestedSwapTransactions` also covers batch/7702 swaps whose type may\n // still read as `batch` rather than `swap`.\n if (\n (txMeta.type && isCrossChainTx(txMeta.type)) ||\n hasNestedSwapTransactions(txMeta)\n ) {\n this.#quoteStatusManager.reportFinalised(txMeta.id, false);\n }\n\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Failed,\n historyKey,\n getEVMTxPropertiesFromTransactionMeta(txMeta),\n );\n };\n\n // Only EVM txs\n readonly #onTransactionConfirmed = ({\n txMeta,\n historyKey,\n isApprovalTxMeta,\n }: {\n txMeta: TransactionMeta;\n historyKey?: string;\n isApprovalTxMeta: boolean;\n }): void => {\n // Return early if the confirmed txMeta is for an approval since we\n // still need to wait for the trade to be confirmed\n if (isApprovalTxMeta) {\n return;\n }\n\n this.#updateHistoryItem({\n historyKey,\n txHash: txMeta.hash,\n });\n\n const isSwap =\n txMeta.type === TransactionType.swap || hasNestedSwapTransactions(txMeta);\n\n if (isSwap) {\n this.#updateHistoryItem({\n historyKey,\n status: StatusTypes.COMPLETE,\n completionTime: Date.now(),\n });\n\n // For EVM intent-based swaps the synthetic tx transitions\n // submitted→confirmed in a single update that carries the CoW\n // settlement hash, so the submitted status handler never has a hash\n // and reportSubmitted is never called. Call it here (before\n // reportFinalised) so the deferred-queue entry is created.\n const historyItem = historyKey\n ? this.state.txHistory[historyKey]\n : undefined;\n if (\n historyKey &&\n historyItem &&\n txMeta.hash &&\n !isNonEvmChainId(historyItem.quote.srcChainId)\n ) {\n this.#reportSubmittedOnce(historyKey, txMeta.hash, txMeta.id);\n }\n this.#quoteStatusManager.reportFinalised(txMeta.id, true);\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Completed,\n historyKey,\n );\n } else if (historyKey) {\n this.#startPollingForTxId(historyKey);\n }\n };\n\n /**\n * Reports the SUBMITTED quote status for non-EVM transactions.\n *\n * EVM transactions report SUBMITTED via the\n * `TransactionController:transactionStatusUpdated` subscription, which also\n * picks up hash replacements (speed-up/cancel) and the late hash assignment\n * of smart/batch transactions. Non-EVM transactions (Solana, Bitcoin, Tron)\n * are submitted through Snaps and never emit TransactionController lifecycle\n * events, so they are reported here once the history item exists and the\n * source tx hash is known.\n *\n * @param historyKey - The key of the history item in `txHistory`\n * @param txMeta - The submitted trade transaction's id and hash\n * @param txMeta.id - The transaction meta id, used for finalization matching\n * @param txMeta.hash - The source chain transaction hash\n */\n readonly #reportSubmittedForNonEvmTx = (\n historyKey: string,\n txMeta?: { id?: string; hash?: string },\n ): void => {\n if (!txMeta?.id || !txMeta.hash) {\n return;\n }\n const historyItem = this.state.txHistory[historyKey];\n if (!historyItem || !isNonEvmChainId(historyItem.quote.srcChainId)) {\n return;\n }\n this.#reportSubmittedOnce(historyKey, txMeta.hash, txMeta.id);\n };\n\n /**\n * Reports a SUBMITTED quote status update exactly once per source tx hash.\n *\n * SUBMITTED can be triggered from several code paths (submission, the first\n * poll where the hash is known, and the final-status branch) and the poll\n * path runs on every interval.\n *\n * For 7702/nested batch sells a single source transaction carries multiple\n * quotes: the parent history item lists all of them in `quoteIds` (each a key\n * into `txHistory`). In that case every quote is reported under the shared\n * source tx hash and `txMetaId`.\n *\n * @param historyKey - The key of the history item in `txHistory`\n * @param srcTxHash - The source chain transaction hash\n * @param txMetaId - The transaction meta id, used for finalization matching\n */\n readonly #reportSubmittedOnce = (\n historyKey: string,\n srcTxHash: string,\n txMetaId: string,\n ): void => {\n const historyItem = this.state.txHistory[historyKey];\n if (!historyItem) {\n return;\n }\n\n // For a 7702/nested batch the parent item lists every quote in `quoteIds`\n // (keys into `txHistory`); resolve each to its real quote id. Otherwise fall\n // back to the item's own single quote id.\n let quoteIds: string[];\n if (historyItem.quoteIds?.length) {\n quoteIds = historyItem.quoteIds\n .map((quoteKey) => this.state.txHistory[quoteKey]?.quoteId)\n .filter((quoteId): quoteId is string => Boolean(quoteId));\n } else if (historyItem.quoteId) {\n quoteIds = [historyItem.quoteId];\n } else {\n quoteIds = [];\n }\n\n if (quoteIds.length === 0) {\n return;\n }\n\n // `reportedSubmittedTxHash` is set once `reportSubmitted` is called.\n // This avoids processing multiple `eportSubmitted` for the\n // same swap/bridge.\n if (historyItem.reportedSubmittedTxHash === srcTxHash) {\n return;\n }\n\n for (const quoteId of quoteIds) {\n this.#quoteStatusManager.reportSubmitted(quoteId, srcTxHash, txMetaId);\n }\n\n this.update((state) => {\n const item = state.txHistory[historyKey];\n if (item) {\n item.reportedSubmittedTxHash = srcTxHash;\n }\n });\n };\n\n resetState = (): void => {\n this.#quoteStatusManager.destroy();\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n state.quoteUpdateStatusStore =\n DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.quoteUpdateStatusStore;\n });\n };\n\n wipeBridgeStatus = ({\n address,\n ignoreNetwork,\n }: {\n address: string;\n ignoreNetwork: boolean;\n }): void => {\n // Wipe all networks for this address\n if (ignoreNetwork) {\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n });\n } else {\n const selectedChainId = getSelectedChainId(this.messenger);\n\n this.#wipeBridgeStatusByChainId(address, selectedChainId);\n }\n };\n\n /**\n * Resets the attempts counter for a bridge transaction history item\n * and restarts polling if it was previously stopped due to max attempts\n *\n * @param identifier - Object containing either txMetaId or txHash to identify the history item\n * @param identifier.txMetaId - The transaction meta ID\n * @param identifier.txHash - The transaction hash\n */\n restartPollingForFailedAttempts = (identifier: {\n txMetaId?: string;\n txHash?: string;\n }): void => {\n const { txMetaId, txHash } = identifier;\n\n if (!txMetaId && !txHash) {\n throw new Error('Either txMetaId or txHash must be provided');\n }\n\n // Find the history item by txMetaId or txHash\n let targetTxMetaId: string | undefined;\n\n if (txMetaId) {\n // Direct lookup by txMetaId\n if (this.state.txHistory[txMetaId]) {\n targetTxMetaId = txMetaId;\n }\n } else if (txHash) {\n // Search by txHash in status.srcChain.txHash\n targetTxMetaId = Object.keys(this.state.txHistory).find(\n (id) => this.state.txHistory[id].status.srcChain.txHash === txHash,\n );\n }\n\n if (!targetTxMetaId) {\n throw new Error(\n `No bridge transaction history found for ${\n txMetaId ? `txMetaId: ${txMetaId}` : `txHash: ${txHash}`\n }`,\n );\n }\n\n const historyItem = this.state.txHistory[targetTxMetaId];\n\n // Capture attempts count before resetting for metrics\n const previousAttempts = historyItem.attempts?.counter ?? 0;\n\n // Reset the attempts counter\n this.update((state) => {\n if (targetTxMetaId) {\n state.txHistory[targetTxMetaId].attempts = undefined;\n }\n });\n\n // Restart polling if it was stopped and this tx still needs status updates\n if (shouldPollHistoryItem(historyItem)) {\n // Check if polling was stopped (no active polling token)\n const existingPollingToken =\n this.#pollingTokensByTxMetaId[targetTxMetaId];\n\n if (!existingPollingToken) {\n // Restart polling\n this.#startPollingForTxId(targetTxMetaId);\n\n // Track polling manually restarted event\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.PollingStatusUpdated,\n targetTxMetaId,\n {\n polling_status: PollingStatus.ManuallyRestarted,\n retry_attempts: previousAttempts,\n },\n );\n }\n }\n };\n\n /**\n * Gets a bridge history item from the history by its transaction meta ID\n *\n * @param txMetaId - The transaction meta ID to look up\n * @returns The bridge history item if found, undefined otherwise\n */\n getBridgeHistoryItemByTxMetaId = (\n txMetaId: string,\n ): BridgeHistoryItem | undefined => {\n return this.state.txHistory[txMetaId];\n };\n\n /**\n * Seeds missing quote-status entries from persisted history on startup.\n *\n * The deferred quote-status entry (keyed by `${quoteId}:${srcTxHash}`) is only\n * created when `reportSubmitted` runs. If the client closes after a swap/bridge\n * is submitted but before that happens, the entry is never created and\n * `QuoteStatusManager.init()` has nothing to reconcile. The persisted history\n * item carries the `quoteId`, source tx hash, and `txMetaId` needed to rebuild\n * the entry, so we replay `reportSubmitted` here (idempotent via\n * `#reportSubmittedOnce`) before `init()` runs.\n */\n readonly #seedQuoteStatusEntriesFromHistory = (): void => {\n if (!this.#quoteStatusManager.enabled) {\n // Skip seeding to prevent `#reportSubmittedOnce` from persisting\n // `reportedSubmittedTxHash` so recent bridge history cannot be marked as\n // already reported with no store entry or backend update.\n return;\n }\n\n for (const [historyKey, historyItem] of Object.entries(\n this.state.txHistory,\n )) {\n const { quoteId, quoteIds, txMetaId } = historyItem;\n // A 7702/nested batch parent reports its quotes via `quoteIds` rather than\n // its own single `quoteId`, so accept either. `#reportSubmittedOnce`\n // resolves the actual set of quotes to report.\n if ((!quoteId && !quoteIds?.length) || !txMetaId) {\n continue;\n }\n\n // Skip items older than the backfill window: the backend would reject\n // a status report for a quote that old, so there is no point creating\n // an entry or making a request.\n if (\n Date.now() - historyItem.startTime >\n QUOTE_STATUS_BACKFILL_WINDOW_MS\n ) {\n continue;\n }\n\n // Prefer the history hash; fall back to the tx hash (covers STX swaps\n // confirmed while closed, where the history hash was never written).\n const srcTxHash =\n historyItem.status.srcChain.txHash ??\n getTransactionMetaById(this.messenger, txMetaId)?.hash;\n if (!srcTxHash) {\n continue;\n }\n\n // Call `reportSubmittedOnce` for each history item that satisfies\n // the above criteria. The method will then take care the rest\n // (ie. if it actually needs to be reported or not because it already has been).\n this.#reportSubmittedOnce(historyKey, srcTxHash, txMetaId);\n }\n };\n\n /**\n * Restart polling for txs that are not in a final state\n * This is called during initialization\n */\n readonly #restartPollingForIncompleteHistoryItems = (): void => {\n // Check for historyItems that do not have a status of complete and restart polling\n const { txHistory } = this.state;\n const historyItems = Object.entries(txHistory);\n const incompleteHistoryItems = historyItems\n .filter(\n ([_, historyItem]) =>\n historyItem.status.status === StatusTypes.PENDING ||\n historyItem.status.status === StatusTypes.UNKNOWN,\n )\n // Only poll items with txMetaId (post-submission items)\n .filter(([_, historyItem]: [string, BridgeHistoryItem]) => {\n if (!historyItem.txMetaId) {\n return false;\n }\n // Check if we are already polling this tx, if so, skip restarting polling for that\n const pollingToken =\n this.#pollingTokensByTxMetaId[historyItem.txMetaId];\n return !pollingToken;\n })\n // Only restart polling for items that still require status updates\n .filter(([_, historyItem]: [string, BridgeHistoryItem]) => {\n return shouldPollHistoryItem(historyItem);\n });\n\n incompleteHistoryItems.forEach(\n ([historyKey, historyItem]: [string, BridgeHistoryItem]) => {\n const shouldSkipFetch = shouldSkipFetchDueToFetchFailures(\n historyItem.attempts,\n );\n if (shouldSkipFetch) {\n return;\n }\n\n // We manually call startPolling() here rather than go through startPollingForBridgeTxStatus()\n // because we don't want to overwrite the existing historyItem in state\n this.#startPollingForTxId(historyKey);\n },\n );\n };\n\n readonly #addTxToHistory = (\n historyKey: string,\n ...args: Parameters<typeof getInitialHistoryItem>\n ): string => {\n const txHistoryItem = getInitialHistoryItem(...args);\n this.update((state) => {\n state.txHistory[historyKey] = txHistoryItem;\n });\n return historyKey;\n };\n\n /**\n * Rekeys a history item from actionId to txMeta.id after successful submission.\n * Also updates txMetaId and srcTxHash which weren't available pre-submission.\n *\n * @param oldKey - The temporary key to use for the history item, usually the actionId\n * @param newKey - The new key to use, typcally the txmeta.id\n * @param txMeta - The transaction meta from the successful submission\n * @param txMeta.id - The transaction meta id to use as the new key\n * @param txMeta.hash - The transaction hash to set on the history item\n */\n readonly #rekeyHistoryItem = (\n oldKey: string,\n newKey: string,\n txMeta: { id: string; hash?: string },\n ): void => {\n this.update((state) => {\n rekeyHistoryItemInState(state, oldKey, newKey, txMeta);\n });\n };\n\n readonly #startPollingForTxId = (txId: string): void => {\n // If we are already polling for this tx, stop polling for it before restarting\n const existingPollingToken = this.#pollingTokensByTxMetaId[txId];\n if (existingPollingToken) {\n this.stopPollingByPollingToken(existingPollingToken);\n }\n\n const txHistoryItem = this.state.txHistory[txId];\n if (txHistoryItem && shouldPollHistoryItem(txHistoryItem)) {\n this.#pollingTokensByTxMetaId[txId] = this.startPolling({\n bridgeTxMetaId: txId,\n });\n }\n };\n\n /**\n * @deprecated For EVM/Solana swap/bridge txs we add tx to history in submitTx()\n * For Solana swap/bridge we start polling in submitTx()\n * For EVM bridge we listen for 'TransactionController:transactionConfirmed' and start polling there\n * No clients currently call this, safe to remove in future versions\n *\n * Adds tx to history and starts polling for the bridge tx status\n *\n * @param txHistoryMeta - The parameters for creating the history item\n */\n startPollingForBridgeTxStatus = (\n txHistoryMeta: StartPollingForBridgeTxStatusArgsSerialized,\n ): void => {\n const { bridgeTxMeta } = txHistoryMeta;\n\n if (!bridgeTxMeta?.id) {\n throw new Error(\n 'Cannot start polling: bridgeTxMeta.id is required for polling',\n );\n }\n\n const historyKey = this.#addTxToHistory(bridgeTxMeta.id, txHistoryMeta);\n this.#startPollingForTxId(historyKey);\n };\n\n // This will be called after you call this.startPolling()\n // The args passed in are the args you passed in to startPolling()\n _executePoll = async (\n pollingInput: BridgeStatusPollingInput,\n ): Promise<void> => {\n await this.#fetchBridgeTxStatus(pollingInput);\n };\n\n /**\n * Handles the failure to fetch the bridge tx status\n * We eventually stop polling for the tx if we fail too many times\n * Failures (500 errors) can be due to:\n * - The srcTxHash not being available immediately for STX\n * - The srcTxHash being invalid for the chain. This case will never resolve so we stop polling for it to avoid hammering the Bridge API forever.\n *\n * @param bridgeTxMetaId - The txMetaId of the bridge tx\n */\n readonly #handleFetchFailure = (bridgeTxMetaId: string): void => {\n const { attempts } = this.state.txHistory[bridgeTxMetaId];\n\n const newAttempts = attempts\n ? {\n counter: attempts.counter + 1,\n lastAttemptTime: Date.now(),\n }\n : {\n counter: 1,\n lastAttemptTime: Date.now(),\n };\n\n // If we've failed too many times, stop polling for the tx\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n if (newAttempts.counter >= MAX_ATTEMPTS && pollingToken) {\n this.stopPollingByPollingToken(pollingToken);\n delete this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n // Track max polling reached event\n const historyItem = this.state.txHistory[bridgeTxMetaId];\n if (historyItem) {\n // Track polling status updated event\n this.#trackPollingStatusUpdatedEvent(\n bridgeTxMetaId,\n PollingStatus.MaxPollingReached,\n );\n }\n }\n\n // Update the attempts counter\n this.#updateHistoryItem({\n historyKey: bridgeTxMetaId,\n attempts: newAttempts,\n });\n };\n\n /**\n * Checks if the history item should be preserved so its status can be fetched.\n *\n * @param bridgeTxMetaId - The txMetaId of the bridge tx\n */\n readonly #handleOldHistoryItem = async (\n bridgeTxMetaId: string,\n ): Promise<void> => {\n // Continue polling on next restart if the history item is valid\n if (\n this.state.txHistory[bridgeTxMetaId] &&\n (await shouldWaitForFinalBridgeStatus(\n this.messenger,\n this.state.txHistory[bridgeTxMetaId],\n ))\n ) {\n return;\n }\n\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n // Track polling status updated event\n this.#trackPollingStatusUpdatedEvent(\n bridgeTxMetaId,\n PollingStatus.InvalidTransactionHash,\n );\n\n // If we've failed too many times, stop polling for the tx\n if (pollingToken) {\n this.stopPollingByPollingToken(pollingToken);\n delete this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n }\n\n // Delete the history item so polling doesn't start over on the next restart.\n // Report finalization as a failure here, this is the only place that\n // permanently ends polling, so it's the correct and non-duplicative point\n // to emit the final status.\n this.#quoteStatusManager.reportFinalised(bridgeTxMetaId, false);\n this.#deleteHistoryItem(bridgeTxMetaId);\n };\n\n readonly #fetchBridgeTxStatus = async ({\n bridgeTxMetaId,\n }: FetchBridgeTxStatusArgs): Promise<void> => {\n // 1. Check for history item\n\n const { txHistory } = this.state;\n const historyItem = txHistory[bridgeTxMetaId];\n if (!historyItem) {\n return;\n }\n\n // 2. Check for previous failures\n\n if (shouldSkipFetchDueToFetchFailures(historyItem.attempts)) {\n return;\n }\n\n // 3. Fetch transaction status\n\n try {\n let status: BridgeHistoryItem['status'];\n let validationFailures: string[] = [];\n\n if (historyItem.quote.intent) {\n const intentTxStatus =\n await this.#intentManager.getIntentTransactionStatus(\n bridgeTxMetaId,\n historyItem.quote.srcChainId,\n historyItem.quote.intent.protocol,\n this.#clientId,\n historyItem.status.srcChain.txHash,\n );\n\n if (\n intentTxStatus?.bridgeStatus === null ||\n intentTxStatus?.bridgeStatus === undefined\n ) {\n return;\n }\n status = intentTxStatus.bridgeStatus.status;\n\n // Report SUBMITTED as soon as the intent's source/settlement hash is\n // known at poll time, before the order reaches a terminal status.\n const intentSrcTxHash = status.srcChain.txHash;\n if (intentSrcTxHash) {\n this.#reportSubmittedOnce(\n bridgeTxMetaId,\n intentSrcTxHash,\n bridgeTxMetaId,\n );\n }\n } else {\n // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx\n // Oddly mostly happens on Optimism, never on Arbitrum. By the 2nd fetch, the Bridge API responds properly.\n // Also srcTxHash may not be available immediately for STX, so we don't want to fetch in those cases\n const srcTxHash = this.#setAndGetSrcTxHash(bridgeTxMetaId);\n\n if (!srcTxHash) {\n return;\n }\n\n // Report SUBMITTED as soon as a srcTxHash is known at poll time, for\n // every chain not just non-EVM sources.\n this.#reportSubmittedOnce(bridgeTxMetaId, srcTxHash, bridgeTxMetaId);\n\n const statusRequest = getStatusRequestWithSrcTxHash(\n historyItem.quote,\n srcTxHash,\n );\n const response =\n (historyItem.quoteId\n ? await fetchBridgeQuoteStatus(\n this.#quoteStatusManager,\n historyItem.quoteId,\n )\n : null) ??\n (await fetchBridgeTxStatus(\n statusRequest,\n this.#clientId,\n await getJwt(this.messenger),\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl,\n ));\n status = response.status;\n validationFailures = response.validationFailures;\n }\n\n if (validationFailures.length > 0) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.StatusValidationFailed,\n bridgeTxMetaId,\n {\n failures: validationFailures,\n refresh_count: historyItem.attempts?.counter ?? 0,\n },\n );\n throw new Error(\n `Bridge status validation failed: ${validationFailures.join(', ')}`,\n );\n }\n\n // 4. Create bridge history item\n\n const newBridgeHistoryItem = {\n ...historyItem,\n status,\n completionTime:\n status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED\n ? Date.now()\n : undefined, // TODO make this more accurate by looking up dest txHash block time\n attempts: undefined,\n };\n\n // No need to purge these on network change or account change, TransactionController does not purge either.\n // TODO In theory we can skip checking status if it's not the current account/network\n // we need to keep track of the account that this is associated with as well so that we don't show it in Activity list for other accounts\n // First stab at this will not stop polling when you are on a different account\n this.update((state) => {\n state.txHistory[bridgeTxMetaId] = newBridgeHistoryItem;\n });\n\n if (historyItem.quote.intent) {\n this.#intentManager.syncTransactionFromIntentStatus(\n bridgeTxMetaId,\n historyItem,\n );\n }\n\n // 5. After effects\n\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n const isFinalStatus =\n status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED;\n\n if (isFinalStatus) {\n if (pollingToken) {\n this.stopPollingByPollingToken(pollingToken);\n delete this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n }\n\n // Ensure a deferred entry exists before reportFinalised is called.\n const settlementTxHash = newBridgeHistoryItem.status.srcChain.txHash;\n if (settlementTxHash) {\n this.#reportSubmittedOnce(\n bridgeTxMetaId,\n settlementTxHash,\n bridgeTxMetaId,\n );\n }\n\n this.#quoteStatusManager.reportFinalised(\n bridgeTxMetaId,\n status.status === StatusTypes.COMPLETE,\n );\n\n if (status.status === StatusTypes.COMPLETE) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Completed,\n bridgeTxMetaId,\n );\n this.messenger.publish(\n 'BridgeStatusController:destinationTransactionCompleted',\n historyItem.quote.destAsset.assetId,\n );\n }\n if (status.status === StatusTypes.FAILED) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Failed,\n bridgeTxMetaId,\n );\n }\n }\n } catch (error) {\n console.warn('Failed to fetch bridge tx status', error);\n this.#handleFetchFailure(bridgeTxMetaId);\n } finally {\n await this.#handleOldHistoryItem(bridgeTxMetaId);\n }\n };\n\n /**\n * Returns the srcTxHash for a non-STX EVM tx, the hash from the bridge status api,\n * or the local hash from the TransactionController if the tx is in a finalized state\n *\n * @param bridgeTxMetaId - The bridge tx meta id\n * @returns The srcTxHash\n */\n readonly #setAndGetSrcTxHash = (\n bridgeTxMetaId: string,\n ): string | undefined => {\n const { txHistory } = this.state;\n // Prefer the srcTxHash from bridgeStatusState so we don't have to look up in TransactionController\n // But it is possible to have bridgeHistoryItem in state without the srcTxHash yet when it is an STX\n const srcTxHash = txHistory[bridgeTxMetaId].status.srcChain.txHash;\n\n if (\n srcTxHash ||\n isNonEvmChainId(txHistory[bridgeTxMetaId].quote.srcChainId)\n ) {\n return srcTxHash;\n }\n\n // Update history with TransactionController's hash if it has been updated\n const txMeta = getTransactionMetaById(this.messenger, bridgeTxMetaId);\n\n if (!txMeta) {\n return undefined;\n }\n\n // Wait for finalized status before updating the history item\n const localTxHash = [\n TransactionStatus.confirmed,\n TransactionStatus.dropped,\n TransactionStatus.rejected,\n TransactionStatus.failed,\n ].includes(txMeta.status)\n ? txMeta.hash\n : undefined;\n this.#updateHistoryItem({\n historyKey: bridgeTxMetaId,\n txHash: localTxHash,\n });\n\n return localTxHash;\n };\n\n readonly #updateHistoryItem = ({\n historyKey,\n status,\n txHash,\n attempts,\n completionTime,\n }: {\n historyKey?: string;\n status?: StatusTypes;\n txHash?: string;\n attempts?: BridgeHistoryItem['attempts'];\n completionTime?: BridgeHistoryItem['completionTime'];\n }): void => {\n if (!historyKey) {\n return;\n }\n this.update((currentState) => {\n if (status) {\n currentState.txHistory[historyKey].status.status = status;\n }\n if (txHash) {\n currentState.txHistory[historyKey].status.srcChain.txHash = txHash;\n }\n if (attempts) {\n currentState.txHistory[historyKey].attempts = attempts;\n }\n if (completionTime) {\n currentState.txHistory[historyKey].completionTime = completionTime;\n }\n });\n };\n\n readonly #deleteHistoryItem = (historyKey: string): void => {\n this.update((currentState) => {\n delete currentState.txHistory[historyKey];\n });\n };\n\n // Wipes the bridge status for the given address and chainId\n // Will match only source chainId to the selectedChainId\n readonly #wipeBridgeStatusByChainId = (\n address: string,\n selectedChainId: Hex,\n ): void => {\n const sourceTxMetaIdsToDelete = Object.keys(this.state.txHistory).filter(\n (txMetaId) => {\n const bridgeHistoryItem = this.state.txHistory[txMetaId];\n\n const hexSourceChainId = numberToHex(\n bridgeHistoryItem.quote.srcChainId,\n );\n\n return (\n bridgeHistoryItem.account === address &&\n hexSourceChainId === selectedChainId\n );\n },\n );\n\n sourceTxMetaIdsToDelete.forEach((sourceTxMetaId) => {\n const pollingToken = this.#pollingTokensByTxMetaId[sourceTxMetaId];\n\n if (pollingToken) {\n this.stopPollingByPollingToken(\n this.#pollingTokensByTxMetaId[sourceTxMetaId],\n );\n delete this.#pollingTokensByTxMetaId[sourceTxMetaId];\n }\n });\n\n this.update((state) => {\n state.txHistory = sourceTxMetaIdsToDelete.reduce(\n (acc, sourceTxMetaId) => {\n delete acc[sourceTxMetaId];\n return acc;\n },\n state.txHistory,\n );\n });\n };\n\n /**\n * ******************************************************\n * TX SUBMISSION HANDLING\n *******************************************************\n */\n\n readonly #executeSubmitStrategy = async (\n params: SubmitStrategyParams<Trade>,\n sharedHistoryItemProperties: {\n startTime: number;\n location: MetaMetricsSwapsEventSource;\n abTests?: Record<string, string>;\n activeAbTests?: { key: string; value: string }[];\n tokenSecurityTypeDestination?: string | null;\n inputPrimaryDenomination?: InputPrimaryDenomination;\n },\n ): Promise<TransactionMeta> => {\n let tradeTxMeta!: TransactionMeta;\n\n const steps = executeSubmitStrategy(params);\n\n // Each submission strategy determines when to execute step, which means these actions can happen in any order\n for await (const { type, payload } of steps) {\n try {\n switch (type) {\n case SubmitStep.RekeyHistoryItem:\n this.#rekeyHistoryItem(\n payload.oldHistoryKey,\n payload.newHistoryKey,\n payload.tradeMeta,\n );\n // Report SUBMITTED as soon as the trade hash is known at submission\n // time, instead of waiting for the delayed transactionStatusUpdated\n // (submitted) event.\n if (payload.tradeMeta.hash) {\n this.#reportSubmittedOnce(\n payload.newHistoryKey,\n payload.tradeMeta.hash,\n payload.tradeMeta.id,\n );\n }\n break;\n\n case SubmitStep.UpdateBatchTransactions:\n updateTransactionsInBatch({\n messenger: this.messenger,\n allTradesWithMetadata: payload.quoteAndTxMetas,\n });\n break;\n\n case SubmitStep.SetTradeMeta:\n tradeTxMeta = payload.tradeMeta;\n break;\n\n case SubmitStep.AddHistoryItem:\n this.#addTxToHistory(payload.historyKey, {\n ...payload,\n ...sharedHistoryItemProperties,\n quoteResponse: payload.quoteResponse,\n accountAddress: params.selectedAccount.address,\n isStxEnabled: params.isStxEnabled,\n slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request\n });\n this.#reportSubmittedForNonEvmTx(\n payload.historyKey,\n payload.bridgeTxMeta,\n );\n break;\n\n case SubmitStep.StartPolling:\n this.#startPollingForTxId(payload.historyKey);\n break;\n\n case SubmitStep.PublishCompletedEvent:\n this.#quoteStatusManager.reportFinalised(payload.historyKey, true);\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Completed,\n payload.historyKey,\n );\n break;\n\n /* c8 ignore start */\n default:\n throw new Error(`Unknown submit step type: ${String(type)}`);\n /* c8 ignore end */\n }\n } catch (error) {\n console.error(\n 'Failed to add to bridge history and start polling.',\n error,\n );\n }\n }\n\n return tradeTxMeta;\n };\n\n /**\n * Submits a cross-chain swap transaction\n *\n * @param accountAddress - The address of the account to submit the transaction for\n * @param maybeQuoteResponses - A single quote response or an array of quote responses\n * @param isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension\n * @param quotesReceivedContext - The context for the QuotesReceived event\n * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore)\n * @param abTests - Legacy A/B test context for `ab_tests` (backward compatibility)\n * @param activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.\n * @param tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.\n * @param batchSellTrades - Contains transaction data for the quotes, provided by the obtainGaslessBatch API\n * @param inputPrimaryDenomination - The denomination shown as the primary source amount input at submission time.\n * @returns The transaction meta\n * @throws An error if transaction submission fails before it gets published\n */\n submitTx = async (\n accountAddress: string,\n maybeQuoteResponses:\n | (QuoteResponse<Trade, Trade> & QuoteMetadata)\n | (QuoteResponse<Trade, Trade> & QuoteMetadata)[],\n isStxEnabled: boolean,\n quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived],\n location: MetaMetricsSwapsEventSource = MetaMetricsSwapsEventSource.Unknown,\n abTests?: Record<string, string>,\n activeAbTests?: { key: string; value: string }[],\n tokenSecurityTypeDestination?: string | null,\n batchSellTrades?: BatchSellTradesResponse | null,\n inputPrimaryDenomination?: InputPrimaryDenomination,\n ): Promise<TransactionMeta> => {\n /**\n * If there are multiple quote responses, we assume that they all originate from the same src chain\n * and the same account. In this case its safe to use the first quote response's properties for\n * metrics and other pre-submission logic\n */\n const quoteResponses = Array.isArray(maybeQuoteResponses)\n ? maybeQuoteResponses\n : [maybeQuoteResponses];\n const quoteResponse = quoteResponses[0];\n\n const { quote } = quoteResponse;\n const startTime = Date.now();\n\n stopPollingForQuotes(this.messenger, quotesReceivedContext);\n\n const selectedAccount = getAccountByAddress(this.messenger, accountAddress);\n if (!selectedAccount) {\n throw new Error(\n 'Failed to submit cross-chain swap transaction: undefined multichain account',\n );\n }\n const accountHardwareType = getAccountHardwareType(selectedAccount);\n\n /**\n * For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval.\n * Extension does not have this issue\n */\n const requireApproval =\n this.#clientId === BridgeClientId.MOBILE && accountHardwareType !== null;\n const isBridgeTx = isCrossChain(quote.srcChainId, quote.destChainId);\n\n const batchId = quoteResponses.some(\n ({ featureId: quoteFeatureId }) =>\n quoteFeatureId === FeatureId.BATCH_SELL,\n )\n ? generateBatchId()\n : undefined;\n\n const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(\n quoteResponse,\n isStxEnabled,\n accountHardwareType,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n batchSellTrades,\n batchId,\n );\n\n try {\n // Emit Submitted event after submit button is clicked\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Submitted,\n undefined,\n {\n ...preConfirmationProperties,\n ...(inputPrimaryDenomination && {\n input_primary_denomination: inputPrimaryDenomination,\n }),\n },\n );\n\n /**\n * Check if the account is an EIP-7702 delegated account.\n * Delegated accounts only allow 1 in-flight tx, so approve + swap\n * must be batched into a single transaction\n */\n const isDelegatedAccount = isNonEvmChainId(quote.srcChainId)\n ? false\n : await checkIsDelegatedAccount(\n this.messenger,\n selectedAccount.address as Hex,\n [formatChainIdToHex(quote.srcChainId)],\n );\n\n const strategyParams: SubmitStrategyParams<Trade> = {\n messenger: this.messenger,\n quoteResponses,\n batchSellTrades,\n isStxEnabled,\n isBridgeTx,\n isDelegatedAccount,\n selectedAccount,\n requireApproval,\n clientId: this.#clientId,\n bridgeApiBaseUrl: this.#config.customBridgeApiBaseUrl,\n addTransactionBatchFn: this.#addTransactionBatchFn,\n fetchFn: this.#fetchFn,\n traceFn: this.#trace,\n batchId,\n };\n\n return await this.#trace(\n getTraceParams(quoteResponse, isStxEnabled),\n async () =>\n await this.#executeSubmitStrategy(strategyParams, {\n startTime,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n inputPrimaryDenomination,\n }),\n );\n } catch (error) {\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.Failed,\n undefined,\n {\n error_message: (error as Error)?.message,\n ...preConfirmationProperties,\n },\n );\n throw error;\n }\n };\n\n /**\n * Submits an intent order and creates a synthetic history entry for UX.\n * The EIP-712 payload is always signed inside this controller via KeyringController.\n *\n * @param params - Object containing intent submission parameters\n * @param params.quoteResponse - Quote carrying intent data\n * @param params.accountAddress - The EOA submitting the order\n * @param params.location - The entry point from which the user initiated the swap or bridge\n * @param params.abTests - Legacy A/B test context for `ab_tests` (backward compatibility)\n * @param params.activeAbTests - New A/B test context for `active_ab_tests` (migration target). Attributes events to specific experiments.\n * @param params.tokenSecurityTypeDestination - The security classification of the destination token, supplied by the client (e.g. from token security/scanning data). Pass `null` when no security data is available.\n * @param params.inputPrimaryDenomination - The denomination shown as the primary source amount input at submission time.\n * @param params.isStxEnabled - Whether smart transactions are enabled on the client, for example the getSmartTransactionsEnabled selector value from the extension\n * @param params.quotesReceivedContext - The context for the QuotesReceived event\n * @returns A lightweight TransactionMeta-like object for history linking\n * @throws An error if intent or transaction submission fails before they get published\n */\n submitIntent = async (params: {\n quoteResponse: QuoteResponse<Trade, Trade> & QuoteMetadata;\n accountAddress: string;\n location?: MetaMetricsSwapsEventSource;\n abTests?: Record<string, string>;\n activeAbTests?: { key: string; value: string }[];\n tokenSecurityTypeDestination?: string | null;\n inputPrimaryDenomination?: InputPrimaryDenomination;\n isStxEnabled?: boolean;\n quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived];\n }): Promise<TransactionMeta> => {\n const {\n quoteResponse,\n accountAddress,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n inputPrimaryDenomination,\n isStxEnabled = false,\n quotesReceivedContext,\n } = params;\n\n // TODO add metrics context\n return await this.submitTx(\n accountAddress,\n quoteResponse,\n isStxEnabled,\n quotesReceivedContext,\n location,\n abTests,\n activeAbTests,\n tokenSecurityTypeDestination,\n undefined,\n inputPrimaryDenomination,\n );\n };\n\n submitBatchSell = async (params: {\n quoteResponses: ((QuoteResponse<Trade, Trade> & QuoteMetadata) | null)[];\n accountAddress: string;\n location?: MetaMetricsSwapsEventSource;\n abTests?: Record<string, string>;\n activeAbTests?: { key: string; value: string }[];\n isStxEnabled?: boolean;\n quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived];\n tokenSecurityTypeDestination?: string | null;\n }): Promise<TransactionMeta> => {\n /**\n * Retrieve the batch sell trades from the BridgeController's state to ensure we submit\n * the original response data from the bridge-api\n */\n const batchSellTrades = getBatchSellTrades(this.messenger);\n return await this.submitTx(\n params.accountAddress,\n params.quoteResponses.filter(\n (\n quoteResponse,\n ): quoteResponse is QuoteResponse<Trade, Trade> & QuoteMetadata =>\n quoteResponse !== null,\n ),\n params.isStxEnabled ?? false,\n params.quotesReceivedContext,\n params.location,\n params.abTests,\n params.activeAbTests,\n params.tokenSecurityTypeDestination,\n batchSellTrades,\n );\n };\n\n readonly #trackPollingStatusUpdatedEvent = (\n historyKey: string,\n pollingStatus: PollingStatus,\n ): void => {\n // Track polling status updated event\n const historyItem = this.state.txHistory[historyKey];\n this.#trackUnifiedSwapBridgeEvent(\n UnifiedSwapBridgeEventName.PollingStatusUpdated,\n historyKey,\n {\n polling_status: pollingStatus,\n retry_attempts: historyItem.attempts?.counter ?? 0,\n },\n );\n };\n\n /**\n * Tracks post-submission events for a cross-chain swap based on the history item\n *\n * @param eventName - The name of the event to track\n * @param txHistoryKey - The txMetaId, actionId or intentUid of the history item to track the event for\n * @param eventProperties - The properties for the event\n */\n readonly #trackUnifiedSwapBridgeEvent = <\n EventName extends\n | typeof UnifiedSwapBridgeEventName.Submitted\n | typeof UnifiedSwapBridgeEventName.Failed\n | typeof UnifiedSwapBridgeEventName.Completed\n | typeof UnifiedSwapBridgeEventName.StatusValidationFailed\n | typeof UnifiedSwapBridgeEventName.PollingStatusUpdated,\n EventProperties extends Omit<\n RequiredEventContextFromClient[EventName],\n 'feature_id'\n > & {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n feature_id?: FeatureId;\n },\n >(\n eventName: EventName,\n txHistoryKey?: string,\n eventProperties?: EventProperties,\n ): void => {\n const historyItem: BridgeHistoryItem | undefined = txHistoryKey\n ? this.state.txHistory[txHistoryKey]\n : undefined;\n\n const featureId =\n eventProperties?.feature_id ??\n historyItem?.featureId ??\n FeatureId.UNIFIED_SWAP_BRIDGE;\n\n if (\n !(\n ALLOWED_FEATURE_IDS_FOR_STATUS_EVENTS.includes(featureId) ||\n eventName === UnifiedSwapBridgeEventName.StatusValidationFailed\n )\n ) {\n return;\n }\n\n // Legacy/new metrics fields are intentionally kept independent during migration.\n const historyAbTests = txHistoryKey\n ? this.state.txHistory?.[txHistoryKey]?.abTests\n : undefined;\n const historyActiveAbTests = txHistoryKey\n ? this.state.txHistory?.[txHistoryKey]?.activeAbTests\n : undefined;\n const resolvedAbTests = eventProperties?.ab_tests ?? historyAbTests;\n const resolvedActiveAbTests =\n eventProperties?.active_ab_tests ?? historyActiveAbTests;\n\n const location =\n historyItem?.location ??\n eventProperties?.location ??\n MetaMetricsSwapsEventSource.Unknown;\n\n const baseProperties = {\n action_type: MetricsActionType.SWAPBRIDGE_V1,\n feature_id: featureId ?? FeatureId.UNIFIED_SWAP_BRIDGE,\n ...(historyItem?.batchId ? { batch_id: historyItem.batchId } : {}),\n ...(eventProperties ?? {}),\n location,\n ...(resolvedAbTests &&\n Object.keys(resolvedAbTests).length > 0 && {\n ab_tests: resolvedAbTests,\n }),\n ...(resolvedActiveAbTests &&\n resolvedActiveAbTests.length > 0 && {\n active_ab_tests: resolvedActiveAbTests,\n }),\n };\n\n // This will publish events for PERPS dropped tx failures as well\n if (!historyItem) {\n trackMetricsEvent({\n messenger: this.messenger,\n eventName,\n properties: baseProperties,\n });\n return;\n }\n\n const { approvalTxId, quote } = historyItem;\n const requestParamProperties = getRequestParamFromHistory(historyItem);\n\n if (eventName === UnifiedSwapBridgeEventName.StatusValidationFailed) {\n trackMetricsEvent({\n messenger: this.messenger,\n eventName,\n properties: {\n ...baseProperties,\n chain_id_source: requestParamProperties.chain_id_source,\n chain_id_destination: requestParamProperties.chain_id_destination,\n token_address_source: requestParamProperties.token_address_source,\n token_address_destination:\n requestParamProperties.token_address_destination,\n token_security_type_destination:\n requestParamProperties.token_security_type_destination,\n refresh_count: historyItem.attempts?.counter ?? 0,\n },\n });\n return;\n }\n\n const selectedAccount = getAccountByAddress(\n this.messenger,\n historyItem.account,\n );\n\n const transactions = getTransactions(this.messenger);\n const txMeta = transactions.find(\n (tx: TransactionMeta) => tx.id === txHistoryKey,\n );\n const approvalTxMeta = transactions.find(\n (tx: TransactionMeta) => tx.id === approvalTxId,\n );\n\n const requiredEventProperties = {\n ...baseProperties,\n ...requestParamProperties,\n ...getRequestMetadataFromHistory(historyItem, selectedAccount),\n ...getTradeDataFromHistory(historyItem),\n ...getTxStatusesFromHistory(historyItem),\n ...getFinalizedTxProperties(historyItem, txMeta, approvalTxMeta),\n ...getPriceImpactFromQuote(quote),\n ...(eventName === UnifiedSwapBridgeEventName.Completed && {\n ...(!isNonEvmChainId(historyItem.quote.srcChainId) &&\n historyItem.txMetaId && {\n transaction_internal_id: historyItem.txMetaId,\n }),\n ...(historyItem.inputPrimaryDenomination && {\n input_primary_denomination: historyItem.inputPrimaryDenomination,\n }),\n }),\n };\n\n trackMetricsEvent({\n messenger: this.messenger,\n eventName,\n properties: requiredEventProperties,\n });\n };\n}\n"]}
|
|
@@ -165,6 +165,28 @@ class QuoteStatusEntryStore {
|
|
|
165
165
|
}
|
|
166
166
|
return null;
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Looks up every entry sharing the given transaction metadata identifier.
|
|
170
|
+
*
|
|
171
|
+
* A single 7702/nested batch transaction submits multiple quotes under one
|
|
172
|
+
* source tx hash and one `txMetaId`, producing several entries that must all
|
|
173
|
+
* be finalized together. Each matching entry has its TTL checked (and is
|
|
174
|
+
* transitioned to {@link QuoteStatusState.Expired} if stale) before being
|
|
175
|
+
* returned.
|
|
176
|
+
*
|
|
177
|
+
* @param txMetaId - Transaction metadata identifier to search for.
|
|
178
|
+
* @returns The matching entries (empty when none exist).
|
|
179
|
+
*/
|
|
180
|
+
getAllByTxMetaId(txMetaId) {
|
|
181
|
+
const matches = [];
|
|
182
|
+
for (const entry of __classPrivateFieldGet(this, _QuoteStatusEntryStore_items, "f").values()) {
|
|
183
|
+
if (entry.txMetaId === txMetaId) {
|
|
184
|
+
this.expireEntryIfStale(entry);
|
|
185
|
+
matches.push(entry);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return matches;
|
|
189
|
+
}
|
|
168
190
|
/**
|
|
169
191
|
* Retrieves an entry by key.
|
|
170
192
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quote-status-entry-store.cjs","sourceRoot":"","sources":["../../src/quote-status-manager/quote-status-entry-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { QuoteStatusState } from './constants';\nimport { QuoteStatusStateFsm } from './quote-status-state-fsm';\nimport {\n QuoteStatusEntryStoreOptions,\n QuoteStatusPersistEntry,\n QuoteStatusRuntimeEntry,\n} from './types';\n\n/**\n * In-memory store for quote status update entries.\n *\n * The store deduplicates entries by key, tracks timestamps used for retries and\n * TTL eviction, and persists a cloned snapshot on each mutating operation.\n */\nexport class QuoteStatusEntryStore {\n readonly #items: Map<string, QuoteStatusRuntimeEntry>;\n\n readonly #entryTtlMs: number;\n\n /**\n * Creates a deterministic key for persisted quote status entries.\n *\n * @param entry - Entry identity fields.\n * @param entry.quoteId - Quote identifier.\n * @param entry.srcTxHash - Source transaction hash.\n * @returns Stable key in `${quoteId}:${srcTxHash}` format.\n */\n static hash(\n entry: Pick<QuoteStatusPersistEntry, 'quoteId' | 'srcTxHash'>,\n ): string {\n return `${entry.quoteId}:${entry.srcTxHash}`;\n }\n\n readonly #onPersistUpdates: (\n updates: Record<string, QuoteStatusPersistEntry>,\n ) => void;\n\n /**\n * Creates a quote status entry store.\n *\n * @param options - Store dependencies and retention configuration.\n * @param options.onPersistUpdates - Callback invoked with cloned snapshot updates.\n * @param options.entryTtlMs - Entry time-to-live in milliseconds.\n * @param options.initial - Optional initial persisted entries used to seed the store.\n */\n constructor({\n onPersistUpdates,\n entryTtlMs,\n initial,\n }: QuoteStatusEntryStoreOptions) {\n this.#onPersistUpdates = onPersistUpdates;\n this.#entryTtlMs = entryTtlMs;\n this.#items = new Map(\n Object.entries(initial ?? {}).map(([key, entry]) => {\n const quoteStatusStateFsm = new QuoteStatusStateFsm(entry.status);\n\n return [\n key,\n // Entries from `initialDeferredUpdates` come from Immer-managed controller\n // state, which deep-freezes all nested objects. Cloning each entry here\n // ensures the in-memory queue holds mutable objects so that mutations\n // (e.g. updating `status` or `lastAttemptAt`) work correctly without\n // throwing a \"read only property\" error.\n { ...entry, status: quoteStatusStateFsm },\n ];\n }),\n );\n\n // Subscribe each seeded FSM after the map (and `#onPersistUpdates`) are set\n // so that any later state transition persists the updated snapshot.\n for (const entry of this.#items.values()) {\n this.#subscribeToStatusUpdates(entry);\n }\n }\n\n /**\n * Subscribes the entry's FSM so that every state transition persists the\n * current snapshot. Kept in one place so seeded and runtime-added entries\n * behave identically.\n *\n * @param entry - Entry whose FSM should trigger persistence on transition.\n */\n #subscribeToStatusUpdates(entry: QuoteStatusRuntimeEntry): void {\n entry.status.onStateUpdate(() => this.#persistToState());\n }\n\n /**\n * Adds a new entry when the key is not already present.\n *\n * If an entry already exists, only a missing `txMetaId` is backfilled to avoid\n * resetting timestamps and creating duplicate submission updates.\n *\n * @param key - Unique map key for the entry.\n * @param value - Entry payload without internal timestamps.\n * @param value.quoteId - Quote identifier.\n * @param value.srcTxHash - Source transaction hash.\n * @param value.status - Latest quote status.\n * @param value.txMetaId - Optional transaction metadata identifier.\n * @returns The tracked entry (the existing one when the key is already\n * present, otherwise the newly created entry).\n */\n put(\n key: string,\n value: Omit<QuoteStatusRuntimeEntry, 'createdAt' | 'lastAttemptAt'>,\n ): QuoteStatusRuntimeEntry {\n // If an entry for this key is already in the queue\n // do not overwrite it. Re-enqueueing would reset state and\n // could cause duplicate SUBMITTED events.\n const existing = this.#items.get(key);\n if (existing) {\n if (!existing.txMetaId && value.txMetaId) {\n existing.txMetaId = value.txMetaId;\n this.#persistToState();\n }\n return existing;\n }\n\n const now = Date.now();\n const entry: QuoteStatusRuntimeEntry = {\n ...value,\n createdAt: now,\n lastAttemptAt: now,\n };\n this.#items.set(key, entry);\n this.#subscribeToStatusUpdates(entry);\n this.#persistToState();\n return entry;\n }\n\n /**\n * Returns an iterator over all tracked entries.\n *\n * Stale entries are transitioned to {@link QuoteStatusState.Expired} first (but\n * kept in the store), so the iterator reflects their up-to-date terminal state.\n *\n * @returns An iterator over the currently tracked entries.\n */\n values(): IterableIterator<QuoteStatusRuntimeEntry> {\n this.expireStaleEntries();\n return this.#items.values();\n }\n\n /**\n * Returns every tracked entry matching the provided quote identifier.\n *\n * Stale entries are transitioned to {@link QuoteStatusState.Expired} first so\n * callers observe their up-to-date terminal state.\n *\n * @param quoteId - Quote identifier to match.\n * @returns The matching entries (empty when none exist).\n */\n getByQuoteId(quoteId: string): QuoteStatusRuntimeEntry[] {\n this.expireStaleEntries();\n\n const matches: QuoteStatusRuntimeEntry[] = [];\n for (const entry of this.#items.values()) {\n if (entry.quoteId === quoteId) {\n matches.push(entry);\n }\n }\n\n return matches;\n }\n\n /**\n * Number of entries currently tracked by the store.\n *\n * Note that this includes terminal entries (`Completed`/`Expired`), which are\n * retained rather than evicted; call {@link expireStaleEntries} (or\n * {@link values}) first when an up-to-date view of entry states is required.\n *\n * @returns The count of tracked entries.\n */\n get size(): number {\n return this.#items.size;\n }\n\n /**\n * Looks up an entry by its transaction metadata identifier.\n *\n * If the matching entry has exceeded its TTL it is transitioned to\n * {@link QuoteStatusState.Expired} (but kept) before being returned.\n *\n * @param txMetaId - Transaction metadata identifier to search for.\n * @returns The matching entry, or `null` if none exists.\n */\n getByTxMetaId(txMetaId: string): QuoteStatusRuntimeEntry | null {\n for (const entry of this.#items.values()) {\n if (entry.txMetaId === txMetaId) {\n this.expireEntryIfStale(entry);\n return entry;\n }\n }\n\n return null;\n }\n\n /**\n * Retrieves an entry by key.\n *\n * If the entry has exceeded its TTL it is transitioned to\n * {@link QuoteStatusState.Expired} (but kept) before being returned.\n *\n * @param key - Unique map key for the entry.\n * @returns The matching entry, or `null` if absent.\n */\n get(key: string): QuoteStatusRuntimeEntry | null {\n const entry = this.#items.get(key);\n if (!entry) {\n return null;\n }\n\n this.expireEntryIfStale(entry);\n return entry;\n }\n\n /**\n * Persists the current snapshot after an in-place mutation of a tracked entry.\n *\n * Used when fields such as `lastAttemptAt` are mutated directly on an entry\n * the caller already holds. No-ops if the entry is no longer tracked (e.g. the\n * store was cleared in the meantime), so persistence only reflects live entries.\n *\n * @param entry - The mutated entry to persist.\n */\n update(entry: QuoteStatusRuntimeEntry): void {\n if (!this.#items.has(QuoteStatusEntryStore.hash(entry))) {\n return;\n }\n\n this.#persistToState();\n }\n\n /**\n * Emits a cloned, serializable snapshot of all tracked entries via the\n * `onPersistUpdates` callback.\n *\n * Each entry's FSM is flattened to its plain `status` value so the snapshot\n * contains no class instances and is safe to store in controller state.\n */\n #persistToState(): void {\n const cloned: Record<string, QuoteStatusPersistEntry> = {};\n for (const [key, entry] of this.#items) {\n cloned[key] = { ...entry, status: entry.status.state };\n }\n this.#onPersistUpdates(cloned);\n }\n\n /**\n * Transitions every stale entry to {@link QuoteStatusState.Expired}, keeping it\n * in the store.\n *\n * Expired entries are retained so that later interactions with the same quote\n * (e.g. a duplicate `reportSubmitted`) can be recognized and rejected. Each\n * transition persists the updated snapshot via the entry's FSM subscription;\n * already-terminal entries cannot transition and are left untouched.\n */\n expireStaleEntries(): void {\n for (const entry of this.#items.values()) {\n if (this.entryHasExpired(entry)) {\n entry.status.transitionTo(QuoteStatusState.Expired);\n }\n }\n }\n\n /**\n * Determines whether an entry has outlived the configured TTL.\n *\n * Expiry is measured from the entry's `createdAt` timestamp, not its last\n * attempt, so an entry's total lifetime is bounded regardless of retries.\n *\n * @param entry - Entry to check.\n * @returns `true` if the entry's age exceeds the TTL.\n */\n entryHasExpired(entry: QuoteStatusRuntimeEntry): boolean {\n const now = Date.now();\n return now - entry.createdAt > this.#entryTtlMs;\n }\n\n /**\n * Transitions an entry to {@link QuoteStatusState.Expired} (keeping it) if it\n * has exceeded its TTL.\n *\n * The transition persists the updated snapshot via the entry's FSM\n * subscription. Already-terminal entries cannot transition and are left\n * untouched.\n *\n * @param entry - Entry to check and possibly expire.\n * @returns `true` if the entry was stale, otherwise `false`.\n */\n expireEntryIfStale(entry: QuoteStatusRuntimeEntry): boolean {\n if (this.entryHasExpired(entry)) {\n entry.status.transitionTo(QuoteStatusState.Expired);\n return true;\n }\n\n return false;\n }\n\n /**\n * Removes every entry from the store.\n *\n * Detaches each entry's FSM listeners before clearing to prevent leaks and\n * stale persist callbacks. Does not emit a persistence update; callers are\n * expected to use this during teardown.\n */\n clear(): void {\n for (const entry of this.#items.values()) {\n entry.status.removeAllListeners();\n }\n\n this.#items.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"quote-status-entry-store.cjs","sourceRoot":"","sources":["../../src/quote-status-manager/quote-status-entry-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { QuoteStatusState } from './constants';\nimport { QuoteStatusStateFsm } from './quote-status-state-fsm';\nimport {\n QuoteStatusEntryStoreOptions,\n QuoteStatusPersistEntry,\n QuoteStatusRuntimeEntry,\n} from './types';\n\n/**\n * In-memory store for quote status update entries.\n *\n * The store deduplicates entries by key, tracks timestamps used for retries and\n * TTL eviction, and persists a cloned snapshot on each mutating operation.\n */\nexport class QuoteStatusEntryStore {\n readonly #items: Map<string, QuoteStatusRuntimeEntry>;\n\n readonly #entryTtlMs: number;\n\n /**\n * Creates a deterministic key for persisted quote status entries.\n *\n * @param entry - Entry identity fields.\n * @param entry.quoteId - Quote identifier.\n * @param entry.srcTxHash - Source transaction hash.\n * @returns Stable key in `${quoteId}:${srcTxHash}` format.\n */\n static hash(\n entry: Pick<QuoteStatusPersistEntry, 'quoteId' | 'srcTxHash'>,\n ): string {\n return `${entry.quoteId}:${entry.srcTxHash}`;\n }\n\n readonly #onPersistUpdates: (\n updates: Record<string, QuoteStatusPersistEntry>,\n ) => void;\n\n /**\n * Creates a quote status entry store.\n *\n * @param options - Store dependencies and retention configuration.\n * @param options.onPersistUpdates - Callback invoked with cloned snapshot updates.\n * @param options.entryTtlMs - Entry time-to-live in milliseconds.\n * @param options.initial - Optional initial persisted entries used to seed the store.\n */\n constructor({\n onPersistUpdates,\n entryTtlMs,\n initial,\n }: QuoteStatusEntryStoreOptions) {\n this.#onPersistUpdates = onPersistUpdates;\n this.#entryTtlMs = entryTtlMs;\n this.#items = new Map(\n Object.entries(initial ?? {}).map(([key, entry]) => {\n const quoteStatusStateFsm = new QuoteStatusStateFsm(entry.status);\n\n return [\n key,\n // Entries from `initialDeferredUpdates` come from Immer-managed controller\n // state, which deep-freezes all nested objects. Cloning each entry here\n // ensures the in-memory queue holds mutable objects so that mutations\n // (e.g. updating `status` or `lastAttemptAt`) work correctly without\n // throwing a \"read only property\" error.\n { ...entry, status: quoteStatusStateFsm },\n ];\n }),\n );\n\n // Subscribe each seeded FSM after the map (and `#onPersistUpdates`) are set\n // so that any later state transition persists the updated snapshot.\n for (const entry of this.#items.values()) {\n this.#subscribeToStatusUpdates(entry);\n }\n }\n\n /**\n * Subscribes the entry's FSM so that every state transition persists the\n * current snapshot. Kept in one place so seeded and runtime-added entries\n * behave identically.\n *\n * @param entry - Entry whose FSM should trigger persistence on transition.\n */\n #subscribeToStatusUpdates(entry: QuoteStatusRuntimeEntry): void {\n entry.status.onStateUpdate(() => this.#persistToState());\n }\n\n /**\n * Adds a new entry when the key is not already present.\n *\n * If an entry already exists, only a missing `txMetaId` is backfilled to avoid\n * resetting timestamps and creating duplicate submission updates.\n *\n * @param key - Unique map key for the entry.\n * @param value - Entry payload without internal timestamps.\n * @param value.quoteId - Quote identifier.\n * @param value.srcTxHash - Source transaction hash.\n * @param value.status - Latest quote status.\n * @param value.txMetaId - Optional transaction metadata identifier.\n * @returns The tracked entry (the existing one when the key is already\n * present, otherwise the newly created entry).\n */\n put(\n key: string,\n value: Omit<QuoteStatusRuntimeEntry, 'createdAt' | 'lastAttemptAt'>,\n ): QuoteStatusRuntimeEntry {\n // If an entry for this key is already in the queue\n // do not overwrite it. Re-enqueueing would reset state and\n // could cause duplicate SUBMITTED events.\n const existing = this.#items.get(key);\n if (existing) {\n if (!existing.txMetaId && value.txMetaId) {\n existing.txMetaId = value.txMetaId;\n this.#persistToState();\n }\n return existing;\n }\n\n const now = Date.now();\n const entry: QuoteStatusRuntimeEntry = {\n ...value,\n createdAt: now,\n lastAttemptAt: now,\n };\n this.#items.set(key, entry);\n this.#subscribeToStatusUpdates(entry);\n this.#persistToState();\n return entry;\n }\n\n /**\n * Returns an iterator over all tracked entries.\n *\n * Stale entries are transitioned to {@link QuoteStatusState.Expired} first (but\n * kept in the store), so the iterator reflects their up-to-date terminal state.\n *\n * @returns An iterator over the currently tracked entries.\n */\n values(): IterableIterator<QuoteStatusRuntimeEntry> {\n this.expireStaleEntries();\n return this.#items.values();\n }\n\n /**\n * Returns every tracked entry matching the provided quote identifier.\n *\n * Stale entries are transitioned to {@link QuoteStatusState.Expired} first so\n * callers observe their up-to-date terminal state.\n *\n * @param quoteId - Quote identifier to match.\n * @returns The matching entries (empty when none exist).\n */\n getByQuoteId(quoteId: string): QuoteStatusRuntimeEntry[] {\n this.expireStaleEntries();\n\n const matches: QuoteStatusRuntimeEntry[] = [];\n for (const entry of this.#items.values()) {\n if (entry.quoteId === quoteId) {\n matches.push(entry);\n }\n }\n\n return matches;\n }\n\n /**\n * Number of entries currently tracked by the store.\n *\n * Note that this includes terminal entries (`Completed`/`Expired`), which are\n * retained rather than evicted; call {@link expireStaleEntries} (or\n * {@link values}) first when an up-to-date view of entry states is required.\n *\n * @returns The count of tracked entries.\n */\n get size(): number {\n return this.#items.size;\n }\n\n /**\n * Looks up an entry by its transaction metadata identifier.\n *\n * If the matching entry has exceeded its TTL it is transitioned to\n * {@link QuoteStatusState.Expired} (but kept) before being returned.\n *\n * @param txMetaId - Transaction metadata identifier to search for.\n * @returns The matching entry, or `null` if none exists.\n */\n getByTxMetaId(txMetaId: string): QuoteStatusRuntimeEntry | null {\n for (const entry of this.#items.values()) {\n if (entry.txMetaId === txMetaId) {\n this.expireEntryIfStale(entry);\n return entry;\n }\n }\n\n return null;\n }\n\n /**\n * Looks up every entry sharing the given transaction metadata identifier.\n *\n * A single 7702/nested batch transaction submits multiple quotes under one\n * source tx hash and one `txMetaId`, producing several entries that must all\n * be finalized together. Each matching entry has its TTL checked (and is\n * transitioned to {@link QuoteStatusState.Expired} if stale) before being\n * returned.\n *\n * @param txMetaId - Transaction metadata identifier to search for.\n * @returns The matching entries (empty when none exist).\n */\n getAllByTxMetaId(txMetaId: string): QuoteStatusRuntimeEntry[] {\n const matches: QuoteStatusRuntimeEntry[] = [];\n for (const entry of this.#items.values()) {\n if (entry.txMetaId === txMetaId) {\n this.expireEntryIfStale(entry);\n matches.push(entry);\n }\n }\n\n return matches;\n }\n\n /**\n * Retrieves an entry by key.\n *\n * If the entry has exceeded its TTL it is transitioned to\n * {@link QuoteStatusState.Expired} (but kept) before being returned.\n *\n * @param key - Unique map key for the entry.\n * @returns The matching entry, or `null` if absent.\n */\n get(key: string): QuoteStatusRuntimeEntry | null {\n const entry = this.#items.get(key);\n if (!entry) {\n return null;\n }\n\n this.expireEntryIfStale(entry);\n return entry;\n }\n\n /**\n * Persists the current snapshot after an in-place mutation of a tracked entry.\n *\n * Used when fields such as `lastAttemptAt` are mutated directly on an entry\n * the caller already holds. No-ops if the entry is no longer tracked (e.g. the\n * store was cleared in the meantime), so persistence only reflects live entries.\n *\n * @param entry - The mutated entry to persist.\n */\n update(entry: QuoteStatusRuntimeEntry): void {\n if (!this.#items.has(QuoteStatusEntryStore.hash(entry))) {\n return;\n }\n\n this.#persistToState();\n }\n\n /**\n * Emits a cloned, serializable snapshot of all tracked entries via the\n * `onPersistUpdates` callback.\n *\n * Each entry's FSM is flattened to its plain `status` value so the snapshot\n * contains no class instances and is safe to store in controller state.\n */\n #persistToState(): void {\n const cloned: Record<string, QuoteStatusPersistEntry> = {};\n for (const [key, entry] of this.#items) {\n cloned[key] = { ...entry, status: entry.status.state };\n }\n this.#onPersistUpdates(cloned);\n }\n\n /**\n * Transitions every stale entry to {@link QuoteStatusState.Expired}, keeping it\n * in the store.\n *\n * Expired entries are retained so that later interactions with the same quote\n * (e.g. a duplicate `reportSubmitted`) can be recognized and rejected. Each\n * transition persists the updated snapshot via the entry's FSM subscription;\n * already-terminal entries cannot transition and are left untouched.\n */\n expireStaleEntries(): void {\n for (const entry of this.#items.values()) {\n if (this.entryHasExpired(entry)) {\n entry.status.transitionTo(QuoteStatusState.Expired);\n }\n }\n }\n\n /**\n * Determines whether an entry has outlived the configured TTL.\n *\n * Expiry is measured from the entry's `createdAt` timestamp, not its last\n * attempt, so an entry's total lifetime is bounded regardless of retries.\n *\n * @param entry - Entry to check.\n * @returns `true` if the entry's age exceeds the TTL.\n */\n entryHasExpired(entry: QuoteStatusRuntimeEntry): boolean {\n const now = Date.now();\n return now - entry.createdAt > this.#entryTtlMs;\n }\n\n /**\n * Transitions an entry to {@link QuoteStatusState.Expired} (keeping it) if it\n * has exceeded its TTL.\n *\n * The transition persists the updated snapshot via the entry's FSM\n * subscription. Already-terminal entries cannot transition and are left\n * untouched.\n *\n * @param entry - Entry to check and possibly expire.\n * @returns `true` if the entry was stale, otherwise `false`.\n */\n expireEntryIfStale(entry: QuoteStatusRuntimeEntry): boolean {\n if (this.entryHasExpired(entry)) {\n entry.status.transitionTo(QuoteStatusState.Expired);\n return true;\n }\n\n return false;\n }\n\n /**\n * Removes every entry from the store.\n *\n * Detaches each entry's FSM listeners before clearing to prevent leaks and\n * stale persist callbacks. Does not emit a persistence update; callers are\n * expected to use this during teardown.\n */\n clear(): void {\n for (const entry of this.#items.values()) {\n entry.status.removeAllListeners();\n }\n\n this.#items.clear();\n }\n}\n"]}
|