Skip to main content

Overview

Utilities for working with ERC-4337 UserOperations on EntryPoint v0.7, including submission to bundlers and hash computation.

Functions

submitKernelUserOperationV07

Submits a UserOperation for a Kernel smart account to an ERC-4337 bundler. Handles gas estimation, nonce management, signature generation, and automatic retries.
async function submitKernelUserOperationV07(parameters: {
  bundlerUrl: string;
  chainRpcUrl: string;
  owner: Address;
  kernelAddress: Address;
  chainId: number;
  kernelCallData: Hex;
  request: RpcRequest;
  onStatus?: ((status: string) => void) | undefined;
}): Promise<Hex>
bundlerUrl
string
required
The ERC-4337 bundler RPC endpoint URL
chainRpcUrl
string
required
The chain RPC endpoint URL for state queries
owner
Address
required
The EOA owner address that will sign the UserOperation
kernelAddress
Address
required
The Kernel smart account address sending the UserOperation
chainId
number
required
The chain ID for the network
kernelCallData
Hex
required
The encoded call data for the Kernel account to execute
request
RpcRequest
required
JSON-RPC request function (method: string, params?: unknown[] | object) => Promise<unknown>
onStatus
(status: string) => void
Optional callback for status updates during submission process
returns
Promise<Hex>
The UserOperation hash returned by the bundler upon successful submission
Example:
import { submitKernelUserOperationV07 } from "@/lib/accountAbstraction/submitUserOpV07";

const userOpHash = await submitKernelUserOperationV07({
  bundlerUrl: "https://bundler.example.com",
  chainRpcUrl: "https://rpc.example.com",
  owner: "0x1234...",
  kernelAddress: "0x5678...",
  chainId: 1,
  kernelCallData: "0xabcd...",
  request: async (method, params) => {
    // Your JSON-RPC implementation
  },
  onStatus: (status) => console.log(status),
});
Features:
  • Verifies Kernel wallet deployment on-chain
  • Reads current nonce from EntryPoint
  • Fetches gas prices from bundler or falls back to chain RPC
  • Estimates gas limits with 50% safety buffer
  • Signs UserOperation hash via personal_sign or eth_sign
  • Automatic retry on nonce conflicts or gas price requirements
  • Provides detailed status callbacks throughout the process

getUserOperationHashV07

Computes the ERC-4337 UserOperation hash for EntryPoint v0.7.
function getUserOperationHashV07(parameters: {
  userOperation: UserOperationV07;
  entryPointAddress: Address;
  chainId: number;
}): Hex
userOperation
UserOperationV07
required
The UserOperation struct to hash
entryPointAddress
Address
required
The EntryPoint contract address
chainId
number
required
The chain ID for the network
returns
Hex
The UserOperation hash that must be signed by the account owner
Example:
import { getUserOperationHashV07 } from "@/lib/accountAbstraction/userOpHashV07";
import { ENTRYPOINT_V07_ADDRESS } from "@/lib/protocols/entryPoint";

const userOpHash = getUserOperationHashV07({
  userOperation: {
    sender: "0x1234...",
    nonce: 0n,
    callData: "0xabcd...",
    callGasLimit: 100000n,
    verificationGasLimit: 200000n,
    preVerificationGas: 50000n,
    maxFeePerGas: 1000000000n,
    maxPriorityFeePerGas: 1000000000n,
    signature: "0x",
  },
  entryPointAddress: ENTRYPOINT_V07_ADDRESS,
  chainId: 1,
});

Type Definitions

UserOperationV07

ERC-4337 UserOperation struct for EntryPoint v0.7.
type UserOperationV07 = {
  sender: Address;
  nonce: bigint;
  callData: Hex;
  callGasLimit: bigint;
  verificationGasLimit: bigint;
  preVerificationGas: bigint;
  maxFeePerGas: bigint;
  maxPriorityFeePerGas: bigint;
  signature: Hex;
  factory?: Address | undefined;
  factoryData?: Hex | undefined;
  paymaster?: Address | undefined;
  paymasterData?: Hex | undefined;
  paymasterVerificationGasLimit?: bigint | undefined;
  paymasterPostOpGasLimit?: bigint | undefined;
};
sender
Address
required
The smart account address sending the UserOperation
nonce
bigint
required
The nonce from EntryPoint.getNonce(sender, key)
callData
Hex
required
The data to pass to the sender account’s execution function
callGasLimit
bigint
required
Gas limit for the execution call
verificationGasLimit
bigint
required
Gas limit for verification step
preVerificationGas
bigint
required
Gas to compensate bundler for pre-verification execution and calldata
maxFeePerGas
bigint
required
Maximum fee per gas (EIP-1559)
maxPriorityFeePerGas
bigint
required
Maximum priority fee per gas (EIP-1559)
signature
Hex
required
Signature over the UserOperation hash
factory
Address
Account factory address (for undeployed accounts)
factoryData
Hex
Data to pass to factory for account creation
paymaster
Address
Paymaster address (for sponsored transactions)
paymasterData
Hex
Data to pass to paymaster
paymasterVerificationGasLimit
bigint
Gas limit for paymaster verification
paymasterPostOpGasLimit
bigint
Gas limit for paymaster post-operation

RpcRequest

type RpcRequest = (method: string, params?: unknown[] | object) => Promise<unknown>
JSON-RPC request function type for wallet provider calls.

encodeEntryPointGetNonce

Encodes calldata for the EntryPoint getNonce() function.
function encodeEntryPointGetNonce(parameters: {
  sender: Address;
  key: bigint;
}): Hex
sender
Address
required
The smart account address to query nonce for
key
bigint
required
The nonce key (used for parallel execution paths)
returns
Hex
Encoded calldata for EntryPoint.getNonce(address,uint192)
Example:
import { encodeEntryPointGetNonce } from "@/lib/protocols/entryPoint";

const calldata = encodeEntryPointGetNonce({
  sender: "0x1234...",
  key: 0n
});
// Use with eth_call to query account nonce

decodeEntryPointGetNonce

Decodes the result of an EntryPoint getNonce() call.
function decodeEntryPointGetNonce(result: Hex): bigint
result
Hex
required
The raw result from eth_call
returns
bigint
The current nonce value
Example:
import { decodeEntryPointGetNonce } from "@/lib/protocols/entryPoint";

const nonce = decodeEntryPointGetNonce("0x0000000000000000000000000000000000000000000000000000000000000005");
// Returns: 5n

Constants

ENTRYPOINT_V07_ADDRESS

const ENTRYPOINT_V07_ADDRESS: Address = "0x0000000071727De22E5E9d8BAf0edAc6f37da032"
The canonical EntryPoint v0.7 contract address.

Build docs developers (and LLMs) love