Skip to Content
TutorialsGasless Transactions

Gasless Transactions

Use the Paymaster to send transactions without paying gas.

This tutorial shows how to configure gas sponsorship so your users can send transactions without holding native tokens. You will learn both the backend approach using the Core SDK and the frontend approach using the UI Kit.

Prerequisites

  • Node.js 18+ installed
  • An EmbarkAI API key from the Dashboard 
  • A deployed wallet (see Deploy a Smart Wallet)
  • A Paymaster contract address (provided by EmbarkAI or self-deployed)

Backend Approach

Step 1: Configure the Paymaster

Pass paymasterAddress when creating the wallet manager:

import { createServerWalletManager, MemoryKeyshareStorage, } from '@embarkai/core' const manager = createServerWalletManager({ apiKey: process.env.EMBARK_API_KEY!, chainId: 994873017, // Lumia Mainnet storage: new MemoryKeyshareStorage(), paymasterAddress: '0xYourPaymasterAddress', })

Step 2: Send a Gasless Transaction

With the Paymaster configured, every transaction is automatically sponsored:

const wallet = await manager.getWallet('my-wallet') // The user pays zero gas -- the Paymaster covers it const userOpHash = await wallet.sendUserOperation( '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', '1000000000000000000', // 1 token ) const receipt = await wallet.waitForUserOperationReceipt(userOpHash) console.log('TX:', receipt.transactionHash) console.log('Gas cost to user: 0')

Step 3: Verify Zero Gas Cost

Check the receipt to confirm sponsorship:

if (receipt.success) { console.log('Gas used:', receipt.actualGasUsed) console.log('Gas cost:', receipt.actualGasCost, '(paid by Paymaster)') }

The actualGasCost reflects gas consumed on-chain, but this cost is deducted from the Paymaster’s deposit — not from the user’s smart account.

Frontend Approach

Step 1: Enable Paymaster in Provider

Pass usePaymaster to the ConnectWalletButton component:

import { Provider, ConnectWalletButton } from '@embarkai/ui-kit' function App() { return ( <Provider projectId={process.env.NEXT_PUBLIC_PROJECT_ID!} chainId={994873017} > <ConnectWalletButton usePaymaster /> <SendForm /> </Provider> ) }

Step 2: Send a Gasless Transaction from the Frontend

Use the useSendTransaction hook — gas sponsorship is handled automatically:

import { useSendTransaction } from '@embarkai/ui-kit' function SendForm() { const { sendTransaction, isLoading, userOpHash, error } = useSendTransaction() const handleSend = async () => { await sendTransaction({ to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', value: '1000000000000000000', }) } return ( <div> <button onClick={handleSend} disabled={isLoading}> {isLoading ? 'Sending...' : 'Send 1 Token (Gasless)'} </button> {userOpHash && <p>UserOp: {userOpHash}</p>} {error && <p>Error: {error.message}</p>} </div> ) }

How the Paymaster Sponsors Gas

Behind the scenes, the sponsorship flow works as follows:

  1. The SDK builds a UserOperation and sets the paymasterAndData field to the configured Paymaster address
  2. The Bundler simulates the operation, calling the Paymaster’s validatePaymasterUserOp to confirm sponsorship
  3. The Bundler submits the UserOperation to the EntryPoint contract
  4. The EntryPoint deducts gas costs from the Paymaster’s on-chain deposit
  5. The user’s smart account balance is untouched

Complete Backend Code

import { createServerWalletManager, MemoryKeyshareStorage, } from '@embarkai/core' async function main() { const manager = createServerWalletManager({ apiKey: process.env.EMBARK_API_KEY!, chainId: 994873017, storage: new MemoryKeyshareStorage(), paymasterAddress: '0xYourPaymasterAddress', }) const wallet = await manager.getWallet('my-wallet') console.log('Sending from:', wallet.smartAccountAddress) const userOpHash = await wallet.sendUserOperation( '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', '1000000000000000000', ) const receipt = await wallet.waitForUserOperationReceipt(userOpHash) console.log('Confirmed:', receipt.transactionHash) console.log('Gas paid by Paymaster, not user') } main().catch(console.error)

Next Steps

Last updated on