Search…
Core SDK

Introduction

The Safe Core SDK facilitates the interaction with the Safe contracts.
It only supports Safe contracts v1.2.0 and ethers.js v5 so far.

Adding the dependencies

The Safe Core SDK is available as a TS library via npm and can be added to your project with
1
npm install @gnosis.pm/safe-core-sdk
Copied!
or
1
yarn add @gnosis.pm/safe-core-sdk
Copied!

Getting Started

1. Set up the SDK using Ethers or Web3

If the app integrating the SDK is using Ethers v5, create an instance of the EthersAdapter. owner1 is the Ethereum account we are connecting and the one who will sign the transactions.
1
import { ethers } from 'ethers'
2
import { EthersAdapter } from '@gnosis.pm/safe-core-sdk'
3
​
4
const web3Provider = // ...
5
const provider = new ethers.providers.Web3Provider(web3Provider)
6
const owner1 = provider.getSigner(0)
7
​
8
const ethAdapterOwner1 = new EthersAdapter({
9
ethers,
10
signer: owner1
11
})
Copied!
If the app integrating the SDK is using Web3 v1, create an instance of the Web3Adapter.
1
import Web3 from 'web3'
2
import { Web3Adapter } from '@gnosis.pm/safe-core-sdk'
3
​
4
const ethAdapterOwner1 = new Web3Adapter({
5
web3,
6
signerAddress: await owner1.getAddress()
7
})
Copied!

2. Deploy a new Safe

To deploy a new Safe account instantiate the SafeFactory class and call the method deploySafe 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 3 owners and threshold equal 3 will be used as the starting point for this example but any Safe configuration is valid.
1
import { Safe, SafeFactory, SafeAccountConfig } from '@gnosis.pm/safe-code-sdk'
2
​
3
const safeFactory = await SafeFactory.create({ ethAdapter })
4
​
5
const owners = ['0x<address>', '0x<address>', '0x<address>']
6
const threshold = 3
7
const safeAccountConfig: SafeAccountConfig = { owners, threshold }
8
​
9
const safeSdk: Safe = await safeFactory.deploySafe(safeAccountConfig)
Copied!
The method deploySafe executes a transaction from owner1 account, deploys a new Safe and returns an instance of the Safe Core SDK connected to the new Safe.
Call the method getAddress, for example, to check the address of the newly deployed Safe.
1
const newSafeAddress = safeSdk.getAddress()
Copied!
To instantiate the Safe Core SDK from an existing Safe just pass to it an instance of the EthAdapter class and the Safe address.
1
import Safe from '@gnosis.pm/safe-core-sdk'
2
​
3
const safeSdk: Safe = await Safe.create({ ethAdapter: ethAdapterOwner1, safeAddress })
Copied!

3. Create a Safe transaction

1
import { SafeTransactionDataPartial } from '@gnosis.pm/safe-core-sdk'
2
​
3
const transactions: SafeTransactionDataPartial[] = [{
4
to: '0x<address>',
5
value: '<eth_value_in_wei>',
6
data: '0x<data>'
7
}]
8
const safeTransaction = await safeSdk.createTransaction(...transactions)
Copied!
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.
1
const owner1Signature = await safeSdk.signTransaction(safeTransaction)
Copied!
Because the signature is off-chain, there is no interaction with the contract and the signature becomes available at safeTransaction.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.
1
const ethAdapterOwner2 = new EthersAdapter({ ethers, signer: owner2 })
2
const safeSdk2 = await safeSdk.connect({ ethAdapter: ethAdapterOwner2, safeAddress })
3
const txHash = await safeSdk2.getTransactionHash(safeTransaction)
4
const approveTxResponse = await safeSdk2.approveTransactionHash(txHash)
5
await approveTxResponse.wait()
Copied!

4. Transaction execution

Lastly, owner3 account is connected to the SDK as a signer and executor of the Safe transaction to execute it.
1
const ethAdapterOwner3 = new EthersAdapter({ ethers, signer: owner3 })
2
const safeSdk3 = await safeSdk2.connect({ ethAdapter: ethAdapterOwner3, safeAddress })
3
const executeTxResponse = await safeSdk3.executeTransaction(safeTransaction)
4
await executeTxResponse.wait()
Copied!
All the signatures used to execute the transaction are now available at safeTransaction.signatures.

Advanced features

For extensive documentation and the API Reference check the GitHub repository.
Last modified 1mo ago