Gelato is deprecating the Relay SDK (@gelatonetwork/relay-sdk) in favor of the new Gasless SDK (@gelatocloud/gasless). The new SDK only supports sponsored transactions. ERC-2771 and SyncFee methods are no longer supported.
What’s Being Deprecated?
The following packages and patterns will no longer be supported:
@gelatonetwork/relay-sdk package
GelatoRelay class and all its methods
sponsoredCall() method
sponsoredCallERC2771() method — no longer supported, see ERC-2771 Migration Guide
callWithSyncFee() and callWithSyncFeeERC2771() methods — no longer supported, see SyncFee Migration Guide
// DEPRECATED - Will no longer work
import { GelatoRelay, SponsoredCallRequest } from "@gelatonetwork/relay-sdk";
const relay = new GelatoRelay();
const request: SponsoredCallRequest = {
chainId: 84532n,
target: contractAddress,
data: encodedData,
};
const relayResponse = await relay.sponsoredCall(request, SPONSOR_API_KEY);
What’s Supported in the Gasless SDK?
The Gasless SDK only supports sponsored transactions (Gas Tank). The following legacy methods have no equivalent in the new SDK:
| Old Method | New SDK |
|---|
sponsoredCall() | sendTransaction({ payment: sponsored() }) |
sponsoredCallERC2771() | Not supported — see ERC-2771 Migration Guide |
callWithSyncFee() | Not supported — see SyncFee Migration Guide |
callWithSyncFeeERC2771() | Not supported — see SyncFee Migration Guide |
Migration Overview
| Old (Relay SDK) | New (Gasless SDK) |
|---|
@gelatonetwork/relay-sdk | @gelatocloud/gasless |
new GelatoRelay() | createGelatoEvmRelayerClient() |
relay.sponsoredCall(request, apiKey) | relayer.sendTransaction({ payment: sponsored() }) |
SponsoredCallRequest | { chainId, to, data, payment } |
| Sponsor API Key per call | API Key configured once in client |
relayResponse.taskId | Task ID + waitForReceipt() |
Migration Steps
Update Dependencies
Remove the old SDK and install the new one:# Remove old SDK
npm uninstall @gelatonetwork/relay-sdk
# Install new SDK
npm install @gelatocloud/gasless viem
Update Imports
Before (Relay SDK):import { GelatoRelay, SponsoredCallRequest } from "@gelatonetwork/relay-sdk";
After (Gasless SDK):import {
createGelatoEvmRelayerClient,
sponsored,
StatusCode,
} from "@gelatocloud/gasless";
Update Client Initialization
Before (Relay SDK):const relay = new GelatoRelay();
After (Gasless SDK):const relayer = createGelatoEvmRelayerClient({
apiKey: process.env.GELATO_API_KEY,
});
Update Sponsored Call
Before (Relay SDK):import { GelatoRelay, SponsoredCallRequest } from "@gelatonetwork/relay-sdk";
import { ethers } from "ethers";
const relay = new GelatoRelay();
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const contract = new ethers.Contract(targetAddress, abi, signer);
const { data } = await contract.increment.populateTransaction();
const request: SponsoredCallRequest = {
chainId: (await provider.getNetwork()).chainId,
target: targetAddress,
data: data,
};
const relayResponse = await relay.sponsoredCall(request, SPONSOR_API_KEY);
console.log(`Task ID: ${relayResponse.taskId}`);
After (Gasless SDK):import { createGelatoEvmRelayerClient, sponsored } from "@gelatocloud/gasless";
import { encodeFunctionData } from "viem";
import { baseSepolia } from "viem/chains";
const relayer = createGelatoEvmRelayerClient({
apiKey: process.env.GELATO_API_KEY,
});
const data = encodeFunctionData({
abi: [{ name: "increment", type: "function", inputs: [], outputs: [] }],
functionName: "increment",
});
const id = await relayer.sendTransaction({
chainId: baseSepolia.id,
to: targetAddress,
data: data,
payment: sponsored(),
});
console.log(`Task ID: ${id}`);
try {
const receipt = await relayer.waitForReceipt({ id });
console.log(`Transaction hash: ${receipt.transactionHash}`);
} catch (error) {
console.log(`Transaction failed: ${error.message}`);
}
Update Status Tracking
Before (Relay SDK):const relayResponse = await relay.sponsoredCall(request, apiKey);
const taskId = relayResponse.taskId;
// Manual polling required
const taskStatus = await relay.getTaskStatus(taskId);
After (Gasless SDK):const id = await relayer.sendTransaction({
chainId: baseSepolia.id,
to: targetAddress,
data: encodedData,
payment: sponsored(),
});
// Built-in wait for receipt
try {
const receipt = await relayer.waitForReceipt({ id });
console.log(`Transaction hash: ${receipt.transactionHash}`);
} catch (error) {
console.log(`Transaction failed: ${error.message}`);
}
Or use the synchronous method that waits automatically:// sendTransactionSync waits for inclusion and returns the receipt
const result = await relayer.sendTransactionSync({
chainId: baseSepolia.id,
to: targetAddress,
data: encodedData,
payment: sponsored(),
});
Key Differences
API Key Configuration
Before: API key passed with every call
relay.sponsoredCall(request, SPONSOR_API_KEY);
After: API key configured once at client creation
const relayer = createGelatoEvmRelayerClient({
apiKey: process.env.GELATO_API_KEY, // Set once
});
relayer.sendTransaction({ ... }); // No API key needed per call
Before:
const request: SponsoredCallRequest = {
chainId: chainId,
target: contractAddress,
data: encodedData,
};
After:
await relayer.sendTransaction({
chainId: chainId,
to: contractAddress, // "target" → "to"
data: encodedData,
payment: sponsored(), // Payment explicitly declared
});
Complete Migration Example
Before (Relay SDK)
After (Gasless SDK)
import { GelatoRelay, SponsoredCallRequest } from "@gelatonetwork/relay-sdk";
import { ethers } from "ethers";
const relay = new GelatoRelay();
const COUNTER_ADDRESS = "0xEEeBe2F778AA186e88dCf2FEb8f8231565769C27";
const SPONSOR_API_KEY = process.env.SPONSOR_API_KEY;
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const abi = ["function increment()"];
const contract = new ethers.Contract(COUNTER_ADDRESS, abi, signer);
const { data } = await contract.increment.populateTransaction();
const request: SponsoredCallRequest = {
chainId: (await provider.getNetwork()).chainId,
target: COUNTER_ADDRESS,
data: data,
};
const relayResponse = await relay.sponsoredCall(request, SPONSOR_API_KEY);
console.log(`Task ID: ${relayResponse.taskId}`);
// Manual polling for status
const interval = setInterval(async () => {
const status = await relay.getTaskStatus(relayResponse.taskId);
if (status?.taskState === "ExecSuccess") {
console.log(`Transaction hash: ${status.transactionHash}`);
clearInterval(interval);
}
}, 2000);
import {
createGelatoEvmRelayerClient,
sponsored,
StatusCode,
} from "@gelatocloud/gasless";
import { encodeFunctionData } from "viem";
import { baseSepolia } from "viem/chains";
const COUNTER_ADDRESS = "0xEEeBe2F778AA186e88dCf2FEb8f8231565769C27";
const relayer = createGelatoEvmRelayerClient({
apiKey: process.env.GELATO_API_KEY,
});
const data = encodeFunctionData({
abi: [{ name: "increment", type: "function", inputs: [], outputs: [] }],
functionName: "increment",
});
const id = await relayer.sendTransaction({
chainId: baseSepolia.id,
to: COUNTER_ADDRESS,
data: data,
payment: sponsored(),
});
console.log(`Task ID: ${id}`);
// Built-in receipt waiting
try {
const receipt = await relayer.waitForReceipt({ id });
console.log(`Transaction hash: ${receipt.transactionHash}`);
} catch (error) {
console.log(`Transaction failed: ${error.message}`);
}
Migrating from ERC-2771 or SyncFee?
If you were using sponsoredCallERC2771, callWithSyncFee, or callWithSyncFeeERC2771, these methods are not available in the new Gasless SDK. See the dedicated migration guides:
Migration Checklist
Need Help?
If you have questions about migrating from the Relay SDK, please reach out through our Discord or GitHub.