feat(funding): useFundingMethods + useOnramp; buy flow on the session engine - #315
feat(funding): useFundingMethods + useOnramp; buy flow on the session engine#315joalavedra wants to merge 8 commits into
Conversation
…at rows
Headless fiat per docs/web2-onramp.contract.ts §5, on the funding
session state machine:
- useFundingMethods(session): server-resolved method rows
(GET /v2/funding/sessions/{id}/methods) — provider hidden, region
routed. On failure the rows are EMPTY, never a static fallback.
- useOnramp(session, method): open() commits
setPaymentMethod({type:'onramp'}), presents the checkout
(popup/redirect/manual) and polls the session to a terminal status —
the popup is never the source of truth. quote() prices the route with
the exact provider a commit would use.
- PaymentMethod becomes a crypto | onramp union (+ cryptoPaymentMethod
narrowing helper); FundingClient gains sessions.methods/quote;
useFundingClient extracted so every funding hook resolves the same
client. All exported.
Deposit hub semantics fixed (no dead or illegal rows):
- fiat rows render only once resolved for the buyer's region — no
static fallback while loading or on failure (compliance, not UX)
- the 'default to Stripe when unresolved' fallback is gone; MoonPay is
no longer treated as executable client-side
- hardcoded fee/limit subtitle claims removed — real numbers come from
the live quote
- uiConfig.funding.country override (QA + apps that know the region +
local dev without a CDN geo header)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…components
The fiat buy now runs on the funding-session state machine end to end:
- Buy (amount screen) mints a fresh funding session per mount and
prices the entered amount with the session-scoped quote — the exact
provider a commit would resolve. Continue is provider-less.
- BuyProcessing commits setPaymentMethod({type:'onramp'}) via
useOnramp: the server resolves the provider, the hosted checkout
opens, and the SESSION status (webhook-driven) decides the outcome —
the popup.closed/URL-sniffing machinery is gone.
- stripeApi/coinbaseApi/onrampQuoteApi/providers.ts deleted — no
provider-specific code remains in the React SDK; BuyFormState carries
{method, session} instead of a providerId.
- Apple Pay gates on ApplePaySession.canMakePayments() (desktop Safari
included); the mobile-only wallet-pay gate is gone. Google Pay stays
UA-gated until isReadyToPay is wired.
- Buy screen inline styles replaced with styled-components.
- Layering fixed: useFundingTarget, onrampMethodsApi, onrampEndpoints
and fundingSources move to hooks/openfort — hooks no longer import
from components, so the funding engine is extractable as a module.
- OnrampPaymentMethod carries providerClientSecret (Stripe embedded
onramp element enabler).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
open() now accepts the OTP-verified walletPay identity (email, US phone, verification + Guest-Checkout agreement timestamps) and forwards it, so apple_pay/google_pay commit a Coinbase native order. The hook presents only the iframe angle; a native commit's url is the in-page Pay-button link, surfaced via url + the new angle field for the caller to mount — never auto-opened. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build the in-modal flow for the native angle so apple_pay/google_pay work end to end: - Amount step (Buy): shows Coinbase's Guest-Checkout consent for wallet pay, gates Continue on it, and stamps agreementAcceptedAt. Routes to contact capture, or straight to commit when the buyer's identity is already complete. - WalletPayContact: gathers email (if missing) + US phone and OTP-verifies the phone via Openfort's OWN phone OTP, stamping phoneNumberVerifiedAt on success (no server verifiedAt exists). - BuyProcessing: passes the verified walletPay identity to open() and mounts Coinbase's in-page Pay button (iframe, allow="payment") for the native angle instead of the hosted-popup path; the manual-advance fallback is suppressed while the buyer is in the Pay sheet. - New themed Checkbox primitive (none existed) and a pure walletPay helper module (isWalletPayMethod / isCompleteWalletPay / needsWalletPayCapture), unit-tested. New buyWalletPayContact route + WalletPayDraft on the buy form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Coinbase's headless onramp docs require sandbox="allow-scripts allow-same-origin" and referrerpolicy="no-referrer" (alongside allow="payment") for the in-page Apple/Google Pay sheet to run. Add them to the native Pay-button frame. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Funding v2 — full PR stack (5 PRs / 4 repos) Funding v2 = web2 onramps (Apple/Google Pay, Card, Bank) + server-side region+asset routing + the execute path. It spans:
Suggested order: #1086 → activation steps → js#327 → react#311 → react#315 → dash#212. The SDK/dash degrade gracefully until the api endpoints are live. Activation after api merges: Still open (next sprint): cross-repo (auto-posted to cross-link the stack) |
Wallet-pay contact capture previously only format-checked an email it collected; now it sends and verifies an Openfort email OTP, mirroring the phone step. Skipped entirely when auth already collected the email. When the phone is already verified, a successful email verification completes the identity and hands off to commit directly. Adds verifyEmailOtp (session-less verification) to useEmailOtpAuth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Apple/Google Pay no longer imply the native Coinbase order client-side: the amount step resolves the session's methods and only requires the Guest-Checkout consent + email/phone OTP capture when the server resolved the method to the native sheet. Wallet pay resolved to the hosted checkout (rest-of-world, or no project CDP creds) commits like a card. The resolved angle rides on buyForm so the commit screen's stale-state guard applies the same rule; unknown angle still assumes native. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Two additions:
Biome + first-party tsc clean, 248 tests, rollup green. 🤖 Generated with Claude Code |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stacks on #311. Puts the fiat rails on the funding-session state machine and exposes them headless.
useFundingMethods(session)anduseOnramp(session, method)— the contract hooks. Server-resolved rows (provider hidden); an angle-agnosticopen()that commits the onramp payment method and follows the SESSION status (not the popup) to a terminal state.stripeApi/coinbaseApi/onrampQuoteApi/providersfiles are removed;BuyFormStatecarries{ method, session }instead of a provider id.ApplePaySession.canMakePayments()(desktop Safari included).hooks/openfortso hooks no longer import from components — the funding engine is now an extractable module.242 unit tests. Depends on the api onramp endpoints (openfort-xyz/api#1086) and the openfort-js onramp client.
🤖 Generated with Claude Code