Zerodev Kernel Account API
This package contains ZeroDev's KernelV2 implementation of the @alchemy/aa-core
BaseSmartContractAccount
class defined in @alchemy/aa-core
.
What is Kernel V2? Documentation
Getting started
Follow the instructions below to install the packages.
via yarn
yarn add @alchemy/aa-core @zerodevapp/sdk@alpha viem
via npm
npm i -s @alchemy/aa-core @zerodevapp/sdk@alpha viem
Kernel Accounts
Example Usage to Interact withBasic Usage
import {
KernelSmartContractAccount,
ZeroDevProvider,
ECDSAValidator,
type ValidatorMode,
} from "@zerodevapp/sdk@alpha";
import { PrivateKeySigner } from "@alchemy/aa-core";
import { polygonMumbai } from "viem/chains";
const KERNEL_ACCOUNT_FACTORY_ADDRESS =
"0x5D006d3880645ec6e254E18C1F879DAC9Dd71A39";
// 1. define the EOA owner of the Smart Account
// This is just one exapmle of how to interact with EOAs, feel free to use any other interface
const owner = PrivateKeySigner.privateKeyToAccountSigner(PRIVATE_KEY);
// 2. Create a ZeroDev Provider
let ecdsaProvider = await ECDSAProvider.init({
projectId, // zeroDev projectId
owner,
// Optional: pass the paymasterConfig to use the verifying paymaster
// opts: {
// paymasterConfig: {
// policy: "VERIFYING_PAYMASTER"
// }
// }
});
// 3. send a UserOperation
const { hash } = await ecdsaProvider.sendUserOperation({
target: "0xTargetAddress",
data: "0xcallData",
value: 0n, // value: bigint or undefined
});
Pay gas in ERC20
ZeroDev currently supports:
USDC
-
PEPE
(mainnet only) -
DAI
(upcoming)
Just pass the paymasterConfig
to createZeroDevProvider
function while creating the provider.
let ecdsaProvider = await ECDSAProvider.init({
projectId, // zeroDev projectId
owner,
opts: {
paymasterConfig: {
policy: "TOKEN_PAYMASTER",
gasToken: "TEST_ERC20",
},
},
});
Change Kernel Account Owner in ECDSAValidator
// 1. Create a ECDSAValidatorProvider
const ecdsaProvider = await ECDSAProvider.init({
projectId: "c73037ef-8c0b-48be-a581-1f3d161151d3",
owner,
});
// 2. Change the owner of the Kernel Account
const { hash } = await ecdsaProvider.changeOwner(<NEW_OWNER_ADDRESS>);
ethers
Via import { Wallet } from "@ethersproject/wallet";
import {
ZeroDevEthersProvider,
convertWalletToAccountSigner,
} from "@zerodevapp/sdk@alpha";
// 1. Create an ethers Wallet
const owner = Wallet.fromMnemonic(OWNER_MNEMONIC);
// 2. Create a ZeroDev ZeroDevEthersProvider passing the ethers Wallet as the signer
const provider = await ZeroDevEthersProvider.init("ECDSA", {
projectId, // zeroDev projectId
owner: convertWalletToAccountSigner(owner),
opts: {
paymasterConfig: {
policy: "VERIFYING_PAYMASTER",
},
},
});
// 3. Get the AccountSigner adapter of ethers signer
const signer = provider.getAccountSigner();
// 4. send a UserOperation
const { hash } = signer.sendUserOperation({
target: "0xTargetAddress",
data: "0xcallData",
value: 0n, // value: bigint or undefined
});
viem
using custom
transport which supports EIP-1193 providers
Via import { createWalletClient, custom } from "viem";
import { polygonMumbai } from "viem/chains";
import {
ECDSAProvider,
convertWalletClientToAccountSigner,
} from "@zerodevapp/sdk@alpha";
// 1. Create a Viem Wallet Client using the custom transport
const client = createWalletClient({
chain: polygonMumbai,
transport: custom(window.ethereum),
});
// 2. Create a ZeroDev ECDSAProvider passing the Viem Wallet Client as the signer
let ecdsaProvider = await ECDSAProvider.init({
projectId, // zeroDev projectId
owner: convertWalletClientToAccountSigner(client),
});
// 3. send a UserOperation
const { hash } = await ecdsaProvider.sendUserOperation({
target: "0xTargetAddress",
data: "0xcallData",
value: 0n, // value: bigint or undefined
});
Magic
Usingimport { ECDSAProvider, getRPCProviderOwner } from "@zerodevapp/sdk@alpha";
import { Magic } from "magic-sdk";
const magic = new Magic("MAGIC_API_KEY", {
// magic config...
});
let ecdsaProvider = await ECDSAProvider.init({
projectId, // zeroDev projectId
owner: getRPCProviderOwner(magic.rpcProvider),
});
Web3Auth
Usingimport { ECDSAProvider, getRPCProviderOwner } from "@zerodevapp/sdk@alpha";
import { Web3Auth } from "@web3auth/modal";
const web3auth = new Web3Auth({
// web3auth config...
});
await web3auth.initModal();
web3auth.connect();
let ecdsaProvider = await ECDSAProvider.init({
projectId, // zeroDev projectId
owner: getRPCProviderOwner(web3auth.provider),
});
Components
Core Components
The primary interfaces are the ZeroDevProvider
, KernelSmartContractAccount
and KernelBaseValidator
The ZeroDevProvider
is an ERC-1193 compliant Provider built on top of Alchemy's SmartAccountProvider
-
sendUserOperation
-- this takes intarget
,callData
, and an optionalvalue
which then constructs a UserOperation (UO), sends it, and returns thehash
of the UO. It handles estimating gas, fetching fee data, (optionally) requesting paymasterAndData, and lastly signing. This is done via a middleware stack that runs in a specific order. The middleware order isgetDummyPaymasterData
=>estimateGas
=>getFeeData
=>getPaymasterAndData
. The paymaster fields are set to0x
by default. They can be changed usingprovider.withPaymasterMiddleware
. -
sendTransaction
-- this takes in a traditional Transaction Request object which then gets converted into a UO. Currently, the only data being used from the Transaction Request object isfrom
,to
,data
andvalue
. Support for other fields is coming soon.
KernelSmartContractAccount
is Kernel's implementation of BaseSmartContractAccount
. 6 main methods are implemented
-
getDummySignature
-- this method should return a signature that will notrevert
during validation. It does not have to pass validation, just not cause the contract to revert. This is required for gas estimation so that the gas estimate are accurate. -
encodeExecute
-- this method should return the abi encoded function data for a call to your contract'sexecute
method -
encodeExecuteDelegate
-- this method should return the abi encoded function data for adelegate
call to your contract'sexecute
method -
signMessage
-- this is used to sign UO Hashes -
signWithEip6492
-- this should return an ERC-191 and EIP-6492 compliant message used to personal_sign -
getAccountInitCode
-- this should return the init code that will be used to create an account if one does not exist. Usually this is the concatenation of the account's factory address and the abi encoded function data of the account factory'screateAccount
method.
The KernelBaseValidator
is a plugin that modify how transactions are validated. It allows for extension and implementation of arbitrary validation logic. It implements 3 main methods:
-
getAddress
-- this returns the address of the validator -
getOwner
-- this returns the eligible signer's address for the active smart wallet -
getSignature
-- this method signs the userop hash using signer object and then concats additional params based on validator mode.
Contributing
- clone the repo
- run
yarn
- Make changes to packages