feat(ramp): surface headless buy errors as data (Phase 7)#29612
Conversation
|
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. |
…adless-buy-phase-7 # Conflicts: # app/components/UI/Ramp/Views/Checkout/Checkout.test.tsx # app/components/UI/Ramp/Views/Checkout/Checkout.tsx # app/components/UI/Ramp/headless/PLAN.md # app/components/UI/Ramp/hooks/useTransakRouting.test.ts # app/components/UI/Ramp/hooks/useTransakRouting.ts
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection: Key changes:
These changes affect the fiat on-ramp buy flow error handling paths, which are tested by SmokeMoney. The changes could affect: buy flow error states, limit exceeded handling, auth failure propagation, and WebView error handling. No other feature areas (swap confirmations, wallet platform, network, accounts) are touched. SmokeMoney's description covers 'ramps: unified buy, sell/off-ramp, region-aware flows' which directly covers these code paths. Per SmokeMoney tag description: 'When selecting SmokeMoney for Card Add Funds or similar flows that execute swaps, also select SmokeSwap and SmokeConfirmations.' However, these changes are specifically about error handling in the headless buy session registry, not about swap execution or confirmation flows. The error paths being modified are failure/cancellation paths, not the happy path that triggers confirmations. Therefore, SmokeConfirmations is not required here. Performance Test Selection: |
|



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 structuredHeadlessBuyErrordata for hard failures instead of depending on Ramp UI surfaces like banners, ErrorViews, or order toasts.Reason
onOrderCreatedand 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 insessionRegistry, preserving explicit error codes/details and closing the session with failed terminal semantics afteronErrorfires.HeadlessHost— usesfailSessionfor auth errors, malformed asset ids, andcontinueWithQuoterejections so the consumer receives one structuredonErrorcallback and one terminal close.useTransakRouting— preservesLimitExceededErrorasLIMIT_EXCEEDED, forwards checkout-processing failures throughonError, 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 throughonErrorfor 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
poc/headless-buy-phase-6). This PR's base ispoc/headless-buy-phase-6so the diff is Phase 7-only.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.tsxyarn 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.tsxyarn lint:tscwas 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
Screenshots/Recordings
Before
N/A — Phase 7 changes error/callback plumbing only.
After
N/A — no user-facing UI changes, but here's a video anyways.
Screen.Recording.2026-05-06.at.4.02.27.PM.mov
Pre-merge author checklist
Performance checks (if applicable)
Pre-merge reviewer checklist
Note
Medium Risk
Changes error handling and navigation unwinding for headless Unified Buy flows across
HeadlessHost,Checkout, anduseTransakRouting, which could affect session lifecycle and user recovery paths if misrouted. Scope is contained to headless-mode branches with added test coverage, but touches core buy/checkout flow control.Overview
Headless buy errors are now surfaced as structured data instead of Ramp UI. A new
failSessionhelper inheadless/sessionRegistrynormalizes thrown/native errors intoHeadlessBuyError(includingLIMIT_EXCEEDEDmapping and optionaldetails), firesonError, and closes the session with failed terminal semantics.Headless flows now consistently use this failure path:
HeadlessHostforwards auth/asset/continue failures viafailSession,Checkoutsends callback-processing and primary WebView HTTP errors throughonErrorand pops the ramp stack instead of rendering an ErrorView, anduseTransakRoutingpreservesLimitExceededErrordetails, suppresses toasts when a live headless session is present, and routes post-checkout processing failures throughfailSession+ stack unwind. Tests are updated/added to cover these headless-specific error paths and regression guards.Reviewed by Cursor Bugbot for commit 7bdaa03. Bugbot is set up for automated code reviews on this repo. Configure here.