Software development kit that facilitates the interaction with the Gnosis Safe contracts.
Install the package with yarn or npm:
yarn install
npm install
Build the package with yarn or npm:
yarn build
npm build
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 { ethers } from 'ethers'
import EthersSafe, { SafeTransaction } from '@gnosis.pm/safe-core-sdk'
const web3Provider = // ...
const provider = new ethers.providers.Web3Provider(web3Provider)
const signer1 = provider.getSigner(0)
const signer2 = provider.getSigner(1)
const signer3 = provider.getSigner(2)
// Existing Safe address (e.g. Safe created via https://app.gnosis-safe.io)
// Where signer1, signer2 and signer3 are the Safe owners
const safeAddress = "0x<safe_address>"
Create an instance of the Safe Core SDK with signer1
connected as the signer.
const safeSdk = await EthersSafe.create(ethers, safeAddress, signer1)
const tx = await safeSdk.createTransaction({
to: safeAddress,
value: '0',
data: '0x',
})
Before executing this transaction, it must be signed by the owners and this can be done off-chain or on-chain. In this example the owner signer1
will sign it off-chain and the owner signer3
would have to explicitly sign it too.
The owner signer1
signs the transaction off-chain.
const signer1Signature = await safeSdk.signTransaction(tx)
Because the signature is off-chain, there is no interaction with the contract and the signature is available at tx.signatures
.
After signer2
account is connected to the SDK as the signer the transaction hash is approved on-chain.
const safeSdk2 = await safeSdk.connect(signer2)
const txHash = await safeSdk2.getTransactionHash(tx)
const signer2Signature = await safeSdk2.approveTransactionHash(txHash)
Lastly, signer3
account is connected to the SDK as the signer and executor of the Safe transaction to execute it.
const safeSdk3 = await safeSdk2.connect(signer3)
const txResponse = await safeSdk3.executeTransaction(tx)
await txResponse.wait()
All the signatures used to execute the transaction are available at tx.signatures
.
Returns an instance of the Safe Core SDK with the providerOrSigner
connected to the safeAddress
.
const safeSdk = await EthersSafe.create(ethers, safeAddress, providerOrSigner)
If providerOrSigner
is not provided, ethers
default provider will be used.
const safeSdk = await EthersSafe.create(ethers, safeAddress)
Returns a new instance of the Safe Core SDK with the providerOrSigner
connected to the safeAddress
.
const safeSdk2 = await safeSdk.connect(providerOrSigner, safeAddress)
If safeAddress
is not provided, the providerOrSigner
will be connected to the previous Safe.
const safeSdk2 = await safeSdk.connect(providerOrSigner)
Returns the connected provider.
const provider = safeSdk.getProvider()
Returns the connected signer.
const signer = safeSdk.getSigner()
Returns the address of the current Safe Proxy contract.
const address = safeSdk.getAddress()
Returns the Safe Master Copy contract version.
const contractVersion = await safeSdk.getContractVersion()
Returns the list of Safe owner accounts.
const owners = await safeSdk.getOwners()
Returns the Safe nonce.
const nonce = await safeSdk.getNonce()
Returns the Safe threshold.
const threshold = await safeSdk.getThreshold()
Returns the chainId of the connected network.
const chainId = await safeSdk.getChainId()
Returns the ETH balance of the Safe.
const balance = await safeSdk.getBalance()
Returns the list of addresses of all the enabled Safe modules.
const modules = await safeSdk.getModules()
Checks if a specific Safe module is enabled for the current Safe.
const isEnabled = await safeSdk.isModuleEnabled(moduleAddress)
Checks if a specific address is an owner of the current Safe.
const isOwner = await safeSdk.isOwner(address)
Returns a Safe transaction ready to be signed by the owners and executed.
Each of the transactions provided as input to this function must be an object with the following properties:
to
: Required.data
: Required.value
: Required.operation
: Optional.OperationType.Call
(0) is the default value.safeTxGas
: Optional. The right gas estimation is the default value.baseGas
: Optional. 0 is the default value.gasPrice
: Optional. 0 is the default value.gasToken
: Optional. 0x address is the default value.refundReceiver
: Optional. 0x address is the default value.nonce
: Optional. The current Safe nonce is the default value.
Read more about the Safe transaction properties.
const partialTx: SafeTransactionDataPartial = {
to: '0x<address>',
data: '0x<data>',
value: '<eth_value_in_wei>'
}
const safeTransaction = await safeSdk.createTransaction(partialTx)
Returns the transaction hash of a Safe transaction.
const tx = await safeSdk.createTransaction({
// ...
})
const txHash = await safeSdk.getTransactionHash(tx)
Signs a hash using the current signer account.
const tx = await safeSdk.createTransaction({
// ...
})
const txHash = await safeSdk.getTransactionHash(tx)
const signature = await safeSdk.signTransactionHash(txHash)
Adds the signature of the current signer to the Safe transaction object.
const tx = await safeSdk.createTransaction({
// ...
})
await safeSdk.signTransaction(tx)
Approves on-chain a hash using the current signer account.
const tx = await safeSdk.createTransaction({
// ...
})
const txHash = await safeSdk.getTransactionHash(tx)
const txResponse = await safeSdk.approveTransactionHash(txHash)
await txResponse.wait()
Returns a list of owners who have approved a specific Safe transaction.
const tx = await safeSdk.createTransaction({
// ...
})
const txHash = await safeSdk.getTransactionHash(tx)
const owners = await safeSdk.getOwnersWhoApprovedTx(txHash)
Returns a Safe transaction ready to be signed that will enable a Safe module.
const tx = await safeSdk.getEnableModuleTx(moduleAddress)
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
Returns a Safe transaction ready to be signed that will disable a Safe module.
const tx = await safeSdk.getDisableModuleTx(moduleAddress)
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
Returns the Safe transaction to add an owner and update the threshold.
const tx = await safeSdk.getAddOwnerTx(newOwnerAddress, newThreshold)
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
If threshold
is not provided, the current threshold will not change.
const tx = await safeSdk.getAddOwnerTx(newOwnerAddress)
Returns the Safe transaction to remove an owner and update the threshold.
const tx = await safeSdk.getRemoveOwnerTx(ownerAddress, newThreshold)
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
If threshold
is not provided, the current threshold will be decreased by one.
const tx = await safeSdk.getRemoveOwnerTx(ownerAddress)
Returns the Safe transaction to replace an owner of the Safe with a new one.
const tx = await safeSdk.getSwapOwnerTx(oldOwnerAddress, newOwnerAddress)
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
Returns the Safe transaction to change the threshold.
const tx = await safeSdk.getChangeThresholdTx(newThreshold)
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
Executes a Safe transaction.
const tx = await safeSdk.createTransaction({
// ...
})
const txResponse = await safeSdk.executeTransaction(tx)
await txResponse.wait()
This library is released under MIT.
- Germán Martínez (germartinez)