|
| 1 | +diff --git a/dist/bridge-status-controller.cjs b/dist/bridge-status-controller.cjs |
| 2 | +index c89f7e4c600ea6e710a532fc6887ed525b80f333..c4c20566a27b77dfa8b88ff56a038ad5344e0efb 100644 |
| 3 | +--- a/dist/bridge-status-controller.cjs |
| 4 | ++++ b/dist/bridge-status-controller.cjs |
| 5 | +@@ -207,7 +207,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 6 | + }); |
| 7 | + }); |
| 8 | + _BridgeStatusController_addTxToHistory.set(this, (startPollingForBridgeTxStatusArgs, actionId) => { |
| 9 | +- const { bridgeTxMeta, statusRequest, quoteResponse, startTime, slippagePercentage, initialDestAssetBalance, targetContractAddress, approvalTxId, isStxEnabled, location, accountAddress: selectedAddress, } = startPollingForBridgeTxStatusArgs; |
| 10 | ++ const { bridgeTxMeta, statusRequest, quoteResponse, startTime, slippagePercentage, initialDestAssetBalance, targetContractAddress, approvalTxId, isStxEnabled, location, abTests, accountAddress: selectedAddress, } = startPollingForBridgeTxStatusArgs; |
| 11 | + // Determine the key for this history item: |
| 12 | + // - For pre-submission (non-batch EVM): use actionId |
| 13 | + // - For post-submission or other cases: use bridgeTxMeta.id |
| 14 | +@@ -248,6 +248,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 15 | + isStxEnabled: isStxEnabled ?? false, |
| 16 | + featureId: quoteResponse.featureId, |
| 17 | + location, |
| 18 | ++ ...(abTests && { abTests }), |
| 19 | + }; |
| 20 | + this.update((state) => { |
| 21 | + // Use actionId as key for pre-submission, or txMeta.id for post-submission |
| 22 | +@@ -716,8 +717,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 23 | + * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore) |
| 24 | + * @returns The transaction meta |
| 25 | + */ |
| 26 | +- this.submitTx = async (accountAddress, quoteResponse, isStxEnabledOnClient, quotesReceivedContext, location = bridge_controller_1.MetaMetricsSwapsEventSource.MainView) => { |
| 27 | +- this.messenger.call('BridgeController:stopPollingForQuotes', bridge_controller_1.AbortReason.TransactionSubmitted, |
| 28 | ++ this.submitTx = async (accountAddress, quoteResponse, isStxEnabledOnClient, quotesReceivedContext, location = bridge_controller_1.MetaMetricsSwapsEventSource.MainView, abTests) => { |
| 29 | ++ this.messenger.call('BridgeController:stopPollingForQuotes', bridge_controller_1.AbortReason.TransactionSubmitted, |
| 30 | + // If trade is submitted before all quotes are loaded, the QuotesReceived event is published |
| 31 | + // If the trade has a featureId, it means it was submitted outside of the Unified Swap and Bridge experience, so no QuotesReceived event is published |
| 32 | + quoteResponse.featureId ? undefined : quotesReceivedContext); |
| 33 | +@@ -726,7 +727,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 34 | + throw new Error('Failed to submit cross-chain swap transaction: undefined multichain account'); |
| 35 | + } |
| 36 | + const isHardwareAccount = (0, bridge_controller_1.isHardwareWallet)(selectedAccount); |
| 37 | +- const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabledOnClient, isHardwareAccount, location); |
| 38 | ++ const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabledOnClient, isHardwareAccount, location, abTests); |
| 39 | + // Emit Submitted event after submit button is clicked |
| 40 | + !quoteResponse.featureId && |
| 41 | + __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Submitted, undefined, preConfirmationProperties); |
| 42 | +@@ -848,6 +849,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 43 | + startTime, |
| 44 | + approvalTxId, |
| 45 | + location, |
| 46 | ++ abTests, |
| 47 | + }, actionId); |
| 48 | + // Pass txFee when gasIncluded is true to use the quote's gas fees |
| 49 | + // instead of re-estimating (which would fail for max native token swaps) |
| 50 | +@@ -888,6 +890,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 51 | + startTime, |
| 52 | + approvalTxId, |
| 53 | + location, |
| 54 | ++ abTests, |
| 55 | + }); |
| 56 | + } |
| 57 | + if ((0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId)) { |
| 58 | +@@ -916,12 +919,12 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 59 | + * @returns A lightweight TransactionMeta-like object for history linking |
| 60 | + */ |
| 61 | + this.submitIntent = async (params) => { |
| 62 | +- const { quoteResponse, signature, accountAddress, location } = params; |
| 63 | ++ const { quoteResponse, signature, accountAddress, location, abTests } = params; |
| 64 | + this.messenger.call('BridgeController:stopPollingForQuotes', bridge_controller_1.AbortReason.TransactionSubmitted); |
| 65 | + // Build pre-confirmation properties for error tracking parity with submitTx |
| 66 | + const account = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccount).call(this, accountAddress); |
| 67 | + const isHardwareAccount = Boolean(account) && (0, bridge_controller_1.isHardwareWallet)(account); |
| 68 | +- const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, false, isHardwareAccount, location); |
| 69 | ++ const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, false, isHardwareAccount, location, abTests); |
| 70 | + try { |
| 71 | + const intent = (0, transaction_1.getIntentFromQuote)(quoteResponse); |
| 72 | + // If backend provided an approval tx for this intent quote, submit it first (on-chain), |
| 73 | +@@ -932,7 +935,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 74 | + // Handle approval silently for better UX in intent flows |
| 75 | + const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval) |
| 76 | + ? quoteResponse.approval |
| 77 | +- : undefined, quoteResponse.resetApproval, |
| 78 | ++ : undefined, quoteResponse.resetApproval, |
| 79 | + /* requireApproval */ false); |
| 80 | + approvalTxId = approvalTxMeta?.id; |
| 81 | + if (approvalTxId) { |
| 82 | +@@ -1017,6 +1020,7 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 83 | + approvalTxId, |
| 84 | + startTime, |
| 85 | + location, |
| 86 | ++ abTests, |
| 87 | + }); |
| 88 | + // Start polling using the orderId key to route to intent manager |
| 89 | + __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeHistoryKey); |
| 90 | +@@ -1043,12 +1047,21 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll |
| 91 | + * @param eventProperties - The properties for the event |
| 92 | + */ |
| 93 | + _BridgeStatusController_trackUnifiedSwapBridgeEvent.set(this, (eventName, txMetaId, eventProperties) => { |
| 94 | ++ const historyAbTests = txMetaId |
| 95 | ++ ? this.state.txHistory?.[txMetaId]?.abTests |
| 96 | ++ : undefined; |
| 97 | ++ const resolvedAbTests = eventProperties?.ab_tests ?? historyAbTests ?? undefined; |
| 98 | ++ |
| 99 | + const baseProperties = { |
| 100 | + action_type: bridge_controller_1.MetricsActionType.SWAPBRIDGE_V1, |
| 101 | + location: eventProperties?.location ?? |
| 102 | + (txMetaId ? this.state.txHistory?.[txMetaId]?.location : undefined) ?? |
| 103 | + bridge_controller_1.MetaMetricsSwapsEventSource.MainView, |
| 104 | + ...(eventProperties ?? {}), |
| 105 | ++ ...(resolvedAbTests && |
| 106 | ++ Object.keys(resolvedAbTests).length > 0 && { |
| 107 | ++ ab_tests: resolvedAbTests, |
| 108 | ++ }), |
| 109 | + }; |
| 110 | + // This will publish events for PERPS dropped tx failures as well |
| 111 | + if (!txMetaId) { |
| 112 | +diff --git a/dist/bridge-status-controller.d.cts b/dist/bridge-status-controller.d.cts |
| 113 | +index a71266a9c15070d9fd9242148b16ad0e454184e9..f5dc880b383ecef194a44539e6c570fbc0fa7b7a 100644 |
| 114 | +--- a/dist/bridge-status-controller.d.cts |
| 115 | ++++ b/dist/bridge-status-controller.d.cts |
| 116 | +@@ -88,7 +88,7 @@ export declare class BridgeStatusController extends BridgeStatusController_base< |
| 117 | + * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore) |
| 118 | + * @returns The transaction meta |
| 119 | + */ |
| 120 | +- submitTx: (accountAddress: string, quoteResponse: QuoteResponse<Trade, Trade> & QuoteMetadata, isStxEnabledOnClient: boolean, quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived], location?: MetaMetricsSwapsEventSource) => Promise<TransactionMeta & Partial<SolanaTransactionMeta>>; |
| 121 | ++ submitTx: (accountAddress: string, quoteResponse: QuoteResponse<Trade, Trade> & QuoteMetadata, isStxEnabledOnClient: boolean, quotesReceivedContext?: RequiredEventContextFromClient[UnifiedSwapBridgeEventName.QuotesReceived], location?: MetaMetricsSwapsEventSource, abTests?: Record<string, string>) => Promise<TransactionMeta & Partial<SolanaTransactionMeta>>; |
| 122 | + /** |
| 123 | + * UI-signed intent submission (fast path): the UI generates the EIP-712 signature and calls this with the raw signature. |
| 124 | + * Here we submit the order to the intent provider and create a synthetic history entry for UX. |
| 125 | +@@ -105,6 +105,7 @@ export declare class BridgeStatusController extends BridgeStatusController_base< |
| 126 | + signature: string; |
| 127 | + accountAddress: string; |
| 128 | + location?: MetaMetricsSwapsEventSource; |
| 129 | ++ abTests?: Record<string, string>; |
| 130 | + }) => Promise<Pick<TransactionMeta, 'id' | 'chainId' | 'type' | 'status'>>; |
| 131 | + } |
| 132 | + export {}; |
| 133 | +diff --git a/dist/types.d.cts b/dist/types.d.cts |
| 134 | +index d0492cd8b8159bc63121174e6395f53c49aba59b..c5402866e8f13e37e535d1196d697756d2330023 100644 |
| 135 | +--- a/dist/types.d.cts |
| 136 | ++++ b/dist/types.d.cts |
| 137 | +@@ -96,6 +96,11 @@ export type BridgeHistoryItem = { |
| 138 | + * Used to attribute swaps to specific flows (e.g. Trending Explore). |
| 139 | + */ |
| 140 | + location?: MetaMetricsSwapsEventSource; |
| 141 | ++ /** |
| 142 | ++ * A/B test context to attribute swap/bridge events to specific experiments. |
| 143 | ++ * Keys are test names, values are variant names (e.g. { token_details_layout: 'treatment' }). |
| 144 | ++ */ |
| 145 | ++ abTests?: Record<string, string>; |
| 146 | + /** |
| 147 | + * Attempts tracking for exponential backoff on failed fetches. |
| 148 | + * We track the number of attempts and the last attempt time for each txMetaId that has failed at least once |
| 149 | +@@ -161,6 +166,7 @@ export type StartPollingForBridgeTxStatusArgs = { |
| 150 | + approvalTxId?: BridgeHistoryItem['approvalTxId']; |
| 151 | + isStxEnabled?: BridgeHistoryItem['isStxEnabled']; |
| 152 | + location?: BridgeHistoryItem['location']; |
| 153 | ++ abTests?: BridgeHistoryItem['abTests']; |
| 154 | + accountAddress: string; |
| 155 | + }; |
| 156 | + /** |
| 157 | +diff --git a/dist/utils/metrics.cjs b/dist/utils/metrics.cjs |
| 158 | +index 775367bc08c8a46c19a78913903573a295d1f677..ef00bf331d866e60a23204475f18a017614fdd57 100644 |
| 159 | +--- a/dist/utils/metrics.cjs |
| 160 | ++++ b/dist/utils/metrics.cjs |
| 161 | +@@ -109,7 +109,7 @@ exports.getPriceImpactFromQuote = getPriceImpactFromQuote; |
| 162 | + * @param location - The entry point from which the user initiated the swap or bridge (e.g. Main View, Token View, Trending Explore) |
| 163 | + * @returns The properties for the pre-confirmation event |
| 164 | + */ |
| 165 | +-const getPreConfirmationPropertiesFromQuote = (quoteResponse, isStxEnabledOnClient, isHardwareAccount, location = bridge_controller_1.MetaMetricsSwapsEventSource.MainView) => { |
| 166 | ++const getPreConfirmationPropertiesFromQuote = (quoteResponse, isStxEnabledOnClient, isHardwareAccount, location = bridge_controller_1.MetaMetricsSwapsEventSource.MainView, abTests) => { |
| 167 | + const { quote } = quoteResponse; |
| 168 | + return { |
| 169 | + ...(0, exports.getPriceImpactFromQuote)(quote), |
| 170 | +@@ -125,6 +125,7 @@ const getPreConfirmationPropertiesFromQuote = (quoteResponse, isStxEnabledOnClie |
| 171 | + action_type: bridge_controller_1.MetricsActionType.SWAPBRIDGE_V1, |
| 172 | + custom_slippage: false, // TODO detect whether the user changed the default slippage |
| 173 | + location, |
| 174 | ++ ...(abTests && Object.keys(abTests).length > 0 && { ab_tests: abTests }), |
| 175 | + }; |
| 176 | + }; |
| 177 | + exports.getPreConfirmationPropertiesFromQuote = getPreConfirmationPropertiesFromQuote; |
0 commit comments