Skip to main content
Switch your user’s embedded wallet to different EVM-compatible networks programmatically. MoonKey makes it easy to change networks for multi-chain applications.

Overview

Switching chains allows your application to interact with different blockchain networks without requiring users to manually change networks. This is particularly useful for:
  • Multi-chain dApps: Support operations across multiple networks
  • Network optimization: Move to cheaper or faster chains for specific operations
  • Feature availability: Access chain-specific protocols and features
  • User experience: Seamlessly switch networks based on app context

React SDK

Basic Usage

To switch the network of an embedded wallet, use the switchChain method from the useSwitchChain hook:
import { useMoonKey } from '@moon-key/react-auth';
import { useSwitchChain } from '@moon-key/react-auth/ethereum';

function SwitchNetworkButton() {
  const { user } = useMoonKey();
  const { switchChain } = useSwitchChain();

  const handleSwitch = async () => {
    if (!user?.wallet) {
      alert('No wallet found');
      return;
    }

    try {
      // Switch to Base (chainId: 8453)
      await switchChain(8453);
      console.log('Switched to Base');
      alert('Network switched successfully!');
    } catch (error) {
      console.error('Failed to switch network:', error);
    }
  };

  return (
    <button onClick={handleSwitch}>
      Switch to Base
    </button>
  );
}

Chain ID Formats

The switchChain method accepts chain IDs in two formats:
// As a decimal number (recommended)
await switchChain(1); // Ethereum Mainnet

// As a hexadecimal string
await switchChain('0x1'); // Ethereum Mainnet
Using decimal numbers is recommended for better readability and consistency across your codebase.

Supported Chains

MoonKey supports switching to any EVM-compatible chain that has been configured in your app. Common networks include:
NetworkChain ID (Decimal)Chain ID (Hex)
Ethereum Mainnet10x1
Sepolia Testnet111551110xaa36a7
Base84530x2105
Optimism100xa
Arbitrum One421610xa4b1
Polygon1370x89
Avalanche C-Chain431140xa86a
BNB Smart Chain560x38
Learn how to configure additional networks in the Configuring EVM Networks guide.

Complete Examples

Multi-Chain Network Selector

'use client';
import { useMoonKey } from '@moon-key/react-auth';
import { useSwitchChain } from '@moon-key/react-auth/ethereum';
import { useState } from 'react';

interface Network {
  name: string;
  chainId: number;
  logo: string;
}

const NETWORKS: Network[] = [
  { name: 'Ethereum', chainId: 1, logo: '🔷' },
  { name: 'Base', chainId: 8453, logo: '🔵' },
  { name: 'Optimism', chainId: 10, logo: '🔴' },
  { name: 'Arbitrum', chainId: 42161, logo: '🔷' },
  { name: 'Polygon', chainId: 137, logo: '🟣' }
];

export default function NetworkSelector() {
  const { user, isAuthenticated } = useMoonKey();
  const { switchChain } = useSwitchChain();
  const [currentChainId, setCurrentChainId] = useState<number>(1);
  const [isSwitching, setIsSwitching] = useState(false);

  const handleSwitchNetwork = async (chainId: number) => {
    if (!user?.wallet) {
      alert('Please connect your wallet first');
      return;
    }

    setIsSwitching(true);

    try {
      await switchChain(chainId);
      setCurrentChainId(chainId);
      console.log(`Switched to chain ${chainId}`);
    } catch (error) {
      console.error('Failed to switch network:', error);
      alert('Failed to switch network. Please try again.');
    } finally {
      setIsSwitching(false);
    }
  };

  if (!isAuthenticated) {
    return <p>Please sign in to switch networks</p>;
  }

  return (
    <div className="network-selector">
      <h2>Select Network</h2>
      
      <div className="networks-grid">
        {NETWORKS.map((network) => (
          <button
            key={network.chainId}
            onClick={() => handleSwitchNetwork(network.chainId)}
            disabled={isSwitching || currentChainId === network.chainId}
            className={`network-button ${
              currentChainId === network.chainId ? 'active' : ''
            }`}
          >
            <span className="network-logo">{network.logo}</span>
            <span className="network-name">{network.name}</span>
            {currentChainId === network.chainId && <span></span>}
          </button>
        ))}
      </div>

      {isSwitching && <p className="switching-text">Switching network...</p>}
    </div>
  );
}

Network Switch with Confirmation

'use client';
import { useMoonKey } from '@moon-key/react-auth';
import { useSwitchChain } from '@moon-key/react-auth/ethereum';
import { useState } from 'react';

export default function NetworkSwitchWithConfirmation() {
  const { user } = useMoonKey();
  const { switchChain } = useSwitchChain();
  const [showConfirmation, setShowConfirmation] = useState(false);
  const [targetChain, setTargetChain] = useState<{ id: number; name: string } | null>(null);

  const requestNetworkSwitch = (chainId: number, chainName: string) => {
    setTargetChain({ id: chainId, name: chainName });
    setShowConfirmation(true);
  };

  const confirmSwitch = async () => {
    if (!user?.wallet || !targetChain) return;

    try {
      await switchChain(targetChain.id);
      alert(`Successfully switched to ${targetChain.name}`);
    } catch (error) {
      console.error('Failed to switch:', error);
      alert('Failed to switch network');
    } finally {
      setShowConfirmation(false);
      setTargetChain(null);
    }
  };

  const cancelSwitch = () => {
    setShowConfirmation(false);
    setTargetChain(null);
  };

  return (
    <div className="network-switch">
      <button onClick={() => requestNetworkSwitch(8453, 'Base')}>
        Switch to Base
      </button>

      {showConfirmation && targetChain && (
        <div className="confirmation-modal">
          <div className="modal-content">
            <h3>Switch Network?</h3>
            <p>
              You are about to switch to <strong>{targetChain.name}</strong> (Chain ID: {targetChain.id})
            </p>
            <p>This will change your wallet's active network.</p>
            <div className="modal-actions">
              <button onClick={confirmSwitch} className="confirm-btn">
                Confirm
              </button>
              <button onClick={cancelSwitch} className="cancel-btn">
                Cancel
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

Error Handling

Handle common errors when switching chains:
import { useMoonKey } from '@moon-key/react-auth';
import { useSwitchChain } from '@moon-key/react-auth/ethereum';

function SafeNetworkSwitch() {
  const { user } = useMoonKey();
  const { switchChain } = useSwitchChain();

  const handleSwitch = async (chainId: number) => {
    if (!user?.wallet) {
      alert('No wallet connected');
      return;
    }

    try {
      await switchChain(chainId);
      console.log('Network switched successfully');
    } catch (error: any) {
      // Handle specific error cases
      if (error.code === 'CHAIN_NOT_CONFIGURED') {
        alert(
          'This network is not configured. Please add it in your app settings.'
        );
      } else if (error.code === 'USER_REJECTED') {
        console.log('User cancelled network switch');
      } else if (error.message?.includes('unsupported')) {
        alert('This chain is not supported by MoonKey');
      } else {
        console.error('Unexpected error:', error);
        alert('Failed to switch network: ' + error.message);
      }
    }
  };

  return (
    <button onClick={() => handleSwitch(8453)}>
      Switch Network
    </button>
  );
}

Getting Current Chain

To get the current chain ID of the wallet:
import { useMoonKey } from '@moon-key/react-auth';
import { useWallets } from '@moon-key/react-auth/ethereum';

function CurrentChainDisplay() {
  const { user } = useMoonKey();
  const { wallets } = useWallets();

  if (!user?.wallet || wallets.length === 0) {
    return <p>No wallet connected</p>;
  }

  const wallet = wallets[0];
  const currentChainId = wallet.chainId;

  return (
    <div className="current-chain">
      <p>Current Chain ID: {currentChainId}</p>
      <p>Current Chain: {getChainName(currentChainId)}</p>
    </div>
  );
}

function getChainName(chainId: number): string {
  const chains: Record<number, string> = {
    1: 'Ethereum Mainnet',
    11155111: 'Sepolia Testnet',
    8453: 'Base',
    10: 'Optimism',
    42161: 'Arbitrum One',
    137: 'Polygon'
  };

  return chains[chainId] || `Chain ${chainId}`;
}

Best Practices

Ensure chains are properly configured in your MoonKeyProvider:
import { MoonKeyProvider } from '@moon-key/react-auth';
import { mainnet, base, optimism, arbitrum } from 'viem/chains';

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    chains: [mainnet, base, optimism, arbitrum]
  }}
>
  {children}
</MoonKeyProvider>
Always inform users when switching networks:
const handleSwitch = async (chainId: number, chainName: string) => {
  // Show loading state
  setIsLoading(true);
  setStatusMessage(`Switching to ${chainName}...`);

  try {
    await switchChain(chainId);
    setStatusMessage(`Successfully switched to ${chainName}`);
  } catch (error) {
    setStatusMessage('Failed to switch network');
  } finally {
    setIsLoading(false);
  }
};
Check chain compatibility before enabling features:
const isFeatureAvailable = (chainId: number): boolean => {
  const supportedChains = [1, 8453, 10]; // Mainnet, Base, Optimism
  return supportedChains.includes(chainId);
};

if (!isFeatureAvailable(currentChainId)) {
  return (
    <div>
      <p>This feature is not available on this network</p>
      <button onClick={() => switchChain(8453)}>
        Switch to Base
      </button>
    </div>
  );
}
Display human-readable names instead of chain IDs:
const CHAIN_NAMES: Record<number, string> = {
  1: 'Ethereum',
  8453: 'Base',
  10: 'Optimism',
  42161: 'Arbitrum'
};

<button onClick={() => switchChain(8453)}>
  Switch to {CHAIN_NAMES[8453]}
</button>
Ensure correct network before executing transactions:
const executeTransaction = async (targetChainId: number) => {
  const currentChainId = wallet.chainId;

  // Check if we're on the right chain
  if (currentChainId !== targetChainId) {
    const confirmed = confirm(
      `This operation requires switching to chain ${targetChainId}. Continue?`
    );

    if (!confirmed) return;

    // Switch to correct chain
    await switchChain(targetChainId);
  }

  // Now execute the transaction
  await sendTransaction({ ... });
};
Provide fallback options when switching fails:
const handleCriticalOperation = async (requiredChainId: number) => {
  try {
    await switchChain(requiredChainId);
    await performOperation();
  } catch (error) {
    // Offer alternative if switch fails
    const useAlternative = confirm(
      'Failed to switch network. Use alternative chain?'
    );

    if (useAlternative) {
      await switchChain(alternativeChainId);
      await performOperation();
    }
  }
};

Troubleshooting

If you get a “chain not configured” error, add the chain to your configuration:
// Add the chain to your MoonKeyProvider
import { MoonKeyProvider } from '@moon-key/react-auth';
import { base } from 'viem/chains';

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    chains: [base] // Add your required chains here
  }}
>
  {children}
</MoonKeyProvider>
See Configuring EVM Networks for more details.
If the network doesn’t seem to switch:
  1. Check wallet state: Ensure wallet is connected
  2. Wait for promise: Make sure to await the switchChain call
  3. Verify chain support: Check if the chain is configured
  4. Check for errors: Look for error messages in console
const handleSwitch = async (chainId: number) => {
  console.log('Current chain:', wallet.chainId);
  
  try {
    await switchChain(chainId);
    console.log('Switch successful');
    console.log('New chain:', wallet.chainId);
  } catch (error) {
    console.error('Switch failed:', error);
  }
};
Avoid switching chains multiple times in quick succession:
let isSwitching = false;

const handleSwitch = async (chainId: number) => {
  if (isSwitching) {
    console.log('Already switching chains, please wait');
    return;
  }

  isSwitching = true;

  try {
    await switchChain(chainId);
  } catch (error) {
    console.error('Switch failed:', error);
  } finally {
    isSwitching = false;
  }
};
If switching with hex strings isn’t working, use decimal numbers:
// ✅ Recommended - use decimal
await switchChain(8453);

// ⚠️ Use hex only if required by your setup
await switchChain('0x2105');

Configure EVM Networks

Add and configure custom EVM networks

Send Transaction

Send transactions on different chains

Get User Wallets

Access wallet information and chain details

Viem Chains

Explore available chain configurations

Next Steps