JSPM

  • Created
  • Published
  • Downloads 71
  • Score
    100M100P100Q54187F
  • License AGPL-3.0-only

ERC-4337 utilities for sending user operations with ethers.js

Package Exports

  • sendop
  • sendop/contract-types

Readme

sendop

A TypeScript library for ERC-4337 account abstraction, making smart contract wallets simple and accessible.

For usage examples of this library, see Smart Account Manager, an open web wallet built on ERC-4337.

Features

  • Multiple Account Types: Support for Kernel, Nexus, Safe7579, and Simple7702 accounts
  • Modular Accounts: Full support for ERC-7579 modular account standard
  • EIP-7702 Support: Utilities for EIP-7702 and ERC-4337 integration
  • Flexible Validation: ECDSA, WebAuthn, and custom validator support
  • Paymaster Integration: Public Paymaster and USDC Paymaster support
  • Multi-Bundler Support: Works with Alchemy, Pimlico, and other ERC-4337 bundlers
  • UserOpBuilder: Intuitive chainable API for constructing user operations

Installation

npm install ethers sendop

Quick Start (v0.5.x)

Deploy a Kernel account and increment the counter

import { getBytes, hexlify, JsonRpcProvider, randomBytes, Wallet } from 'ethers'
import { alchemy, pimlico } from 'evm-providers'
import {
    ADDRESS,
    ERC4337Bundler,
    ERC4337Error,
    fetchGasPricePimlico,
    getECDSAValidator,
    getPublicPaymaster,
    INTERFACES,
    KernelAccountAPI,
    KernelAPI,
    SingleEOAValidation,
    UserOpBuilder,
} from 'sendop'

const { ALCHEMY_API_KEY = '', PIMLICO_API_KEY = '', PRIVATE_KEY = '' } = process.env

// Setup providers
const CHAIN_ID = 84532 // Base Sepolia
const client = new JsonRpcProvider(alchemy(CHAIN_ID, ALCHEMY_API_KEY))
const bundler = new ERC4337Bundler(pimlico(CHAIN_ID, PIMLICO_API_KEY))

// Setup signer and validator
const signer = new Wallet(PRIVATE_KEY)
const ecdsaValidator = getECDSAValidator({ ownerAddress: signer.address })

const { accountAddress, factory, factoryData } = await KernelAPI.getDeployment({
    client,
    validatorAddress: ecdsaValidator.address,
    validatorData: ecdsaValidator.initData,
    salt: hexlify(randomBytes(32)),
})

// Create account API
const kernelAPI = new KernelAccountAPI({
    validation: new SingleEOAValidation(),
    validatorAddress: ecdsaValidator.address,
})

// Define operations to execute
const executions = [
    {
        to: ADDRESS.Counter,
        value: 0n,
        data: INTERFACES.Counter.encodeFunctionData('increment'),
    },
]

// Build operation
const op = new UserOpBuilder({
    chainId: CHAIN_ID,
    bundler,
    entryPointAddress: kernelAPI.entryPointAddress,
})
    .setSender(accountAddress)
    .setFactory({
        factory,
        factoryData,
    })
    .setCallData(await kernelAPI.getCallData(executions))
    .setNonce(await kernelAPI.getNonce(client, accountAddress))
    .setSignature(await kernelAPI.getDummySignature())

// Set paymaster and gas price
op.setPaymaster(getPublicPaymaster())
op.setGasPrice(await fetchGasPricePimlico(pimlico(CHAIN_ID, PIMLICO_API_KEY)))

// Estimate gas
await op.estimateGas()

// Inspect userop
console.log('op.preview', op.preview())
console.log('op.toRequestParams', op.toRequestParams())
console.log('op.toSendRequest', op.toSendRequest())
console.log('op.encodeHandleOpsDataWithDefaultGas', op.encodeHandleOpsDataWithDefaultGas())

// Sign and send
const sig = await signer.signMessage(getBytes(op.hash()))
op.setSignature(await kernelAPI.formatSignature(sig))

try {
    await op.send()
} catch (error) {
    if (error instanceof ERC4337Error) {
        console.error('error.message', error.message)
        console.error('error.code', error.code)
        console.error('error.method', error.method)
        console.error('error.payload', error.payload)
        console.error('error.userOp', error.userOp)
    }
    process.exit(1)
}

const receipt = await op.wait()

console.log('Operation success:', receipt.success)

Run Tests

bun run test # vitest (recommended)

bun test # bun built-in test; some tests may fail
bun test -t 'test case'

Dev Commands

bun install
bun typecheck
bun run build
bun run build:contract-types

License

Copyright (C) 2024-2025 Johnson Chen

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.