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 >
);
}
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' );
Next Steps