Перейти к основному содержимому
Base mainnet / viem 2.x / non-custodial

USDC-to-fiat in one SDK call.

offramp() creates the deposit, delegates pricing to the managed vault, and returns a deposit ID. Your users settle on Venmo, Revolut, Wise, Cashapp, Zelle, Monzo, or PayPal without leaving your app.

Webhook delivery~60sUp to 5 retries, HMAC-signed

Agent bundle

Point your agent at these.

Drop the skill into Claude Code or Codex, hand llms-full.txt to any assistant, or scaffold a working app from a starter. Every artifact is machine-readable.

Flow

What the SDK handles.

Validate01

Collect payout details

Validate amount, platform, currency, and payout identifier before the wallet prompt.

PLATFORMS.*.validate()
Sign02

Create the deposit

offramp() registers the payout route, approves USDC, and creates the escrow deposit on Base.

offramp(walletClient, params)
Delegate03

Hand off pricing

Fresh deposits delegate to the managed vault for rate updates. Your backend does not quote.

rateManagerId
Sync04

Watch settlement

Use signed webhooks or deposits() to sync fills, closes, and OTC taker activity.

deposit.filled

First call

One signature, four runtimes.

Browser hooks and class instances can replay within a tab, but bots and workers need real duplicate prevention: call deposits(address) and check your own order database before creating inventory.

import { useOfframp } from "@usdctofiat/offramp/react";
import { CURRENCIES, PLATFORMS } from "@usdctofiat/offramp";

function SellButton({ walletClient }) {
  const { offramp, step, isLoading } = useOfframp({
    integratorId: "your-app",
    referralId: "partner-123",
  });

  return (
    <button
      disabled={isLoading}
      onClick={() =>
        offramp(walletClient, {
          amount: "100",
          platform: PLATFORMS.VENMO,
          currency: CURRENCIES.USD,
          identifier: "alice",
        })
      }
    >
      {isLoading ? step ?? "Working..." : "Sell 100 USDC"}
    </button>
  );
}
ResultConfirmed on Base
depositId0xfa3c...b8821
txHash0x1f4a90b2...d04e
resumedfalse
otcLinknull for public deposits

OTC deposits return a shareable otc.usdctofiat.xyz/d/... link for the approved buyer.

Integration doctor

Five checks before mainnet traffic.

The same invariants ship from the SDK via OFFRAMP_INTEGRATION_CHECKLIST and getOfframpAgentPrompt().

Base mainnet wallet client

Use a viem WalletClient on chain 8453. There is no public sandbox mode.

Delegate-vault pricing

Every SDK-created deposit delegates pricing to the managed Delegate vault.

PayPal/Wise recovery

Catch EXTENSION_REGISTRATION_REQUIRED and drive Peer extension seller registration.

Server-side dedup

Bots and workers must check deposits(address) plus their own order database.

Raw-body webhooks

Verify timestamp.rawBody before JSON parsing.

Agent handoff
Build a USDC-to-fiat integration with @usdctofiat/offramp.

Before coding, read:
- https://usdctofiat.xyz/skills/usdctofiat.md
- https://usdctofiat.xyz/llms.txt

Non-negotiables:
- Inspect OFFRAMP_DEVELOPER_RESOURCES.upstreamSourceTruths before inventing protocol fields, proof payloads, addresses, or extension metadata.
- Use Base mainnet chainId 8453 and a viem WalletClient; do not invent a sandbox.
- SDK-created deposits must delegate to the managed Delegate vault; do not add manual rate controls.
- For PayPal and Wise, catch EXTENSION_REGISTRATION_REQUIRED and run the Peer extension seller-registration flow.
- For bots/workers, deduplicate with deposits(address) plus your own order database; do not rely on idempotencyKey.
- For webhooks, verify timestamp.rawBody with HMAC-SHA256 before parsing JSON.

Source truths

Check upstream before guessing.

The SDK exposes the same map as OFFRAMP_DEVELOPER_RESOURCES.upstreamSourceTruths. Use it when an agent needs protocol fields, proof payloads, contract addresses, or extension behavior.

@zkp2p/sdk

Contracts, Curator clients, payment-method catalogs, and Peer extension metadata.

Curator API

Maker registration, taker tiers, route quotes, and signing behavior.

Attestation service

Seller credential bundles for SAR-capable rails. Do not invent proof fields.

@zkp2p/contracts-v2

EscrowV2, Orchestrator, whitelist hook, and Base mainnet ABIs.

Boundaries

Know what you own.

Keys

Your WalletClient signs

The SDK holds no keys. User wallets and server wallets sign through your viem WalletClient.

Fiat

P2P payout rails stay direct

Buyers pay sellers on Venmo, Revolut, Wise, Cashapp, Zelle, Monzo, or PayPal. The SDK does not route fiat.

Rates

Pricing is delegated

Deposits delegate to the managed vault, so you do not run oracle wiring, quote jobs, or rate crons.

Scaffold

Start with a working wallet flow.

Three templates ship with create-offramp-app. Set a real referralId before shipping partner attribution. Reference scripts and the live demo source live in the starters repo.

--template=nextNext.js + PrivyApp Router, wallet client, sell button, deposit list. Production-shaped.
--template=viteVite + ReactSPA template with the same SDK call and fewer moving parts.
--template=telegram-botTelegram botServer-side maker flow with a managed wallet client (grammy + viem).

Webhooks

Signed lifecycle events.

Register endpoints and rotate signing secrets at peerlytics.xyz/developers#offramp-webhooks — same API key, both products. Every delivery includes X-Usdctofiat-Signature, X-Usdctofiat-Event, and X-Usdctofiat-Delivery-Id. Verify the raw body before JSON parsing.

POST your endpointX-Usdctofiat-Event: deposit.createdX-Usdctofiat-Signature: t=1745392504,v1=8a1c...b9f2X-Usdctofiat-Delivery-Id: 5b1a3f2c-9ad8-4f0a-8c03

Selected event

deposit.created

A deposit landed on Base. Use it to create internal inventory records.

Register at Peerlytics

Ship the first deposit.

Read the API reference for signatures, then mint an API key on Peerlytics when you need webhooks or paid analytics.