Account Abstraction
While Account Abstraction is not built into the core viem
library, you can use a third-party library like permissionless.js and ZeroDev to integrate with ERC-4337.
permissionless.js
permissionless.js is a TypeScript library built on viem for interacting with ERC-4337 bundlers, paymasters, and User Operations.
Below are instructions for setting up a Bundler Client.
1. Install
npm i permissionless
2. Set up a Bundler Client
import { createClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { bundlerActions } from 'permissionless'
const bundlerClient = createClient({
chain: mainnet,
transport: http("https://api.pimlico.io/v1/goerli/rpc?apikey=YOUR_API_KEY_HERE")
}).extend(bundlerActions)
3. Consume Actions
Now you can consume Actions that are supported by permissionless.js.
See a full list of Bundler Actions.
import { createClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { bundlerActions } from 'permissionless'
const bundlerClient = createClient({
chain: mainnet,
transport: http("https://api.pimlico.io/v1/goerli/rpc?apikey=YOUR_API_KEY_HERE")
}).extend(bundlerActions)
const supportedEntryPoints = await bundlerClient.supportedEntryPoints()
ZeroDev
ZeroDev is an SDK for building wallets and DApps using modular smart accounts. The SDK uses Viem's client-action architecture to model smart accounts and their plugins.
Below are instructions for setting up a smart account client (which interacts with bundlers using a modular smart account).
1. Install
Install the core SDK and a plugin.
npm i @zerodev/sdk @zerodev/ecdsa-validator
2. Create a public client
import { createPublicClient, http } from "viem"
const publicClient = createPublicClient({
transport: http("RPC_URL"), // use your RPC provider or bundler
})
3. Create a signer
This can be any Viem account type. In this case we use a Local Account.
import { Hex } from "viem"
import { privateKeyToAccount } from "viem/accounts"
const signer = privateKeyToAccount("PRIVATE_KEY" as Hex) // replace with actual private key
4. Create a validator plugin
In this case, we are creating a smart account that uses ECDSA for validation (just like EOAs).
import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator"
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
signer,
})
5. Create a smart account
import { createKernelAccount } from "@zerodev/sdk"
const account = await createKernelAccount(publicClient, {
plugins: {
validator: ecdsaValidator,
},
})
6. Create an account client
import { createKernelAccountClient } from "@zerodev/sdk"
import { http } from "viem"
import { polygonMumbai } from 'viem/chains'
const kernelClient = createKernelAccountClient({
account,
chain: polygonMumbai,
transport: http('BUNDLER_RPC'), // use your bundler RPC
sponsorUserOperation, // optional -- only if you want to use a paymaster
})
7. Send UserOps
Now you can send UserOps using the account client:
const txnHash = await kernelClient.sendTransaction({
to: "TO_ADDRESS",
value: VALUE, // default to 0
data: "0xDATA", // default to 0x
})
You can also extend the account client with bundlerActions
from Permissionless.js if you need to call any bundler RPCs:
import { bundlerActions } from "permissionless"
const bundlerClient = kernelClient.extend(bundlerActions)
const receipt = await bundlerClient.waitForUserOperationReceipt({
hash: userOpHash,
})