Skip to content

buildUserOperation

Builds an unsigned UserOperation (UO) struct with all middleware of the SmartAccountClient run through the middleware pipeline.

Learn more about ClientMiddleware to learn more about the internals of SmartAccountClient middleware pipeline that builds the user operation request given the user transaction call data and the operating account data.

Usage

example.ts
import { smartAccountClient } from "./smartAccountClient";

// build single
const uoStruct = await smartAccountClient.buildUserOperation({
  uo: {
    target: TO_ADDRESS,
    data: ENCODED_DATA,
    value: VALUE, // optional
  },
});
 
// signUserOperation signs the above unsigned user operation struct built
// using the account connected to the smart account client
const request = await smartAccountClient.signUserOperation({ uoStruct });
 
// You can use the BundlerAction `sendRawUserOperation` (packages/core/src/actions/bundler/sendRawUserOperation.ts)
// to send the signed user operation request to the bundler, requesting the bundler to send the signed uo to the
// EntryPoint contract pointed at the entryPoint address parameter
const entryPointAddress = client.account.getEntryPoint().address;
const uoHash = await smartAccountClient.sendRawUserOperation({
  request,
  entryPoint: entryPointAddress,
});
 
// build batch
 
// NOTE: Not all Smart Contract Accounts support batching.
// The `SmartContractAccount` implementation must have the `encodeBatchExecute` method
// implemented for the `SmartAccountClient` to execute the batched user operation successfully.
const batchedUoStruct = await smartAccountClient.buildUserOperation({
  uo: [
    {
      data: "0xCalldata",
      target: "0xTarget",
    },
    {
      data: "0xCalldata2",
      target: "0xTarget2",
      value: 1000n, // in wei
    },
  ],
});
 
// signUserOperation signs the above unsigned user operation struct built
// using the account connected to the smart account client
const request = await smartAccountClient.signUserOperation({ uoStruct });
 
// You can use the BundlerAction `sendRawUserOperation` (packages/core/src/actions/bundler/sendRawUserOperation.ts)
// to send the signed user operation request to the bundler, requesting the bundler to send the signed uo to the
// EntryPoint contract pointed at the entryPoint address parameter
const entryPointAddress = client.account.getEntryPoint().address;
const uoHash = await smartAccountClient.sendRawUserOperation({
  request,
  entryPoint: entryPointAddress,
});

Returns

Promise<UserOperationStruct>

A Promise containing the unsigned UO struct resulting from the middleware pipeline

Parameters

SendUserOperationParameters

SendUserOperationParameters
export type SendUserOperationParameters<
  TAccount extends SmartContractAccount | undefined,
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined,
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
> = {
  uo: UserOperationCallData | BatchUserOperationCallData;
} & GetAccountParameter<TAccount> &
  GetContextParameter<TContext> &
  UserOperationOverridesParameter<TEntryPointVersion>;
  • uo: UserOperationCallData | BatchUserOperationCallData

    UserOperationCallData
    export type UserOperationCallData =
      | {
          /* the target of the call */
          target: Address;
          /* the data passed to the target */
          data: Hex;
          /* the amount of native token to send to the target (default: 0) */
          value?: bigint;
        }
      | Hex;
    • target: Address - the target of the call (equivalent to to in a transaction)
    • data: Hex - can be either 0x or a call data string
    • value?: bigint - optionally, set the value in wei you want to send to the target
  • overrides?: UserOperationOverrides

Optional parameter where you can specify override values for maxFeePerGas, maxPriorityFeePerGas, callGasLimit, preVerificationGas, verificationGasLimit, paymasterAndData, or nonceKey for the user operation request. You can also specify a stateOverride to be passed into eth_estimateUserOperationGas during gas estimation.

  • account?: TAccount extends SmartContractAccount | undefined

When using this action, if the SmartContractAccount has not been connected to the SmartAccountClient (e.g. SmartAccountClient not instantiated with your SmartContractAccount during createSmartAccountClient). You can check if the account is connected to the client by checking the account field of SmartAccountClient. If the account is not connected, you can specify the SmartContractAccount instance to use for the function call.