# Execute transactions

In this guide, you will learn how to create Safe transactions, sign them, collect the signatures from the different owners, and execute them.

See the [Protocol Kit reference](../../../reference-sdk-protocol-kit/overview.mdx) to find more details and configuration options.

## Prerequisites

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
- An existing Safe with several signers.

## Install dependencies

First, you need to install some dependencies.


```bash
pnpm add @safe-global/api-kit \
  @safe-global/protocol-kit \
  @safe-global/types-kit
```


## Steps

<Steps>

  ### Imports

  Here are all the necessary imports for this guide.


  ```typescript
  import SafeApiKit from '@safe-global/api-kit'
  import Safe from '@safe-global/protocol-kit'
  import {
    MetaTransactionData,
    OperationType
  } from '@safe-global/types-kit'
  ```


  ### Setup

  You need a Safe account setup with two or more signers and threshold two, so at least multiple signatures have to be collected when executing a transaction.

  This example uses private keys, but any EIP-1193 compatible signers can be used.


  ```typescript
  const SAFE_ADDRESS = // ...

  const OWNER_1_ADDRESS = // ...
  const OWNER_1_PRIVATE_KEY = // ...

  const OWNER_2_PRIVATE_KEY = // ...

  const RPC_URL = 'https://ethereum-sepolia-rpc.publicnode.com'
  ```


  This guide uses Sepolia, but you can use any chain from the Safe Transaction Service [supported networks](../../../advanced/smart-account-supported-networks.mdx?service=Transaction+Service&service=Safe{Core}+SDK).

  ### Initialize the Protocol Kit

  To handle transactions and signatures, you need to create an instance of the Protocol Kit with the `provider`, `signer` and `safeAddress`.

  Optionally, you can [track your Safe transactions on-chain](../../onchain-tracking.mdx) by using the `onchainAnalytics` property.


  ```typescript
  const protocolKitOwner1 = await Safe.init({
    provider: RPC_URL,
    signer: OWNER_1_PRIVATE_KEY,
    safeAddress: SAFE_ADDRESS,
    onchainAnalytics // Optional
  })
  ```


  ### Create a transaction

  Create a `safeTransactionData` object with the properties of the transaction, add it to an array of transactions you want to execute, and pass it to the `createTransaction` method.


  ```typescript
  const safeTransactionData: MetaTransactionData = {
    to: '0x',
    value: '1', // 1 wei
    data: '0x',
    operation: OperationType.Call
  }

  const safeTransaction = await protocolKitOwner1.createTransaction({
    transactions: [safeTransactionData]
  })
  ```


  For more details on what to include in a transaction, see the [`createTransaction`](../../../reference-sdk-protocol-kit/transactions/createtransaction.mdx) method in the reference.

  ### Propose the transaction

  Before a transaction can be executed, the signer who creates it needs to send it to the Safe Transaction Service so that it is accessible by the other owners, who can then give their approval and sign the transaction.

  Firstly, you need to create an instance of the API Kit. In chains where the [Safe Transaction Service](../../../core-api/transaction-service-overview.mdx) is supported, it's enough to specify the `chainId` property.


  ```typescript
  // How to get an Api key => http://docs.safe.global/core-api/how-to-use-api-keys
  const apiKit = new SafeApiKit({
    chainId: 11155111n,
    apiKey: 'YOUR_API_KEY'
  })
  ```


  You need to calculate the Safe transaction hash, sign the transaction hash, and call the `proposeTransaction` method from the API Kit instance to propose a transaction.

  For a full list and description of the properties see [`proposeTransaction`](../../../reference-sdk-api-kit/proposetransaction.mdx) in the API Kit reference.


  ```typescript
  // Deterministic hash based on transaction parameters
  const safeTxHash = await protocolKitOwner1.getTransactionHash(safeTransaction)

  // Sign transaction to verify that the transaction is coming from owner 1
  const senderSignature = await protocolKitOwner1.signHash(safeTxHash)

  await apiKit.proposeTransaction({
    safeAddress,
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress: OWNER_1_ADDRESS,
    senderSignature: senderSignature.data
  })
  ```


  ### Retrieve the pending transactions

  The other signers need to retrieve the pending transactions from the Safe Transaction Service. Depending on the situation, different methods in the API Kit are available.

  Call the [`getPendingTransactions`](../../../reference-sdk-api-kit/getpendingtransactions.mdx) method to retrieve all the pending transactions of a Safe account.


  ```typescript
  const pendingTransactions = (await apiKit.getPendingTransactions(safeAddress)).results
  ```


  ### Confirm the transaction

  Once a signer has the pending transaction, they need to sign it with the Protocol Kit and submit the signature to the service using the [`confirmTransaction`](../../../reference-sdk-api-kit/confirmtransaction.mdx) method.


  ```typescript
  const protocolKitOwner2 = await Safe.init({
    provider: RPC_URL,
    signer: OWNER_2_PRIVATE_KEY,
    safeAddress: SAFE_ADDRESS
  })

  const safeTxHash = transaction.transactionHash
  const signature = await protocolKitOwner2.signHash(safeTxHash)

  // Confirm the Safe transaction
  const signatureResponse = await apiKit.confirmTransaction(
    safeTxHash,
    signature.data
  )
  ```


  ### Execute the transaction

  The Safe transaction is now ready to be executed. This can be done using the [Safe\{Wallet\}](https://app.safe.global) web interface, the [Protocol Kit](../../../reference-sdk-protocol-kit/transactions/executetransaction.mdx), the [Safe CLI](../../../advanced/cli-reference/tx-service-commands.mdx#execute-pending-transaction) or any other tool that's available.

  In this guide, the first signer will get the transaction from the service by calling the [`getTransaction`](../../../reference-sdk-api-kit/gettransaction.mdx) method and execute it by passing the transaction with all the signatures to the [`executeTransaction`](../../../reference-sdk-protocol-kit/transactions/executetransaction.mdx) method.


  ```typescript
  const safeTransaction = await apiKit.getTransaction(safeTxHash)
  const executeTxResponse = await protocolKitOwner1.executeTransaction(safeTransaction)
  ```


</Steps>

## Recap and further reading

After following this guide, you are able to create, sign, and execute Safe transactions with the Protocol Kit and share the signatures with the different signers using the API Kit.
