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:
Using useSwitchChain
Using Wallet Method
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 >
);
}
import { useMoonKey } from '@moon-key/react-auth' ;
import { useWallets } from '@moon-key/react-auth/ethereum' ;
function SwitchNetworkButton () {
const { user } = useMoonKey ();
const { wallets } = useWallets ();
const handleSwitch = async () => {
if ( wallets . length === 0 ) {
alert ( 'No wallet found' );
return ;
}
const wallet = wallets [ 0 ];
try {
// Switch to Optimism (chainId: 10)
await wallet . switchChain ( 10 );
console . log ( 'Switched to Optimism' );
alert ( 'Network switched successfully!' );
} catch ( error ) {
console . error ( 'Failed to switch network:' , error );
}
};
return (
< button onClick = { handleSwitch } >
Switch to Optimism
</ button >
);
}
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:
Network Chain ID (Decimal) Chain ID (Hex) Ethereum Mainnet 1 0x1 Sepolia Testnet 11155111 0xaa36a7 Base 8453 0x2105 Optimism 10 0xa Arbitrum One 42161 0xa4b1 Polygon 137 0x89 Avalanche C-Chain 43114 0xa86a BNB Smart Chain 56 0x38
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
Configure chains before switching
Provide clear user feedback
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 );
}
};
Handle chain-specific features gracefully
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 >
);
}
Use descriptive chain names
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 >
Validate chain before operations
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 ({ ... });
};
Handle network switch failures gracefully
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
Chain not configured error
If the network doesn’t seem to switch:
Check wallet state : Ensure wallet is connected
Wait for promise : Make sure to await the switchChain call
Verify chain support : Check if the chain is configured
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