Integration with Gelato
The Gelato relay (opens in a new tab) allows developers to execute gasless transactions.
Prerequisites
- Node.js and npm (opens in a new tab).
- Have a Safe account configured with threshold equal to 1, where only one signature is needed to execute transactions.
- To use Gelato 1Balance an API key (opens in a new tab) is required.
Install dependencies
_10yarn add ethers @safe-global/relay-kit @safe-global/protocol-kit @safe-global/safe-core-sdk-types
Relay Kit options
Currently, the Relay Kit is only compatible with the Gelato relay (opens in a new tab). The Gelato relay can be used in two ways:
Gelato 1Balance
Gelato 1Balance (opens in a new tab) allows you to execute transactions using a prepaid deposit. This can be used to sponsor transactions to other Safes or even to use a deposit on Polygon to pay the fees for a wallet on another chain.
For the 1Balance quickstart tutorial, you will use the Gelato relayer to pay for the gas fees on BNB Chain using the Polygon USDC you have deposited into your Gelato 1Balance account.
Setup
- Start with a 1/1 Safe on BNB Chain (opens in a new tab).
- Deposit Polygon USDC into Gelato 1Balance (opens in a new tab) (transaction 0xa5f38 (opens in a new tab)).
- The Safe owner 0x6Dbd26Bca846BDa60A90890cfeF8fB47E7d0f22c (opens in a new tab) signs a transaction to send 0.0005 BNB and submits it to Gelato relay.
- Track the relay request (opens in a new tab) of Gelato Task ID 0x1bf7 (opens in a new tab).
- Transaction 0x814d3 (opens in a new tab) is executed on the blockchain.
Use a Safe as the Relay
While using Gelato, you can specify that you only want the relay to allow transactions from specific smart contracts. If one of those smart contracts is a Safe smart contract, you will need to either verify the contract on a block explorer or get the ABI of the contract implementation (not the ABI of the smart contract address). This is because the Safe smart contracts use the Proxy Pattern (opens in a new tab), so the implementation logic for your smart contract exists on a different address.
Imports
_10import { ethers } from 'ethers'_10import { GelatoRelayPack } from '@safe-global/relay-kit'_10import Safe, { EthersAdapter } from '@safe-global/protocol-kit'_10import {_10 MetaTransactionData,_10 MetaTransactionOptions_10} from '@safe-global/safe-core-sdk-types'
Initialize the transaction settings
Modify the variables to customize to match your desired transaction settings.
_10// https://chainlist.org_10const RPC_URL='https://endpoints.omniatech.io/v1/bsc/mainnet/public'_10const provider = new ethers.JsonRpcProvider(RPC_URL)_10const signer = new ethers.Wallet(process.env.OWNER_1_PRIVATE_KEY!, provider)_10const safeAddress = '0x...' // Safe from which the transaction will be sent_10_10// Any address can be used for destination. In this example, we use vitalik.eth_10const destinationAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'_10const withdrawAmount = ethers.parseUnits('0.005', 'ether').toString()
Create a transaction
_10// Create a transactions array with one transaction object_10const transactions: MetaTransactionData[] = [{_10 to: destinationAddress,_10 data: '0x',_10 value: withdrawAmount_10}]_10_10const options: MetaTransactionOptions = {_10 isSponsored: true_10}
Instantiate the Protocol Kit and Relay Kit
_14const ethAdapter = new EthersAdapter({_14 ethers,_14 signerOrProvider: signer_14})_14_14const protocolKit = await Safe.create({_14 ethAdapter,_14 safeAddress_14})_14_14const relayKit = new GelatoRelayPack({_14 apiKey: process.env.GELATO_RELAY_API_KEY!,_14 protocolKit_14})
Prepare the transaction
_10const safeTransaction = await relayKit.createRelayedTransaction({_10 transactions,_10 options_10})_10_10const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction)
Send the transaction to the relay
_10const response = await relayKit.executeRelayTransaction(_10 signedSafeTransaction,_10 options_10)_10_10console.log(`Relay Transaction Task ID: https://relay.gelato.digital/tasks/status/${response.taskId}`)
Gelato SyncFee
Gelato SyncFee (opens in a new tab) allows you to execute a transaction and pay the gas fees directly with funds in your Safe, even if you don't have ETH or the native blockchain token.
For the SyncFee quickstart tutorial, you will use the Gelato relayer to pay for the gas fees on the BNB Chain using the BNB you hold in your Safe. No need to have funds on your signer.
Imports
_10import { ethers } from 'ethers'_10import { GelatoRelayPack } from '@safe-global/relay-kit'_10import Safe, { EthersAdapter } from '@safe-global/protocol-kit'_10import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'
Initialize the transaction settings
Modify the variables to customize to match your desired transaction settings.
_10// https://chainlist.org_10const RPC_URL='https://endpoints.omniatech.io/v1/bsc/mainnet/public'_10const provider = new ethers.JsonRpcProvider(RPC_URL)_10const signer = new ethers.Wallet(process.env.OWNER_1_PRIVATE_KEY!, provider)_10const safeAddress = '0x...' // Safe from which the transaction will be sent_10_10// Any address can be used for destination. In this example, we use vitalik.eth_10const destinationAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'_10const withdrawAmount = ethers.parseUnits('0.005', 'ether').toString()
Create a transaction
_10// Create a transactions array with one transaction object_10const transactions: MetaTransactionData[] = [{_10 to: destinationAddress,_10 data: '0x',_10 value: withdrawAmount_10}]
Instantiate the Protocol Kit and Relay Kit
_11const ethAdapter = new EthersAdapter({_11 ethers,_11 signerOrProvider: signer_11})_11_11const protocolKit = await Safe.create({_11 ethAdapter,_11 safeAddress_11})_11_11const relayKit = new GelatoRelayPack({ protocolKit })
Prepare the transaction
_10const safeTransaction = await relayKit.createRelayedTransaction({ transactions })_10_10const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction)
Send the transaction to the relay
_10const response = await relayKit.executeRelayTransaction(signedSafeTransaction)_10_10console.log(`Relay Transaction Task ID: https://relay.gelato.digital/tasks/status/${response.taskId}`)