Live demo surface for Stripe stablecoin flows

Ship stablecoin experiences that feel native to your product

Stablecoin showcases on-ramp quotes, checkout concepts, and webhook handling patterns. Clean UI, safe defaults, and production-ready structure.

Next.js App RouterTypeScriptTailwindServer ActionsStripe Webhooks
app/api/webhooks/route.ts — idempotent handler
import { headers } from "next/headers";
import type { NextRequest } from "next/server";

export async function POST(req: NextRequest) {
  const sig = (await headers()).get("stripe-signature");
  const raw = await req.text();

  // Verify signature early — avoid partially mutating state before trust.
  const event = verifyStripeSignature(raw, sig);

  // Idempotency guard: ensure we only apply each event once.
  const applied = await hasProcessed(event.id);
  if (applied) return Response.json({ ok: true });

  switch (event.type) {
    case "crypto.onramp.quote.created":
    case "crypto.onramp.session.updated":
    case "treasury.credit_reversal.created":
    case "transfer.created": {
      await applyStateTransition(event);
      break;
    }
    default: {
      // keep noisy events visible in logs without failing the webhook
      console.info("Unhandled event", event.type);
    }
  }

  await markProcessed(event.id);
  return Response.json({ ok: true });
}

// ——— helpers (server-only) ———
function verifyStripeSignature(raw: string, sig: string | null) {
  if (!sig) throw new Error("Missing signature");
  // stripe.webhooks.constructEvent(raw, sig, process.env.STRIPE_WEBHOOK_SECRET!)
  // return event
  return { id: "evt_123", type: "transfer.created", data: { object: {} } } as any; // demo stub
}

async function hasProcessed(id: string) { return false; }
async function markProcessed(id: string) { /* persist */ }
async function applyStateTransition(event: any) { /* write durable state */ }

What Stablecoin. demonstrates

Opinionated patterns you can lift directly into production. Swap the Stablecoin. surfaces for your actual product flows.