Skip to main content

Send your first gasless transaction

embedded walletsaccount abstractiongasless paymastererc-4337web3authMetaMask Developer Relations | October 22, 2024

This guide demonstrates how you can use the Pimlico gasless Paymaster with Embedded Wallets' Account Abstraction Provider to sponsor the transaction for your users without requiring the user to pay gas fees.

note

A paymaster is a vital component in the ERC-4337 standard, responsible for covering transaction costs on behalf of the user. Various types of paymasters are available such as gasless paymasters, ERC-20 paymasters, and more.

tip

Find the full demo code on GitHub.

Prerequisites

Step 1: Set up the dashboard

1.1 If you haven't already, sign up on the Embedded Wallets platform. Access to the Embedded Wallets base plan is free.

1.2 Create a new project.

Step 2: Integrate AccountAbstractionProvider

The Embedded Wallets' account abstraction provider manages the complex logic behind configuring account abstraction, the bundler, and preparing user operations. If you're already using the Embedded Wallets SDK in your project, move onto Step 3.

2.1 Install @web3auth/account-abstraction-provider:

npm install --save @web3auth/account-abstraction-provider

Step 3: Configure the paymaster

The AccountAbstractionProvider requires specific configurations to function correctly such as the paymaster. Embedded Wallets supports custom paymaster configurations, allowing you to deploy your own paymaster and integrate it with the provider.

Paymaster

Note that paymaster support is not limited to Pimlico. You may choose from a variety of paymaster services available in the ecosystem—giving you the flexibility to integrate any compatible paymaster service that suits your requirements. See the documentation for React, JS, and Vue.

In this guide, we use SafeSmartAccount, but you choose your favorite smart account provider from the available options.

note

SafeSmartAccount is a Safe-based smart account implementation used to create and manage the user's contract wallet. You can swap it for other supported smart account types.

Import the account abstraction provider and your chosen smart account implementation:

import {
AccountAbstractionProvider,
SafeSmartAccount,
} from '@web3auth/account-abstraction-provider'

const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: '0xaa36a7',
rpcTarget: 'https://rpc.sepolia.org',
displayName: 'Ethereum Sepolia Testnet',
blockExplorerUrl: 'https://sepolia.etherscan.io',
ticker: 'ETH',
tickerName: 'Ethereum',
logo: 'https://cryptologos.cc/logos/ethereum-eth-logo.png',
}

const accountAbstractionProvider = new AccountAbstractionProvider({
config: {
chainConfig,
bundlerConfig: {
// Get the pimlico API Key from dashboard.pimlico.io
url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
},
smartAccountInit: new SafeSmartAccount(),
paymasterConfig: {
// Get the pimlico API Key from dashboard.pimlico.io
url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
},
},
})

Step 4: Configure Embedded Wallets

Once you have configured your AccountAbstractionProvider, you can now plug it in your Embedded Wallets Modal/No Modal instance. If you are using an external wallets such as MetaMask, you can define whether you want to use the AccountAbstractionProvider, or EthereumPrivateKeyProvider by setting the useAAWithExternalWallet in IWeb3AuthCoreOptions.

If you are setting useAAWithExternalWallet to true, it'll create a new smart account for your user, where the signer/creator of the smart account would be the external wallet.

If you are setting useAAWithExternalWallet to false, it'll skip creating a new smart account, and directly use the external wallet to sign the transactions.

import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { Web3Auth } from "@web3auth/modal";

const privateKeyProvider = new EthereumPrivateKeyProvider({
// Use the chain config we declared earlier
config: { chainConfig },
});

const web3auth = new Web3Auth({
clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
privateKeyProvider,
// Use the account abstraction provider we configured earlier
accountAbstractionProvider
// This will allow you to use EthereumPrivateKeyProvider for
// external wallets, while use the AccountAbstractionProvider
// for Web3Auth embedded wallets.
useAAWithExternalWallet: false,
});

Step 5: Configure the signer

The Embedded Wallets smart account feature is compatible with popular signer SDKs, including Wagmi, Ethers, and Viem. You can choose your preferred package to configure the signer.

You can retrieve the provider to configure the signer from your Embedded Wallets instance.

Wagmi

Wagmi doesn't require any special configuration to use the signer with smart accounts. Once you have set up your Embedded Wallets provider and connected your wallet, Wagmi's hooks (such as useSigner or useAccount) will automatically use the smart account as the signer. You can interact with smart accounts using Wagmi just like you would with a regular EOA (Externally Owned Account) signer—no additional setup is needed.

import { createWalletClient } from 'viem'

// Use your Web3Auth instance to retreive the provider.
const provider = web3auth.provider

const walletClient = createWalletClient({
transport: custom(provider),
})

Step 6: Send a transaction

Developers can use their preferred signer or Wagmi hooks to initiate onchain transactions, while Web3Auth manages the creation and submission of the user operation. Only the to, data, and value fields need to be provided. Any additional parameters will be ignored and automatically overridden.

To ensure reliable execution, the bundler client sets maxFeePerGas and maxPriorityFeePerGas values. If custom values are required, developers can use the Viem BundlerClient to manually construct and send the user operation.

Since smart accounts are deployed as smart contracts, the user's first transaction also triggers the onchain deployment of their wallet.

// Convert 1 ether to WEI format
const amount = parseEther('1')

// Submits a user operation to the blockchain
const hash = await walletClient.sendTransaction({
to: 'DESTINATION_ADDRESS',
value: amount,
// This will perform the transfer of ETH
data: '0x',
})

// Wait for the transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({ hash })

Congratulations, you have successfully sent your first gasless transaction using the Pimlico paymaster with Embedded Wallets Account Abstraction Provider.

Next steps