Skip to content

feat(bridge-controller): add SwapBridge failure telemetry schema and classifiers - #9947

Open
Battambang wants to merge 5 commits into
mainfrom
feat/WPN-1877-failure-telemetry-schema
Open

feat(bridge-controller): add SwapBridge failure telemetry schema and classifiers#9947
Battambang wants to merge 5 commits into
mainfrom
feat/WPN-1877-failure-telemetry-schema

Conversation

@Battambang

@Battambang Battambang commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Explanation

Problem. SwapBridge Failed today is one bucket. Mixpanel cannot tell quote-fetch vs submit vs source vs dest vs poll, or whether a source/dest hash existed. That hides Tron/non-EVM diagnosis behind a blended "on-chain" failure rate. Free-text error_message is not a reliable classifier.

This PR adds the schema and classifiers only. It does not change Mixpanel payloads - runtime analytics behavior is unchanged until the follow-up wires these into emit paths.

Classification is always derived from the failing code path and hash presence, never from error_message text.

Content

Each classifier lives in the package that will call it. bridge-controller keeps the shared schema plus quote-fetch (the only failure it owns); submit and status classifiers live in bridge-status-controller.

Package Added
@metamask/bridge-controller FailurePhase, SwapBridgeErrorCode enums · HashPresenceData, FailureTelemetryData types · getQuoteFetchErrorCode
@metamask/bridge-status-controller getSubmitErrorCode · getHashPresenceProperties · getStatusFailurePhase · getSubmitFailureTelemetry · getStatusFailureTelemetry · HashPresenceProperties, FailureTelemetryProperties types

Event context types (all optional, additive)

Event New optional fields
Quotes Error failure_phase, error_code
Failed failure_phase, error_code, source_hash_present, destination_hash_present
Submitted source_hash_present, destination_hash_present
Completed source_hash_present, destination_hash_present

Property values

Property Values
failure_phase quote · broadcast · source_execution · destination_execution · poll · unknown
error_code quote_fetch_failed · missing_error_object · non_error_rejection · status_failed_without_reason · unknown
source_hash_present / destination_hash_present boolean

Classification rules

  • getQuoteFetchErrorCodemissing_error_object when the thrown value is nullish, quote_fetch_failed for an Error, non_error_rejection otherwise.
  • getSubmitFailureTelemetry always reports broadcast with both hash flags false, because Core currently emits Failed before executeSubmitStrategy.
  • getStatusFailurePhase prefers destination_execution when a dest hash exists, then source_execution when a source hash exists, and falls back to poll only when neither is present.

A follow-up PR (#9949) emits these fields from Quotes Error, submit catch, EVM failed, poll, Submitted, and Completed.

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

Low Risk
Additive optional TypeScript metrics fields and new exported utilities with no controller emit-path changes; behavior stays the same until a follow-up wires classifiers in.

Overview
Introduces structured SwapBridge failure telemetry ahead of wiring it into Mixpanel: shared enums (FailurePhase, SwapBridgeErrorCode), types (HashPresenceData, FailureTelemetryData), and pure classifiers that derive failure_phase / error_code from the failing code path and tx hash presence—not from error_message.

In @metamask/bridge-controller, exports getQuoteFetchErrorCode for quote-fetch failures and extends Unified SwapBridge event context types with optional failure_phase / error_code on Quotes Error and Failed, plus optional source_hash_present / destination_hash_present on Failed, Submitted, and Completed.

In @metamask/bridge-status-controller, adds and exports submit/status helpers (getSubmitErrorCode, getHashPresenceProperties, getStatusFailurePhase, getSubmitFailureTelemetry, getStatusFailureTelemetry)—e.g. submit failures always map to broadcast with no hashes; status failures use hash presence to pick execution phase and status_failed_without_reason.

Runtime analytics payloads are unchanged until a follow-up connects these helpers at emit sites; this PR is schema, exports, classifiers, and unit tests only.

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

@Battambang

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@8.0.0-preview-bbf9454b2
@metamask-previews/accounts-controller@39.1.0-preview-bbf9454b2
@metamask-previews/address-book-controller@7.1.2-preview-bbf9454b2
@metamask-previews/ai-controllers@0.8.0-preview-bbf9454b2
@metamask-previews/analytics-controller@2.0.0-preview-bbf9454b2
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-bbf9454b2
@metamask-previews/announcement-controller@8.1.0-preview-bbf9454b2
@metamask-previews/app-metadata-controller@2.0.1-preview-bbf9454b2
@metamask-previews/approval-controller@9.0.2-preview-bbf9454b2
@metamask-previews/assets-controller@14.0.0-preview-bbf9454b2
@metamask-previews/assets-controllers@111.1.1-preview-bbf9454b2
@metamask-previews/authenticated-user-storage@3.0.1-preview-bbf9454b2
@metamask-previews/base-controller@9.1.0-preview-bbf9454b2
@metamask-previews/base-data-service@0.1.3-preview-bbf9454b2
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-bbf9454b2
@metamask-previews/bridge-controller@79.3.0-preview-bbf9454b2
@metamask-previews/bridge-status-controller@75.2.0-preview-bbf9454b2
@metamask-previews/build-utils@3.0.4-preview-bbf9454b2
@metamask-previews/chain-agnostic-permission@1.7.0-preview-bbf9454b2
@metamask-previews/chomp-api-service@4.0.0-preview-bbf9454b2
@metamask-previews/claims-controller@0.6.0-preview-bbf9454b2
@metamask-previews/client-controller@1.0.1-preview-bbf9454b2
@metamask-previews/client-utils@2.1.0-preview-bbf9454b2
@metamask-previews/compliance-controller@2.1.0-preview-bbf9454b2
@metamask-previews/composable-controller@12.0.1-preview-bbf9454b2
@metamask-previews/config-registry-controller@3.0.0-preview-bbf9454b2
@metamask-previews/connectivity-controller@0.3.0-preview-bbf9454b2
@metamask-previews/controller-utils@12.3.0-preview-bbf9454b2
@metamask-previews/core-backend@8.1.2-preview-bbf9454b2
@metamask-previews/delegation-controller@3.0.2-preview-bbf9454b2
@metamask-previews/earn-controller@12.2.5-preview-bbf9454b2
@metamask-previews/eip-5792-middleware@3.0.5-preview-bbf9454b2
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-bbf9454b2
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-bbf9454b2
@metamask-previews/eth-block-tracker@15.0.1-preview-bbf9454b2
@metamask-previews/eth-json-rpc-middleware@24.0.0-preview-bbf9454b2
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-bbf9454b2
@metamask-previews/foundryup@1.0.1-preview-bbf9454b2
@metamask-previews/gas-fee-controller@26.3.1-preview-bbf9454b2
@metamask-previews/gator-permissions-controller@5.0.1-preview-bbf9454b2
@metamask-previews/geolocation-controller@1.0.0-preview-bbf9454b2
@metamask-previews/java-tron-up@1.0.0-preview-bbf9454b2
@metamask-previews/json-rpc-engine@10.5.0-preview-bbf9454b2
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-bbf9454b2
@metamask-previews/keyring-controller@27.1.1-preview-bbf9454b2
@metamask-previews/kyc-controller@0.0.0-preview-bbf9454b2
@metamask-previews/local-node-utils@1.0.0-preview-bbf9454b2
@metamask-previews/logging-controller@9.0.0-preview-bbf9454b2
@metamask-previews/message-manager@14.1.2-preview-bbf9454b2
@metamask-previews/messenger@2.0.0-preview-bbf9454b2
@metamask-previews/messenger-cli@0.2.0-preview-bbf9454b2
@metamask-previews/money-account-api-data-service@0.4.0-preview-bbf9454b2
@metamask-previews/money-account-balance-service@2.4.1-preview-bbf9454b2
@metamask-previews/money-account-controller@1.0.0-preview-bbf9454b2
@metamask-previews/money-account-upgrade-controller@3.0.1-preview-bbf9454b2
@metamask-previews/money-account-utils@1.1.0-preview-bbf9454b2
@metamask-previews/multichain-account-service@13.0.2-preview-bbf9454b2
@metamask-previews/multichain-api-middleware@4.0.2-preview-bbf9454b2
@metamask-previews/multichain-network-controller@3.2.3-preview-bbf9454b2
@metamask-previews/multichain-transactions-controller@7.1.2-preview-bbf9454b2
@metamask-previews/name-controller@9.1.2-preview-bbf9454b2
@metamask-previews/network-connection-banner-controller@0.2.0-preview-bbf9454b2
@metamask-previews/network-controller@35.0.1-preview-bbf9454b2
@metamask-previews/network-enablement-controller@6.0.4-preview-bbf9454b2
@metamask-previews/notification-services-controller@26.0.1-preview-bbf9454b2
@metamask-previews/passkey-controller@3.0.0-preview-bbf9454b2
@metamask-previews/permission-controller@13.1.1-preview-bbf9454b2
@metamask-previews/permission-log-controller@5.1.0-preview-bbf9454b2
@metamask-previews/perps-controller@12.2.0-preview-bbf9454b2
@metamask-previews/phishing-controller@17.3.1-preview-bbf9454b2
@metamask-previews/platform-api-docs@0.0.0-preview-bbf9454b2
@metamask-previews/polling-controller@16.0.9-preview-bbf9454b2
@metamask-previews/preferences-controller@23.1.0-preview-bbf9454b2
@metamask-previews/profile-metrics-controller@4.0.3-preview-bbf9454b2
@metamask-previews/profile-sync-controller@29.0.0-preview-bbf9454b2
@metamask-previews/ramps-controller@20.0.0-preview-bbf9454b2
@metamask-previews/rate-limit-controller@7.0.1-preview-bbf9454b2
@metamask-previews/react-data-query@0.2.2-preview-bbf9454b2
@metamask-previews/remote-feature-flag-controller@6.0.0-preview-bbf9454b2
@metamask-previews/sample-controllers@5.0.4-preview-bbf9454b2
@metamask-previews/seedless-onboarding-controller@10.1.1-preview-bbf9454b2
@metamask-previews/selected-network-controller@26.1.6-preview-bbf9454b2
@metamask-previews/sentinel-api-service@1.0.0-preview-bbf9454b2
@metamask-previews/shield-controller@6.0.0-preview-bbf9454b2
@metamask-previews/signature-controller@39.2.9-preview-bbf9454b2
@metamask-previews/smart-transactions-controller@25.1.0-preview-bbf9454b2
@metamask-previews/snap-account-service@2.1.2-preview-bbf9454b2
@metamask-previews/social-controllers@2.7.1-preview-bbf9454b2
@metamask-previews/solana-test-validator-up@1.0.0-preview-bbf9454b2
@metamask-previews/stellar-quickstart-up@0.0.0-preview-bbf9454b2
@metamask-previews/storage-service@1.0.2-preview-bbf9454b2
@metamask-previews/subscription-controller@8.0.0-preview-bbf9454b2
@metamask-previews/transaction-controller@69.5.2-preview-bbf9454b2
@metamask-previews/transaction-pay-controller@26.4.1-preview-bbf9454b2
@metamask-previews/user-operation-controller@41.2.8-preview-bbf9454b2
@metamask-previews/wallet@12.0.1-preview-bbf9454b2
@metamask-previews/wallet-cli@0.0.0-preview-bbf9454b2

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an additive telemetry schema and pure helper functions to classify SwapBridge failures into stable phases/error codes based on code path + tx-hash presence (not error_message), preparing richer analytics for a follow-up PR that will wire these fields into emitted events.

Changes:

  • Introduces FailurePhase and SwapBridgeErrorCode enums and exports them from the package entrypoint.
  • Adds failure-telemetry classifier helpers (+ unit tests) for quote-fetch, submit, and status/poll failure classification.
  • Extends Unified SwapBridge metrics context types with optional failure-telemetry and hash-presence fields for relevant events.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/bridge-controller/src/utils/metrics/types.ts Adds HashPresenceData / FailureTelemetryData and threads them into selected Unified SwapBridge event context types.
packages/bridge-controller/src/utils/metrics/failure-telemetry.ts New helper functions to derive error codes, phases, and hash-presence flags.
packages/bridge-controller/src/utils/metrics/failure-telemetry.test.ts Unit tests covering the new classification helpers.
packages/bridge-controller/src/utils/metrics/constants.ts Adds the new telemetry enums used by schema + helpers.
packages/bridge-controller/src/index.ts Re-exports the new enums, types, and helper functions from the package entrypoint.
packages/bridge-controller/CHANGELOG.md Documents the new telemetry exports/types for consumers.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/bridge-controller/src/utils/metrics/types.ts
@Battambang
Battambang force-pushed the feat/WPN-1877-failure-telemetry-schema branch 2 times, most recently from f8653bd to c766626 Compare August 26, 2026 11:53
Battambang added a commit that referenced this pull request Aug 26, 2026
…sence

Wire Quotes Error, submit Failed, EVM Failed, poll Failed, Submitted, and Completed to the classifiers from #9947. Mixpanel can now split quote vs broadcast vs source vs dest vs poll without parsing error_message.
Comment on lines +31 to +60
/**
* Classify a thrown value from submit (sign/broadcast) catch paths.
*
* @param error - The thrown value from submit.
* @returns The Mixpanel `error_code`.
*/
export const getSubmitErrorCode = (error: unknown): SwapBridgeErrorCode => {
if (error === undefined || error === null) {
return SwapBridgeErrorCode.MissingErrorObject;
}
if (error instanceof Error) {
return SwapBridgeErrorCode.Unknown;
}
return SwapBridgeErrorCode.NonErrorRejection;
};

/**
* @param sourceHash - Source tx hash if known at emit time.
* @param destinationHash - Destination tx hash if known at emit time.
* @returns Boolean hash-presence properties.
*/
export const getHashPresenceProperties = (
sourceHash?: string | null,
destinationHash?: string | null,
): HashPresenceProperties => {
return {
source_hash_present: Boolean(sourceHash),
destination_hash_present: Boolean(destinationHash),
};
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move these and the functions below to the bridge-status-controller's metrics utils

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quote-fetch classification has to stay in bridge-controller (getQuoteFetchErrorCode + the shared enums/types), because Quotes Error is emitted there and status-controller cannot be a dependency of bridge-controller.

I have moved getHashPresenceProperties, getStatusFailurePhase, getSubmitErrorCode / getSubmitFailureTelemetry, and getStatusFailureTelemetry into bridge-status-controller metrics utils

@Battambang
Battambang force-pushed the feat/WPN-1877-failure-telemetry-schema branch 2 times, most recently from fc635b0 to e9a6717 Compare August 27, 2026 15:37
Battambang added a commit that referenced this pull request Aug 27, 2026
…sence

Wire Quotes Error, submit Failed, EVM Failed, poll Failed, Submitted, and Completed to the classifiers from #9947. Mixpanel can now split quote vs broadcast vs source vs dest vs poll without parsing error_message.
Battambang added a commit that referenced this pull request Aug 27, 2026
…sence

Wire Quotes Error, submit Failed, EVM Failed, poll Failed, Submitted, and Completed to the classifiers from #9947. Mixpanel can now split quote vs broadcast vs source vs dest vs poll without parsing error_message.
@Battambang
Battambang force-pushed the feat/WPN-1877-failure-telemetry-schema branch 2 times, most recently from 0a5cd49 to ce2699e Compare August 28, 2026 10:10
Battambang added a commit that referenced this pull request Aug 28, 2026
…sence

Wire Quotes Error, submit Failed, EVM Failed, poll Failed, Submitted, and Completed to the classifiers from #9947. Mixpanel can now split quote vs broadcast vs source vs dest vs poll without parsing error_message.
…classifiers

Add FailurePhase and SwapBridgeErrorCode plus helpers so a follow-up emit can classify failures from the code path and hash presence, without parsing error_message. No Mixpanel payloads change in this commit.
…ields

Quote fetch is pre-tx, so the changelog should not list source_hash_present or destination_hash_present on Quotes Error.
…ntroller

Keep quote-fetch classification in bridge-controller. Hash presence and submit/status helpers belong with the controller that will emit them.
…etrics utils

Fold submit/status failure telemetry helpers into the existing metrics files instead of a new module.
@Battambang
Battambang force-pushed the feat/WPN-1877-failure-telemetry-schema branch from ce2699e to edca7dc Compare August 28, 2026 11:46
Battambang added a commit that referenced this pull request Aug 28, 2026
…sence

Wire Quotes Error, submit Failed, EVM Failed, poll Failed, Submitted, and Completed to the classifiers from #9947. Mixpanel can now split quote vs broadcast vs source vs dest vs poll without parsing error_message.
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.

3 participants