Safe reference
Initialization
init
The init
method initializes the Protocol Kit instance and connects the Safe account.
_10import Safe from '@safe-global/protocol-kit'_10_10const protocolKit = await Safe.init({_10 provider,_10 signer,_10 safeAddress // or predictedSafe_10})
-
The
safeAddress
property is the address of the Safe account. Use this property if the Safe is already deployed. -
The
predictedSafe
property is an object that contains the Safe account configuration and deployment details. Using this property allows initializing the Protocol Kit with limited functionality, with a Safe account that has yet to be deployed. This object contains the following properties:safeAccountConfig
:owners
: An array of Safe owner addresses.threshold
: The number of signatures required to execute a Safe transaction.to
(optional): The contract address for optional delegate call.data
(optional): The data payload for optional delegate call.fallbackHandler
(optional): The fallback handler address.paymentToken
(optional): The token that should be used for the payment (0 is ETH).payment
(optional): The value that should be paid.paymentReceiver
(optional): The address that should receive the payment (or 0 if tx.origin).
safeDeploymentConfig
:saltNonce
(optional): The salt nonce to use. Changing this value will update the predicted Safe account address.safeVersion
(optional): The Safe contract version to use.deploymentType
(optional): The Safe deployment type to use. It can becanonical
,eip155
, orzksync
. Changing this value affects the search algorithm used to find the Safe deployment address (opens in a new tab) for any Safe contract, resulting in a change to the predicted address.
Depending on whether the Safe account is deployed or not, you can initialize the Protocol Kit in two different ways:
Initialization of a deployed Safe using the safeAddress
property.
_10import Safe from '@safe-global/protocol-kit'_10_10const protocolKit = await Safe.init({_10 provider,_10 signer,_10 safeAddress: '0x...'_10})
- The
provider
property can be an EIP-1193 (opens in a new tab) compatible provider or an RPC URL.
_10import Safe from '@safe-global/protocol-kit'_10_10const rpcURL = 'https://sepolia.infura.io/v3/...'_10_10const protocolKit = await Safe.init({_10 provider: rpcURL,_10 signer,_10 safeAddress: '0x...'_10})
- The
signer
property can be a Safe owner address, its private key or a passkey object.
_10import Safe from '@safe-global/protocol-kit'_10_10const signerAddress = '0x...'_10_10const protocolKit = await Safe.init({_10 provider,_10 signer: signerAddress,_10 safeAddress: '0x...'_10})
-
The
isL1SafeSingleton
flagTwo versions of the Safe contracts are available: Safe.sol (opens in a new tab) that doesn't trigger events to save gas and SafeL2.sol (opens in a new tab) that does, which is more appropriate for L2 networks.
By default
Safe.sol
will only be used on Ethereum Mainnet. For the rest of the networks where the Safe contracts are already deployed, theSafeL2.sol
contract will be used unless you add theisL1SafeSingleton
flag to force using theSafe.sol
contract._10const protocolKit = await Safe.init({_10provider,_10signer,_10safeAddress,_10isL1SafeSingleton: true_10}) -
The
contractNetworks
propertyIf the Safe contracts aren't deployed to your current network, the
contractNetworks
property will be required to point to the addresses of the Safe contracts previously deployed by you._37import {_37ContractNetworksConfig,_37SafeProvider_37} from '@safe-global/protocol-kit'_37_37const safeProvider = new SafeProvider({ provider, signer })_37const chainId = await safeProvider.getChainId()_37_37const contractNetworks: ContractNetworksConfig = {_37[chainId]: {_37safeSingletonAddress: '<SINGLETON_ADDRESS>',_37safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',_37multiSendAddress: '<MULTI_SEND_ADDRESS>',_37multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',_37fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',_37signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',_37createCallAddress: '<CREATE_CALL_ADDRESS>',_37simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',_37safeWebAuthnSignerFactoryAddress:'<SAFE_WEB_AUTHN_SIGNER_FACTORY_ADDRESS>',_37safeSingletonAbi: '<SINGLETON_ABI>', // Optional. Only needed with web3.js_37safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js_37multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js_37multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js_37fallbackHandlerAbi: '<FALLBACK_HANDLER_ABI>', // Optional. Only needed with web3.js_37signMessageLibAbi: '<SIGN_MESSAGE_LIB_ABI>', // Optional. Only needed with web3.js_37createCallAbi: '<CREATE_CALL_ABI>', // Optional. Only needed with web3.js_37simulateTxAccessorAbi: '<SIMULATE_TX_ACCESSOR_ABI>' // Optional. Only needed with web3.js_37safeWebAuthnSignerFactoryAbi: '<SAFE_WEB_AUTHN_SIGNER_FACTORY_ABI>' // Optional. Only needed with web3.js_37}_37}_37_37const protocolKit = await Safe.init({_37provider,_37signer,_37safeAddress,_37contractNetworks_37})
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 signer
property while the new connected Safe can be passed using a safeAddress
or a predictedSafe
.
The provider
property can be an EIP-1193 (opens in a new tab) compatible provider or an RPC URL. The signer
property can be the signer address or its private key.
Connection of a deployed Safe using the safeAddress
property:
_10let protocolKit = await Safe.init({_10 provider,_10 signer,_10 safeAddress_10})_10_10protocolKit = await protocolKit.connect({_10 signer: anotherSigner,_10 safeAddress: anotherSafeAddress_10})
Connection of an undeployed 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:
_16import { PredictedSafeProps } from '@safe-global/protocol-kit'_16_16const predictedSafe: PredictedSafeProps = {_16 safeAccountConfig,_16 safeDeploymentConfig_16}_16_16let protocolKit = await Safe.init({_16 provider,_16 signer,_16 safeAddress _16})_16_16// ..._16_16protocolKit = await protocolKit.connect({ predictedSafe })
-
The
isL1SafeSingleton
flagTwo versions of the Safe contracts are available: Safe.sol (opens in a new tab) that doesn't trigger events to save gas and SafeL2.sol (opens in a new tab) that does, which is more appropriate for L2 networks.
By default
Safe.sol
will only be used on Ethereum Mainnet. For the rest of the networks where the Safe contracts are already deployed, theSafeL2.sol
contract will be used unless you add theisL1SafeSingleton
flag to force using theSafe.sol
contract._10protocolKit = await protocolKit.connect({_10provider,_10signer,_10safeAddress,_10isL1SafeSingleton: true_10}) -
The
contractNetworks
propertyIf the Safe contracts aren't deployed to your current network, the
contractNetworks
property will be required to point to the addresses of the Safe contracts previously deployed by you._40import {_40ContractNetworksConfig,_40SafeProvider_40} from '@safe-global/protocol-kit'_40_40const safeProvider = new SafeProvider({ provider, signer })_40const chainId = await safeProvider.getChainId()_40_40const contractNetworks: ContractNetworksConfig = {_40[chainId]: {_40safeSingletonAddress: '<SINGLETON_ADDRESS>',_40safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',_40multiSendAddress: '<MULTI_SEND_ADDRESS>',_40multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',_40fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',_40signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',_40createCallAddress: '<CREATE_CALL_ADDRESS>',_40simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',_40safeWebAuthnSignerFactoryAddress:'<SAFE_WEB_AUTHN_SIGNER_FACTORY_ADDRESS>',_40safeSingletonAbi: '<SINGLETON_ABI>', // Optional. Only needed with web3.js_40safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js_40multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js_40multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js_40fallbackHandlerAbi: '<FALLBACK_HANDLER_ABI>', // Optional. Only needed with web3.js_40signMessageLibAbi: '<SIGN_MESSAGE_LIB_ABI>', // Optional. Only needed with web3.js_40createCallAbi: '<CREATE_CALL_ABI>', // Optional. Only needed with web3.js_40simulateTxAccessorAbi: '<SIMULATE_TX_ACCESSOR_ABI>' // Optional. Only needed with web3.js_40safeWebAuthnSignerFactoryAbi: '<SAFE_WEB_AUTHN_SIGNER_FACTORY_ABI>' // Optional. Only needed with web3.js_40}_40}_40_40let protocolKit = await Safe.init({_40provider,_40signer,_40safeAddress_40})_40_40// ..._40_40protocolKit = await protocolKit.connect({ contractNetworks })
Safe Info
getAddress
Returns the address of the current SafeProxy contract.
_10const safeAddress = await protocolKit.getAddress()
getBalance
Returns the ETH balance of the Safe.
_10const balance = await protocolKit.getBalance()
getChainId
Returns the chain ID of the connected network.
_10const chainId = await protocolKit.getChainId()
getContractVersion
Returns the Safe singleton contract version.
_10const contractVersion = await protocolKit.getContractVersion()
getNonce
Returns the Safe nonce.
_10const nonce = await protocolKit.getNonce()
Safe Deployment
The Protocol Kit has been updated to simplify the creation of new Safes. It now includes the createSafeDeploymentTransaction
method for deploying Safes. This method returns an Ethereum transaction object that is ready to be executed using the Ethereum client of your choice.
createSafeDeploymentTransaction
Returns a transaction object ready to be executed and deploy a new Safe.
Before deploying a new Safe, you must initialize and configure the Protocol Kit.
_26const predictedSafe = {_26 safeAccountConfig: {_26 owners: ['0x...', '0x...', '0x...'],_26 threshold: 2_26 // ..._26 },_26 safeDeploymentConfig: {_26 saltNonce, // Optional_26 safeVersion, // Optional_26 deploymentType // Optional_26 }_26}_26_26let protocolKit = await Safe.init({_26 provider,_26 signer,_26 predictedSafe_26})_26_26const deploymentTransaction = await protocolKit.createSafeDeploymentTransaction()_26_26const txHash = await client.sendTransaction({_26 to: deploymentTransaction.to,_26 value: BigInt(deploymentTransaction.value),_26 data: `0x${deploymentTransaction.data}`_26})
Reconnecting to the deployed Safe using the connect
method
Once the transaction is executed and the Safe has been successfully deployed, it is necessary to reconnect the Protocol Kit instance to the newly created Safe address by using the connect
method.
_10const txReceipt = await client.waitForTransactionReceipt({ hash: txHash })_10_10const safeAddress = getSafeAddressFromDeploymentTx(txReceipt, safeVersion)_10_10protocolKit = await protocolKit.connect({ safeAddress })_10_10console.log('Is Safe deployed:', await protocolKit.isSafeDeployed())_10console.log('Safe Address:', await protocolKit.getAddress())_10console.log('Safe Owners:', await protocolKit.getOwners())_10console.log('Safe Threshold:', await protocolKit.getThreshold())
getSafeAddressFromDeploymentTx
Returns the Safe address from a Safe deployment transaction receipt. It scans the events emitted during the transaction to identify the creation event of a Safe account (opens in a new tab) and returns its address.
_10const txReceipt = await client.waitForTransactionReceipt({ hash: txHash })_10const safeAddress = getSafeAddressFromDeploymentTx(txReceipt, safeVersion)
Transactions
copyTransaction
Copies a Safe transaction.
_10const safeTransaction1 = await protocolKit.createTransaction({ transactions })_10const safeTransaction2 = await copyTransaction(safeTransaction1)
createRejectionTransaction
Returns a Safe transaction ready to be signed by the owners that invalidates the pending Safe transaction(s) with a specific nonce.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const rejectionTransaction = await protocolKit.createRejectionTransaction(safeTransaction.data.nonce)
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.
This method takes an array of MetaTransactionData
objects representing the individual transactions we want to include in our MultiSend transaction.
When the array contains only one transaction, it's not wrapped in the MultiSend.
_16const transactions: MetaTransactionData[] = [_16 {_16 to,_16 data,_16 value,_16 operation // Optional_16 },_16 {_16 to,_16 data,_16 value,_16 operation // Optional_16 }_16 // ..._16]_16const safeTransaction = await protocolKit.createTransaction({ transactions })
This method can also receive the options
parameter to set the optional properties in the MultiSend transaction:
_24const transactions: MetaTransactionData[] = [_24 {_24 to,_24 data,_24 value,_24 operation // Optional_24 },_24 {_24 to,_24 data,_24 value,_24 operation // Optional_24 }_24 // ..._24]_24const options: SafeTransactionOptionalProps = {_24 safeTxGas, // Optional_24 baseGas, // Optional_24 gasPrice, // Optional_24 gasToken, // Optional_24 refundReceiver, // Optional_24 nonce // Optional_24}_24const safeTransaction = await protocolKit.createTransaction({ transactions, options })
In addition, the optional onlyCalls
parameter, which is false
by default, allows forcing the use of the MultiSendCallOnly
instead of the MultiSend
contract when sending a batch transaction:
_10const onlyCalls = true_10const safeTransaction = await protocolKit.createTransaction({_10 transactions,_10 options,_10 onlyCalls_10})
If the optional properties aren't 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.
executeTransaction
Executes a Safe transaction.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
Optionally, some properties can be passed as execution options:
_10const options: TransactionOptions = {_10 from, // Optional_10 gasLimit, // Optional_10 gasPrice, // Optional_10 maxFeePerGas, // Optional_10 maxPriorityFeePerGas // Optional_10 nonce // Optional_10}
_10const txResponse = await protocolKit.executeTransaction(safeTransaction, options)
getTransactionHash
Returns the transaction hash of a Safe transaction.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const txHash = await protocolKit.getTransactionHash(safeTransaction)
isValidTransaction
Checks if a Safe transaction can be executed successfully with no errors.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const isValidTx = await protocolKit.isValidTransaction(safeTransaction)
Optionally, some properties can be passed as execution options:
_10const options: TransactionOptions = {_10 from, // Optional_10 gasLimit, // Optional_10 gasPrice, // Optional_10 maxFeePerGas, // Optional_10 maxPriorityFeePerGas // Optional_10 nonce // Optional_10}
_10const isValidTx = await protocolKit.isValidTransaction(safeTransaction, options)
Transaction signatures
approveTransactionHash
Approves a hash on-chain using the current owner account.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const txHash = await protocolKit.getTransactionHash(safeTransaction)_10const txResponse = await protocolKit.approveTransactionHash(txHash)_10await txResponse.transactionResponse?.wait()
Optionally, some properties can be passed as execution options:
_10const options: TransactionOptions = {_10 from, // Optional_10 gasLimit, // Optional_10 gasPrice, // Optional_10 maxFeePerGas, // Optional_10 maxPriorityFeePerGas // Optional_10 nonce // Optional_10}
_10const txResponse = await protocolKit.approveTransactionHash(txHash, options)
signHash
Signs a hash using the current owner account.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const txHash = await protocolKit.getTransactionHash(safeTransaction)_10const signature = await protocolKit.signHash(txHash)
signTransaction
Returns a new SafeTransaction
object that includes the signature of the current owner.
You can use multiple signing methods, such as:
- ETH_SIGN (
eth_sign
): Regular hash signature - ETH_SIGN_TYPED_DATA_V4 (
eth_signTypedData_v4
): Typed data signature v4, The default method if no signing method is passed - ETH_SIGN_TYPED_DATA_V3
eth_signTypedData_v3
: Typed data signature v3 - ETH_SIGN_TYPED_DATA
eth_signTypedData
: Typed data signature - SAFE_SIGNATURE: Signing with another Safe contract as signer
The third parameter (optional) is the preImageSafeAddress. If the preimage is required, this is the address of the Safe that will be used to calculate the preimage. It's a mandatory parameter for 1.3.0 and 1.4.1 contract versions. This is because the safe uses the old EIP-1271 interface, which uses bytes
instead of bytes32
for the message; we need to use the pre-image of the message to calculate the message hash. This parameter is used in conjunction with the SAFE_SIGNATURE signing method.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction)
Optionally, an additional parameter can be passed to specify a different way of signing:
_10const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction, SigningMethod.ETH_SIGN_TYPED_DATA_V4) // Default option_10const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction, SigningMethod.ETH_SIGN)_10const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction, SigningMethod.SAFE_SIGNATURE, parentSafeAddress).
signTypedData
Signs a transaction according to the EIP-712 using the current signer account.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const signature = await protocolKit.signTypedData(safeTransaction)
Owners
createAddOwnerTx
Returns the Safe transaction to add an owner and optionally change the threshold.
_10const params: AddOwnerTxParams = {_10 ownerAddress,_10 threshold // Optional. If `threshold` isn't provided the current threshold won't change._10}_10const safeTransaction = await protocolKit.createAddOwnerTx(params)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
Instead of using an address, this method also supports the use of a passkey to set the address of the new owner:
_11const passkey: PasskeyArgType = {_11 rawId,_11 coordinates_11}_11const params: AddPasskeyOwnerTxParams = {_11 passkey,_11 threshold // Optional. If `threshold` isn't provided the current threshold won't change._11}_11const safeTransaction = await protocolKit.createAddOwnerTx(params)_11const txResponse = await protocolKit.executeTransaction(safeTransaction)_11await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createAddOwnerTx(params, options)
createRemoveOwnerTx
Returns the Safe transaction to remove an owner and optionally change the threshold.
_10const params: RemoveOwnerTxParams = {_10 ownerAddress,_10 newThreshold // Optional. If `newThreshold` isn't provided, the current threshold will be decreased by one._10}_10const safeTransaction = await protocolKit.createRemoveOwnerTx(params)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
Instead of using an address, this method also supports the use of a passkey to remove an owner:
_11const passkey: PasskeyArgType = {_11 rawId,_11 coordinates_11}_11const params: AddPasskeyOwnerTxParams = {_11 passkey,_11 threshold // Optional. If `newThreshold` isn't provided, the current threshold will be decreased by one._11}_11const safeTransaction = await protocolKit.createRemoveOwnerTx(params)_11const txResponse = await protocolKit.executeTransaction(safeTransaction)_11await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createRemoveOwnerTx(params, options)
createSwapOwnerTx
Returns the Safe transaction to replace an owner of the Safe with a new one.
_10const params: SwapOwnerTxParams = {_10 oldOwnerAddress,_10 newOwnerAddress_10}_10const safeTransaction = await protocolKit.createSwapOwnerTx(params)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
Instead of using an address, this method also supports any combination of passkey and address:
_11const newOwnerPasskey: PasskeyArgType = {_11 rawId,_11 coordinates_11}_11const params: SwapOwnerTxParams = {_11 oldOwnerAddress,_11 newOwnerPasskey_11}_11const safeTransaction = await protocolKit.createSwapOwnerTx(params)_11const txResponse = await protocolKit.executeTransaction(safeTransaction)_11await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createSwapOwnerTx(params, options)
getOwners
Returns the list of Safe owner accounts.
_10const ownerAddresses = await protocolKit.getOwners()
getOwnersWhoApprovedTx
Returns a list of owners who have approved a specific Safe transaction.
_10const transactions: MetaTransactionData[] = [{_10 // ..._10}]_10const safeTransaction = await protocolKit.createTransaction({ transactions })_10const txHash = await protocolKit.getTransactionHash(safeTransaction)_10const ownerAddresses = await protocolKit.getOwnersWhoApprovedTx(txHash)
isOwner
Checks if a specific address is an owner of the current Safe.
_10const isOwner = await protocolKit.isOwner(address)
Threshold
createChangeThresholdTx
Returns the Safe transaction to change the threshold.
_10const safeTransaction = await protocolKit.createChangeThresholdTx(newThreshold)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createChangeThresholdTx(newThreshold, options)
getThreshold
Returns the Safe threshold.
_10const threshold = await protocolKit.getThreshold()
Safe Guards
createDisableGuardTx
Returns the Safe transaction to disable a Safe Guard.
_10const safeTransaction = await protocolKit.createDisableGuardTx()_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createDisableGuardTx(options)
createEnableGuardTx
Returns the Safe transaction to enable a Safe Guard.
_10const safeTransaction = await protocolKit.createEnableGuardTx(guardAddress)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = {_10 safeTxGas, // Optional_10 baseGas, // Optional_10 gasPrice, // Optional_10 gasToken, // Optional_10 refundReceiver, // Optional_10 nonce // Optional_10}_10const safeTransaction = await protocolKit.createEnableGuardTx(guardAddress, options)
getGuard
Returns the enabled Safe Guard or 0x address if no guards are enabled.
_10const guardAddress = await protocolKit.getGuard()
Safe Modules
createDisableModuleTx
Returns a Safe transaction ready to be signed that will disable a Safe Module.
_10const safeTransaction = await protocolKit.createDisableModuleTx(moduleAddress)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createDisableModuleTx(moduleAddress, options)
createEnableModuleTx
Returns a Safe transaction ready to be signed that will enable a Safe Module.
_10const safeTransaction = await protocolKit.createEnableModuleTx(moduleAddress)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createEnableModuleTx(moduleAddress, options)
getModules
Returns the list of addresses of all the enabled Safe Modules.
_10const moduleAddresses = await protocolKit.getModules()
isModuleEnabled
Checks if a specific Safe Module is enabled for the current Safe.
_10const isEnabled = await protocolKit.isModuleEnabled(moduleAddress)
FallbackHandler
createDisableFallbackHandlerTx
Returns the Safe transaction to disable the fallback handler.
_10const safeTransaction = await protocolKit.createDisableFallbackHandlerTx()_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = { ... }_10const safeTransaction = await protocolKit.createDisableFallbackHandlerTx(options)
createEnableFallbackHandlerTx
Returns the Safe transaction to enable the fallback handler.
_10const safeTransaction = await protocolKit.createEnableFallbackHandlerTx(fallbackHandlerAddress)_10const txResponse = await protocolKit.executeTransaction(safeTransaction)_10await txResponse.transactionResponse?.wait()
This method can optionally receive the options
parameter:
_10const options: SafeTransactionOptionalProps = {_10 safeTxGas, // Optional_10 baseGas, // Optional_10 gasPrice, // Optional_10 gasToken, // Optional_10 refundReceiver, // Optional_10 nonce // Optional_10}_10const safeTransaction = await protocolKit.createEnableFallbackHandlerTx(fallbackHandlerAddress, options)
Messages
createMessage
Returns a SafeMessage ready to be signed by the owners.
_10const rawMessage: string | EIP712TypedData = 'I am the owner of this Safe'_10const message = protocolKit.createMessage(rawMessage)
getSafeMessageHash
Retrieve the Safe message hash of a string, or EIP-712 typed data. It produces the identical hash as invoking the CompatibilityFallbackHandler's getMessageHash method.
_10const rawMessage = ... // String or EIP-712 typed data_10const messageHash = hashSafeMessage(rawMessage)_10_10const safeMessageHash = await protocolKit.getSafeMessageHash(messageHash)
isValidSignature
Calls the CompatibilityFallbackHandler isValidSignature method (EIP-1271).
It requires two parameters:
- messageHash: The hash of the message
- signature: The signature to be validated or '0x'. You can send as signature one of the following:
- An array of SafeSignature. In this case the signatures are concatenated for validation (buildSignatureBytes())
- The concatenated signatures as string
- '0x' if you want to validate an on-chain message (Approved hash)
The method returns if the signature is valid
_10const rawMessage = ... // String or EIP-712 typed data_10const messageHash = hashSafeMessage(rawMessage)_10const safeMessageHash = await protocolKit.getSafeMessageHash(messageHash)_10_10const isValidSignature = await protocolKit.isValidSignature(safeMessageHash, signature)_10..._10const isValidSignature = await protocolKit.isValidSignature(safeMessageHash, [signature1, signature2])_10..._10const isValidSignature = await protocolKit.isValidSignature(safeMessageHash, '0x')
signMessage
Returns a new SafeMessage
object that includes the signature of the current owner.
You can use multiple signing methods, such as:
- ETH_SIGN (
eth_sign
): Regular hash signature - ETH_SIGN_TYPED_DATA_V4 (
eth_signTypedData_v4
): Typed data signature v4, The default method if no signing method is passed - ETH_SIGN_TYPED_DATA_V3
eth_signTypedData_v3
: Typed data signature v3 - ETH_SIGN_TYPED_DATA
eth_signTypedData
: Typed data signature - SAFE_SIGNATURE: Signing with another Safe contract as signer
The third parameter (optional) is the preImageSafeAddress. If the preimage is required, this is the address of the Safe that will be used to calculate the preimage. It's a mandatory parameter for 1.3.0 and 1.4.1 contract versions. This is because the safe uses the old EIP-1271 interface, which uses bytes
instead of bytes32
for the message; we need to use the pre-image of the message to calculate the message hash. This parameter is used in conjunction with the SAFE_SIGNATURE signing method.
_10const rawMessage: string | EIP712TypedData = 'I am the owner of this Safe'_10const message = protocolKit.createMessage(rawMessage)_10const signedMessage = await protocolKit.signMessage(message)
Optionally, an additional parameter can be passed to specify a different way of signing:
_10const signedMessage = await protocolKit.signMessage(signedMessage, SigningMethod.ETH_SIGN_TYPED_DATA_V4) // Default option_10const signedMessage = await protocolKit.signMessage(signedMessage, SigningMethod.ETH_SIGN)_10const signedMessage = await protocolKit.signMessage(signedMessage, SigningMethod.SAFE_SIGNATURE, parentSafeAddress).