Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
What We’re Building
A Next.js app that pairs Dynamic’s embedded wallets with Iron Finance’s payment rails so a user can:- Complete one-time KYC, register their embedded wallet, and add a SEPA bank account
- Onramp: get a live EUR → USDC quote, execute it, and receive a virtual IBAN (vIBAN) to send a SEPA transfer to. USDC is delivered to the embedded wallet automatically.
- Offramp: get a live USDC → EUR quote, execute it, and receive a deposit address. Sending USDC to it triggers a SEPA payout to the registered IBAN.
- View prior onramps and offramps with live status
How It Works
Iron exposes a quote + execute model around its/api/autoramps endpoint:
- Quote (
GET /api/autoramps/quote) returns a signed, time-limited rate for the requested direction, amount, and rails. - Execute (
POST /api/autoramps) creates an autoramp from that quote. The response includesdeposit_rails— a vIBAN (for onramps) or a deposit crypto address (for offramps) the user sends funds to. - When the deposit arrives, Iron converts and settles automatically to the destination registered on the autoramp (the user’s embedded wallet for onramps, their IBAN for offramps).
- Create an Iron customer
- Complete KYC identity verification (hosted link)
- Sign any required compliance documents
- Register the Dynamic embedded wallet (signed proof of ownership — Travel Rule)
- Add a SEPA bank account
- Done
Building the Application
Project setup
Follow the React Quickstart using the Custom setup path: Ethereum (EVM) with viem, without Wagmi. Scaffold withcreate-next-app and apply the same core packages and DynamicContextProvider setup.
In the Dynamic dashboard: under Chains & Networks enable the networks you’ll use with Iron (e.g. Ethereum, Base). Under Sign-in Methods and Wallets enable Embedded wallets. Under Security → Allowed Origins add the origin you’re running on (for example
http://localhost:3000).Install Dependencies
Configure Environment Variables
.env.local
IRON_ENVIRONMENT is either sandbox or production. The client derives the Iron API base URL from it (https://api.sandbox.iron.xyz vs https://api.iron.xyz). Ask Iron for a sandbox IRON_API_KEY — in sandbox you can simulate KYC approval without real documents.
Configure Dynamic Providers
src/lib/providers.tsx
Server-Side Iron Client
Iron expects anX-API-Key header and an IDEMPOTENCY-KEY on writes. Wrap both in a small server-only client:
src/lib/iron-client.ts
Proxy API Routes
Build thin route handlers that forward to Iron. A few representative ones:src/app/api/iron/customers/route.ts
src/app/api/iron/wallets/self-hosted/route.ts
src/app/api/iron/banks/route.ts
POST /api/iron/customers/[id]/kyc→POST /api/customers/{id}/identifications(returns a hosted verification URL)GET /api/iron/customers/[id]/signings→GET /api/customers/{id}/required-signingsPOST /api/iron/customers/[id]/signings→POST /api/customers/{id}/signingsGET /api/iron/customers/[id]/wallets→GET /api/addresses/crypto/{customer_id}?filter=AllGET /api/iron/customers/[id]/banks→GET /api/addresses/fiat/{customer_id}GET /api/iron/customers/[id]/autoramps→GET /api/customers/{customer_id}/autoramps(transaction history)
Persist Onboarding State with Dynamic Metadata
Store progress inside Dynamic user metadata so users can resume on any device. Use theuseUserUpdateRequest hook to sync.
src/lib/hooks/useKYCMetadata.ts
Build the Onboarding Flow
The onboarding page walks through the six steps. Each step calls one of your proxied routes and advancesstep in metadata.
Step 1 — Create the Iron customer
{ approved: true } to Iron’s sandbox identification endpoint and then auto-signing any required documents.
Step 3 — Sign compliance documents
Ethereum, Polygon, Arbitrum, Base, Solana, Stellar, Citrea). Iron activates customers asynchronously after signings, so retry briefly if the request comes back Customer is not active.
Quote + Execute: Unified Ramp Endpoints
A single/api/onramp route handles both fetching a quote and executing it, discriminated by an action field. /api/offramp mirrors the shape for the other direction. This matches the GET /api/autoramps/quote → POST /api/autoramps pattern on Iron.
src/app/api/onramp/route.ts
recipient_account is the IBAN:
Drive the Ramp UI from Quote + Execute
The client-side flow: the user picks the direction and amount → you fetch a quote → show the rate → the user confirms → you execute and render the deposit rails from the response.autoramp.deposit_rails[0] holds the rails the user sends funds to:
- Onramp — a vIBAN (
iban,bic,beneficiary_name). The user sends a SEPA transfer; USDC is delivered to their embedded wallet automatically. - Offramp — a deposit crypto address. The user sends USDC; EUR lands in their registered IBAN automatically.
Transaction History
List prior ramps withGET /api/iron/customers/[id]/autoramps. Each item includes kind, status, the embedded quote, and the deposit_rails so you can render a detail view without re-fetching.
Run the Application
http://localhost:3000. Make sure that origin is in Security → Allowed Origins in the Dynamic dashboard.
Conclusion
- Embedded Wallets — Dynamic handles wallet creation, auth, and message signing; no seed phrases.
- KYC & Compliance — Iron’s hosted identity flow plus signed proof-of-ownership covers KYC and Travel Rule.
- Onramp — Users get a live quote and a vIBAN; EUR in via SEPA becomes USDC in their embedded wallet.
- Offramp — Users get a live quote and a deposit address; USDC sent there becomes EUR in their registered IBAN.
- Resumable onboarding — All progress is stored in Dynamic user metadata so users can pick up where they left off on any device.