Multi-chain Apps

Account Kit supports multi-chain apps, allowing you to build applications that interact with multiple blockchains. This guide will show you how to set up your app to work with multiple chains.

Update your config

In order to support multiple chains in your app, the first thing you need to do is update your createConfig call to include the chains you want to support.

import { 
const createConfig: (props: CreateConfigProps, ui?: AlchemyAccountsUIConfig) => AlchemyAccountsConfigWithUI

Wraps the createConfig that is exported from @aa-sdk/core to allow passing an additional argument, the configuration object for the Auth Components UI (the modal and AuthCard).

createConfig
} from "@account-kit/react";
import {
const sepolia: Chain
sepolia
,
const mainnet: Chain
mainnet
} from "@account-kit/infra";
export const
const config: AlchemyAccountsConfigWithUI
config
=
function createConfig(props: CreateConfigProps, ui?: AlchemyAccountsUIConfig): AlchemyAccountsConfigWithUI

Wraps the createConfig that is exported from @aa-sdk/core to allow passing an additional argument, the configuration object for the Auth Components UI (the modal and AuthCard).

createConfig
({
apiKey: string
apiKey
: "ALCHEMY_API_KEY",
// this is the default chain
chain: Chain
chain
:
const sepolia: Chain
sepolia
,
chains: { chain: Chain; policyId: string; }[]
chains
: [
{
chain: Chain
chain
:
const mainnet: Chain
mainnet
, // optional: you can specify a policy ID for this chain, if you want to sponsor gas
policyId?: string | string[] | undefined
policyId
: "MAINNET_GAS_MANAGER_POLICY_ID",
}, {
chain: Chain
chain
:
const sepolia: Chain
sepolia
,
// optional: you can specify a policy ID for this chain, if you want to sponsor gas
policyId?: string | string[] | undefined
policyId
: "SEPOLIA_GAS_MANAGER_POLICY_ID",
}, ], });

Change chains

Once your app is configured to use multiple chains, you can switch between them at any time using the useChain hook.

import React from "react";
import { 
function useChain(mutationArgs?: UseChainParams): UseChainResult

A hook that returns the current chain as well as a function to set the chain. Note: when calling setChain the chain that's passed in must be defined in your initial createConfig call. Calling setChain causes the chain to change across the board. For example, if you use set chain then use useSmartAccountClient, the client will flip to the loading state and address for the account on the changed chain.

For switching chains, you can also use createBundlerClient or createSmartAccoutClient directly and create a different client for each chain. You would have to manage different clients, but you wouldn't have to wait for any hooks to complete and can run these queries in parallel. This way the chain set in the config that the smart account client and other hooks inherit is not also affected.

useChain
} from "@account-kit/react";
import {
const mainnet: Chain
mainnet
,
const sepolia: Chain
sepolia
} from "@account-kit/infra";
export default function
function MyComponent(): JSX.Element
MyComponent
() {
const {
const chain: Chain
chain
,
const setChain: (params: { chain: Chain; }) => void
setChain
} =
function useChain(mutationArgs?: UseChainParams): UseChainResult

A hook that returns the current chain as well as a function to set the chain. Note: when calling setChain the chain that's passed in must be defined in your initial createConfig call. Calling setChain causes the chain to change across the board. For example, if you use set chain then use useSmartAccountClient, the client will flip to the loading state and address for the account on the changed chain.

For switching chains, you can also use createBundlerClient or createSmartAccoutClient directly and create a different client for each chain. You would have to manage different clients, but you wouldn't have to wait for any hooks to complete and can run these queries in parallel. This way the chain set in the config that the smart account client and other hooks inherit is not also affected.

useChain
();
return ( <
React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
<
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Current chain: {
const chain: Chain
chain
.
name: string

Human-readable name

name
}</
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
<
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={() =>
const setChain: (params: { chain: Chain; }) => void
setChain
({
chain: Chain
chain
:
const mainnet: Chain
mainnet
})}>
Switch to Mainnet </
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
>
<
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={() =>
const setChain: (params: { chain: Chain; }) => void
setChain
({
chain: Chain
chain
:
const sepolia: Chain
sepolia
})}>
Switch to Sepolia </
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
>
</
React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
); }