Developers · Apps

Build a sell-USDC flow users can actually finish.

A good off-ramp app is mostly boring state management: collect the route, let the wallet sign, recover extension-gated payment methods, show a deposit link, and reconcile lifecycle events after the tab closes.

01

Frontend path

  1. 1Collect amount, payment platform, fiat currency, and payout identifier.
  2. 2Pass the connected viem WalletClient to useOfframp() or createOfframp({ walletClient }).
  3. 3Surface progress states: approving, registering, depositing, confirming, delegating, restricting, resuming, done.
  4. 4Catch EXTENSION_REGISTRATION_REQUIRED for PayPal and Wise, then drive usePeerExtensionRegistration(platform).
  5. 5Call deposits(address) on page load so a refresh does not strand an in-flight seller.
02

State you should store

FieldReason
depositIdPrimary handle for close(), OTC links, and support
txHashProof that the user signed and broadcast the deposit transaction
platform + currencyRoute display, support, and analytics segmentation
identifier labelHuman-readable payout reference; do not store secrets
integratorIdStable attribution for product telemetry and support
03

UX constraints

  • The SDK targets Base mainnet; there is no public sandbox. Test with the 1 USDC minimum.
  • Every SDK-created deposit delegates pricing to the Delegate vault. Do not present manual rate controls for this path.
  • Fiat stays outside the SDK. The buyer and seller settle directly inside the selected payment app.
  • Treat webhooks as lifecycle hints, then reconcile narrow owner state with deposits(); use Peerlytics API for broader market data and analytics.

Common questions

Should a wallet app use the standalone function or the React hook?

Use the React hook when you want built-in loading, progress, error, and result state. Use createOfframp({ walletClient }) when your app has its own state machine.

What should I show when PayPal or Wise fails registration?

Catch EXTENSION_REGISTRATION_REQUIRED, prompt the user to install or connect the Peer extension, complete seller-credential capture through usePeerExtensionRegistration(), then retry the original deposit.