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)
Backend Approach
Step 1: Configure the Paymaster
Every supported chain ships with an embarkAI paymaster, and sponsorship is on by default: the manager resolves the paymaster from your Dashboard policy and falls back to the built-in one. Pass paymasterAddress only to use your own paymaster:
import {
createServerWalletManager,
MemoryKeyshareStorage,
} from '@embarkai/core'
const manager = createServerWalletManager({
apiKey: process.env.EMBARK_API_KEY!,
chainId: 994873017, // Lumia Mainnet
storage: new MemoryKeyshareStorage(),
paymasterAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', // optional: your own paymaster
})Step 2: Send a Gasless Transaction
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(
'0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
'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!}
initialConfig={{ network: { 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: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
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}</p>}
</div>
)
}How the Paymaster Sponsors Gas
Behind the scenes, the sponsorship flow works as follows:
- The SDK builds a UserOperation and sets the
paymasterandpaymasterDatafields (ERC-4337 v0.7) for the resolved Paymaster - The Bundler simulates the operation, calling the Paymaster’s
validatePaymasterUserOpto confirm sponsorship - The Bundler submits the UserOperation to the EntryPoint contract
- The EntryPoint deducts gas costs from the Paymaster’s on-chain deposit
- 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: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', // optional: your own paymaster
})
const wallet = await manager.getWallet('my-wallet')
console.log('Sending from:', wallet.smartAccountAddress)
const userOpHash = await wallet.sendUserOperation(
'0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
'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
- Paymaster Concepts — Understand Paymaster architecture and cost considerations
- ERC-20 Transfers — Send token transfers with gas sponsorship
- Send Your First Transaction — Basic transaction flow without Paymaster
- Account Abstraction — How gas sponsorship fits into ERC-4337