Send a user operation
User operations are the ERC-4337 counterpart to traditional blockchain transactions. They incorporate significant enhancements that improve user experience and provide greater flexibility in account management and transaction execution.
User operations consist of executions (represented by an ExecutionStruct
) that express the user's intent.
Before submission, additional required and optional information, such as gas fees and payment
details, must be included.
User operations are not directly sent to the network.
Instead, they are sent to a bundler, which validates, optimizes, and aggregates them before network submission.
The bundler provides methods such as estimateUserOpGas
, getUserOpByHash
, and pollForReceipt
to
facilitate the overall process.
Prerequisites
- Install and set up the MetaMask Delegation Toolkit.
- Configure the toolkit.
Send a user operation using Viem SDK
The following is a simplified example of sending a user operation using Viem SDK. Viem SDK offers more granular control for developers who require it.
In the example, a user operation is created with the necessary gas limits.
This user operation is passed to a bundler instance, and the EntryPoint
address is retrieved from the client.
const userOp = await client.createUserOp(
data,
{
verificationGasLimit: 100000000n,
preVerificationGas: 100000000n,
callGasLimit: 100000000n,
}
);
const bundlerUrl = "<bundler-url>";
const bundler = createBundlerClient(bundlerUrl);
const hash = await bundler.sendUserOp(
userOp,
client.account.environment.EntryPoint,
)
In this example, verificationGasLimit
, preVerificationGas
, and callGasLimit
are set to arbitrarily high values. This might result in overpayment for the user operation, and might even cause the bundler to reject the user operation, so we recommend replacing these values with a correct estimate before submitting to the bundler.
Poll for the transaction hash
You can use the hash of the user operation to poll the bundler to access the transaction receipt, which
contains the on-chain transactionHash
.
For example:
const { result: receipt } = await bundler.pollForReceipt(hash);
console.log(receipt.receipt.transactionHash);