feat(bridge): emit SwapBridge failure_phase, error_code, and hash presence - #9949
Conversation
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
70a6371 to
18c3a0d
Compare
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
e405382 to
9fa5c93
Compare
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
add0474 to
45e4590
Compare
45e4590 to
b13d916
Compare
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
ee694b1 to
efbf04a
Compare
…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.
…ed hash presence Promote broadcast, poll, or unknown to source_execution when history already has a source hash, so Mixpanel does not report a pre-broadcast failure after a source hash exists.
Quote fetch is pre-tx, so the emit changelog should not list source_hash_present or destination_hash_present on Quotes Error.
… use Move failure classifiers above getEVMTxPropertiesFromTransactionMeta so ESLint no-use-before-define passes.
…to getBroadcastFailureProperties Match the helper name to failure_phase broadcast rather than the submitTx catch site.
…to getFailurePropertiesFromHistory The helper is used for any Failed emit that has history hashes, not only status polling.
Keep the helper internal; only the controller emit path uses it.
…troller BridgeController no longer invents failure_phase / error_code / hash flags for Failed events; it only enriches and forwards caller values. The Failed event input type now requires FailureTelemetryProperties so typed callers omitting the four fields fail at build time. BridgeStatusController owns the runtime fallbacks on its no-history Failed path (submit catch / any future caller that bypasses classification), defaulting to unknown / false when the caller omits them. The history path already derives all four fields from getFailurePropertiesFromHistory, so it is unchanged.
8fbba64 to
6fd5164
Compare
|
Related to Bugbot comment with the Approval phase: Using a persistent "approval was involved" flag as a proxy for "approval failed" is not the same thing. The net effect is that the Approval phase can mislabel non-EVM source-submit failures as approval, which defeats the diagnosability goal of the PR.
@micaelae From adding the approval phase. Not sure we can have this phase in the scope of this PR. |
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
| ); | ||
| expect(failedCall?.[2]).toStrictEqual( | ||
| expect.objectContaining({ | ||
| failure_phase: 'source_execution', |
There was a problem hiding this comment.
Bridge status polling doesn't start until the src hash is available. Shouldn't this result in a destination_execution failure phase?
| failure_phase: 'source_execution', | |
| failure_phase: 'destination_execution', |
There was a problem hiding this comment.
source_execution is correct here. The test polls once and gets MockStatusResponse.getFailed() which sets srcChain.txHash (source hash present) but destChain with no txHash (destination hash absent). Logic for this is in getStatusFailurePhase from src/utils/metrics.ts: destination_execution requires the destination hash to be present which it is not in this case.
Phase is categorized poll regarding the hash presence because there is no thrown error for status failure. It has to be considered as a fallback where nothing is known, the status endpoint reported FAILED with no detail and no hash at source and destination.
| @@ -6691,6 +6798,7 @@ exports[`BridgeStatusController subscription handlers TransactionController:tran | |||
| "quoted_vs_used_gas_ratio": 0, | |||
| "security_warnings": [], | |||
| "slippage_limit": 0, | |||
| "source_hash_present": true, | |||
There was a problem hiding this comment.
This test is for a failed approval, for which I expect the suggested failure_phase and source_hash_present properties. Can this case be covered in this PR?
| "failure_phase": "approval", | |
| "feature_id": "unified_swap_bridge", | |
| "gas_included": false, | |
| "gas_included_7702": false, | |
| @@ -6691,6 +6798,7 @@ exports[`BridgeStatusController subscription handlers TransactionController:tran | |
| "quoted_vs_used_gas_ratio": 0, | |
| "security_warnings": [], | |
| "slippage_limit": 0, | |
| "source_hash_present": false, |
There was a problem hiding this comment.
Seeing the same property mismatches for these test cases
should track failed event for bridge transaction if approval is droppedTron swap with approval should handle approval transaction errorsEVM bridge should throw an error if approval tx fails
There was a problem hiding this comment.
The "approval" phase is trying to introduce some edge cases logic that is not straightforward to handle in the scope of this PR. The risk here is having incoherent telemetry as reported previously by Bugbot.
It is better to handle this case in another ticket as a better enhancement with phase.
Reverting Approval addition.
6fd5164 to
75e7d79
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c73f0b7. Configure here.
|
LGTM |

Explanation
Stacked on #9947 (schema + classifiers only). This PR emits the new Mixpanel fields so Failed is no longer a blended "on-chain" rate. Every value comes from the code path and hash presence, never from
error_message.What each event emits
bridge-controllerfailure_phase=quote,error_codefromgetQuoteFetchErrorCode(error)executeSubmitStrategy)bridge-status-controllergetSubmitFailureTelemetry(error)→broadcast, both hash flagsfalsebridge-status-controllersource_executionwhen the tx has a hash, elsebroadcast;error_codeunknownwhen the tx carries an error, elsemissing_error_objectbridge-status-controllerdestination_execution>source_execution>poll, from history src/dest hashesbridge-status-controllerfalse(emit is still before the submit strategy)bridge-status-controllerAlso added
promoteFailurePhase(new inbridge-status-controller/src/utils/metrics.ts) reconciles the phase reported by the emitting path with the combined hash presence — history flags OR-ed with any caller-supplied flags. It upgrades todestination_executionon a dest hash and tosource_executionon a source hash, but only frombroadcast/poll/unknown, so a genuine no-hash broadcast failure is never reclassified aspoll.On Failed, a caller-supplied
failure_phasewins over the status-derived one, and itserror_codeis kept (defaulting tounknown); when the caller supplies no phase, both come fromgetStatusFailureTelemetry.Ownership
bridge-status-controllerowns submit, poll, and EVM emit.bridge-controllerowns Quotes Error and the Failed property defaults — when a client omits them, Failed falls back tofailure_phase=unknown,error_code=unknown, and both hash flagsfalse, so the properties are always present in the payload.After #9947 merges, retarget this PR to
main.References
Checklist
Note
Low Risk
Changes are limited to analytics payload shaping and classifier wiring; swap/bridge execution behavior is unchanged.
Overview
This PR wires up emission of the SwapBridge failure telemetry schema from #9947 so Mixpanel events carry structured
failure_phase,error_code, and hash-presence fields derived from code paths (noterror_message).bridge-controlleraddsfailure_phase=quoteand a classifiederror_codeon Quotes Error (viagetQuoteFetchErrorCodein the quote-fetch catch and in the event property builder). Failed event assembly is adjusted so client-supplied failure fields merge correctly with quote/request metadata.bridge-status-controllerattaches telemetry across the trade lifecycle: Submitted always emits both hash flags asfalse; Completed adds hash presence from bridge history; Failed combines broadcast catch helpers (getBroadcastFailureProperties), history-based classification (getFailurePropertiesFromHistory), EVM tx-meta fields, andpromoteFailurePhaseso phases align with combined hash presence without turning no-hash broadcast failures intopoll. Failed events without a history item still get explicit defaults for all four fields.Public helper renames:
getSubmitFailureTelemetry→getBroadcastFailureProperties,getStatusFailureTelemetry→getFailurePropertiesFromHistory. The Failed event type now requiresFailureTelemetryPropertiesinstead of optional telemetry data.Reviewed by Cursor Bugbot for commit c73f0b7. Bugbot is set up for automated code reviews on this repo. Configure here.