Skip to main content
MoonKey is compatible with any EVM-compatible blockchain, making it easy to deploy your application on Ethereum, Layer 2s, sidechains, and custom networks. Whether you’re building on Ethereum mainnet, Base, Polygon, Arbitrum, Optimism, or a custom EVM chain, MoonKey provides flexible network configuration to match your needs.

Overview

MoonKey exposes two key parameters for network configuration: a default chain and a list of supported chains. If you don’t configure these parameters, MoonKey will use its default configuration which supports popular networks out of the box.

Default Chain

The default chain is the primary network that your application’s wallets will use. For embedded wallets:
  • When users authenticate or create a wallet, MoonKey initializes it on the default chain
  • The embedded wallet will use the default chain for all operations unless explicitly switched to another supported chain
For external wallets:
  • When users connect, MoonKey will prompt them to switch to the default chain if their wallet supports it
  • Users can decline the prompt and remain on their current network
  • Users can manually switch their wallet’s network at any time (MoonKey cannot prevent this)
Some wallets have limited network support. Rainbow Wallet’s mobile app doesn’t support testnets, and Trust Wallet SWIFT only supports specific networks (BSC, Polygon, Avalanche C-Chain, Arbitrum, OP Mainnet, Base, OpBNB).

Supported Chains

The supported chains list defines which networks are permitted in your application. This acts as a guardrail to prevent accidental transactions on unintended networks. For embedded wallets:
  • Attempting to send transactions on unsupported chains will throw an error
  • Attempting to switch to an unsupported chain will throw an error
For external wallets:
  • Programmatic network switches to unsupported chains will throw an error
  • Users can still manually switch their wallet to any network (this cannot be prevented)
Configuration behavior:
  • If you set supportedChains but not defaultChain, embedded wallets default to the first entry in the supported chains list
  • External wallets won’t be prompted to switch networks on connection
  • The default chain must be included in the supported chains list

Configuration

MoonKey embedded wallets support any EVM-compatible chain. Here’s how to configure them.

Using viem-Supported Networks

If your network is supported by viem/chains, follow these instructions. Check the full list of supported networks.
Step 1: Install viem First, install the viem package which contains JSON representations of popular EVM networks:
npm install viem
Step 2: Import your desired chains Import the chains you want to use from viem/chains:
import { base, polygon, arbitrum, optimism } from 'viem/chains';
Step 3: Configure the MoonKeyProvider Add the chains to your MoonKeyProvider configuration:
import { MoonKeyProvider } from '@moon-key/react-auth';
import { base, polygon, arbitrum, optimism } from 'viem/chains';

export default function Providers({ children }) {
  return (
    <MoonKeyProvider
      publishableKey="your-moonkey-publishableKey"
      config={{
        // Set your default network
        defaultChain: base,
        // Define all permitted networks
        supportedChains: [base, polygon, arbitrum, optimism]
      }}
    >
      {children}
    </MoonKeyProvider>
  );
}
Important notes:
  • supportedChains cannot be an empty array
  • defaultChain must be included in supportedChains
  • The provider will throw an error if these rules are violated
That’s it! Your app now supports multiple EVM networks. 🎉

Using Custom Networks

If your network isn’t supported by viem/chains, you can still use it with MoonKey by defining it manually.
Step 1: Define your custom chain Use viem’s defineChain method to create a chain configuration:
import { defineChain } from 'viem';

export const myCustomChain = defineChain({
  id: 123456789, // Your chain's ID
  name: 'My Custom Chain',
  network: 'my-custom-chain',
  nativeCurrency: {
    decimals: 18,
    name: 'Custom Token',
    symbol: 'CUSTOM'
  },
  rpcUrls: {
    default: {
      http: ['https://rpc.my-custom-chain.network'],
      webSocket: ['wss://ws.my-custom-chain.network']
    }
  },
  blockExplorers: {
    default: {
      name: 'CustomScan',
      url: 'https://explorer.my-custom-chain.network'
    }
  }
});
Required fields:
  • id — Chain ID
  • name — Human-readable name
  • network — Network identifier
  • nativeCurrency — Native token details (name, symbol, decimals)
  • rpcUrls — RPC endpoints (HTTP and/or WebSocket)
  • blockExplorers — Block explorer URL
Step 2: Use your custom chain Pass your custom chain to the MoonKeyProvider:
import { MoonKeyProvider } from '@moon-key/react-auth';
import { mainnet } from 'viem/chains';
import { myCustomChain } from './chains';

export default function Providers({ children }) {
  return (
    <MoonKeyProvider
      publishableKey="your-moonkey-publishableKey"
      config={{
        defaultChain: myCustomChain,
        supportedChains: [mainnet, myCustomChain]
      }}
    >
      {children}
    </MoonKeyProvider>
  );
}

Custom RPC Providers

By default, MoonKey uses its own RPC providers for transactions. These are subject to rate limits suitable for development and moderate production usage. For production applications with significant traffic, we strongly recommend using your own RPC providers from services like Alchemy, Infura, QuickNode, or Blast. Benefits of custom RPC providers:
  • Control over rate limits and throughput
  • Better monitoring and analytics
  • Reduced latency with dedicated infrastructure
  • SLA guarantees

Overriding RPC URLs

To use a custom RPC provider with MoonKey: Step 1: Import the helper function
import { addRpcUrlOverrideToChain } from '@moon-key/chains';
import { mainnet } from 'viem/chains';
Step 2: Override the RPC URL
const mainnetWithCustomRpc = addRpcUrlOverrideToChain(
  mainnet,
  'https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY'
);
Step 3: Use the modified chain
<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    defaultChain: mainnetWithCustomRpc,
    supportedChains: [mainnetWithCustomRpc]
  }}
>
  {children}
</MoonKeyProvider>

Multiple chains with custom RPCs

Override multiple chains at once:
import { addRpcUrlOverrideToChain } from '@moon-key/chains';
import { mainnet, polygon, arbitrum } from 'viem/chains';

const mainnetOverride = addRpcUrlOverrideToChain(
  mainnet,
  'https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY'
);

const polygonOverride = addRpcUrlOverrideToChain(
  polygon,
  'https://polygon-mainnet.g.alchemy.com/v2/YOUR-API-KEY'
);

const arbitrumOverride = addRpcUrlOverrideToChain(
  arbitrum,
  'https://arb-mainnet.g.alchemy.com/v2/YOUR-API-KEY'
);

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    defaultChain: mainnetOverride,
    supportedChains: [mainnetOverride, polygonOverride, arbitrumOverride]
  }}
>
  {children}
</MoonKeyProvider>

Default Configuration

If you don’t specify defaultChain or supportedChains, MoonKey defaults to supporting popular EVM networks:
Need a network not listed below? Configure it using the instructions above.

Default Supported Networks

NetworkChain IDTestnet
Ethereum Mainnet1
Ethereum Sepolia11155111
Base8453
Base Sepolia84532
Polygon137
Polygon Amoy80002
Arbitrum One42161
Arbitrum Sepolia421614
Optimism10
Optimism Sepolia11155420
Avalanche C-Chain43114
Avalanche Fuji43113
BNB Smart Chain56
BNB Testnet97
Celo42220
Celo Alfajores44787
Linea59144
Linea Testnet59140
Zora7777777
Zora Sepolia999999999
Default behavior:
  • Embedded wallets initialize on Ethereum mainnet (or the user’s last-used network)
  • External wallets aren’t prompted to switch networks
  • All networks in the table above are available for use

Switching Networks

Once configured, you can programmatically switch networks using MoonKey hooks.

Switch embedded wallet network

import { useSwitchChain } from '@moon-key/react-auth/ethereum';
import { polygon } from 'viem/chains';

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

  const handleSwitch = async () => {
    await switchChain({ chainId: polygon.id });
  };

  return <button onClick={handleSwitch}>Switch to Polygon</button>;
}

Get current network

import { useChainId } from '@moon-key/react-auth/ethereum';

function CurrentNetwork() {
  const chainId = useChainId();

  return <div>Current Chain ID: {chainId}</div>;
}

Common Configurations

Mainnet-only application

import { mainnet } from 'viem/chains';

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    defaultChain: mainnet,
    supportedChains: [mainnet]
  }}
>
  {children}
</MoonKeyProvider>

Layer 2 focused

import { base, polygon, arbitrum, optimism } from 'viem/chains';

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    defaultChain: base,
    supportedChains: [base, polygon, arbitrum, optimism]
  }}
>
  {children}
</MoonKeyProvider>

Development with testnets

import { sepolia, baseSepolia, polygonAmoy } from 'viem/chains';

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    defaultChain: sepolia,
    supportedChains: [sepolia, baseSepolia, polygonAmoy]
  }}
>
  {children}
</MoonKeyProvider>

Multi-chain with custom RPC

import { addRpcUrlOverrideToChain } from '@moon-key/chains';
import { mainnet, polygon } from 'viem/chains';

const mainnetWithRpc = addRpcUrlOverrideToChain(
  mainnet,
  process.env.NEXT_PUBLIC_MAINNET_RPC
);

const polygonWithRpc = addRpcUrlOverrideToChain(
  polygon,
  process.env.NEXT_PUBLIC_POLYGON_RPC
);

<MoonKeyProvider
  publishableKey="your-moonkey-publishableKey"
  config={{
    defaultChain: mainnetWithRpc,
    supportedChains: [mainnetWithRpc, polygonWithRpc]
  }}
>
  {children}
</MoonKeyProvider>

Best Practices

Choose appropriate networks

  • Mainnet for production — Use mainnet and established L2s for production deployments
  • Testnets for development — Use Sepolia, Amoy, etc. during development to avoid real costs
  • Limit network count — Only support networks your application actually uses

Use environment variables

Store RPC URLs and chain configurations in environment variables:
// .env.local
NEXT_PUBLIC_MAINNET_RPC=https://eth-mainnet.g.alchemy.com/v2/YOUR-KEY
NEXT_PUBLIC_POLYGON_RPC=https://polygon-mainnet.g.alchemy.com/v2/YOUR-KEY
const mainnetWithRpc = addRpcUrlOverrideToChain(
  mainnet,
  process.env.NEXT_PUBLIC_MAINNET_RPC!
);

Monitor RPC usage

When using custom RPC providers:
  • Set up monitoring and alerts for rate limits
  • Track RPC call volumes and errors
  • Have fallback providers configured
  • Monitor response times and uptime

Test network switching

Always test network switching functionality:
  • Verify embedded wallets switch correctly
  • Test external wallet prompts
  • Handle user rejection of network switches
  • Display clear network indicators in your UI

Troubleshooting

Chain not appearing in wallet

Problem: Users don’t see your configured chain in their wallet. Solutions:
  • Verify the chain is in supportedChains
  • Check that chain ID and RPC URL are correct
  • For custom chains, ensure all required fields are defined
  • Some wallets require manual network addition

RPC rate limit errors

Problem: Transactions fail with rate limit errors. Solutions:
  • Use custom RPC providers (Alchemy, Infura, QuickNode)
  • Implement RPC URL overrides
  • Add fallback RPC endpoints
  • Monitor your RPC usage and upgrade plans as needed

Network switch fails

Problem: switchChain throws an error or doesn’t work. Solutions:
  • Ensure target chain is in supportedChains
  • For external wallets, check wallet supports the network
  • Handle errors gracefully when users decline switches
  • Verify RPC endpoints are accessible

Configuration errors on startup

Problem: MoonKeyProvider throws an error during initialization. Solutions:
  • Ensure defaultChain is included in supportedChains
  • Don’t pass empty array to supportedChains
  • Verify chain objects are properly formatted
  • Check for typos in chain imports