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 exports, optional type fields, and classifiers with tests; no changes to submit, polling, or Mixpanel emission yet.

Overview
Adds structured SwapBridge failure telemetry ahead of a follow-up that will populate Mixpanel payloads. @metamask/bridge-controller introduces FailurePhase and SwapBridgeErrorCode, shared types (HashPresenceData, FailureTelemetryData), optional fields on Unified SwapBridge event context types (failure_phase / error_code on Quotes Error and Failed; source_hash_present / destination_hash_present on Failed, Submitted, and Completed), and getQuoteFetchErrorCode to classify quote-fetch throws without parsing error_message.

@metamask/bridge-status-controller exports helpers to derive the same fields for submit and status failures: hash presence from tx hashes, getStatusFailurePhase (destination → source → poll), submit broadcast telemetry with no hashes, and status failures with status_failed_without_reason. Unit tests cover both packages. Runtime analytics behavior is unchanged until callers wire these helpers into emit paths.

Reviewed by Cursor Bugbot for commit 847c0f6. 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 from c766626 to fc635b0 Compare August 26, 2026 20:55
…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.
@Battambang
Battambang force-pushed the feat/WPN-1877-failure-telemetry-schema branch 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.
…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 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.
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