Appearance
Integrating smart accounts with wagmi
If your app uses wagmi and one of Privy's account abstraction integrations to set up smart accounts for the embedded wallet, you can configure wagmi to reflect the smart account for the embedded wallet instead of the externally-owned account (e.g. signer) by following the instructions below.
0. Setup
This guide assumes that you have already integrated both Privy and wagmi into your app, and are now looking to set up wagmi with smart accounts.
If you have not yet set up the basic integration, please first follow the Privy quickstart and our wagmi integration guide.
1. Initialize an EIP1193 provider for the smart account
Once you've set up your app with wagmi, implement a function that initializes the smart account of your choice (Kernel, SimpleAccount, Biconomy, etc.) from the Privy embedded wallet.
As a parameter, the function should accept an object with a signer
field that contains a viem EIP1193Provider
for the Privy embedded wallet. It should then initialize a smart account, using the embedded wallet as a signer, and should return a Promise for a viem EIP1193Provider
for the smart account.The function should have the following type:
tsx
async ({signer}: {signer: EIP1193Provider}) => Promise<EIP1193Provider>;
As an example, if you are using Privy alongside ZeroDev for smart account support, you can define this function like so:
tsx
import {signerToEcdsaValidator} from '@zerodev/ecdsa-validator';
import {
createKernelAccount,
createZeroDevPaymasterClient,
createKernelAccountClient,
KernelEIP1193Provider,
KernelAccountClient,
} from '@zerodev/sdk';
import {ENTRYPOINT_ADDRESS_V07, providerToSmartAccountSigner} from 'permissionless';
import {EntryPoint} from 'permissionless/_types/types';
import {http, createPublicClient, EIP1193Provider} from 'viem';
import {baseSepolia} from 'viem/chains';
// Create a public client
const publicClient = createPublicClient({
transport: http(process.env.BUNDLER_RPC),
});
const entryPoint = ENTRYPOINT_ADDRESS_V07;
export const signerToZeroDevSmartAccount = async ({
signer,
}: {
signer: EIP1193Provider;
}): Promise<EIP1193Provider> => {
// Convert EIP1193Provider for the embedded wallet to a signer
const smartAccountSigner = await providerToSmartAccountSigner(signer);
// Create an ECDSA validator
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
signer: smartAccountSigner,
entryPoint,
});
// Create a Kernel account
const account = await createKernelAccount(publicClient, {
plugins: {
sudo: ecdsaValidator,
},
entryPoint,
});
// Initialize a Kernel (smart account) client from the signer
const kernelClient = createKernelAccountClient({
account,
entryPoint,
chain: baseSepolia,
bundlerTransport: http(process.env.BUNDLER_RPC),
middleware: {
sponsorUserOperation: async ({userOperation}) => {
const paymasterClient = createZeroDevPaymasterClient({
chain: baseSepolia,
transport: http(process.env.PAYMASTER_RPC),
entryPoint,
});
return paymasterClient.sponsorUserOperation({
userOperation,
entryPoint,
});
},
},
}) as KernelAccountClient<EntryPoint>;
// Get an EIP1193Provider for the Kernel smart account and return it
const kernelProvider = new KernelEIP1193Provider(kernelClient);
return kernelProvider as EIP1193Provider;
};
2. Use the smart account's EIP1193Provider to register a wagmi connector
Next, import the useEmbeddedSmartAccountConnector
hook from @privy-io/wagmi
. This hook allows you to register a smart account connector for wagmi that replaces the regular embedded wallet connector.
tsx
import {useEmbeddedSmartAccountConnector} from '@privy-io/wagmi';
Now, call the useEmbeddedSmartAccountConnector
hook to register a smart account connector with wagmi. As a parameter to the hook, pass an object with the following fields:
Field | Type | Description |
---|---|---|
getSmartAccountFromSigner | async ({signer}: {signer: EIP1193Provider}) => Promise<EIP1193Provider> | A function that takes an EIP1193Provider for the user's embedded wallet and converts it to an EIP1193Provider for the smart account. This is the same function you implemented in step 1. |
INFO
The useEmbeddedSmartAccountConnector
hook must be mounted at all times when using wagmi with the smart account. We recommend calling the hook in a component close to the root of your application.
As an example, if you are using Privy alongside ZeroDev for smart account support, you might call the hook like so:
tsx
// This hook must be mounted whenever using wagmi with the smart account
// See step 1 for the implementation of `signerToZeroDevSmartAccount`
useEmbeddedSmartAccountConnector({
getSmartAccountFromSigner: signerToZeroDevSmartAccount,
});
That's it! You've now registered a smart account connector for the embedded wallet with Privy's wagmi integration, and can use wagmi hooks to interface with the smart account 🎉.
INFO
Currently, Privy's wagmi integration only supports using a smart account with embedded wallets, not external wallets (e.g. MetaMask). With the setup above, if a user has an embedded wallet, the smart account connector will be the only wallet connected to wagmi.
If a user does not have an embedded wallet and is using an external wallet, wagmi will interface with the external wallets as usual.