npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gelato-protocol-kit

v1.3.1

Published

SDK to interact with Safe smart contracts

Downloads

4

Readme

Protocol Kit

NPM Version GitHub Release GitHub

Software development kit that facilitates the interaction with the Safe contracts.

Table of contents

Installation

Install the package with yarn or npm:

yarn add @safe-global/protocol-kit
npm install @safe-global/protocol-kit

Build

Build the package with yarn or npm:

yarn build
npm run build

Tests

Create a .env file with environment variables. You can use the .env.example file as a reference.

Test the package with yarn or npm:

yarn test
npm run test

Getting Started

The following steps show how to set up the Protocol Kit, deploy a new Safe, create a Safe transaction, generate the required signatures from owners and execute the transaction. However, using the Protocol Kit alone will not allow for the collection of owner signatures off-chain. To do this and be able to see and confirm the pending transactions shown in the Safe Web App, it is recommended that you follow this other guide that covers the use of the Protocol Kit, combined with the API Kit.

1. Instantiate an EthAdapter

First of all, we need to create an EthAdapter, which contains all the required utilities for the SDKs to interact with the blockchain. It acts as a wrapper for web3.js or ethers.js Ethereum libraries.

Depending on the library used by the Dapp, there are two options:

Once the instance of EthersAdapter or Web3Adapter is created, it can be used in the SDK initialization.

2. Deploy a new Safe

To deploy a new Safe account instantiate the SafeFactory class and call the deploySafe method with the right params to configure the new Safe. This includes defining the list of owners and the threshold of the Safe. A Safe account with three owners and threshold equal three will be used as the starting point for this example but any Safe configuration is valid.

import Safe, { SafeFactory, SafeAccountConfig } from '@safe-global/protocol-kit'

const safeFactory = await SafeFactory.create({ ethAdapter })

const owners = ['0x<address>', '0x<address>', '0x<address>']
const threshold = 3
const safeAccountConfig: SafeAccountConfig = {
  owners,
  threshold
  // ...
}

const safeSdk: Safe = await safeFactory.deploySafe({ safeAccountConfig })

The deploySafe method executes a transaction from the owner1 account, deploys a new Safe and returns an instance of the Protocol Kit connected to the new Safe. Check the deploySafe method in the API Reference for more details on additional configuration parameters and callbacks.

Call the getAddress method, for example, to check the address of the newly deployed Safe.

const newSafeAddress = await safeSdk.getAddress()

To instantiate the Protocol Kit from an existing Safe just pass to it an instance of the EthAdapter class and the Safe address.

import Safe from '@safe-global/protocol-kit'

const safeSdk: Safe = await Safe.create({ ethAdapter: ethAdapterOwner1, safeAddress })

Check the create method in the API Reference for more details on additional configuration parameters.

3. Create a Safe transaction

import { SafeTransactionDataPartial } from '@safe-global/safe-core-sdk-types'

const safeTransactionData: SafeTransactionDataPartial = {
  to: '0x<address>',
  value: '<eth_value_in_wei>',
  data: '0x<data>'
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })

Check the createTransaction method in the API Reference for additional details on creating MultiSend transactions.

Before executing this transaction, it must be signed by the owners and this can be done off-chain or on-chain. In this example owner1 will sign it off-chain, owner2 will sign it on-chain and owner3 will execute it (the executor also signs the transaction transparently).

3.a. Off-chain signatures

The owner1 account signs the transaction off-chain.

const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction)

Because the signature is off-chain, there is no interaction with the contract and the signature becomes available at signedSafeTransaction.signatures.

3.b. On-chain signatures

To connect owner2 to the Safe we need to create a new instance of the class EthAdapter passing to its constructor the owner we would like to connect. After owner2 account is connected to the SDK as a signer the transaction hash will be approved on-chain.

const ethAdapterOwner2 = new EthersAdapter({ ethers, signerOrProvider: owner2 })
const safeSdk2 = await safeSdk.connect({ ethAdapter: ethAdapterOwner2, safeAddress })
const txHash = await safeSdk2.getTransactionHash(safeTransaction)
const approveTxResponse = await safeSdk2.approveTransactionHash(txHash)
await approveTxResponse.transactionResponse?.wait()

4. Transaction execution

Lastly, owner3 account is connected to the SDK as a signer and executor of the Safe transaction to execute it.

const ethAdapterOwner3 = new EthersAdapter({ ethers, signerOrProvider: owner3 })
const safeSdk3 = await safeSdk2.connect({ ethAdapter: ethAdapterOwner3, safeAddress })
const executeTxResponse = await safeSdk3.executeTransaction(safeTransaction)
await executeTxResponse.transactionResponse?.wait()

All the signatures used to execute the transaction are now available at safeTransaction.signatures.

Safe Factory API Reference

create

Returns an instance of the Safe Factory.

import { SafeFactory } from '@safe-global/protocol-kit'

const safeFactory = await SafeFactory.create({ ethAdapter })
  • The isL1SafeMasterCopy flag

    There are two versions of the Safe contracts: Safe.sol that does not trigger events in order to save gas and SafeL2.sol that does, which is more appropriate for L2 networks.

    By default Safe.sol will be only used on Ethereum Mainnet. For the rest of the networks where the Safe contracts are already deployed, the SafeL2.sol contract will be used unless you add the isL1SafeMasterCopy flag to force the use of the Safe.sol contract.

    const safeFactory = await SafeFactory.create({ ethAdapter, isL1SafeMasterCopy: true })
  • The contractNetworks property

    If the Safe contracts are not deployed to your current network, the contractNetworks property will be required to point to the addresses of the Safe contracts previously deployed by you.

    import { ContractNetworksConfig } from '@safe-global/protocol-kit'
    
    const chainId = await ethAdapter.getChainId()
    const contractNetworks: ContractNetworksConfig = {
      [chainId]: {
        safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
        safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
        multiSendAddress: '<MULTI_SEND_ADDRESS>',
        multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
        fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
        signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
        createCallAddress: '<CREATE_CALL_ADDRESS>',
        simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
        safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
        safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
        multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
        multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
        fallbackHandlerAbi: '<FALLBACK_HANDLER_ABI>', // Optional. Only needed with web3.js
        signMessageLibAbi: '<SIGN_MESSAGE_LIB_ABI>', // Optional. Only needed with web3.js
        createCallAbi: '<CREATE_CALL_ABI>', // Optional. Only needed with web3.js
        simulateTxAccessorAbi: '<SIMULATE_TX_ACCESSOR_ABI>' // Optional. Only needed with web3.js
      }
    }
    
    const safeFactory = await SafeFactory.create({ ethAdapter, contractNetworks })
  • The safeVersion property

    The SafeFactory constructor also accepts the safeVersion property to specify the Safe contract version that will be deployed. This string can take the values 1.0.0, 1.1.1, 1.2.0, 1.3.0 or 1.4.1. If not specified, the DEFAULT_SAFE_VERSION value will be used.

    const safeVersion = 'X.Y.Z'
    const safeFactory = await SafeFactory.create({ ethAdapter, safeVersion })

deploySafe

Deploys a new Safe and returns an instance of the Protocol Kit connected to the deployed Safe. The address of the Master Copy, Safe contract version and the contract (Safe.sol or SafeL2.sol) of the deployed Safe will depend on the initialization of the safeFactory instance.

const safeAccountConfig: SafeAccountConfig = {
  owners,
  threshold,
  to, // Optional
  data, // Optional
  fallbackHandler, // Optional
  paymentToken, // Optional
  payment, // Optional
  paymentReceiver // Optional
}

const safeSdk = await safeFactory.deploySafe({ safeAccountConfig })

This method can optionally receive the saltNonce parameter.

const safeAccountConfig: SafeAccountConfig = {
  owners,
  threshold,
  to, // Optional
  data, // Optional
  fallbackHandler, // Optional
  paymentToken, // Optional
  payment, // Optional
  paymentReceiver // Optional
}

const saltNonce = '<YOUR_CUSTOM_VALUE>'

const safeSdk = await safeFactory.deploySafe({ safeAccountConfig, saltNonce })

Optionally, some properties can be passed as execution options:

const options: Web3TransactionOptions = {
  from, // Optional
  gas, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const options: EthersTransactionOptions = {
  from, // Optional
  gasLimit, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const safeSdk = await safeFactory.deploySafe({ safeAccountConfig, safeDeploymentConfig, options })

It can also take an optional callback which receives the txHash of the Safe deployment transaction prior to returning a new instance of the Protocol Kit:

const callback = (txHash: string): void => {
  console.log({ txHash })
}

const safeSdk = await safeFactory.deploySafe({ safeAccountConfig, callback })

Safe Core SDK API Reference

create

Returns an instance of the Protocol Kit connected to a Safe. The provided Safe must be a safeAddress or a predictedSafe.

Initialization of a deployed Safe using the safeAddress property:

import Safe from '@safe-global/protocol-kit'

const safeSdk = await Safe.create({ ethAdapter, safeAddress })

Initialization of a not deployed Safe using the predictedSafe property. Because Safes are deployed in a deterministic way, passing a predictedSafe will allow to initialize the SDK with the Safe configuration and use it to some extent before it is deployed:

import Safe, { PredictedSafeProps } from '@safe-global/protocol-kit'

const predictedSafe: PredictedSafeProps = {
  safeAccountConfig,
  safeDeploymentConfig
}

const safeSdk = await Safe.create({ ethAdapter, predictedSafe })
  • The isL1SafeMasterCopy flag

    There are two versions of the Safe contracts: Safe.sol that does not trigger events in order to save gas and SafeL2.sol that does, which is more appropriate for L2 networks.

    By default Safe.sol will be only used on Ethereum Mainnet. For the rest of the networks where the Safe contracts are already deployed, the SafeL2.sol contract will be used unless you add the isL1SafeMasterCopy flag to force the use of the Safe.sol contract.

    const safeSdk = await Safe.create({ ethAdapter, safeAddress, isL1SafeMasterCopy: true })
  • The contractNetworks property

    If the Safe contracts are not deployed to your current network, the contractNetworks property will be required to point to the addresses of the Safe contracts previously deployed by you.

    import { ContractNetworksConfig } from '@safe-global/protocol-kit'
    
    const chainId = await ethAdapter.getChainId()
    const contractNetworks: ContractNetworksConfig = {
      [chainId]: {
        safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
        safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
        multiSendAddress: '<MULTI_SEND_ADDRESS>',
        multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
        fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
        signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
        createCallAddress: '<CREATE_CALL_ADDRESS>',
        simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
        safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
        safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
        multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
        multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
        fallbackHandlerAbi: '<FALLBACK_HANDLER_ABI>', // Optional. Only needed with web3.js
        signMessageLibAbi: '<SIGN_MESSAGE_LIB_ABI>', // Optional. Only needed with web3.js
        createCallAbi: '<CREATE_CALL_ABI>', // Optional. Only needed with web3.js
        simulateTxAccessorAbi: '<SIMULATE_TX_ACCESSOR_ABI>' // Optional. Only needed with web3.js
      }
    }
    
    const safeSdk = await Safe.create({ ethAdapter, safeAddress, contractNetworks })

connect

Returns a new instance of the Protocol Kit connected to a new Safe or a new Signer. The new connected signer can be passed via the ethAdapter property while the new connected Safe can be passed using a safeAddress or a predictedSafe.

Connection of a deployed Safe using the safeAddress property:

const safeSdk = await safeSdk.connect({ ethAdapter, safeAddress })

Connection of a not deployed Safe using the predictedSafe property. Because Safes are deployed in a deterministic way, passing a predictedSafe will allow to connect a Safe to the SDK with the Safe configuration:

import { PredictedSafeProps } from '@safe-global/protocol-kit'

const predictedSafe: PredictedSafeProps = {
  safeAccountConfig,
  safeDeploymentConfig
}

const safeSdk = await safeSdk.connect({ ethAdapter, predictedSafe })
  • The isL1SafeMasterCopy flag

    There are two versions of the Safe contracts: Safe.sol that does not trigger events in order to save gas and SafeL2.sol that does, which is more appropriate for L2 networks.

    By default Safe.sol will be only used on Ethereum Mainnet. For the rest of the networks where the Safe contracts are already deployed, the SafeL2.sol contract will be used unless you add the isL1SafeMasterCopy flag to force the use of the Safe.sol contract.

    const safeSdk = await Safe.connect({ ethAdapter, safeAddress, isL1SafeMasterCopy: true })
  • The contractNetworks property

    If the Safe contracts are not deployed to your current network, the contractNetworks property will be required to point to the addresses of the Safe contracts previously deployed by you.

    import { ContractNetworksConfig } from '@safe-global/protocol-kit'
    
    const chainId = await ethAdapter.getChainId()
    const contractNetworks: ContractNetworksConfig = {
      [chainId]: {
        safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
        safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
        multiSendAddress: '<MULTI_SEND_ADDRESS>',
        multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
        fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
        signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
        createCallAddress: '<CREATE_CALL_ADDRESS>',
        simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
        safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
        safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
        multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
        multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
        fallbackHandlerAbi: '<FALLBACK_HANDLER_ABI>', // Optional. Only needed with web3.js
        signMessageLibAbi: '<SIGN_MESSAGE_LIB_ABI>', // Optional. Only needed with web3.js
        createCallAbi: '<CREATE_CALL_ABI>', // Optional. Only needed with web3.js
        simulateTxAccessorAbi: '<SIMULATE_TX_ACCESSOR_ABI>' // Optional. Only needed with web3.js
      }
    }
    const safeSdk = await Safe.connect({ ethAdapter, safeAddress, contractNetworks })

getAddress

Returns the address of the current SafeProxy contract.

const safeAddress = await safeSdk.getAddress()

getContractVersion

Returns the Safe Master Copy contract version.

const contractVersion = await safeSdk.getContractVersion()

getOwners

Returns the list of Safe owner accounts.

const ownerAddresses = await safeSdk.getOwners()

getNonce

Returns the Safe nonce.

const nonce = await safeSdk.getNonce()

getThreshold

Returns the Safe threshold.

const threshold = await safeSdk.getThreshold()

getChainId

Returns the chainId of the connected network.

const chainId = await safeSdk.getChainId()

getBalance

Returns the ETH balance of the Safe.

const balance = await safeSdk.getBalance()

getGuard

Returns the enabled Safe guard or 0x address if no guards are enabled.

const guardAddress = await safeSdk.getGuard()

getModules

Returns the list of addresses of all the enabled Safe modules.

const moduleAddresses = await safeSdk.getModules()

isModuleEnabled

Checks if a specific Safe module is enabled for the current Safe.

const isEnabled = await safeSdk.isModuleEnabled(moduleAddress)

isOwner

Checks if a specific address is an owner of the current Safe.

const isOwner = await safeSdk.isOwner(address)

createTransaction

Returns a Safe transaction ready to be signed by the owners and executed. The Protocol Kit supports the creation of single Safe transactions but also MultiSend transactions.

  • Single transactions

    This method can take an object of type SafeTransactionDataPartial that represents the transaction we want to execute (once the signatures are collected). It accepts some optional properties as follows.

    import { SafeTransactionDataPartial } from '@safe-global/safe-core-sdk-types'
    
    const safeTransactionData: SafeTransactionDataPartial = {
      to,
      data,
      value,
      operation, // Optional
      safeTxGas, // Optional
      baseGas, // Optional
      gasPrice, // Optional
      gasToken, // Optional
      refundReceiver, // Optional
      nonce // Optional
    }
    const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
  • MultiSend transactions

    This method can take an array of MetaTransactionData objects that represent the multiple transactions we want to include in our MultiSend transaction. If we want to specify some of the optional properties in our MultiSend transaction, we can pass a second argument to the createTransaction method with the SafeTransactionOptionalProps object.

    const safeTransactionData: MetaTransactionData[] = [
      {
        to,
        data,
        value,
        operation // Optional
      },
      {
        to,
        data,
        value,
        operation // Optional
      }
      // ...
    ]
    const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })

    This method can also receive the options parameter to set the optional properties in the MultiSend transaction:

    const safeTransactionData: MetaTransactionData[] = [
      {
        to,
        data,
        value,
        operation // Optional
      },
      {
        to,
        data,
        value,
        operation // Optional
      }
      // ...
    ]
    const options: SafeTransactionOptionalProps = {
      safeTxGas, // Optional
      baseGas, // Optional
      gasPrice, // Optional
      gasToken, // Optional
      refundReceiver, // Optional
      nonce // Optional
    }
    const safeTransaction = await safeSdk.createTransaction({ safeTransactionData, options })

    In addition, the optional callsOnly parameter, which is false by default, allows to force the use of the MultiSendCallOnly instead of the MultiSend contract when sending a batch transaction:

    const callsOnly = true
    const safeTransaction = await safeSdk.createTransaction({
      safeTransactionData,
      options,
      callsOnly
    })

If the optional properties are not manually set, the Safe transaction returned will have the default value for each one:

  • operation: OperationType.Call (0) is the default value.
  • safeTxGas: The right gas estimation is the default value.
  • baseGas: 0 is the default value.
  • gasPrice: 0 is the default value.
  • gasToken: 0x address is the default value.
  • refundReceiver: 0x address is the default value.
  • nonce: The current Safe nonce is the default value.

Read more about create transactions from a Safe.

createRejectionTransaction

Returns a Safe transaction ready to be signed by the owners that invalidates the pending Safe transaction/s with a specific nonce.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const rejectionTransaction = await safeSdk.createRejectionTransaction(safeTransaction.data.nonce)

copyTransaction

Copies a Safe transaction.

const safeTransaction1 = await safeSdk.createTransaction({ safeTransactionData })
const safeTransaction2 = await copyTransaction(safeTransaction1)

getTransactionHash

Returns the transaction hash of a Safe transaction.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const txHash = await safeSdk.getTransactionHash(safeTransaction)

signTransactionHash

Signs a hash using the current owner account.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const txHash = await safeSdk.getTransactionHash(safeTransaction)
const signature = await safeSdk.signTransactionHash(txHash)

signTypedData

Signs a transaction according to the EIP-712 using the current signer account.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const signature = await safeSdk.signTypedData(safeTransaction)

signTransaction

Returns a new SafeTransaction object that includes the signature of the current owner. eth_sign will be used by default to generate the signature.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction)

Optionally, an additional parameter can be passed to specify a different way of signing:

const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction, 'eth_signTypedData')
const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction, 'eth_sign') // default option.

approveTransactionHash

Approves a hash on-chain using the current owner account.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const txHash = await safeSdk.getTransactionHash(safeTransaction)
const txResponse = await safeSdk.approveTransactionHash(txHash)
await txResponse.transactionResponse?.wait()

Optionally, some properties can be passed as execution options:

const options: Web3TransactionOptions = {
  from, // Optional
  gas, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const options: EthersTransactionOptions = {
  from, // Optional
  gasLimit, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const txResponse = await safeSdk.approveTransactionHash(txHash, options)

getOwnersWhoApprovedTx

Returns a list of owners who have approved a specific Safe transaction.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const txHash = await safeSdk.getTransactionHash(safeTransaction)
const ownerAddresses = await safeSdk.getOwnersWhoApprovedTx(txHash)

createEnableFallbackHandlerTx

Returns the Safe transaction to enable the fallback handler.

const safeTransaction = await safeSdk.createEnableFallbackHandlerTx(fallbackHandlerAddress)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = {
  safeTxGas, // Optional
  baseGas, // Optional
  gasPrice, // Optional
  gasToken, // Optional
  refundReceiver, // Optional
  nonce // Optional
}
const safeTransaction = await safeSdk.createEnableFallbackHandlerTx(fallbackHandlerAddress, options)

createDisableFallbackHandlerTx

Returns the Safe transaction to disable the fallback handler.

const safeTransaction = await safeSdk.createDisableFallbackHandlerTx()
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createDisableFallbackHandlerTx(options)

createEnableGuardTx

Returns the Safe transaction to enable a Safe guard.

const safeTransaction = await safeSdk.createEnableGuardTx(guardAddress)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = {
  safeTxGas, // Optional
  baseGas, // Optional
  gasPrice, // Optional
  gasToken, // Optional
  refundReceiver, // Optional
  nonce // Optional
}
const safeTransaction = await safeSdk.createEnableGuardTx(guardAddress, options)

createDisableGuardTx

Returns the Safe transaction to disable a Safe guard.

const safeTransaction = await safeSdk.createDisableGuardTx()
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createDisableGuardTx(options)

createEnableModuleTx

Returns a Safe transaction ready to be signed that will enable a Safe module.

const safeTransaction = await safeSdk.createEnableModuleTx(moduleAddress)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createEnableModuleTx(moduleAddress, options)

createDisableModuleTx

Returns a Safe transaction ready to be signed that will disable a Safe module.

const safeTransaction = await safeSdk.createDisableModuleTx(moduleAddress)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createDisableModuleTx(moduleAddress, options)

createAddOwnerTx

Returns the Safe transaction to add an owner and optionally change the threshold.

const params: AddOwnerTxParams = {
  ownerAddress,
  threshold // Optional. If `threshold` is not provided the current threshold will not change.
}
const safeTransaction = await safeSdk.createAddOwnerTx(params)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createAddOwnerTx(params, options)

createRemoveOwnerTx

Returns the Safe transaction to remove an owner and optionally change the threshold.

const params: RemoveOwnerTxParams = {
  ownerAddress,
  newThreshold // Optional. If `newThreshold` is not provided, the current threshold will be decreased by one.
}
const safeTransaction = await safeSdk.createRemoveOwnerTx(params)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createRemoveOwnerTx(params, options)

createSwapOwnerTx

Returns the Safe transaction to replace an owner of the Safe with a new one.

const params: SwapOwnerTxParams = {
  oldOwnerAddress,
  newOwnerAddress
}
const safeTransaction = await safeSdk.createSwapOwnerTx(params)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createSwapOwnerTx(params, options)

createChangeThresholdTx

Returns the Safe transaction to change the threshold.

const safeTransaction = await safeSdk.createChangeThresholdTx(newThreshold)
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

This method can optionally receive the options parameter:

const options: SafeTransactionOptionalProps = { ... }
const safeTransaction = await safeSdk.createChangeThresholdTx(newThreshold, options)

isValidTransaction

Checks if a Safe transaction can be executed successfully with no errors.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const isValidTx = await safeSdk.isValidTransaction(safeTransaction)

Optionally, some properties can be passed as execution options:

const options: Web3TransactionOptions = {
  from, // Optional
  gas, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const options: EthersTransactionOptions = {
  from, // Optional
  gasLimit, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const isValidTx = await safeSdk.isValidTransaction(safeTransaction, options)

executeTransaction

Executes a Safe transaction.

const safeTransactionData: SafeTransactionDataPartial = {
  // ...
}
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData })
const txResponse = await safeSdk.executeTransaction(safeTransaction)
await txResponse.transactionResponse?.wait()

Optionally, some properties can be passed as execution options:

const options: Web3TransactionOptions = {
  from, // Optional
  gas, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const options: EthersTransactionOptions = {
  from, // Optional
  gasLimit, // Optional
  gasPrice, // Optional
  maxFeePerGas, // Optional
  maxPriorityFeePerGas // Optional
  nonce // Optional
}
const txResponse = await safeSdk.executeTransaction(safeTransaction, options)

License

This library is released under MIT.

Contributors