Untitled
import { Address, createPublicClient, Hex, http, HttpTransport, PublicClient } from "viem" import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" import { arbitrum, Chain } from "viem/chains" import { createKernelAccount, CreateKernelAccountReturnType } from "../accounts/index.js" import { KernelPluginManager, KernelValidator } from "../types/kernel.js" import { switchChain } from "viem/actions" export { KernelEIP1193Provider } from "./KernelEIP1193Provider.js" const privateKey = generatePrivateKey() const signer = privateKeyToAccount(privateKey) // Construct a public client const publicClient = createPublicClient({ // Use your own RPC provider (e.g. Infura/Alchemy). transport: http(""), chain: arbitrum, }) // Construct a validator const ecdsaValidator = await signerToEcdsaValidator(publicClient, { signer, entryPoint, kernelVersion }) // Construct a Kernel account const account = await createKernelAccount(publicClient, { plugins: { sudo: ecdsaValidator, }, entryPoint, kernelVersion }) type KernelMultichainParams<TEntryPointVersion extends EntryPointVersion> = { chains: [Chain, ...Chain[]], entryPoint: TEntryPointVersion, kernelVersion: string, clientFactory: (chain: Chain) => PublicClient<HttpTransport, Chain>, pluginFactory: (chain: Chain) => KernelPluginManager<TEntryPointVersion>; } type ServerIntent = { openInfos: { chain: number; amount: bigint; address: Address; calldata: Hex; }[] destination: { chain: number; address: Address; calldatas: Hex[]; } } type MultichainKernelClient = CreateKernelAccountReturnType<> & { currentChain: Chain; switchChain: (chain: Chain) => Promise<void> handleServerIntent: (intent: ServerIntent) => Promise<boolean> } const clientCache = new Map<number, PublicClient<HttpTransport, Chain>>() const pluginCache = new Map<number, KernelPluginManager<string>>() const accountCache = new Map<number, CreateKernelAccountReturnType<string>>() export function createMultichainKernel<TEntryPointVersion extends EntryPointVersion>( {chains, entryPoint, kernelVersion, clientFactory, pluginFactory}: KernelMultichainParams<TEntryPointVersion> ): MultichainKernelClient { const getClient = (chain: Chain) => { if (clientCache.get(chain.id)) { return clientCache.get(chain.id) } const newClient = clientFactory(chain); clientCache.set(chain.id, newClient) return newClient; } const getPluginFactory = (chain: Chain) => { if (pluginCache.get(chain.id)) { return pluginCache.get(chain.id) } const newPlugin = pluginFactory(chain); pluginCache.set(chain.id, newPlugin) return newPlugin; } const getAccount = (chain: Chain) => { if (accountCache.get(chain.id)) { return accountCache.get(chain.id) } const client = getClient(currentchain); const plugin = getPluginFactory(currentchain); return createKernelAccount(client, { plugins: plugin, entryPoint, kernelVersion }); } const handleServerIntent = async (intent: ServerIntent) => { const waitingPromises: Promise<void>[] = []; for (const open of intent.openInfos) { const client = await getAccount(open.chain); const userOpHash = await client.sendUserUserOp({ tx: { to: open.address, value: open.amount, data: open.calldata, } }) // user op process + wait for user op waitingPromises.push(client.waitForUserOp(userOpHash)) } await Promise.all(waitingPromises); } let currentchain = chains[0]; let account = getAccount(currentchain); return { ...acount, currentChain: currentchain, switchChain: (chain: Chain) => { currentchain = chain; account = getAccount(chain); }, } }
Leave a Comment