Skip to main content

What We’re Building

A Next.js application that lets users create an embedded wallet via social login, complete a KYC application, and receive a virtual Visa debit card funded by stablecoins (USDC). The complete flow covers:
  • Social login and automatic wallet creation with Dynamic
  • Gasless transactions via ZeroDev account abstraction
  • Multi-step KYC form submitted to the Rain Card API
  • Virtual card issuance, balance display, and USDC deposits
  • JWT-authenticated API routes using Dynamic’s JWKS endpoint
The full example is on GitHub.

Prerequisites

  • A Dynamic environment ID and API key
  • A Rain Card API key and base URL
  • Node.js 18+

Step 1: Install Dependencies

The key packages:

Step 2: Configure Environment Variables

.env.local

Step 3: Set Up Dynamic with Account Abstraction

Wrap your app with DynamicContextProvider, registering both standard Ethereum connectors and ZeroDev smart wallet connectors. The smart wallet connectors enable gasless USDC deposits from the user’s embedded wallet to their card account.
lib/providers.tsx
Add this to your root layout:
app/layout.tsx

Step 4: Authenticate API Routes with Dynamic JWTs

Dynamic issues a JWT for every authenticated user. Protect your server-side API routes by verifying that token against Dynamic’s JWKS endpoint. This gives you access to the user’s verified credentials (wallet address, email) inside every handler.
lib/dynamic/dynamic-auth.ts
The JWKS URI must include your environment ID in production: https://app.dynamicauth.com/api/v0/sdk/{environmentId}/.well-known/jwks

Step 5: Build the KYC Application Flow

The KYC form collects personal, address, and financial information across three steps. On submit, a server action POSTs to your /api/apply route, which forwards the data to Rain and automatically creates a card.

Application API route

app/api/apply/route.ts
The Rain API auto-approves applications in test mode. In production, applications go through manual KYC review before a card can be created.

Calling the route from the client

Pass the Dynamic auth token as a Bearer token in every request to your API routes:

Step 6: Display Card Details and Balance

Once a card is created, its reference is stored in the user’s Dynamic metadata. Retrieve the card and check the Rain balance from separate API routes, then render them in a card component.

Balance API route

app/api/balance/route.ts

Card details (encrypted)

Card numbers, CVVs, and expiry dates come back from Rain encrypted. Retrieve them per session and render client-side with a show/hide toggle:
app/api/card-details/route.ts

Step 7: Fund the Card with USDC

Users deposit USDC from their embedded wallet to the card’s on-chain account. Use viem’s writeContract to call the ERC-20 transfer function, with ZeroDev sponsoring gas so users don’t need ETH.
hooks/useDepositTokens.ts
Offer preset amounts (5,5, 10, $25) and a custom input so users can quickly top up their card:
components/FundCard.tsx

Complete User Flow


Supported Networks


Last modified on May 25, 2026