Migration Guide
(beta) ERC-4337 UserOps => ERC-7683 Intents
This is a beta feature. Only use this if you are in touch with the ZeroDev team.
import { createIntentClient, installIntentExecutor } from "@zerodev/intent"
const main = async () => {
// Construct a Kernel account
const account = await createKernelAccount(publicClient, {
plugins: {
sudo: ecdsaValidator,
},
entryPoint,
kernelVersion,
initConfig: [installIntentExecutor],
})
// Construct a paymaster client
const zerodevPaymaster = createZeroDevPaymasterClient({
chain,
transport: http(PAYMASTER_RPC),
})
// Construct a Kernel account client
const kernelClient = createKernelAccountClient({
account,
chain,
bundlerTransport: http(BUNDLER_RPC),
client: publicClient,
paymaster: {
getPaymasterData(userOperation) {
return zerodevPaymaster.sponsorUserOperation({userOperation})
}
},
userOperation: {
estimateFeesPerGas: async ({bundlerClient}) => {
return getUserOperationGasPrice(bundlerClient)
}
}
})
// Construct an intent client
const intentClient = createIntentClient({
account: kernelAccount,
chain,
bundlerTransport: http(bundlerRpc, { timeout }),
})
// Send a UserOp
const userOpHash = await kernelClient.sendUserOperation({
callData: await kernelClient.account.encodeCalls([{
// ...
}]),
})
// Send an intent
const result = await intentClient.sendUserIntent({
calls: [
// ...
],
})
// Wait for the userop
await kernelClient.waitForUserOperationReceipt({
hash: userOpHash,
timeout: 1000 * 15,
})
// Wait for the intent
const receipt = await intentClient.waitForUserIntentExecutionReceipt({
uiHash: result.uiHash,
})
}
SDK 5.3.x => 5.4.x
In version 5.4.x of the @zerodev/sdk
, we've migrated to using viem@2.18.x
with native Account Abstraction (AA) modules instead of the permissionless
package. This change brings significant updates to types, imports, function signatures, and overall API usage.
This guide will help you migrate your codebase to be compatible with the new version.
Update dependencies
-
Remove the
permissionless
package:npm uninstall permissionless
-
Ensure you have
viem@^2.21.40
version
Update permissionless
Account Abstractions
Replace any imports from permissionless
with the equivalent from viem/account-abstraction
or @zerodev/sdk
if applicable.
Update Type Definitions
Replace EntryPoint
Types
import type { EntryPoint } from 'permissionless/types';
import type { EntryPointVersion } from 'viem/account-abstraction';
Replace UserOperation
Types
import type { UserOperation } from 'permissionless/types';
import type { UserOperation } from 'viem/account-abstraction';
Replaced entryPoint: Address
with entryPoint: { address: Address; version: EntryPointVersion}
For createKernelAccount
and signerToEcdsaValidator
among other plugins, replace the entryPoint
parameter as shown:
import { getEntryPoint } from "@zerodev/sdk/constants";
createKernelAccount(publicClient, {
// ...
entryPoint: ENTRYPOINT_ADDRESS_V07,
entryPoint: getEntryPoint("0.7"),
})
signerToEcdsaValidator(publicClient, {
// ...
entryPoint: ENTRYPOINT_ADDRESS_V07,
entryPoint: getEntryPoint("0.7"),
})
Removed entryPoint
from createKernelAccountClient
const kernelClient = createKernelAccountClient({
entryPoint,
// ...
});
Replaced middleware.sponsorUserOperation
from createKernelAccountClient
with paymaster.getPaymasterData
const kernelClient = createKernelAccountClient({
middleware: {
sponsorUserOperation: paymasterClient.sponsorUserOperation,
},
paymaster: {
getPaymasterData(userOperation) {
return paymasterClient.sponsorUserOperation({ userOperation })
}
}
// ...
});
Added client
to createKernelAccountClient
client
is now required in createKernelAccountClient
.
const kernelClient = createKernelAccountClient({
client: publicClient,
// ...
});
Added estimateFeesPerGas
to userOperation
in createKernelAccountClient
estimateFeesPerGas
is now required in userOperation
in createKernelAccountClient
to estimate the gas price for the user operation.
The default gas prices might be too high, so it's recommended to use this function to estimate the gas price.
const kernelClient = createKernelAccountClient({
userOperation: {
estimateFeesPerGas: async ({bundlerClient}) => {
return getUserOperationGasPrice(bundlerClient)
}
},
// ...
});
kernelClient.sendUserOperation
and kernelClient.signUserOperation
now take userOperation
properties directly
await kernelClient.sendUserOperation({
userOperation: { sender, callData, nonce, ...rest },
sender,
callData,
nonce,
...rest
});
await kernelClient.signUserOperation({
userOperation: { sender, callData, nonce, ...rest },
sender,
callData,
nonce,
...rest
});
Replaced account.encodeCallData
with account.encodeCalls
await account.encodeCallData(
{
to: zeroAddress,
value: BigInt(0),
data: "0x",
callType
},
),
await account.encodeCalls([
{
to: zeroAddress,
value: BigInt(0),
data: "0x",
},
], callType),
Replaced kernelClient.sendTransactions
with kernelClient.sendTransaction
await kernelClient.sendTransactions({
transactions: [
// ...
],
});
await kernelClient.sendTransaction({
calls: [
// ...
],
});
KernelAccountClient
extends bundlerActions
by default
For example:
const bundlerClient = kernelClient.extend(bundlerActions(entryPoint));
await bundlerClient.waitForUserOperationReceipt({
hash: userOpHash,
});
await kernelClient.waitForUserOperationReceipt({ hash })
Merged bundlerClient.sendUserOperation
and kernelClient.sendUserOperation
kernelClient.sendUserOperation
now prepares the userOperation
if needed and directly calls eth_sendUserOperation
.
SDK 5.1.x => 5.2.x
Most functions now take an entryPoint
param
EntryPoint 0.7 is the most recent update to ERC-4337, but we will still be supporting EntryPoint 0.6.
The SDK will automatically use Kernel v3 for EntryPoint 0.7, and Kernel v2 for EntryPoint 0.6.
You will need to specify an entryPoint
parameter to many functions, including:
- Functions for creating validators, such as
signerToEcdsaValidator
- Functions for creating Kernel accounts, such as
createKernelAccount
- Function for creating Kernel client:
createKernelAccountClient
For example:
import { ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07 } from "permissionless"
// If migrating a live app
const entryPoint = ENTRYPOINT_ADDRESS_V06
// If launching a new app
const entryPoint = ENTRYPOINT_ADDRESS_V07
const account = await createKernelAccount(publicClient, {
plugins: {
sudo: ecdsaValidator,
},
entryPoint,
})
- If you are migrating a live app that is using EntryPoint 0.6 (Kernel v2), set
entryPoint
toENTRYPOINT_ADDRESS_V06
. - If you are launching a new app, set
entryPoint
toENTRYPOINT_ADDRESS_V07
.
Replaced transport
with bundlerTransport
inside createKernelAccountClient
const kernelClient = createKernelAccountClient({
transport: http(bundlerUrl),
bundlerTransport: http(bundlerUrl),
// ...
})
Replaced sponsorUserOperation
with middleware.sponsorUserOperation
Instead of accepting just a sponsorUserOperation
middleware, createSmartAccountClient
now accepts a middleware
function that can specify a sponsorUserOperation
function internally, as well as a gasPrice
function.
const kernelClient = createKernelAccountClient({
sponsorUserOperation: paymasterClient.sponsorUserOperation,
middleware: {
sponsorUserOperation: paymasterClient.sponsorUserOperation,
},
// ...
})