What We’re Building
A cross-chain swap application built with Next.js that integrates Dynamic’s JavaScript SDK (no React SDK dependency) with Mayan’s bridge aggregator. This app enables users to:- Sign in with email OTP, Google, or an injected wallet via a fully custom auth UI
- Execute token swaps from any EVM network to EVM or non-EVM destinations (Solana, Sui, HyperCore)
- Access competitive exchange rates through Mayan’s routing system
- Track swap progress in real-time
Building the Application
Project setup
This recipe uses Next.js with Dynamic’s JavaScript SDK (@dynamic-labs-sdk/client and @dynamic-labs-sdk/evm) plus @dynamic-labs-sdk/react-hooks for reactive auth state. All signing and wallet creation uses the headless JS SDK; the react-hooks package only provides DynamicProvider, useUser, and useGetWalletAccounts for managing auth state in React without a full UI SDK dependency.
Dashboard: Under Chains & Networks, enable every EVM network your Mayan routes use (Ethereum, Polygon, BSC, Avalanche, Arbitrum, Optimism, Base). Under Sign-in Methods and Wallets, enable what your flow needs (including Embedded wallets). Under Security → Allowed Origins, add the origin where the app runs (for example
http://localhost:3000).Install dependencies
Configure Environment
.env
Initialize Dynamic Client
Createsrc/lib/dynamic.ts to set up the JS SDK client and register the EVM extension:
src/lib/dynamic.ts
Create Wallet Context
Createsrc/lib/providers.tsx. DynamicProvider (from @dynamic-labs-sdk/react-hooks) owns reactive auth state; InnerProviders reads it via useUser() and useGetWalletAccounts(). The core signing and wallet creation logic still uses the headless JS SDK:
src/lib/providers.tsx
Define Supported Chains
Createsrc/constants/chains.ts. The FROM chain must be EVM (the wallet signs the transaction); the TO chain can be any chain Mayan supports:
src/constants/chains.ts
Create Multi-Chain Swap Component
Createsrc/components/MultiChainSwap.tsx. The core integration uses getSwapFromEvmTxPayload to build the transaction and createWalletClientForWalletAccount to send it via the user’s EVM wallet:
src/components/MultiChainSwap.tsx
How It Works
Technical Implementation
Authentication (JS SDK + react-hooks for reactive state)
createDynamicClient→ initializes the headless Dynamic client with your environment ID.addEvmExtension→ registers EVM wallet support (called client-side only).sendEmailOTP/verifyOTP→ email magic-link authentication.authenticateWithSocial→ social OAuth (Google, etc.) with redirect handling.connectAndVerifyWithWalletProvider→ connect MetaMask or other injected wallets.createWaasWalletAccounts→ auto-create an embedded EVM wallet on sign-up.
Chain Switching
Before any transaction,wallet_switchEthereumChain is called on the Dynamic wallet client to ensure the user’s wallet is on the correct network. A custom viem transport is then created that proxies all requests through the Dynamic wallet, with eth_chainId overridden to match the target chain.
Quote Generation
fetchQuote from @mayanfinance/swap-sdk accepts the from/to token contracts and chain keys, returning one or more route candidates. The integration uses the first (best) quote.
ERC-20 Approval
Before executing a non-native token swap, the integration:- Reads the current allowance via
publicClient.readContract - If insufficient, calls
walletClient.writeContractto approve the Mayan Forwarder contract - Waits for the approval receipt before proceeding
Swap Execution
getSwapFromEvmTxPayload builds the EVM transaction payload (no ethers.js signer required). The payload is sent directly via walletClient.sendTransaction.
Supported Chains
Referral Fee Setup
Run the Application
Conclusion
This recipe demonstrates how to build a production-grade cross-chain swap interface using Dynamic’s JavaScript SDK with@dynamic-labs-sdk/react-hooks for reactive auth state. All signing, wallet creation, and session management use the headless JS SDK; the react-hooks package adds lightweight DynamicProvider/useUser/useGetWalletAccounts bindings without pulling in a full UI SDK.