What We’re Building
A React (Next.js) app that connects Dynamic’s embedded wallets to Iron’s payment rails, allowing users to:- Complete KYC onboarding and link their bank account
- Offramp: Convert stablecoins (e.g. USDC) to fiat currency (e.g. EUR) via SEPA — send crypto to an Iron-managed wallet address and receive EUR in your bank account
- Onramp: Convert fiat currency (e.g. EUR) to stablecoins (e.g. USDC) — deposit EUR to a virtual IBAN (vIBAN) and receive USDC in your embedded wallet
- View transaction history across onramps and offramps
How It Works
Iron uses an autoramp model: you create a persistent conversion rule that links a source and destination account. Once set up, any deposit to the source automatically converts and settles to the destination — no per-transaction execution needed. 1. One-time onboarding — Before a user can ramp, they must:- Create a customer profile with Iron
- Complete KYC identity verification (via Iron’s hosted link)
- Sign required compliance documents
- Register their Dynamic embedded wallet with Iron (for Travel Rule compliance)
- Add a SEPA bank account (IBAN)
- Offramp autoramp: Specifies crypto source (e.g. USDC on Ethereum) → fiat destination (e.g. EUR to their IBAN). Iron returns a wallet address — the user sends USDC there and EUR lands in their bank.
- Onramp autoramp: Specifies fiat source (e.g. EUR) → crypto destination (e.g. USDC to their embedded wallet). Iron returns a virtual IBAN (vIBAN) — the user sends a SEPA transfer there and USDC lands in their wallet.
Building the Application
Project Setup
Start by creating a new Dynamic project with Next.js:Install Dependencies
Configure Environment Variables
Create a.env.local file with your credentials:
.env.local
IRON_API_KEY. Set NEXT_PUBLIC_IRON_ENVIRONMENT=sandbox while testing — in sandbox mode, KYC approvals can be simulated without real documents.
Configure Dynamic Providers
Updatesrc/lib/providers.tsx to set up Dynamic with React Query:
src/lib/providers.tsx
Create Server-Side Iron API Routes
All calls to Iron are made from Next.js API routes that verify the Dynamic JWT first. This keeps your Iron credentials server-side only. Create a shared Iron client helper atsrc/lib/iron-client.ts:
src/lib/iron-client.ts
src/app/api/iron/customers/route.ts:
src/app/api/iron/customers/route.ts
/api/iron/customers/[id]/wallets— register a crypto wallet with an Iron customer (required for Travel Rule compliance)/api/iron/customers/[id]/banks— add a SEPA bank account (fiat address)/api/iron/autoramps— create an onramp or offramp autoramp/api/iron/autoramps/[id]— fetch autoramp status and deposit details/api/iron/fiatcurrencies— list supported fiat currencies
Persist Onboarding State with Dynamic Metadata
Iron’s onboarding involves multiple steps. Use Dynamic’s user metadata to persist progress across sessions so users don’t have to restart if they close the tab. Createsrc/lib/hooks/useKYCMetadata.ts:
src/lib/hooks/useKYCMetadata.ts
Build the Onboarding Flow
The onboarding page (src/app/onboard/page.tsx) walks users through six steps before they can ramp. Each step calls your proxied Iron API routes.
Step 1 — Create Iron Customer
Collect basic user details and create an Iron customer record:
Build the Ramp Interface
With onboarding complete,src/app/ramp/page.tsx lets users create autoramps for either direction. The UI has two tabs: Offramp (crypto → fiat) and Onramp (fiat → crypto).
Iron’s autoramp model is persistent — once created, the returned address or vIBAN can be used for repeated deposits. There’s no per-transaction “execute” step.
Creating an Offramp Autoramp (Crypto → Fiat)
The user specifies the source crypto token, blockchain, and which registered bank account should receive the fiat payout. Iron returns a wallet address — the user sends crypto there and EUR is automatically deposited to their IBAN.
deposit_rails — the wallet address the user should send crypto to:
deposit_rails — the vIBAN the user should send a SEPA transfer to:
status field reflects the current state: active, pending, paused, or cancelled. An active autoramp is ready to receive deposits.
Load Registered Wallets and Banks
Fetch the user’s registered accounts from Iron to populate the dropdowns in the ramp UI:Run the Application
http://localhost:3000.
Add http://localhost:3000 to the CORS origins in your Dynamic dashboard under Developer Settings → CORS Origins.
Conclusion
This integration demonstrates how Dynamic’s embedded wallets combine with Iron’s payment infrastructure to deliver a compliant onramp and offramp experience:- Embedded Wallets — Dynamic handles wallet creation, authentication, and message signing; no seed phrase management for users
- KYC & Compliance — Iron’s hosted onboarding flow handles identity verification, document signing, and Travel Rule compliance
- Offramp — Users send USDC to an Iron-managed wallet address and receive EUR via SEPA directly in their bank account
- Onramp — Users send EUR via SEPA to a virtual IBAN and receive USDC in their Dynamic embedded wallet
- Persistent Autoramps — Conversion rules are set up once and reused for every subsequent deposit
- Persistent State — Dynamic user metadata keeps onboarding progress safe across sessions