What is this about?
Goal
Enable a headless buy flow so external features (like MM Pay confirmation) can launch on-ramp checkout directly, without showing TokenSelection / BuildQuote (this is critical as we already know what we need to buy and the amount) screens, and receive orderId programmatically.
Why We Need This
- We need to integrate buy flow into confirmation UX.
- Current integration requires stitching together internal screens/routing (
BuildQuote, native OTP flow, checkout callbacks), which is brittle.
- Callback handling differs between provider flows (native vs aggregator), and this leaks complexity to feature teams.
- We need
orderId immediately to store in TransactionPayController and later orchestrate post-fiat steps (Relay).
Requested Capability
- Expose a public, supported headless API from the Ramps module/hook (not screen-coupled).
- Allow caller to start buy with preselected context:
assetId
amount
currency (we currently need forced USD)
providerId
paymentMethodId
walletAddress
metadata // Optional object: This needs to be included into order at the end of checkout, so that we can send { transactionId: "XXX"} and can do regular checks on RampsController state to understand if order is filled
- Ramps handles provider-specific auth/checkout/callback internally.
- Ramps returns lifecycle events to caller:
onOrderCreated(orderId, providerId)
onOrderStatusChange(orderId, status)
onCheckoutClosed(reason)
onError(error)
- Preserve ability to render checkout WebView/modal, but caller should not manage intermediate Ramps pages.
- Ensure order creation callback works for both native and aggregator providers consistently.
Expected API Shape (Example)
startHeadlessBuy({
assetId,
amount,
currency: 'USD',
metadata,
providerId,
paymentMethodId,
walletAddress,
onOrderCreated,
onOrderStatusChange,
onClose,
onError,
});
Acceptance Criteria
- No navigation to BuildQuote in headless mode.
- Works for native and aggregator providers.
orderId is reliably emitted when available.
- Caller can close/dismiss and return to its own screen without custom route hacks.
- Callback URL differences are fully abstracted by Ramps.
- Public docs/example added for integration teams.
Non-goals (For This Task)
- UI redesign of existing Ramps screens.
- Reworking non-headless buy flow behavior.
Demo recording after feature implemented
https://github.com/user-attachments/assets/c1735559-32a4-40f1-9c5a-dc3e7b31776a
Stakeholder review needed before the work gets merged
What is this about?
Goal
Enable a headless buy flow so external features (like MM Pay confirmation) can launch on-ramp checkout directly, without showing
TokenSelection/BuildQuote(this is critical as we already know what we need to buy and the amount) screens, and receiveorderIdprogrammatically.Why We Need This
BuildQuote, native OTP flow, checkout callbacks), which is brittle.orderIdimmediately to store inTransactionPayControllerand later orchestrate post-fiat steps (Relay).Requested Capability
assetIdamountcurrency(we currently need forcedUSD)providerIdpaymentMethodIdwalletAddressmetadata// Optional object: This needs to be included intoorderat the end of checkout, so that we can send{ transactionId: "XXX"}and can do regular checks onRampsControllerstate to understand if order is filledonOrderCreated(orderId, providerId)onOrderStatusChange(orderId, status)onCheckoutClosed(reason)onError(error)Expected API Shape (Example)
Acceptance Criteria
orderIdis reliably emitted when available.Non-goals (For This Task)
Demo recording after feature implemented
https://github.com/user-attachments/assets/c1735559-32a4-40f1-9c5a-dc3e7b31776a
Stakeholder review needed before the work gets merged