Skip to content

useSendUserOperation

The useSendUserOperation hook enables sending UserOperations on behalf of the user's Embedded Account.

Import

import { useSendUserOperation } from "@alchemy/aa-alchemy/react";

Usage

Without awaiting the transaction hash

useSendUserOperation.tsx
import {
  useSendUserOperation,
  useSmartAccountClient,
} from "@alchemy/aa-alchemy/react";
 
export function ComponentWithSendUserOperation() {
  /**
   * Assumes the app has context of a signer with an authenticated user
   * by using the `AlchemyAccountProvider` from `@alchemy/aa-alchemy/react`.
   */
  const { client } = useSmartAccountClient({
    type: "MultiOwnerModularAccount",
  });
  const { sendUserOperation, isSendingUserOperation } = useSendUserOperation({
    client,
    onSuccess: ({ hash, request }) => {
      // [optional] Do something with the hash and request
    },
    onError: (error) => {
      // [optional] Do something with the error
    },
    // [optional] ...additional mutationArgs
  });
 
  return (
    <div>
      <button
        onClick={() =>
          sendUserOperation({
            target: "0xTARGET_ADDRESS",
            data: "0x",
            value: 0n,
          })
        }
        disabled={isSendingUserOperation}
      >
        {isSendingUserOperation ? "Sending..." : "Send UO"}
      </button>
    </div>
  );
}

Await the tx to mine and retry failures

The below example uses the useSendUserOperation with the waitForTxn flag set to true and makes one drop and replace call if the UserOperation fails to be mined.

useSendUserOperationWithRetries.tsx
import {
  useDropAndReplace,
  useSendUserOperation,
  useSmartAccountClient,
} from "@alchemy/aa-alchemy/react";
import { WaitForUserOperationError } from "@alchemy/aa-core";
 
export function ComponentWithSendUserOperation() {
  /**
   * Assumes the app has context of a signer with an authenticated user
   * by using the `AlchemyAccountProvider` from `@alchemy/aa-alchemy/react`.
   */
  const { client } = useSmartAccountClient({
    type: "MultiOwnerModularAccount",
  });

  const { dropAndReplace, isDroppingAndReplacingUserOperation } =
    useDropAndReplace({ client });
 
  const { sendUserOperation, isSendingUserOperation } = useSendUserOperation({
    client,
    waitForTxn: true, 
    onError: (error) => {
      if (error instanceof WaitForUserOperationError) {
        dropAndReplace({ uoToDrop: error.request });
      }
    },
  });
 
  return (
    <div>
      <button
        onClick={() =>
          sendUserOperation({
            target: "0xTARGET_ADDRESS",
            data: "0x",
            value: 0n,
          })
        }
        disabled={isSendingUserOperation || isDroppingAndReplacingUserOperation}
      >
        {isSendingUserOperation ? "Sending..." : "Send UO"}
      </button>
    </div>
  );
}

Params

client

AlchemySmartAccountClient | undefined A AlchemySmartAccountClient with methods to interact with an Alchemy smart account.

waitForTxn

boolean | undefined An optional flag to additionally wait for the transaction hash in which the send UserOperation lands. Defaults to false.

...mutationArgs

You can optionally specify any of the React Query useMutation parameters as parameters to this hook.

Return Type

import { type UseSendUserOperation } from "@alchemy/aa-alchemy/react";

Returns an object containing the following state.

sendUserOperation

UseMutateFunction A React query mutation function to send a UserOperation. It returns a SendUserOperationResult object.

SendUserOperationResult
types.ts
export type SendUserOperationResult<
  TEntryPointVersion extends EntryPointVersion = EntryPointVersion
> = {
  hash: Hash;
  request: UserOperationRequest<TEntryPointVersion>;
};

It takes in SendUserOperationParameters which has the following type:

SendUserOperationParameters
types.ts
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>;

sendUserOperationAsync

UseMutateAsyncFunction A React query async mutation function to send a UserOperation. Via an awaitable promise, it returns a SendUserOperationResult object shown above.

sendUserOperationResult

An object of the shown above SendUserOperationResult type if the mutation has run successfully, undefined otherwise. The hash field is the UserOperation hash if waitForTxn is false, otherwise it is the hash of the transaction in which the UserOperation lands.

isSendingUserOperation

boolean A flag that determines whether the mutation is still running or not.

error

Error | null A field that relays any errors from the mutation. It is null if there is no error.