Skip to content

Types

BatchUserOperationCallData

An array of UserOperationCallData, representing a sequence of UserOperations to be executed in batch by calling the executeBatch function on the SmartContractAccount contract. Check out our guide on How to submit batch transactions to learn more about batching multiple transactions into a single UserOperation.

BatchUserOperationCallData
ts
export type BatchUserOperationCallData = Exclude<UserOperationCallData, Hex>[];

BigNumberish

A type that can be a hexadecimal string prefixed with Hex, a bigint, or a number. It is used to represent values that can be converted to or operate as big integers.

BigNumberish
ts
export const BigNumberishSchema = z.union([HexSchema, z.number(), z.bigint()]);

BigNumberishRange

An object type that may contain optional min and max fields, each of which accepts a BigNumberish value. This type is used to specify a numerical range, including both the minimum and maximum bounds.

BigNumberishRange
ts
export const BigNumberishRangeSchema = z
  .object({
    min: BigNumberishSchema.optional(),
    max: BigNumberishSchema.optional(),
  })
  .strict();

BundlerAction

Bundler Actions are viem Actions that map one-to-one with "public" Bundler RPC methods (eth_sendUserOperation, eth_getUserOperationByHash, etc.) under the EIP-4337 and EIP-6900 standards. They are used with a BundlerClient. BundlerActions do not require any special permissions, nor do they provide "signing" capabilities to the user. Examples of BundlerActions include retrieving the details of a specific user operation, estimating user operation gas, etc.

BundlerAction
ts
export type BundlerActions = {
  /**
   * calls `eth_estimateUserOperationGas` and  returns the result
   *
   * @param request - the {@link UserOperationRequest} to estimate gas for
   * @param entryPoint - the entry point address the op will be sent to
   * @param stateOverride - the state override to use for the estimation
   * @returns the gas estimates for the given response (see: {@link UserOperationEstimateGasResponse})
   */
  estimateUserOperationGas<
    TEntryPointVersion extends EntryPointVersion = EntryPointVersion
  >(
    request: UserOperationRequest<TEntryPointVersion>,
    entryPoint: Address,
    stateOverride?: StateOverride
  ): Promise<UserOperationEstimateGasResponse<TEntryPointVersion>>;

  /**
   * calls `eth_sendUserOperation` and returns the hash of the sent UserOperation
   *
   * @param request - the {@link UserOperationRequest} to send
   * @param entryPoint - the entry point address the op will be sent to
   * @returns the hash of the sent UserOperation
   */
  sendRawUserOperation<
    TEntryPointVersion extends EntryPointVersion = EntryPointVersion
  >(
    request: UserOperationRequest<TEntryPointVersion>,
    entryPoint: Address
  ): Promise<Hash>;

  /**
   * calls `eth_getUserOperationByHash` and returns the {@link UserOperationResponse}
   *
   * @param hash - the hash of the UserOperation to fetch
   * @returns - {@link UserOperationResponse}
   */
  getUserOperationByHash(hash: Hash): Promise<UserOperationResponse | null>;

  /**
   * calls `eth_getUserOperationReceipt` and returns the {@link UserOperationReceipt}
   *
   * @param hash - the hash of the UserOperation to get the receipt for
   * @returns - {@link UserOperationReceipt}
   */
  getUserOperationReceipt(hash: Hash): Promise<UserOperationReceipt | null>;

  /**
   * calls `eth_supportedEntryPoints` and returns the entry points the RPC supports
   *
   * @returns - {@link Address}[]
   */
  getSupportedEntryPoints(): Promise<Address[]>;
};

BundlerClient

BundlerClient is a custom viem Client we have built our own, where we extended viem's PublicClient with BundlerActions, which are Actions that provide custom functionalities of EIP-4337 and EIP-6900 standards. BundlerClient is an intermediary or connector that enables client applications to interact with the Bundler that you are using. BundlerClient, because it extends PublicClient, supports Public Actions for client applications to connect, query, and interact with the blockchain (i.e., sending transactions, smart contract executions, data retrieval, etc.).

BundlerClient
ts
export type BundlerClient<T extends Transport = Transport> = Client<
  T,
  Chain,
  undefined,
  [...PublicRpcSchema, ...BundlerRpcSchema],
  PublicActions<T, Chain> & BundlerActions
>;

export const createBundlerClientFromExisting: <
  T extends Transport | FallbackTransport = Transport
>(
  client: PublicClient<T, Chain>
) => BundlerClient<T> = <T extends Transport | FallbackTransport = Transport>(
  client: PublicClient<T, Chain>
): BundlerClient<T> => {
  return client.extend(bundlerActions);
};

ClientMiddleware

Middleware represents different operations involved in the SmartAccountClient pipeline for constructing a user operation given the user inputs by populating the UO with other data, including gas fees, paymaster data, etc.

ClientMiddleware
ts
export type ClientMiddleware<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = {
  dummyPaymasterAndData: ClientMiddlewareFn<TContext>;
  feeEstimator: ClientMiddlewareFn<TContext>;
  gasEstimator: ClientMiddlewareFn<TContext>;
  customMiddleware: ClientMiddlewareFn<TContext>;
  paymasterAndData: ClientMiddlewareFn<TContext>;
  userOperationSimulator: ClientMiddlewareFn<TContext>;
  signUserOperation: ClientMiddlewareFn<TContext>;
};

ClientMiddlewareConfig

Configuration object to configure ClientMiddleware of the SmartAccountClient during the client instantiation. You can configure using this object to configure the middleware of your interest selectively.

ClientMiddlewareFn
ts
export type ClientMiddlewareConfig<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = Omit<
  Partial<ClientMiddleware<TContext>>,
  "dummyPaymasterAndData" | "paymasterAndData"
> & {
  paymasterAndData?: {
    dummyPaymasterAndData: () =>
      | UserOperationRequest<"0.6.0">["paymasterAndData"]
      | Pick<UserOperationRequest<"0.7.0">, "paymaster" | "paymasterData">;
    paymasterAndData: ClientMiddlewareFn<TContext>;
  };
};

ClientMiddlewareFn

Each middleware is a function that takes in a user operation object, UserOperationStruct, performs its job to retrieve or compute the data, and populate different fields of the user operation to pass onto the next middleware in the pipeline before being signed and sent to the network. ClientMiddlewareFn is the function type that represents each middleware. In optional UserOperationOverrides, and UserOperationFeeOptions, and returns a promise that resolves to a modified UserOperationStruct. This function is what you specify as your overridden middleware value for applying custom logic during the UserOperationStruct object to be sent to the bundler for on-chain execution.

ClientMiddlewareFn
ts
export type ClientMiddlewareFn<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = <
  TAccount extends SmartContractAccount,
  C extends MiddlewareClient,
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
>(
  struct: Deferrable<UserOperationStruct<TEntryPointVersion>>,
  args: {
    overrides?: UserOperationOverrides<TEntryPointVersion>;
    context?: TContext;
    feeOptions?: UserOperationFeeOptions;
    account: TAccount;
    client: C;
  }
) => Promise<Deferrable<UserOperationStruct<TEntryPointVersion>>>;

EntryPointDef

An object type that defines the interface for EntryPoint functions for packing the user operation to the optimized data structure to enhance performance and reduce gas costs of transactions, and generating the hash of the user operation for the format compatible to the specified Chain and EntryPointVersion.

EntryPointDef
ts
export type EntryPointDef<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion,
  TChain extends Chain = Chain,
  TAbi extends Abi | readonly unknown[] = Abi
> = {
  version: TEntryPointVersion;
  address: Address;
  chain: TChain;
  abi: GetContractParameters<Transport, TChain, Account, TAbi>["abi"];
  getUserOperationHash: (
    request: UserOperationRequest<TEntryPointVersion>
  ) => Hex;
  packUserOperation: (
    userOperation: UserOperationRequest<TEntryPointVersion>
  ) => Hex;
};

Multiplier

An object type with a required multipler field, which is a number value with max precision of 4 decimal places.

Multiplier
ts
export const MultiplierSchema = z
  .object({
    /**
     * Multiplier value with max precision of 4 decimal places
     */
    multiplier: z.number().refine(
      (n) => {
        return (n.toString().split(".")[1]?.length ?? 0) <= 4;
      },
      { message: "Max precision is 4 decimal places" }
    ),
  })
  .strict();

SmartAccountAuthenticator

An extension of the SmartAccountSigner interface, this interface contains authentication-related functions in addition to the signing methods of the SmartAccountSigner. It provides methods to authenticate the signer (authenticate) as the "authorized" signer, often as the owner, of the SmartContractAccount. It also has methods to retrieve authentication details (getAuthDetails) about the signer instance that the user is using to authenticate to one's account.

SmartAccountAuthenticator
ts
import type {
  GetEntryPointFromAccount,
  SmartContractAccount,
} from "../account/smartContractAccount";
import type { UserOperationContext } from "../actions/smartAccount/types";
import type {
  UserOperationFeeOptions,
  UserOperationOverrides,
  UserOperationStruct,
} from "../types";
import type { Deferrable } from "../utils";
import type { MiddlewareClient } from "./actions";

//#region ClientMiddlewareFn
export type ClientMiddlewareFn<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = <
  TAccount extends SmartContractAccount,
  C extends MiddlewareClient,
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
>(
  struct: Deferrable<UserOperationStruct<TEntryPointVersion>>,
  args: {
    overrides?: UserOperationOverrides<TEntryPointVersion>;
    context?: TContext;
    feeOptions?: UserOperationFeeOptions;
    account: TAccount;
    client: C;
  }
) => Promise<Deferrable<UserOperationStruct<TEntryPointVersion>>>;
//#endregion ClientMiddlewareFn

//#region ClientMiddleware
export type ClientMiddleware<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = {
  dummyPaymasterAndData: ClientMiddlewareFn<TContext>;
  feeEstimator: ClientMiddlewareFn<TContext>;
  gasEstimator: ClientMiddlewareFn<TContext>;
  customMiddleware: ClientMiddlewareFn<TContext>;
  paymasterAndData: ClientMiddlewareFn<TContext>;
  userOperationSimulator: ClientMiddlewareFn<TContext>;
  signUserOperation: ClientMiddlewareFn<TContext>;
};
//#endregion ClientMiddleware

SmartAccountClient

SmartAccountClient is a custom viem Client, like the BundlerClient, which is an intermediary or connector that enables your client application to interact with the SmartContractAccount. SmartAccountClient is analogous to the WalletClient. The difference is that while WalletClient has WalletActions that lets your client application interact with an Externally-owned account (EOA) with a wallet, SmartAccountClient provides SmartAccountClientActions for client applications to interact with SmartContractAccounts.

SmartAccountClient
ts
export type SmartAccountClient<
  transport extends Transport = Transport,
  chain extends Chain | undefined = Chain | undefined,
  account extends SmartContractAccount | undefined =
    | SmartContractAccount
    | undefined,
  actions extends Record<string, unknown> = Record<string, unknown>,
  rpcSchema extends RpcSchema = SmartAccountClientRpcSchema,
  context extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = Prettify<
  Client<
    transport,
    chain,
    account,
    rpcSchema,
    actions & SmartAccountClientActions<chain, account, context>
  >
>;

SmartAccountClientAction

SmartAccountClientActions are viem Actions that map one-to-one with smart contract account-related or "signable" actions, such as constructing user operation requests to be sent to the Bundler, signing messages or user operation requests, sending user operations to the Bundler, upgrading accounts to different implementation address, etc. They are used with a SmartAccountClient. SmartAccountClientActions require special permissions and provide signing capabilities for SmartContractAccounts.

SmartAccountClientAction
ts
export type SmartAccountClientActions<
  chain extends Chain | undefined = Chain | undefined,
  account extends SmartContractAccount | undefined =
    | SmartContractAccount
    | undefined,
  context extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = BaseSmartAccountClientActions<chain, account, context> &
  BundlerActions &
  PublicActions;

SmartAccountSigner

An interface representing a signer capable of signing messages and typed data. It provides methods to retrieve the signer's address (getAddress), sign a message (signMessage), and sign typed data (signTypedData). SmartAccountSigner refers to the Signer instance responsible for the signing activities using its private key for smart account activities. Often, the Signer is referred to as the Owner of the account as it has the authority to use the smart account on-chain with its signatures.

SmartAccountSigner
ts
import type {
  GetEntryPointFromAccount,
  SmartContractAccount,
} from "../account/smartContractAccount";
import type { UserOperationContext } from "../actions/smartAccount/types";
import type {
  UserOperationFeeOptions,
  UserOperationOverrides,
  UserOperationStruct,
} from "../types";
import type { Deferrable } from "../utils";
import type { MiddlewareClient } from "./actions";

//#region ClientMiddlewareFn
export type ClientMiddlewareFn<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = <
  TAccount extends SmartContractAccount,
  C extends MiddlewareClient,
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
>(
  struct: Deferrable<UserOperationStruct<TEntryPointVersion>>,
  args: {
    overrides?: UserOperationOverrides<TEntryPointVersion>;
    context?: TContext;
    feeOptions?: UserOperationFeeOptions;
    account: TAccount;
    client: C;
  }
) => Promise<Deferrable<UserOperationStruct<TEntryPointVersion>>>;
//#endregion ClientMiddlewareFn

//#region ClientMiddleware
export type ClientMiddleware<
  TContext extends UserOperationContext | undefined =
    | UserOperationContext
    | undefined
> = {
  dummyPaymasterAndData: ClientMiddlewareFn<TContext>;
  feeEstimator: ClientMiddlewareFn<TContext>;
  gasEstimator: ClientMiddlewareFn<TContext>;
  customMiddleware: ClientMiddlewareFn<TContext>;
  paymasterAndData: ClientMiddlewareFn<TContext>;
  userOperationSimulator: ClientMiddlewareFn<TContext>;
  signUserOperation: ClientMiddlewareFn<TContext>;
};
//#endregion ClientMiddleware

SmartContractAccount

As smart contract accounts are essentially the contract codes that operate on the blockchain, SmartContractAccount defines the interface with different functionalities for managing and interacting with the contract account. It includes different functionalities for creating, managing, and using your smart account. In addition to supporting all functionalities achieved with a basic EOA alone, SmartContractAccount can have custom capabilities such as automating processes or executing actions based on predefined conditions. Smart contract wallets allow users to customize how they manage their digital assets, offering a more tailored approach to handling funds securely. SmartContractAccount type extends viem's Account, and instantiation of an account is done using the toSmartContractAccount action.

SmartContractAccount
ts
export type SmartContractAccount<
  Name extends string = string,
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> = LocalAccount<Name> & {
  source: Name;
  getDummySignature: () => Hex | Promise<Hex>;
  encodeExecute: (tx: AccountOp) => Promise<Hex>;
  encodeBatchExecute: (txs: AccountOp[]) => Promise<Hex>;
  signUserOperationHash: (uoHash: Hex) => Promise<Hex>;
  signMessageWith6492: (params: { message: SignableMessage }) => Promise<Hex>;
  signTypedDataWith6492: <
    const typedData extends TypedData | Record<string, unknown>,
    primaryType extends keyof typedData | "EIP712Domain" = keyof typedData
  >(
    typedDataDefinition: TypedDataDefinition<typedData, primaryType>
  ) => Promise<Hex>;
  encodeUpgradeToAndCall: (params: UpgradeToAndCallParams) => Promise<Hex>;
  getNonce(nonceKey?: bigint): Promise<bigint>;
  getInitCode: () => Promise<Hex>;
  isAccountDeployed: () => Promise<boolean>;
  getFactoryAddress: () => Promise<Address>;
  getFactoryData: () => Promise<Hex>;
  getEntryPoint: () => EntryPointDef<TEntryPointVersion>;
  getImplementationAddress: () => Promise<NullAddress | Address>;
};

StateOverride

A type defining state overrides for eth_call method. An optional address-to-state mapping, where each entry specifies some state to be ephemerally overridden prior to executing the call. State overrides allow you to customize the network state for the purpose of the simulation, so this feature is useful when you need to test or simulate scenarios under conditions that aren’t currently present on the live network.

ToSmartContractAccountParams

This type defines the parameters to the SmartContractAccount instantiation action, toSmartContractAccount. You can configure this parameter to specify the Transport, Chain, EntryPointDef, and other base functionalities of the smart account that you are creating.

ToSmartContractAccountParams
ts
export type ToSmartContractAccountParams<
  Name extends string = string,
  TTransport extends Transport = Transport,
  TChain extends Chain = Chain,
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> = {
  source: Name;
  transport: TTransport;
  chain: TChain;
  entryPoint: EntryPointDef<TEntryPointVersion, TChain>;
  accountAddress?: Address;
  getAccountInitCode: () => Promise<Hex>;
  getDummySignature: () => Hex | Promise<Hex>;
  encodeExecute: (tx: AccountOp) => Promise<Hex>;
  encodeBatchExecute?: (txs: AccountOp[]) => Promise<Hex>;
  // if not provided, will default to just using signMessage over the Hex
  signUserOperationHash?: (uoHash: Hex) => Promise<Hex>;
  encodeUpgradeToAndCall?: (params: UpgradeToAndCallParams) => Promise<Hex>;
} & Omit<CustomSource, "signTransaction" | "address">;

User

User is a type that defines the model for the details of a user's Embedded Account via an Alchemy Signer. It includes the user's email, orgId, userId, userId, address (the EOA signer address corresponding to the user credentials), and credentialId. You can use the useUser react hook to look up a user.

User
ts
export type User = {
  email?: string;
  orgId: string;
  userId: string;
  address: Address;
  credentialId?: string;
};

UserOperationCallData

UserOperationCallData is a type that represents the user's "intent" or the desired outcome representing a specific objective a user aims to accomplish. It includes target (the destination address), data (the Transaction calldata), and value (the amount value of ETH, or the native token to send). It acts as the input to the sendUserOperation method on SmartAccountClient.

UserOperationCallData
ts
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;

UserOperationEstimateGasResponse

An interface that defines the structure for the response received from the RPC method eth_estimateUserOperationGas. This response provides detailed information about the estimated gas usage for a UserOperation.

UserOperationEstimateGasResponse
ts
export interface UserOperationEstimateGasResponse<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> {
  /* Gas overhead of this UserOperation */
  preVerificationGas: BigNumberish;
  /* Actual gas used by the validation of this UserOperation */
  verificationGasLimit: BigNumberish;
  /* Value used by inner account execution */
  callGasLimit: BigNumberish;
  /*
   * EntryPoint v0.7.0 operations only.
   * The amount of gas to allocate for the paymaster validation code.
   * Note: `eth_estimateUserOperationGas` does not return paymasterPostOpGasLimit.
   */
  paymasterVerificationGasLimit: TEntryPointVersion extends "0.7.0"
    ? BigNumberish | undefined
    : never;
}

UserOperationOverrides

Partial structure for overriding default values in a UserOperationStruct, such as gas limits and fees. Available fields include maxFeePerGas, maxPriorityFeePerGas, callGasLimit, preVerificationGas, verificationGasLimit, paymasterAndData, or nonceKey. You can also specify a stateOverride to be passed into eth_estimateUserOperationGas during gas estimation. These override values are available from each ClientMiddleware of the SmartAccountClient. Check out UserOperationOverrides page to learn more.

UserOperationOverrides
ts
export type UserOperationOverrides<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> = Partial<
  {
    callGasLimit:
      | UserOperationStruct<TEntryPointVersion>["callGasLimit"]
      | Multiplier;
    maxFeePerGas:
      | UserOperationStruct<TEntryPointVersion>["maxFeePerGas"]
      | Multiplier;
    maxPriorityFeePerGas:
      | UserOperationStruct<TEntryPointVersion>["maxPriorityFeePerGas"]
      | Multiplier;
    preVerificationGas:
      | UserOperationStruct<TEntryPointVersion>["preVerificationGas"]
      | Multiplier;
    verificationGasLimit:
      | UserOperationStruct<TEntryPointVersion>["verificationGasLimit"]
      | Multiplier;
    /**
     * This can be used to override the key used when calling `entryPoint.getNonce`
     * It is useful when you want to use parallel nonces for user operations
     *
     * NOTE: not all bundlers fully support this feature and it could be that your bundler will still only include
     * one user operation for your account in a bundle
     */
    nonceKey: bigint;

    /**
     * The same state overrides for
     * [`eth_call`](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-eth#eth-call) method.
     * An address-to-state mapping, where each entry specifies some state to be ephemerally overridden
     * prior to executing the call. State overrides allow you to customize the network state for
     * the purpose of the simulation, so this feature is useful when you need to estimate gas
     * for user operation scenarios under conditions that aren’t currently present on the live network.
     */
    stateOverride: StateOverride;
  } & UserOperationPaymasterOverrides<TEntryPointVersion>
>;

UserOperationReceipt

An interface that defines the structure for the response received from the RPC method eth_getUserOperationReceipt. It includes details like sender, nonce, gas cost, and success status of the UserOperation.

UserOperationReceipt
ts
export interface UserOperationReceipt {
  /* The request hash of the UserOperation. */
  userOpHash: Hash;
  /* The entry point address used for the UserOperation. */
  entryPoint: Address;
  /* The account initiating the UserOperation. */
  sender: Address;
  /* The nonce used in the UserOperation. */
  nonce: BigNumberish;
  /* The paymaster used for this UserOperation (or empty). */
  paymaster?: Address;
  /* The actual amount paid (by account or paymaster) for this UserOperation. */
  actualGasCost: BigNumberish;
  /* The total gas used by this UserOperation (including preVerification, creation, validation, and execution). */
  actualGasUsed: BigNumberish;
  /* Indicates whether the execution completed without reverting. */
  success: boolean;
  /* In case of revert, this is the revert reason. */
  reason?: string;
  /* The logs generated by this UserOperation (not including logs of other UserOperations in the same bundle). */
  logs: string[];
  /* The TransactionReceipt object for the entire bundle, not only for this UserOperation. */
  receipt: TransactionReceipt;
}

UserOperationRequest

Interface for the request format required for a JSON-RPC request to eth_sendUserOperation. It includes sender, nonce, gas limits, fees, and more fields.

UserOperationRequest
ts
// Reference: https://eips.ethereum.org/EIPS/eip-4337#definitions
export type UserOperationRequest<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> = TEntryPointVersion extends "0.6.0"
  ? UserOperationRequest_v6
  : TEntryPointVersion extends "0.7.0"
  ? UserOperationRequest_v7
  : never;

UserOperationResponse

An interface that defines the structure for the response received from the RPC method eth_getUserOperationByHash, detailing the result of executing a UserOperation. It includes the block number, block hash, transaction hash and more information associated with the UO.

UserOperationResponse
ts
export interface UserOperationResponse<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> {
  /* the User Operation */
  userOperation: UserOperationRequest<TEntryPointVersion>;
  /* the address of the entry point contract that executed the user operation */
  entryPoint: Address;
  /* the block number the user operation was included in */
  blockNumber: BigNumberish;
  /* the hash of the block the user operation was included in */
  blockHash: Hash;
  /* the hash of the transaction that included the user operation */
  transactionHash: Hash;
}

UserOperationStruct

Interface for structuring a UserOperation, with fields similar to UserOperationRequest but used for building requests.

UserOperationStruct
ts
export type UserOperationStruct<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> = TEntryPointVersion extends "0.6.0"
  ? UserOperationStruct_v6
  : TEntryPointVersion extends "0.7.0"
  ? UserOperationStruct_v7
  : never;