Best Practices/Recommendations:
  • We recommend users to rely on the exact values returned by the eth_getUserOperationGasPrice endpoint rather than applying buffers, as the values provided by our bundler are designed to handle gas price volatility effectively.
  • In case you want to estimate gas cost with some state overrides such as balance, code, etc., you can check our state override section.
Below are two ways to use eth_estimateUserOperationGas endpoint with our bundler:
  1. Using Viem - Recommended for developers using the Viem library
  2. Using Bundler API Endpoints - Use this approach if you have all your user operation values ready for estimation

Using Viem

To start estimating gas using Viem, follow these steps:
1

Create a API Key

Check out our How-To Guide for detailed instructions on generating a API key.
2

Import Dependencies

import { createPublicClient, http } from 'viem'
import { createBundlerClient, toSoladySmartAccount } from "viem/account-abstraction";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";
3

Setup Smart Account

Any smart account that implements viem’s Account type can be used here. Check out other available smart accounts here.
const publicClient = createPublicClient({ chain: mainnet, transport: http() });
const signer = privateKeyToAccount(PRIVATE_KEY as any);

const account = await toSoladySmartAccount({ 
  client: publicClient, 
  owner: signer, 
}) 
4

Create a Bundler Client

Create a BundlerClient with the account and publicClient and pass the apiKey and sponsored set to true as query parameter to the transport option.If using other payment methods, set sponsored to false or omit it. Learn more about Bundler Client here.
const bundlerClient = createBundlerClient({
  account,
  client: publicClient,
  transport: http(`https://api.gelato.digital/bundlers/${chainID}/rpc?apiKey=${apiKey}&sponsored=true`),
  userOperation: {
    estimateFeesPerGas: async ({ account, bundlerClient, userOperation }) => {
      const gasPrices =
        await bundlerClient.request<EthGetUserOperationGasPriceRpc>({
          method: "eth_getUserOperationGasPrice",
          params: [],
        });
      return {
        maxFeePerGas: BigInt(gasPrices.maxFeePerGas),
        maxPriorityFeePerGas: BigInt(gasPrices.maxPriorityFeePerGas),
      };
    },
  },
})
5

Estimate Gas

Estimate gas for a UserOperation with the bundlerClient and the account.In case of sponsorship with Gas Tank, eth_getUserOperationGasPrice endpoint will return maxFeePerGas and maxPriorityFeePerGas as 0.
const results = await bundlerClient.estimateUserOperationGas({
  account,
  calls: [{ to: account.address, value: 0n, data: "0x" }],
  maxFeePerGas: 0n,
  maxPriorityFeePerGas: 0n,
})

console.log("Estimated gas values: ", results);

Using Bundler API Endpoints

To start estimating gas directly with Bundler API Endpoints, follow these steps:
1

Create a API Key

Check out our How-To Guide for detailed instructions on generating a API key.
2

Set `sponsored` query parameter to `true`

When calling Gelato API endpoints, make sure to include the apiKey and sponsored set to true as a query parameter.Your Bundler URL will look like this:
https://api.gelato.digital/bundlers/${chainID}/rpc?apiKey=${apiKey}&sponsored=true
3

Configure the UserOperation Parameters

  • Set maxFeePerGas and maxPriorityFeePerGas to 0 (0x0).
  • Leave all paymaster-related fields empty (i.e paymaster, paymasterData, paymasterPostOpGasLimit, paymasterVerificationGasLimit).
Check out the required parameters for estimating gas in the following scenarios:

State Overrides

While estimating gas, you can also include state overrides such as balance, code, etc. to test the gas cost with different state values.
const results = await bundlerClient.estimateUserOperationGas({
  account,
  stateOverride: [
    {
      address: account.address,
      balance: 100000000000000000000n,
    },
  ],
  calls: [{ to: account.address, value: 0n, data: "0x" }],
});

console.log("Estimated gas values: ", results);
Or you can include state override object while sending request to the API endpoints like this:
const stateOverride = {
  [account.address]: {
    //code: "",
    //nonce: "",
    balance: toHex(100000000000000000000n),
    //state:{},    
    //stateDiff:{}, 
  },
};
Checkout parameters for state overrides here and full example code here.