Step-by-step guide to building a gasless Web3 application. Learn how to implement gas sponsorship, paymasters, and frictionless onboarding for your dApp
Handles transaction orchestration, gas sponsorship, and cross-chain execution
MEE (Modular Execution Environment)
SDK
Developer integration
AbstractJS SDK
Biconomy’s MEE provides all the functionality of traditional ERC-4337 bundlers and paymasters in a unified, easier-to-use package. Instead of configuring separate bundler and paymaster services, MEE handles everything automatically.
import { createMeeClient, toMultichainNexusAccount } from "@biconomy/abstractjs";import { privateKeyToAccount } from "viem/accounts";import { base } from "viem/chains";// Create multichain accountconst account = await toMultichainNexusAccount({ signer: privateKeyToAccount("0x..."), // User's signer chains: [base]});// Create MEE client - handles all bundler and paymaster functionalityconst meeClient = await createMeeClient({ account });console.log("Smart Account Address:", account.address);
MEE (Modular Execution Environment) replaces the need to configure separate bundlers and paymasters. It provides all ERC-4337 functionality plus cross-chain capabilities in a single, unified interface.
How do I send a gasless transaction?
Once configured, sending gasless transactions is simple with MEE:
// The user pays NOTHING - gas is sponsored through MEEconst quote = await meeClient.getQuote({ instructions: [ { calls: [{ to: "0xRecipientAddress", value: 0n, data: "0x" // Or encoded function call }] } ], feeToken: { address: "sponsored" } // Gas sponsored});const { hash } = await meeClient.executeQuote({ quote });console.log("Transaction hash:", hash);
For contract interactions:
import { encodeFunctionData } from "viem";// Encode your contract callconst data = encodeFunctionData({ abi: yourContractABI, functionName: "mint", args: [userAddress, tokenId]});// Send gasless transaction via MEEconst quote = await meeClient.getQuote({ instructions: [ { calls: [{ to: contractAddress, value: 0n, data }] } ], feeToken: { address: "sponsored" }});const { hash } = await meeClient.executeQuote({ quote });
MEE automatically handles gas sponsorship based on your dashboard configuration.
How do I integrate with popular wallet connectors?
import { useWalletClient } from "wagmi";import { createMeeClient, toMultichainNexusAccount } from "@biconomy/abstractjs";import { base } from "viem/chains";function App() { const { data: walletClient } = useWalletClient(); async function initMeeClient() { if (!walletClient) return; const account = await toMultichainNexusAccount({ signer: walletClient, chains: [base] }); const meeClient = await createMeeClient({ account }); return meeClient; }}
How do I configure sponsorship policies?
Sponsorship policies control who and what gets sponsored. Configure in the Biconomy Dashboard:Dashboard Configuration:
Navigate to MEE sponsorship settings
Set spending limits (per transaction, total)
MEE handles gas sponsorship (traditionally done by ERC-4337 paymasters) as part of its unified execution environment. You configure policies in the dashboard, and MEE applies them automatically.
Policy Examples:Sponsor all transactions (development):
async function sendWithRetry(instructions, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const quote = await meeClient.getQuote({ instructions, feeToken: { address: "sponsored" } }); return await meeClient.executeQuote({ quote }); } catch (error) { if (i === maxRetries - 1) throw error; await new Promise(r => setTimeout(r, 1000 * (i + 1))); } }}
What's a complete example of a gasless app?
Here’s a complete gasless NFT minting app using MEE:
// lib/biconomy.tsimport { createMeeClient, toMultichainNexusAccount } from "@biconomy/abstractjs";import { base } from "viem/chains";export async function createGaslessMeeClient(signer: any) { const account = await toMultichainNexusAccount({ signer, chains: [base] }); return createMeeClient({ account });}
// components/MintButton.tsximport { useState } from "react";import { createGaslessMeeClient } from "@/lib/biconomy";import { encodeFunctionData } from "viem";import { nftAbi, NFT_ADDRESS } from "@/lib/contracts";export function MintButton({ signer }) { const [loading, setLoading] = useState(false); const [txHash, setTxHash] = useState(null); async function handleMint() { setLoading(true); try { // Initialize MEE client const meeClient = await createGaslessMeeClient(signer); // Encode mint function const data = encodeFunctionData({ abi: nftAbi, functionName: "mint", args: [1] // Mint 1 NFT }); // Get quote and execute gasless transaction via MEE const quote = await meeClient.getQuote({ instructions: [ { calls: [{ to: NFT_ADDRESS, data, value: 0n }] } ], feeToken: { address: "sponsored" } }); const { hash } = await meeClient.executeQuote({ quote }); setTxHash(hash); } catch (error) { console.error("Mint failed:", error); alert("Minting failed. Please try again."); } finally { setLoading(false); } } return ( <div> <button onClick={handleMint} disabled={loading}> {loading ? "Minting..." : "Mint NFT (Free!)"} </button> {txHash && ( <p> Success! <a href={`https://basescan.org/tx/${txHash}`}>View transaction</a> </p> )} </div> );}
MEE provides all the functionality of traditional ERC-4337 bundlers and paymasters in a single, unified interface. No need to configure separate bundler URLs or paymaster URLs.