Wagmi + Dynamic Integration

This integration combines Wagmi’s type-safe React hooks with Dynamic’s infrastructure to provide advanced wallet management capabilities. This approach gives you the best of both worlds: Wagmi’s excellent developer experience and Dynamic’s powerful wallet features.

Prerequisites

  • React application
  • Node.js and npm/yarn
  • Dynamic account and environment ID
  • Basic understanding of React hooks

Step 1: Create React Application

Create a new React application with TypeScript:

npx create-react-app my-sei-dapp --template typescript
cd my-sei-dapp

Step 2: Install Dependencies

Install the required packages:

npm install @dynamic-labs/sdk-react-core @dynamic-labs/wagmi-connector @dynamic-labs/ethereum wagmi viem @tanstack/react-query @sei-js/sei-global-wallet

Step 3: Get Dynamic Environment ID

1

Sign up for Dynamic

Visit dynamic.xyz and create a free account

2

Create a new project

Click “Create Project” and fill in your project details

3

Get your Environment ID

Copy the Environment ID from your project dashboard

4

Configure allowed origins

Add your development URL (e.g., http://localhost:3000) to allowed origins

Step 4: Configure Your Application

Update your App.tsx file with the complete Wagmi + Dynamic configuration:

App.tsx
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createConfig, WagmiProvider, useAccount } from 'wagmi';
import { http } from 'viem';
import { sei, seiTestnet } from 'viem/chains';

// Dynamic imports
import { DynamicContextProvider, DynamicWidget } from '@dynamic-labs/sdk-react-core';
import { DynamicWagmiConnector } from '@dynamic-labs/wagmi-connector';
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';

// Import Sei Global Wallet for EIP-6963 discovery
import '@sei-js/sei-global-wallet/eip6963';

const queryClient = new QueryClient();

const wagmiConfig = createConfig({
  chains: [sei, seiTestnet],
  transports: {
    [sei.id]: http('https://evm-rpc.sei-apis.com'),
    [seiTestnet.id]: http('https://evm-rpc-testnet.sei-apis.com')
  }
});

export default function App() {
  return (
    <DynamicContextProvider
      settings={{
        environmentId: 'REPLACE-WITH-YOUR-ENVIRONMENT-ID', // <- Replace with your Environment ID
        walletConnectors: [EthereumWalletConnectors],
        overrides: {
          evmNetworks: (networks) => [
            ...networks,
            {
              blockExplorerUrls: ['https://seitrace.com'],
              chainId: 1329,
              chainName: 'Sei Network',
              iconUrls: ['https://app.dynamic.xyz/assets/networks/sei.svg'],
              name: 'Sei',
              nativeCurrency: {
                decimals: 18,
                name: 'Sei',
                symbol: 'SEI'
              },
              networkId: 1329,
              rpcUrls: ['https://evm-rpc.sei-apis.com'],
              vanityName: 'Sei Mainnet'
            },
            {
              blockExplorerUrls: ['https://seitrace.com/?chain=testnet'],
              chainId: 1328,
              chainName: 'Sei Testnet',
              iconUrls: ['https://app.dynamic.xyz/assets/networks/sei.svg'],
              name: 'Sei Testnet',
              nativeCurrency: {
                decimals: 18,
                name: 'Sei',
                symbol: 'SEI'
              },
              networkId: 1328,
              rpcUrls: ['https://evm-rpc-testnet.sei-apis.com'],
              vanityName: 'Sei Testnet'
            }
          ]
        }
      }}
    >
      <WagmiProvider config={wagmiConfig}>
        <QueryClientProvider client={queryClient}>
          <DynamicWagmiConnector>
            <div className="app-container">
              <h1>Dynamic + Wagmi + Sei Global Wallet</h1>
              <DynamicWidget />
              <AccountInfo />
            </div>
          </DynamicWagmiConnector>
        </QueryClientProvider>
      </WagmiProvider>
    </DynamicContextProvider>
  );
}

function AccountInfo() {
  const { address, isConnected, chain } = useAccount();

  if (!isConnected) {
    return <p>Connect your wallet to see account info</p>;
  }

  return (
    <div className="account-info">
      <h3>Account Information</h3>
      <p>
        <strong>Address:</strong> {address}
      </p>
      <p>
        <strong>Chain:</strong> {chain?.name} (ID: {chain?.id})
      </p>
      <p>
        <strong>Connected:</strong> {isConnected ? 'Yes' : 'No'}
      </p>
    </div>
  );
}

Step 5: Add Environment ID

Replace 'REPLACE-WITH-YOUR-ENVIRONMENT-ID' with your actual Dynamic Environment ID from your dashboard.

Keep your Environment ID secure and don’t commit it to public repositories. Consider using environment variables for production deployments.

Step 6: Run Your Application

Start your development server:

npm start

Your application will be available at http://localhost:3000.

Expected Behavior

Once configured correctly, your application will:

  1. Show Dynamic Widget: Dynamic’s wallet connection interface appears
  2. Support Multiple Wallets: Users can choose from various wallet options including Sei Global Wallet
  3. Sei Network Support: Both Sei mainnet and testnet are available
  4. Social Login: Sei Global Wallet provides social authentication options
  5. Wagmi Integration: All Wagmi hooks work seamlessly with connected wallets

Dynamic Features

Dynamic provides advanced features beyond basic wallet connection:

Multi-Wallet Support

Users can connect multiple wallets simultaneously

Social Authentication

Support for Google, Twitter, Discord, and email login

User Analytics

Detailed analytics on user behavior and wallet usage

Custom Branding

White-label the wallet experience to match your brand

Advanced Configuration

Custom Authentication Methods

Configure specific authentication methods:

<DynamicContextProvider
  settings={{
    environmentId: 'YOUR-ENVIRONMENT-ID',
    walletConnectors: [EthereumWalletConnectors],
    initialAuthenticationMode: 'connect-and-sign',
    authenticationMethods: ['email', 'google', 'twitter'],
    // ... other settings
  }}
>

Custom Styling

Customize the Dynamic widget appearance:

<DynamicContextProvider
  settings={{
    environmentId: 'YOUR-ENVIRONMENT-ID',
    walletConnectors: [EthereumWalletConnectors],
    cssOverrides: `
      .dynamic-widget-card {
        background: #f5f5f5;
        border-radius: 12px;
      }
      .dynamic-widget-button {
        background: #9E1F19;
        color: white;
      }
    `,
    // ... other settings
  }}
>

Network Switching

Handle network switching with Dynamic:

import { useDynamicContext } from '@dynamic-labs/sdk-react-core';

function NetworkSwitcher() {
  const { primaryWallet } = useDynamicContext();

  const switchToSeiMainnet = async () => {
    if (primaryWallet) {
      await primaryWallet.switchNetwork({ networkChainId: 1329 });
    }
  };

  const switchToSeiTestnet = async () => {
    if (primaryWallet) {
      await primaryWallet.switchNetwork({ networkChainId: 1328 });
    }
  };

  return (
    <div>
      <button onClick={switchToSeiMainnet}>Switch to Sei Mainnet</button>
      <button onClick={switchToSeiTestnet}>Switch to Sei Testnet</button>
    </div>
  );
}

Using Wagmi Hooks

With this setup, you can use all Wagmi hooks as normal:

import { useBalance, useContractRead, useContractWrite } from 'wagmi';

function WalletBalance() {
  const { address } = useAccount();
  const { data: balance, isLoading } = useBalance({
    address: address
  });

  if (isLoading) return <div>Loading balance...</div>;

  return (
    <div>
      Balance: {balance?.formatted} {balance?.symbol}
    </div>
  );
}

Troubleshooting

Production Considerations

Environment Variables

Use environment variables for sensitive configuration:

// .env.local
REACT_APP_DYNAMIC_ENVIRONMENT_ID=your_environment_id_here

// In your component
environmentId: process.env.REACT_APP_DYNAMIC_ENVIRONMENT_ID!

Error Boundaries

Implement error boundaries for better error handling:

import { ErrorBoundary } from 'react-error-boundary';

function ErrorFallback({error}: {error: Error}) {
  return (
    <div role="alert">
      <h2>Something went wrong:</h2>
      <pre>{error.message}</pre>
    </div>
  );
}

// Wrap your app
<ErrorBoundary FallbackComponent={ErrorFallback}>
  <App />
</ErrorBoundary>

Next Steps

Additional Resources