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) => AlchemyAccountsConfigWithUIWraps 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: Chainsepolia, const mainnet: Chainmainnet } from "@account-kit/infra";
export const const config: AlchemyAccountsConfigWithUIconfig = function createConfig(props: CreateConfigProps, ui?: AlchemyAccountsUIConfig): AlchemyAccountsConfigWithUIWraps 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: stringapiKey: "ALCHEMY_API_KEY",
// this is the default chain
chain: Chainchain: const sepolia: Chainsepolia,
chains: {
chain: Chain;
policyId: string;
}[]chains: [
{
chain: Chainchain: const mainnet: Chainmainnet, // optional: you can specify a policy ID for this chain, if you want to sponsor gas
policyId?: string | string[] | undefinedpolicyId: "MAINNET_GAS_MANAGER_POLICY_ID",
},
{
chain: Chainchain: const sepolia: Chainsepolia,
// optional: you can specify a policy ID for this chain, if you want to sponsor gas
policyId?: string | string[] | undefinedpolicyId: "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): UseChainResultA 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: Chainmainnet, const sepolia: Chainsepolia } from "@account-kit/infra";
export default function function MyComponent(): JSX.ElementMyComponent() {
const { const chain: Chainchain, const setChain: (params: {
chain: Chain;
}) => voidsetChain } = function useChain(mutationArgs?: UseChainParams): UseChainResultA 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: Chainchain.name: stringHuman-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> | undefinedonClick={() => const setChain: (params: {
chain: Chain;
}) => voidsetChain({ chain: Chainchain: const mainnet: Chainmainnet })}>
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> | undefinedonClick={() => const setChain: (params: {
chain: Chain;
}) => voidsetChain({ chain: Chainchain: const sepolia: Chainsepolia })}>
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>
);
}