Skip to main content

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
If you want to take a quick look at the final code, check out the GitHub repository.

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 SecurityAllowed Origins, add the origin where the app runs (for example http://localhost:3000).

Install dependencies

Configure Environment

.env

Initialize Dynamic Client

Create src/lib/dynamic.ts to set up the JS SDK client and register the EVM extension:
src/lib/dynamic.ts

Create Wallet Context

Create src/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

Create src/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

Create src/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
The full component with state management, token loading, and UI rendering is available in the GitHub repository.

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:
  1. Reads the current allowance via publicClient.readContract
  2. If insufficient, calls walletClient.writeContract to approve the Mayan Forwarder contract
  3. 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

Open http://localhost:3000.

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.

Additional Resources

Last modified on June 24, 2026