Skip to content

How to sponsor gas for a User Operation

Gas fees are a significant barrier to entry for new user of your app. With Account Kit you can remove this barrier by sponsoring gas fees for transactions via the Gas Manager. This guide explains how to sponsor gas by creating a gas policy, linking it to your client, and sending sponsored UserOperations (UOs) from a smart account.

After setting up Account Kit in your project, follow these steps to sponsor gas.

Create a Gas Manager policy

A gas manager policy is a set of rules that define which UOs are eligible for gas sponsorship. You can control which operations are eligible for sponsorship by defining rules:

  • Spending rules: limit the amount of money or the number of user ops that can be sponsored by this policy
  • Allowlist: restrict wallet addresses that are eligible for sponsorship. The policy will only sponsor gas for UOs that were sent by addresses on this list.
  • Blocklist: ban certain addresses from receiving sponsorship under this policy
  • Policy duration: define the duration of your policy and the sponsorship expiry period. This is the period for which the Gas Manager signature (paymaster data) will remain valid once it is generated.

To learn more about policy configuration, refer to the guide on setting up a gas manager policy.

Once you have decided on policy rules for your app, create a policy in the Gas Manager dashboard.

Now you should have a Gas policy created with a policy id you can use to sponsor gas for your users.

Policy ID

Send a sponsored User Operation with the Policy ID

Now you can send a sponsored User Operation with the Policy ID.

gas-sponsorship.tsx
import React, { useState, useEffect } from "react";
import { View, Button } from "react-native";
import {
  createLightAccountClient,
  LightAccount,
} from "@account-kit/smart-contracts";
import { sepolia, alchemy } from "@account-kit/infra";
import { User } from "@account-kit/signer";
 
// import the signer
import { signer } from "./signer.ts";
 
export default function MyComponent() {
  const [client, setClient] = useState<SmartAccountClient | null>(null);
  const [user, setUser] = useState<User | null>(null);
  const [isSendingUserOperation, setIsSendingUserOperation] = useState(false);
 
  // Assume the user is already authenticated
  useEffect(() => {
    signer.getAuthDetails().then(setUser);
  }, []);
 
  useEffect(() => {
    if (user) {
      // Create a smart account client for the authenticated user with the policy ID
      createLightAccountClient({
        signer,
        chain: sepolia,
        policyId: "YOUR_GAS_POLICY_ID", 
        transport: alchemy({ apiKey: "API_KEY" }),
      }).then((client) => {
        setClient(client);
      });
    }
  }, [user]);
 
  const handleSendUserOperation = async () => {
    if (!client) return;
    // Send a sponsored User Operation
    try {
      setIsSendingUserOperation(true);
 
      const { hash } = await client.sendUserOperation({
        uo: {
          target: "0xTARGET_ADDRESS",
          data: "0x",
          value: 0n,
        },
        account: client.account,
      });
 
      Alert.alert("User Operation Sent", hash);
    } catch (error) {
      Alert.alert("Error", "Error sending user operation");
    } finally {
      setIsSendingUserOperation(false);
    }
  };
 
  return (
    <View>
      <Button
        onClick={handleSendUserOperation}
        disabled={isSendingUserOperation}
        title={
          isSendingUserOperation
            ? "Sending..."
            : "Send Sponsored User Operation"
        }
      />
    </View>
  );
}