Sponsor User Fees
Enable gasless transactions by sponsoring transaction fees for your users. Tempo's native fee sponsorship allows applications to pay fees on behalf of users, improving UX and removing friction from payment flows.
Demo
Sponsor User Fees
demoSteps
Set up the fee payer service
You can stand up a minimal fee payer service using the Handler.feePayer handler provided by the Tempo TypeScript SDK (link). To sponsor transactions, you need a funded account that will act as the fee payer.
import { createClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { tempo } from 'tempo.ts/chains'
import { Handler } from 'tempo.ts/server'
const client = createClient({
chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }),
transport: http(),
})
const handler = Handler.feePayer({
account: privateKeyToAccount('0x...'),
client,
})
const server = createServer(handler.listener)
server.listen(3000)Configure your client to use the fee payer service
Use the withFeePayer transport provided by the TypeScript SDK (link). It routes transactions to the configured fee payer service for sponsorship when feePayer: true is requested on a transaction.
import { tempo } from 'tempo.ts/chains'
import { withFeePayer } from 'tempo.ts/viem'
import { KeyManager, webAuthn } from 'tempo.ts/wagmi'
import { createConfig, http } from 'wagmi'
export const config = createConfig({
connectors: [
webAuthn({
keyManager: KeyManager.localStorage(),
}),
],
chains: [tempo({ feeToken: '0x20c0000000000000000000000000000000000001' })],
multiInjectedProviderDiscovery: false,
transports: {
[tempo.id]: withFeePayer(http(), http('https://sponsor.testnet.tempo.xyz')),
},
})Sponsor your user's transactions
Now you can sponsor transactions by passing feePayer: true in the transaction parameters. For more details on how to send a transaction, see the Send a payment guide.
import { Hooks } from 'tempo.ts/wagmi'
import { parseUnits } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
function SendSponsoredPayment() {
const sponsorAccount = privateKeyToAccount('0x...')
const sendPayment = Hooks.token.useTransferSync()
const metadata = Hooks.token.useGetMetadata({
token: alphaUsd,
})
return (
<form onSubmit={
(event) => {
event.preventDefault()
const formData = new FormData(event.target as HTMLFormElement)
const recipient = (formData.get('recipient') ||
'0x0000000000000000000000000000000000000000') as `0x${string}`
sendPayment.mutate({
amount: parseUnits('100', metadata.data.decimals),
feePayer: true,
to: recipient,
token: alphaUsd,
})
}
}>
<div>
<label htmlFor="recipient"> Recipient address </label>
<input type="text" placeholder="0x..." />
</div>
<button type="submit" disabled={sendPayment.isPending}>
Send Payment
</button>
</form>
)
}Next Steps
Now that you've implemented fee sponsorship, you can:
- Learn more about the Tempo Transaction type and fee payer signature details
- Explore Batch Transactions to sponsor multiple operations at once
- Learn how to Pay Fees in Any Stablecoin
Recipes
Local account sponsorship
The example above uses a fee payer server to sign and sponsor transactions. If you want to sponsor transactions locally, you can easily do so by passing a local account to the feePayer parameter.
import { createClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { tempo } from 'tempo.ts/chains'
const client = createClient({
chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }),
transport: http(),
})
const { receipt } = await client.token.transferSync({
amount: parseUnits('10.5', 6),
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
token: '0x20c0000000000000000000000000000000000000',
feePayer: privateKeyToAccount('0x...'),
}):::
Best practices
- Set sponsorship limits: Implement daily or per-user limits to control costs
- Monitor expenses: Track sponsorship costs regularly to stay within budget
- Consider selective sponsorship: Only sponsor fees for specific operations or user segments
- Educate users: Clearly communicate when fees are being sponsored
Security Considerations
- Transaction-specific: Fee payer signatures are tied to specific transactions
- No delegation risk: Fee payer can't execute arbitrary transactions
- Balance checks: Network verifies fee payer has sufficient balance
- Signature validation: Both signatures must be valid