Paymaster & Gasless Transactions
Sponsor gas fees for your users with the built-in Paymaster or a policy-driven custom Paymaster configured from the EmbarkAI Dashboard.
A Paymaster is an ERC-4337 contract that pays gas fees on behalf of users. When configured, your users can send transactions without holding any native tokens — the Paymaster covers the cost.
Built-in vs. Custom Paymaster
| Built-in Paymaster | Custom Paymaster (Dashboard) | |
|---|---|---|
| Setup | Zero configuration — enable usePaymaster | Configure a Wallet Policy per network |
| Funding | Funded by EmbarkAI (development) | Funded by your project deposit |
| Limits | Rate-limited, small per-user quotas | Custom per-transaction / per-day / per-month caps |
| Contract allowlist | No | Yes — restrict sponsorship to specific contracts |
| Intended use | Trying things out, demos, hackathons | Production |
The built-in Paymaster is intended to unblock getting-started flows. For production, create a custom Paymaster with explicit policies in the Dashboard — otherwise you will hit rate limits, and you won’t have fine-grained control over which contracts your users can interact with gas-free.
Dynamic Paymaster Resolution
Since @embarkai/core v0.3.3, the SDK resolves the paymaster address automatically at runtime:
- Explicit override —
paymasterAddressinServerWalletManagerConfig(always wins) - Dashboard policy — looks up the project’s active policy for the current
chainIdvia the Dashboard API (dashboardApiUrl) - Built-in chain default — falls back to the hard-coded paymaster address from
getChainConfig(chainId)(rate-limited, for development only)
If you need to call the resolution logic yourself (for debugging or custom flows):
import { resolveProjectPaymaster } from '@embarkai/core'
import type { ResolvedPaymaster } from '@embarkai/core'
const result: ResolvedPaymaster = await resolveProjectPaymaster({
chainId: 994873017,
apiKey: process.env.EMBARK_API_KEY!,
// optional overrides:
// explicitPaymasterAddress: '0x...',
// dashboardApiUrl: 'https://dashboard.lumiapassport.com/api',
// cacheTtlMs: 300_000,
})
console.log(result.address) // '0x...' or null
console.log(result.source) // 'dashboard' | 'override' | 'default' | 'none'The result is cached in memory (default 5 min TTL) and deduplicates concurrent requests for the same chainId.
What is a Paymaster?
In the ERC-4337 flow, the EntryPoint contract checks whether a UserOperation includes a paymasterAndData field. If present, the EntryPoint calls the Paymaster contract to verify sponsorship and deducts gas costs from the Paymaster’s deposit instead of the user’s smart account.
This enables fully gasless experiences where users interact with your application without ever needing to acquire native tokens.
Enabling on the Backend
Pass paymasterAddress in the ServerWalletManager configuration:
import { createServerWalletManager, MemoryKeyshareStorage } from '@embarkai/core'
const manager = createServerWalletManager({
apiKey: process.env.EMBARK_API_KEY!,
chainId: 994873017, // Lumia Mainnet
storage: new MemoryKeyshareStorage(),
paymasterAddress: '0xYourPaymasterAddress',
})
const wallet = await manager.getWallet('my-wallet')
// This transaction is gas-sponsored -- the user pays nothing
const userOpHash = await wallet.sendUserOperation(
'0xRecipientAddress',
'1000000000000000000',
)When paymasterAddress is set, every UserOperation sent through this manager instance is automatically routed through the Paymaster.
Enabling on the Frontend
In the UI Kit, pass the usePaymaster prop to ConnectWalletButton:
import { Provider, ConnectWalletButton } from '@embarkai/ui-kit'
function App() {
return (
<Provider
projectId={process.env.NEXT_PUBLIC_PROJECT_ID!}
chainId={994873017}
>
<ConnectWalletButton usePaymaster />
</Provider>
)
}When usePaymaster is enabled, all transactions initiated through the UI Kit hooks (useSendTransaction) are automatically gas-sponsored.
How Sponsorship Works
The gas sponsorship flow follows these steps:
- UserOperation construction — The SDK builds the UserOperation and includes the Paymaster address in the
paymasterAndDatafield - Paymaster validation — The Bundler calls the Paymaster’s
validatePaymasterUserOpmethod during simulation to confirm sponsorship - Submission — The Bundler submits the UserOperation to the EntryPoint
- Gas payment — The EntryPoint deducts gas costs from the Paymaster’s on-chain deposit, not from the user’s account
- Post-operation — The Paymaster’s
postOpmethod runs for any cleanup or accounting
Supported Chains
| Chain | Chain ID | Paymaster Available |
|---|---|---|
| Lumia Mainnet (Prisma) | 994873017 | Yes |
| Lumia Testnet (Beam) | 2030232745 | Yes |
| Sepolia | 11155111 | Yes |
Cost Considerations
- The Paymaster contract must have a sufficient deposit in the EntryPoint to cover gas costs
- Monitor your Paymaster balance to avoid failed transactions
- Consider implementing rate limiting or allowlists to prevent abuse
- Gas costs are paid by whoever funds the Paymaster deposit — typically the application developer
- On testnets, gas costs are negligible and ideal for development
Next Steps
- Dashboard → Wallet Policies — Create a custom Paymaster with limits and contract allowlists
- Account Abstraction — Understand the full ERC-4337 architecture
- Gasless Transactions Tutorial — Step-by-step guide to sending gasless transactions
- Server Wallets — Configure
paymasterAddressin your backend - Supported Chains — See all available chains and contract addresses