Connecting to an ERC-4337 bundler is easy using userop.js

Userop.js allows you connect to a bundler RPC using the client interface.

An instance of a client is an abstraction for building and sending your User Operations to the eth_sendUserOperation RPC method on a bundler.


These interfaces are built using UserOperation, UserOperationBuilder, and BigNumberish from ethers.js.


An instance of client exposes methods to help get your UserOperation to an ERC-4337 Bundler.

interface IClient {
  sendUserOperation: (
    builder: IUserOperationBuilder,
    opts?: ISendUserOperationOpts
  ) => Promise<ISendUserOperationResponse>;

  buildUserOperation: (
    builder: IUserOperationBuilder
  ) => Promise<IUserOperation>;

interface ISendUserOperationOpts {
  onBuild?: (op: IUserOperation) => Promise<any> | any;

interface ISendUserOperationResponse {
  userOpHash: string;
  wait: () => Promise<UserOperationEventEvent | null>;


One instance should be initialized for each node and network your application supports.

import { Client } from "userop";

const client = await Client.init(rpcUrl, entryPoint);


A method for directing a builder instance to create a User Operation and send it to a bundler via eth_sendUserOperation.

const response = await client.sendUserOperation(builder);
const userOperationEvent = await response.wait();



This method will also call resetOp on a builder if successful.


This method can be used to direct a builder using the client's entryPoint and chainID. However it will only return the UserOperation and not initiate a send request.

const userOp = await client.buildUserOperation(builder);



This method will not call resetOp on a builder.


A instance of a client has several constants that can be set.

// The maximum amount of time to wait for the UserOperationEvent after calling response.wait()
client.waitTimeoutMs = 30000;

// The interval at which it will poll the node to look up UserOperationEvent.
client.waitIntervalMs = 5000;