Skip to content

feat: track token_security_type_destination in Unified SwapBridge metrics#8595

Open
infiniteflower wants to merge 10 commits intomainfrom
swaps-4422-resultType-metrics
Open

feat: track token_security_type_destination in Unified SwapBridge metrics#8595
infiniteflower wants to merge 10 commits intomainfrom
swaps-4422-resultType-metrics

Conversation

@infiniteflower
Copy link
Copy Markdown
Contributor

@infiniteflower infiniteflower commented Apr 27, 2026

Explanation

Adds a new token_security_type_destination field to every Unified SwapBridge analytics event that already carries token_address_destination. This lets the product team measure how often users swap into flagged tokens and quantify the impact of the destination-token security badge UI.

Current state. Unified SwapBridge events report which token a user is swapping into (token_address_destination) but not whether the client surfaced any security warning for that token. Without this signal we can't correlate the security badge with user behavior (e.g. drop-off after a "Malicious" classification).

Solution. A single string-or-null value is threaded through the metric pipeline:

  1. Clients pass token_security_type_destination once when calling BridgeController.updateBridgeQuoteRequestParams (via the context arg).
  2. BridgeController stores it on state (tokenSecurityTypeDestination: string | null, default null) so all pre-submit events (InputChanged, QuotesRequested, QuotesReceived, QuotesError, QuotesValidationFailed, etc.) automatically include it via getRequestParams.
  3. Clients pass it again as an optional arg to BridgeStatusController.submitTx / submitIntent. The value is persisted onto the BridgeHistoryItem so post-submit events fired hours later (Submitted, Completed, Failed, PollingStatusUpdated, StatusValidationFailed) can read it back via getRequestParamFromHistory without depending on BridgeController state, which may have moved on by then.

Non-obvious choices.

  • string | null, not string | undefined. BridgeControllerState must satisfy @metamask/base-controller's StateConstraint, whose values are Json-compatible — and Json does not allow undefined. null also matches the existing convention in RequestParams (e.g. token_address_destination: CaipAssetType | null). The controller defensively coerces undefined → null at the updateBridgeQuoteRequestParams boundary so JS callers passing undefined don't end up with "token_security_type_destination": undefined keys getting dropped by JSON.stringify.
  • Conditional spread on BridgeHistoryItem. Persisting unconditionally would have broken every MockTxHistory snapshot. The history item uses ...(tokenSecurityTypeDestination !== undefined && { tokenSecurityTypeDestination }) (matches the existing abTests / activeAbTests pattern); metric output is normalized with ?? null at emit time.
  • StatusValidationFailed needs an explicit add. Most post-confirm events spread requestParamProperties, but StatusValidationFailed builds its payload with explicit Picks. The new field had to be added in two places: getRequestParamFromHistory AND the explicit pick in #trackUnifiedSwapBridgeEvent.
  • Why pass it explicitly to submitTx instead of reading from BridgeController state at submit time? Considered but rejected. Reading state would require widening bridge-status-controller's messenger AllowedActions with BridgeController:getState (a heavy permission) plus client wiring updates. The explicit-arg approach matches the existing pattern for every other analytics context piece on submitTx (abTests, activeAbTests, location, quotesReceivedContext) and keeps the cross-controller surface narrow.
Screen.Recording.2026-04-27.at.4.30.49.PM.mov

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Medium risk due to breaking metrics type/signature changes (RequestParams, getRequestParams, and updateBridgeQuoteRequestParams context) and new optional parameters on BridgeStatusController submission methods that downstream clients must wire correctly to keep analytics consistent.

Overview
Adds a new token_security_type_destination analytics property and threads it through the Unified SwapBridge metrics pipeline.

BridgeController now stores a client-provided destination-token security classification (tokenSecurityTypeDestination) from updateBridgeQuoteRequestParams context, resets it with resetState, and includes it in all pre-submit tracked events via a breaking getRequestParams(quoteRequest, tokenSecurityTypeDestination) API.

BridgeStatusController accepts an optional tokenSecurityTypeDestination on submitTx/submitIntent, persists it on BridgeHistoryItem, and emits it on post-submit status/completion/failure analytics. Tests and snapshots are updated across both packages, and changelogs document the breaking changes.

Reviewed by Cursor Bugbot for commit 71fe3dc. Bugbot is set up for automated code reviews on this repo. Configure here.

@infiniteflower infiniteflower changed the title chore: update types feat: track token_security_type_destination in Unified SwapBridge metrics Apr 27, 2026
@infiniteflower infiniteflower marked this pull request as ready for review April 27, 2026 22:24
@infiniteflower infiniteflower requested review from a team as code owners April 27, 2026 22:24
Comment thread packages/bridge-controller/src/constants/bridge.ts
Comment thread packages/bridge-controller/src/bridge-controller.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants