> ## Documentation Index
> Fetch the complete documentation index at: https://docs.base.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Sponsor Gas

> Use Paymasters to sponsor your users' transactions

One of the biggest UX enhancements unlocked by Base Account is the ability for app developers to sponsor their users' transactions.
If your app supports Base Account, you can start sponsoring your users'
transactions by using [standardized Paymaster service communication](https://erc7677.xyz) enabled by [new wallet RPC methods](https://eip5792.xyz).

This guide is specific to using Base Account, you can find our more about using Paymasters with Base in
the [Coinbase Developer Platform documentation](https://docs.cdp.coinbase.com/paymaster/introduction/welcome).

## Implementation Guide

<Steps>
  <Step title="Set up your Paymaster service">
    As a prerequisite, you'll need to obtain a Paymaster service URL from a Paymaster service provider.

    We'll use [Coinbase Developer Platform](https://www.coinbase.com/developer-platform) as a Paymaster service provider,
    currently offering up to \$15k in gas credits as part of the [Base Gasless Campaign](/base-account/more/base-gasless-campaign).

    <Warning>
      **ERC-7677-Compliant Paymaster Providers**

      If you choose to use a different Paymaster service provider, ensure they are [ERC-7677-compliant](https://www.erc7677.xyz/ecosystem/paymasters).
    </Warning>

    Once you have signed up for [Coinbase Developer Platform](https://www.coinbase.com/developer-platform), you get your Paymaster service URL by navigating to **Onchain Tools > Paymaster** as shown below:

    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
      <Frame>
        <img alt="Paymaster CDP" src="https://mintcdn.com/base-a060aa97/8PjRmmTngJV9JYD_/images/smart-wallet/PaymasterCDP.png?fit=max&auto=format&n=8PjRmmTngJV9JYD_&q=85&s=040048ba1269654414b47b547dd2a315" width="1000" loading="lazy" data-path="images/smart-wallet/PaymasterCDP.png" />
      </Frame>

      <em>How to get your Paymaster service URL</em>
    </div>

    <Warning>
      **Should you create a proxy for your Paymaster service?**

      We recommend using a proxy to protect the Paymaster service URL to prevent it from being exposed/leaked on a frontend client.

      For local development, you can use the same URL for the Paymaster service and the proxy.
    </Warning>

    Once you have your Paymaster service URL, you can proceed to setting up your contracts allowlist.
    This is a list of contracts and function calls that you want to be sponsored by the Paymaster.

    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
      <Frame>
        <img alt="Paymaster CDP Allowlist" src="https://mintcdn.com/base-a060aa97/8PjRmmTngJV9JYD_/images/smart-wallet/PaymasterAllowlist.png?fit=max&auto=format&n=8PjRmmTngJV9JYD_&q=85&s=a8a3748a4dd7a39ec86d3c91b4d1437a" width="1000" loading="lazy" data-path="images/smart-wallet/PaymasterAllowlist.png" />
      </Frame>

      <em>How to set your Paymaster contracts allowlist</em>
    </div>

    Congrats! You've set up your Paymaster service and contracts allowlist.
    It's time to set up the Base Account SDK.

    <Check>
      **You can also choose to create custom advanced policies !**

      You can create a `willSponsor` function to add some extra validation if you need more control over the policy enforcement.

      `willSponsor` is most likely not needed if you are using [Coinbase Developer Platform](https://www.coinbase.com/developer-platform) as it has built-in policy enforcement features,
      but know that this is still possible if you need it.
    </Check>
  </Step>

  <Step title="Setup Base Account SDK">
    Install and initialize the Base Account SDK to interact with Base Account:

    ### Installation

    <CodeGroup>
      ```bash npm theme={null}
      npm install @base-org/account
      ```

      ```bash pnpm theme={null}
      pnpm add @base-org/account
      ```

      ```bash yarn theme={null}
      yarn add @base-org/account
      ```

      ```bash bun theme={null}
      bun add @base-org/account
      ```
    </CodeGroup>

    ### Initialize the SDK

    ```tsx theme={null}
    import { createBaseAccountSDK, base } from '@base-org/account';

    const sdk = createBaseAccountSDK({
      appName: 'Paymaster Demo',
      appLogoUrl: 'https://base.org/logo.png',
      appChainIds: [base.constants.CHAIN_IDS.baseSepolia], // or base.constants.CHAIN_IDS.base for mainnet
    });

    const provider = sdk.getProvider();
    ```
  </Step>

  <Step title="Send transactions with Paymaster service capability">
    Once you have your Paymaster service set up, you can now use `wallet_sendCalls` with paymaster capabilities to sponsor transactions.

    <Note>
      **Pass in the proxy URL**

      If you set up a proxy in your app's backend as recommended in step (1) above, you'll want to pass in the proxy URL you created.
    </Note>

    ### Basic Sponsored Transaction

    Here's how to send a sponsored transaction using the `wallet_sendCalls` RPC method:

    ```tsx theme={null}
    import { createBaseAccountSDK, getCryptoKeyAccount, base } from '@base-org/account';
    import { numberToHex, encodeFunctionData, parseEther } from 'viem';

    // Example NFT contract ABI
    const nftABI = [
      {
        name: 'safeMint',
        type: 'function',
        stateMutability: 'nonpayable',
        inputs: [{ name: 'to', type: 'address' }],
        outputs: []
      }
    ] as const;

    async function sendSponsoredTransaction() {
      const sdk = createBaseAccountSDK({
        appName: 'Paymaster Demo',
        appLogoUrl: 'https://base.org/logo.png',
        appChainIds: [base.constants.CHAIN_IDS.baseSepolia],
      });

      const provider = sdk.getProvider();
      
      try {
        // Get the user's account
        const cryptoAccount = await getCryptoKeyAccount();
        const fromAddress = cryptoAccount?.account?.address;
        
        if (!fromAddress) {
          throw new Error('No account found');
        }

        // Your Paymaster service URL (use your proxy URL)
        const paymasterServiceUrl = process.env.NEXT_PUBLIC_PAYMASTER_PROXY_SERVER_URL;
        
        // Prepare the transaction call
        const nftAddress = '0x119Ea671030FBf79AB93b436D2E20af6ea469a19';
        const calls = [
          {
            to: nftAddress,
            value: '0x0',
            data: encodeFunctionData({
              abi: nftABI,
              functionName: 'safeMint',
              args: [fromAddress]
            })
          }
        ];

        // Send the transaction with paymaster capabilities
        const result = await provider.request({
          method: 'wallet_sendCalls',
          params: [{
            version: '1.0',
            chainId: numberToHex(base.constants.CHAIN_IDS.baseSepolia),
            from: fromAddress,
            calls: calls,
            capabilities: {
              paymasterService: {
                url: paymasterServiceUrl
              }
            }
          }]
        });

        console.log('Sponsored transaction sent:', result);
        return result;
      } catch (error) {
        console.error('Sponsored transaction failed:', error);
        throw error;
      }
    }
    ```

    ### Multiple Sponsored Transactions

    You can also batch multiple transactions and have them all sponsored:

    ```tsx theme={null}
    async function sendMultipleSponsoredTransactions() {
      const sdk = createBaseAccountSDK({
        appName: 'Paymaster Demo',
        appLogoUrl: 'https://base.org/logo.png',
        appChainIds: [base.constants.CHAIN_IDS.baseSepolia],
      });

      const provider = sdk.getProvider();
      const cryptoAccount = await getCryptoKeyAccount();
      const fromAddress = cryptoAccount?.account?.address;

      const paymasterServiceUrl = process.env.NEXT_PUBLIC_PAYMASTER_PROXY_SERVER_URL;

      // Multiple calls in a single sponsored transaction
      const calls = [
        {
          to: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
          value: numberToHex(parseEther('0.001')),
          data: '0x' // Simple ETH transfer
        },
        {
          to: '0x742d35Cc6634C0532925a3b844Bc9e7595f6E456',
          value: numberToHex(parseEther('0.001')),
          data: '0x' // Another ETH transfer
        }
      ];

      const result = await provider.request({
        method: 'wallet_sendCalls',
        params: [{
          version: '1.0',
          chainId: numberToHex(base.constants.CHAIN_IDS.baseSepolia),
          from: fromAddress,
          calls: calls,
          capabilities: {
            paymasterService: {
              url: paymasterServiceUrl
            }
          }
        }]
      });

      return result;
    }
    ```

    ### Check Paymaster Capabilities

    Before sending sponsored transactions, you can check if the wallet supports paymaster services:

    ```tsx theme={null}
    async function checkPaymasterSupport() {
      const sdk = createBaseAccountSDK({
        appName: 'Paymaster Demo',
        appLogoUrl: 'https://base.org/logo.png',
        appChainIds: [base.constants.CHAIN_IDS.baseSepolia],
      });

      const provider = sdk.getProvider();
      const cryptoAccount = await getCryptoKeyAccount();
      const address = cryptoAccount?.account?.address;

      try {
        const capabilities = await provider.request({
          method: 'wallet_getCapabilities',
          params: [address]
        });

        const baseCapabilities = capabilities[base.constants.CHAIN_IDS.baseSepolia];
        
        if (baseCapabilities?.paymasterService?.supported) {
          console.log('Paymaster service is supported');
          return true;
        } else {
          console.log('Paymaster service is not supported');
          return false;
        }
      } catch (error) {
        console.error('Failed to check paymaster capabilities:', error);
        return false;
      }
    }
    ```

    That's it! Base Account will handle the rest. If your Paymaster service is able to sponsor the transaction,
    in the UI Base Account will indicate to your user that the transaction is sponsored.
  </Step>
</Steps>
