Skip to main content
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 MethodNew 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 callAPI Key configured once in client
relayResponse.taskIdTask ID + waitForReceipt()

Migration Steps

1

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
2

Update Imports

Before (Relay SDK):
import { GelatoRelay, SponsoredCallRequest } from "@gelatonetwork/relay-sdk";
After (Gasless SDK):
import {
  createGelatoEvmRelayerClient,
  sponsored,
  StatusCode,
} from "@gelatocloud/gasless";
3

Update Client Initialization

Before (Relay SDK):
const relay = new GelatoRelay();
After (Gasless SDK):
const relayer = createGelatoEvmRelayerClient({
  apiKey: process.env.GELATO_API_KEY,
});
4

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}`);
}
5

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

Request Format

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

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);

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

  • Uninstall @gelatonetwork/relay-sdk
  • Install @gelatocloud/gasless and viem
  • Replace new GelatoRelay() with createGelatoEvmRelayerClient()
  • Replace sponsoredCall() with sendTransaction({ payment: sponsored() })
  • Update target field to to in request
  • Replace manual polling with waitForReceipt() or use sendTransactionSync()
  • If using ERC-2771 or SyncFee, follow the dedicated migration guides above
  • Test on testnet
  • Deploy to production

Need Help?

If you have questions about migrating from the Relay SDK, please reach out through our Discord or GitHub.