When using the relayer (without smart account), your transaction must include an ERC-20 transfer to Gelato’s fee collector. Use getCapabilities and getFeeQuote to get the fee collector address and fee amount, then include a token transfer in your transaction payload. This is handled automatically when using the 7702 Smart Account.
npm install @gelatocloud/gasless viem
Create an API Key
Check out our How-To Guide for detailed instructions on generating an API key. Initialize Relayer Client
import { createGelatoEvmRelayerClient, StatusCode, token } from '@gelatocloud/gasless';
import { createPublicClient, encodeFunctionData, http } from 'viem';
import { baseSepolia } from 'viem/chains';
const USDC_ADDRESS = '0x036CbD53842c5426634e7929541eC2318f3dCF7e'; // Base Sepolia
const relayer = createGelatoEvmRelayerClient({
apiKey: process.env.GELATO_API_KEY,
testnet: true
});
const publicClient = createPublicClient({
chain: baseSepolia,
transport: http()
});
Get Fee Collector
Get the fee collector address for your chain:const capabilities = await relayer.getCapabilities();
const feeCollector = capabilities[baseSepolia.id].feeCollector;
Get Fee Quote
Estimate gas and get the fee amount in your payment token:const gasEstimate = await publicClient.estimateGas({
to: '0xE27C1359cf02B49acC6474311Bd79d1f10b1f8De',
data: '0xd09de08a'
});
const quote = await relayer.getFeeQuote({
chainId: baseSepolia.id,
gas: gasEstimate,
token: USDC_ADDRESS
});
console.log('Fee:', quote.fee); // Fee amount in token units
Build Calldata with Fee Transfer
Build calldata that includes a token transfer to the fee collector:// Encode ERC-20 transfer to fee collector
const transferData = encodeFunctionData({
abi: [{
name: 'transfer',
type: 'function',
inputs: [
{ name: 'to', type: 'address' },
{ name: 'amount', type: 'uint256' }
],
outputs: [{ type: 'bool' }]
}],
functionName: 'transfer',
args: [feeCollector, quote.fee]
});
// Your main transaction calldata
const targetCalldata = '0xd09de08a'; // increment()
// Use a multicall contract or your own contract to batch:
// 1. Transfer fee to feeCollector
// 2. Execute your target call
const data = encodeMulticall([
{ to: USDC_ADDRESS, data: transferData },
{ to: '0xE27C1359cf02B49acC6474311Bd79d1f10b1f8De', data: targetCalldata }
]);
Send Transaction
const id = await relayer.sendTransaction({
chainId: baseSepolia.id,
data: data,
payment: token(USDC_ADDRESS),
to: multicallContractAddress
});
console.log(`Gelato transaction id: ${id}`);
const status = await relayer.waitForStatus({ id });
if (status.status === StatusCode.Included) {
console.log(`Transaction hash: ${status.receipt.transactionHash}`);
} else {
console.log(`Transaction failed: ${status.message}`);
}
When using the 7702 Smart Account, fee payment is handled automatically. You don’t need to manually include a transfer to the fee collector.
npm install @gelatocloud/gasless viem
Create an API Key
Check out our How-To Guide for detailed instructions on generating an API key. Create Smart Account
import {
createGelatoSmartAccountClient,
toGelatoSmartAccount,
token,
StatusCode,
} from "@gelatocloud/gasless";
import { createPublicClient, http, type Hex } from "viem";
import { baseSepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
const owner = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
const client = createPublicClient({
chain: baseSepolia,
transport: http(),
});
const account = toGelatoSmartAccount({
client,
owner,
});
Create Relayer Client
const relayer = await createGelatoSmartAccountClient({
account,
apiKey: process.env.GELATO_API_KEY,
});
Send Transaction
const tokenAddress = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // USDC (Base Sepolia)
const result = await relayer.sendTransactionSync({
payment: token(tokenAddress),
calls: [
{
to: "0xE27C1359cf02B49acC6474311Bd79d1f10b1f8De",
data: "0xd09de08a",
},
],
});
if (result.status === StatusCode.Included) {
console.log(`Transaction hash: ${result.receipt.transactionHash}`);
} else {
console.log(`Failed: ${result.message}`);
}