# Send User Operations

In this guide, you will learn how to create Safe [user operations](../../../home/glossary.md#useroperation), sign them, collect the signatures from the different owners, and execute them.

For more detailed information, see the [Starter Kit Reference](../../../reference-sdk-starter-kit/overview.mdx).

[Pimlico](https://pimlico.io) is used in this guide as the service provider, but any other provider compatible with the ERC-4337 can be used.

## Prerequisites

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- A [Pimlico account](https://dashboard.pimlico.io) and an API key.

## Install dependencies

First, you need to install some dependencies.

```bash
pnpm add @safe-global/sdk-starter-kit
```

## Steps

<Steps>

  ### Imports

  Here are all the necessary imports for this guide.


  ```typescript
  import {
    createSafeClient,
    safeOperations,
    BundlerOptions
  } from '@safe-global/sdk-starter-kit'
  ```


  ### Create a signer

  Firstly, you need to get a signer, which will be the owner of a Safe account after it's deployed.

  This example uses a private key, but any way to get an EIP-1193 compatible signer can be used.


  ```typescript
  const SIGNER_ADDRESS = // ...
  const SIGNER_PRIVATE_KEY = // ...
  const RPC_URL = 'https://rpc.ankr.com/eth_sepolia'
  ```


  ### Initialize the `SafeClient`


  <Tabs items={['New Safe account', 'Existing Safe account']}>
    <Tabs.Tab>
      When deploying a new Safe account, you need to pass the configuration of the Safe in the `safeOptions` property. The Safe account is configured with your signer as the only owner in this case.

      ```typescript
      const safeClient = await createSafeClient({
        provider: RPC_URL,
        signer: SIGNER_PRIVATE_KEY,
        safeOptions: {
          owners: [SIGNER_ADDRESS],
          threshold: 1
        }
      })
      ```
    </Tabs.Tab>
    <Tabs.Tab>
      When connecting an existing Safe account, you need to pass the `safeAddress`.

      ```typescript
      const safeClient = await createSafeClient({
        provider: RPC_URL,
        signer: SIGNER_PRIVATE_KEY,
        safeAddress: '0x...'
      })
      ```
    </Tabs.Tab>
  </Tabs>


  As this guide is related with ERC-4337 user operations, you need to add the `safeOperations` extension to the `safeClient` instance to support this functionality.


  ```typescript
  const bundlerOptions: BundlerOptions = {
    bundlerUrl: `https://api.pimlico.io/v1/sepolia/rpc?add_balance_override&apikey=${PIMLICO_API_KEY}`
  }

  const paymasterOptions: PaymasterOptions = {
    isSponsored: true,
    paymasterUrl: `https://api.pimlico.io/v2/sepolia/rpc?add_balance_override&apikey=${PIMLICO_API_KEY}`
  }

  const safeClientWithSafeOperation = await safeClient.extend(
    safeOperations(bundlerOptions, paymasterOptions)
  )
  ```

  The `safeClientWithSafeOperation` instance has now support for managing user operations.


  ### Create a Safe transaction

  Create an array of Safe transactions to execute.


  ```typescript
  const transactions = [{
    to: '0x...',
    data: '0x',
    value: '0'
  }]
  ```


  ### Send the Safe operation

  If you configured your Safe with `threshold` equal to `1`, calling the [`sendSafeOperation`](../../../reference-sdk-starter-kit/safe-operations/sendsafeoperation.mdx) method will execute the user operation. However, if the `threshold` is greater than `1` the other owners of the Safe will need to confirm the user operation until the required number of signatures are collected.


  ```typescript
  const safeOperationResult = await safeClientWithSafeOperation.sendSafeOperation({
    transactions
  })

  const safeOperationHash = safeOperationResult.safeOperations?.safeOperationHash
  ```


  ### Confirm the Safe operations

  If the user operation needs to be confirmed by other Safe owners, call the [`confirmSafeOperation`](../../../reference-sdk-starter-kit/safe-operations/confirmsafeoperation.mdx) method from a new `SafeClient` instance initialized with each of the signers that need to confirm it.


  ```typescript
  const newSafeClient = await createSafeClient({
    provider: RPC_URL,
    signer,
    safeAddress: '0x...'
  })

  const newSafeClientWithSafeOperation = await newSafeClient.extend(
    safeOperations({
      bundlerUrl: `https://api.pimlico.io/v1/sepolia/rpc?add_balance_override&apikey=${PIMLICO_API_KEY}`
    }, {
      isSponsored: true,
      paymasterUrl: `https://api.pimlico.io/v2/sepolia/rpc?add_balance_override&apikey=${PIMLICO_API_KEY}`
    })
  )
  ```

  Finally, retrieve all the pending user operations from the Safe Transaction Service and confirm the one you just created with each missing owner.


  ```typescript
  const pendingSafeOperations =
    await newSafeClientWithSafeOperation.getPendingSafeOperations()

  for (const safeOperation of pendingSafeOperations.results) {
    if (safeOperation.safeOperationHash !== safeOperationHash) {
      return
    }

    const safeOperationResult =
      await newSafeClientWithSafeOperation.confirmSafeOperation({ safeOperationHash })
  }
  ```


</Steps>

## Recap and further reading

After following this guide, you are able to deploy new Safe accounts and create, sign, and submit user operations with the Starter Kit.
