Send User Operations
In this guide, you will learn how to create Safe user operations, sign them, collect the signatures from the different owners, and execute them.
For more detailed information, see the Starter Kit Reference.
Pimlico (opens in a new tab) is used in this guide as the service provider, but any other provider compatible with the ERC-4337 can be used.
Prerequisites
- Node.js and npm (opens in a new tab)
- A Pimlico account (opens in a new tab) and an API key.
Install dependencies
First, you need to install some dependencies.
_10pnpm add @safe-global/sdk-starter-kit
Steps
Imports
Here are all the necessary imports for this guide.
_10import {_10 createSafeClient,_10 safeOperations,_10 BundlerOptions_10} from '@safe-global/sdk-starter-kit'
Create a signer
Firstly, you need to get a signer, which will be the owner of a Safe account after it's deployed.
This example uses a private key, but any way to get an EIP-1193 compatible signer can be used.
_10const SIGNER_ADDRESS = // ..._10const SIGNER_PRIVATE_KEY = // ..._10const RPC_URL = 'https://rpc.ankr.com/eth_sepolia'
Initialize the SafeClient
When deploying a new Safe account, you need to pass the configuration of the Safe in the safeOptions
property. The Safe account is configured with your signer as the only owner in this case.
_10const safeClient = await createSafeClient({_10 provider: RPC_URL,_10 signer: SIGNER_PRIVATE_KEY,_10 safeOptions: {_10 owners: [SIGNER_ADDRESS],_10 threshold: 1_10 }_10})
As this guide is related with ERC-4337 user operations, you need to add the safeOperations
extension to the safeClient
instance to support this functionality.
_12const bundlerOptions: BundlerOptions = {_12 bundlerUrl: `https://api.pimlico.io/v1/sepolia/rpc?apikey=${PIMLICO_API_KEY}`_12}_12_12const paymasterOptions: PaymasterOptions = {_12 isSponsored: true,_12 paymasterUrl: `https://api.pimlico.io/v2/sepolia/rpc?apikey=${PIMLICO_API_KEY}`_12}_12_12const safeClientWithSafeOperation = await safeClient.extend(_12 safeOperations(bundlerOptions, paymasterOptions)_12)
The safeClientWithSafeOperation
instance has now support for managing user operations.
Create a Safe transaction
Create an array of Safe transactions to execute.
_10const transactions = [{_10 to: '0x...',_10 data: '0x',_10 value: '0'_10}]
Send the Safe operation
If you configured your Safe with threshold
equal to 1
, calling the sendSafeOperation
method will execute the user operation. However, if the threshold
is greater than 1
the other owners of the Safe will need to confirm the user operation until the required number of signatures are collected.
_10const safeOperationResult = await safeClientWithSafeOperation.sendSafeOperation({_10 transactions_10})_10_10const safeOperationHash = safeOperationResult.safeOperations?.safeOperationHash
Confirm the Safe operations
If the user operation needs to be confirmed by other Safe owners, call the confirmSafeOperation
method from a new SafeClient
instance initialized with each of the signers that need to confirm it.
_14const newSafeClient = await createSafeClient({_14 provider: RPC_URL,_14 signer,_14 safeAddress: '0x...'_14})_14_14const newSafeClientWithSafeOperation = await newSafeClient.extend(_14 safeOperations({_14 bundlerUrl: `https://api.pimlico.io/v1/sepolia/rpc?apikey=${PIMLICO_API_KEY}`_14 }, {_14 isSponsored: true,_14 paymasterUrl: `https://api.pimlico.io/v2/sepolia/rpc?apikey=${PIMLICO_API_KEY}`_14 })_14)
Finally, retrieve all the pending user operations from the Safe Transaction Service and confirm the one you just created with each missing owner.
_11const pendingSafeOperations =_11 await newSafeClientWithSafeOperation.getPendingSafeOperations()_11_11for (const safeOperation of pendingSafeOperations.results) {_11 if (safeOperation.safeOperationHash !== safeOperationHash) {_11 return_11 }_11_11 const safeOperationResult =_11 await newSafeClientWithSafeOperation.confirmSafeOperation({ safeOperationHash })_11}
Recap and further reading
After following this guide, you are able to deploy new Safe accounts and create, sign, and submit user operations with the Starter Kit.