Skip to content

feat(ramp): surface headless buy errors as data (Phase 7)#29612

Draft
saustrie-consensys wants to merge 1 commit intopoc/headless-buy-phase-6from
saustrie-consensys/headless-buy-phase-7
Draft

feat(ramp): surface headless buy errors as data (Phase 7)#29612
saustrie-consensys wants to merge 1 commit intopoc/headless-buy-phase-6from
saustrie-consensys/headless-buy-phase-7

Conversation

@saustrie-consensys
Copy link
Copy Markdown
Contributor

Description

This PR closes Phase 7 of the incremental Unified Buy (v2) headless buy plan (app/components/UI/Ramp/headless/PLAN.md): headless consumers now receive structured HeadlessBuyError data for hard failures instead of depending on Ramp UI surfaces like banners, ErrorViews, or order toasts.

Reason

  • Phase 6 (#29340) fired onOrderCreated and bypassed the order-details redirect on success, but several failure paths were still UI-coupled. Limit failures could be wrapped into generic display errors, Checkout/WebView failures rendered local UI, and one Transak success path could still show a toast before a headless consumer regained control.

What changed

  • HeadlessBuyErrorCode + failSession — centralizes error normalization in sessionRegistry, preserving explicit error codes/details and closing the session with failed terminal semantics after onError fires.
  • HeadlessHost — uses failSession for auth errors, malformed asset ids, and continueWithQuote rejections so the consumer receives one structured onError callback and one terminal close.
  • useTransakRouting — preserves LimitExceededError as LIMIT_EXCEEDED, forwards checkout-processing failures through onError, and suppresses the manual-bank-transfer toast path when a live headless session owns the flow.
  • Checkout — routes callback-processing failures and primary WebView HTTP errors through onError for headless sessions, then unwinds the ramp stack instead of rendering the checkout ErrorView.
  • BuildQuote — keeps legacy headless params from falling back to banner-only error handling if they are encountered.
  • PLAN.md — marks Phase 7 complete.

References

  • Stacked on Phase 6: #29340 (poc/headless-buy-phase-6). This PR's base is poc/headless-buy-phase-6 so the diff is Phase 7-only.
  • Continues from Phase 5: #29338 (Headless Host + quote-first start).

Tests

  • yarn eslint app/components/UI/Ramp/headless/types.ts app/components/UI/Ramp/headless/sessionRegistry.ts app/components/UI/Ramp/headless/sessionRegistry.test.ts app/components/UI/Ramp/Views/HeadlessHost/HeadlessHost.tsx app/components/UI/Ramp/Views/HeadlessHost/HeadlessHost.test.tsx app/components/UI/Ramp/hooks/useTransakRouting.ts app/components/UI/Ramp/hooks/useTransakRouting.test.ts app/components/UI/Ramp/Views/Checkout/Checkout.tsx app/components/UI/Ramp/Views/Checkout/Checkout.test.tsx app/components/UI/Ramp/Views/BuildQuote/BuildQuote.tsx
  • yarn jest --watchman=false app/components/UI/Ramp/headless/sessionRegistry.test.ts app/components/UI/Ramp/Views/HeadlessHost/HeadlessHost.test.tsx app/components/UI/Ramp/hooks/useTransakRouting.test.ts app/components/UI/Ramp/Views/Checkout/Checkout.test.tsx app/components/UI/Ramp/Views/BuildQuote/BuildQuote.test.tsx
  • yarn lint:tsc was attempted, but the local run is blocked by unrelated existing type errors in SocialLeaderboard tests and controller messenger types.

Changelog

CHANGELOG entry: null

Related issues

Fixes: No GitHub issue — incremental POC on branch saustrie-consensys/headless-buy-phase-7.

Continuity: #29340 (Phase 6 — headless order success callback + stack unwind). #29338 (Phase 5 — Headless Host + quote-first start).

Manual testing steps

Feature: Headless Buy Phase 7 (structured errors)

  Scenario: Native Transak limit failure surfaces as data
    Given the app is an internal build and I am signed in
    And I open Settings → Fiat on-ramp → Headless Buy playground
    When I start a headless native quote that exceeds the user's Transak limit
    Then the playground event log should show `onError({ code: "LIMIT_EXCEEDED" })`
    And the session should close without showing a Ramp-only toast or order-details redirect

  Scenario: Aggregator Checkout failure surfaces as data
    Given I start a headless aggregator quote from the playground
    When the Checkout callback or primary WebView request fails
    Then the consumer should receive `onError({ code: "UNKNOWN", message })`
    And the app should unwind out of the Ramp stack instead of rendering the Checkout ErrorView

  Scenario: Non-headless Buy flow is unchanged
    Given I open Wallet → Buy through the regular flow
    When a quote, checkout, or limit error occurs
    Then the existing Ramp UI surfaces should render as before

Screenshots/Recordings

Before

N/A — Phase 7 changes error/callback plumbing only.

After

N/A — no user-facing UI changes.

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
  • I've tested with a power user scenario
  • I've instrumented key operations with Sentry traces for production performance metrics

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbotv2 metamaskbotv2 Bot added the team-money-movement issues related to Money Movement features label May 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - draft PR

All E2E tests pre-selected.

View GitHub Actions results

@github-actions github-actions Bot added the size-L label May 1, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 1, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

E2E Fixture Validation — Schema is up to date
12 value mismatches detected (expected — fixture represents an existing user).
View details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size-L team-money-movement issues related to Money Movement features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant