Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@gelatonetwork/relay-sdk

Package Overview
Dependencies
Maintainers
16
Versions
54
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@gelatonetwork/relay-sdk - npm Package Compare versions

Comparing version 0.5.0 to 1.0.1-0

dist/constants/index.d.ts

4

dist/index.d.ts

@@ -1,3 +0,1 @@

export * as utils from "./utils";
export * as RelaySDK from "./lib";
export * from "./types";
export * as GelatoRelaySDK from "./lib";
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {

@@ -25,9 +21,4 @@ if (k2 === undefined) k2 = k;

};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RelaySDK = exports.utils = void 0;
exports.utils = __importStar(require("./utils"));
exports.RelaySDK = __importStar(require("./lib"));
__exportStar(require("./types"), exports);
exports.GelatoRelaySDK = void 0;
exports.GelatoRelaySDK = __importStar(require("./lib"));

@@ -1,9 +0,3 @@

import { RelayTransaction } from "../types/";
import { BigNumber } from "ethers";
declare const sendRelayTransaction: (chainId: number, dest: string, data: string, token: string, relayerFee: BigNumber) => Promise<RelayTransaction>;
declare const isChainSupported: (chainId: number) => Promise<boolean>;
declare const isOracleActive: (chainId: number) => Promise<boolean>;
declare const getPaymentTokens: (chainId: number) => Promise<string[]>;
declare const getEstimatedFee: (chainId: number, paymentToken: string, gasLimit: BigNumber, isHighPriority: boolean, gasLimitL1?: BigNumber | undefined) => Promise<BigNumber>;
declare const getTaskStatus: (taskId: string) => Promise<import("@gelatonetwork/core-sdk").TransactionStatus | undefined>;
export { isChainSupported, sendRelayTransaction, isOracleActive, getPaymentTokens, getEstimatedFee, getTaskStatus, };
export { relayWithUserSignature } from "./userAuthCall";
export { relayWithSyncFee } from "./callWithSyncFee";
export { PaymentType } from "./types";
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTaskStatus = exports.getEstimatedFee = exports.getPaymentTokens = exports.isOracleActive = exports.sendRelayTransaction = exports.isChainSupported = void 0;
const axios_1 = __importDefault(require("axios"));
const core_sdk_1 = require("@gelatonetwork/core-sdk");
const sendRelayTransaction = (chainId, dest, data, token, relayerFee) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
const params = { dest, data, token, relayerFee: relayerFee.toString() };
let output;
try {
const res = yield axios_1.default.post(`${core_sdk_1.RELAY_URL}/relays/${chainId}`, params);
output = res.data;
}
catch (error) {
let message = `RelaySdkError: ${error.message} `;
if (axios_1.default.isAxiosError(error)) {
message += (_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message;
}
throw new Error(message);
}
return output;
});
exports.sendRelayTransaction = sendRelayTransaction;
const isChainSupported = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
const chainsSupportedByGelato = yield getGelatoRelayChains();
return chainsSupportedByGelato.includes(chainId.toString());
});
exports.isChainSupported = isChainSupported;
const getGelatoRelayChains = () => __awaiter(void 0, void 0, void 0, function* () {
let result = [];
try {
const res = yield axios_1.default.get(`${core_sdk_1.RELAY_URL}/relays/`);
result = res.data.relays;
}
catch (error) { } // eslint-disable-line no-empty
return result;
});
const isOracleActive = core_sdk_1.Oracle.isOracleActive;
exports.isOracleActive = isOracleActive;
const getPaymentTokens = core_sdk_1.Oracle.getPaymentTokens;
exports.getPaymentTokens = getPaymentTokens;
const getEstimatedFee = core_sdk_1.Oracle.getEstimatedFee;
exports.getEstimatedFee = getEstimatedFee;
const getTaskStatus = core_sdk_1.Status.getTaskStatus;
exports.getTaskStatus = getTaskStatus;
exports.PaymentType = exports.relayWithSyncFee = exports.relayWithUserSignature = void 0;
var userAuthCall_1 = require("./userAuthCall");
Object.defineProperty(exports, "relayWithUserSignature", { enumerable: true, get: function () { return userAuthCall_1.relayWithUserSignature; } });
var callWithSyncFee_1 = require("./callWithSyncFee");
Object.defineProperty(exports, "relayWithSyncFee", { enumerable: true, get: function () { return callWithSyncFee_1.relayWithSyncFee; } });
var types_1 = require("./types");
Object.defineProperty(exports, "PaymentType", { enumerable: true, get: function () { return types_1.PaymentType; } });

@@ -1,2 +0,5 @@

export * from "./constants";
export * from "./errors";
export * from "./signTypedDataV4";
export * from "./calculateDeadline";
export * from "./getUserNonce";
export * from "./eip712";
export * from "./getFeeToken";
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {

@@ -17,3 +13,6 @@ if (k2 === undefined) k2 = k;

Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./constants"), exports);
__exportStar(require("./errors"), exports);
__exportStar(require("./signTypedDataV4"), exports);
__exportStar(require("./calculateDeadline"), exports);
__exportStar(require("./getUserNonce"), exports);
__exportStar(require("./eip712"), exports);
__exportStar(require("./getFeeToken"), exports);
{
"name": "@gelatonetwork/relay-sdk",
"version": "0.5.0",
"description": "SDK to integrate the Gelato Multichain Relay",
"version": "1.0.1-0",
"description": "SDK to integrate with Gelato Relay",
"main": "dist/index.js",

@@ -11,8 +11,7 @@ "types": "dist/index.d.ts",

"scripts": {
"build": "rm -rf dist/ && npx tsc",
"format": "prettier --write '*/**/*.{js,json,md,ts}'",
"format:check": "prettier --check '*/**/*.{js,json,md,ts}'",
"build": "rm -rf dist && npx tsc",
"format:check": "prettier --check \"*/**/*.{js,json,md,ts}\"",
"format": "prettier --write */**/*.{js,json,md,ts}",
"lint": "eslint --cache .",
"prepare": "yarn build && yarn format && yarn lint",
"test": "ts-mocha --check-leaks --exit --timeout 60000 'test/**/*.spec.ts'"
"prepare": "husky install"
},

@@ -23,36 +22,26 @@ "keywords": [],

"devDependencies": {
"@tsconfig/recommended": "^1.0.1",
"@types/chai": "^4.2.21",
"@types/chai-as-promised": "^7.1.4",
"@types/chai-subset": "^1.3.3",
"@types/mocha": "^9.0.0",
"@types/node": "^16.11.12",
"@types/sinon": "^10.0.2",
"@types/sinon-chai": "^3.2.5",
"@typescript-eslint/eslint-plugin": "^5.6.0",
"@typescript-eslint/parser": "^5.6.0",
"chai": "^4.3.6",
"chai-arrays": "^2.2.0",
"chai-as-promised": "^7.1.1",
"chai-bignumber": "^3.0.0",
"chai-subset": "^1.6.0",
"eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.2",
"lint-staged": "^11.1.2",
"mocha": "^9.2.0",
"prettier": "^2.3.2",
"sinon": "^13.0.1",
"sinon-chai": "^3.7.0",
"ts-generator": "^0.1.1",
"ts-mocha": "^9.0.2",
"typescript": "^4.5.3"
"@tsconfig/recommended": "1.0.1",
"@types/node": "16.11.12",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"@typescript-eslint/parser": "^5.30.0",
"eslint": "^8.18.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^3.1.3",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.1.0",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"typescript": "4.5.3"
},
"dependencies": {
"@gelatonetwork/core-sdk": "^0.4.0",
"axios": "^0.24.0",
"ethers": "^5.5.2"
"@gelatonetwork/1balance-sdk": "0.2.2-9",
"@gelatonetwork/core-sdk": "^0.3.0",
"axios": "0.24.0",
"ethers": "5.5.2"
},
"gitHead": "962873487a3637a83cf0062f3e2fc7984ccb96c7"
"lint-staged": {
"*.{js,json,md,ts}": "yarn format",
"*.{ts,js}": "yarn lint"
}
}

@@ -1,4 +0,4 @@

# Gelato Multichain Relay SDK <!-- omit in toc -->
# Gelato Relay SDK <!-- omit in toc -->
SDK to integrate into Gelato Multichain Relay.
SDK to integrate into Gelato Multichain Relay
<br/>

@@ -9,7 +9,11 @@

- [Installation](#installation)
- [Getting Started](#getting-started)
- [Examples](#examples)
- [Supported Chains](#supported-chains)
- [Gelato Contract Addresses](#gelato-contract-addresses)
- [RelayTransit Contract Addresses](#relaytransit-contract-addresses)
- [Introduction](#introduction)
- [Quick Start](#quick-start)
- [Payment Types](#payment-types)
- [Request Types](#request-types)
- [Sending ForwardCall](#sending-forwardcall)
- [Sending ForwardRequest](#sending-forwardrequest)
- [Sending MetaTxRequest](#sending-metatxrequest)
- [Querying Task Status](#querying-task-status)
- [Estimating maxFee](#estimating-maxfee)

@@ -19,3 +23,3 @@ ## Installation

```bash
yarn add @gelatonetwork/relay-sdk
yarn add @gelatonetwork/gelato-relay-sdk
```

@@ -26,177 +30,436 @@

```bash
npm install @gelatonetwork/relay-sdk
npm install @gelatonetwork/gelato-relay-sdk
```
## Getting Started
## Introduction
Import the Gelato Multichain Relay into your project
Gelato Relay SDK offers a convenient suite of functions in order to interact with Gelato Relay API.
Gelato Relay API is a service that allows users and developers to get transactions mined fast, reliably and securely, without having to deal with the low-level complexities of blockchains.
```typescript
import { RelaySDK } from "@gelatonetwork/relay-sdk";
As requests are submitted to Gelato Relay API, a network of Gelato Executors will execute and get said transactions mined as soon as they become executable (hence paying for gas fees). ECDSA signatures enforce the integrity of data whenever necessary, while gas fee refunds can be handled in any of our supported payment types. In this way, users and developers no longer have to become their own central point of failure with regards to their blockchain infrastructure, which may improve on the UX, costs, security and liveness of their Web3 systems.
## Quick Start
Below is a simple example in order to get us started. We get Gelato Relay to call a `HelloWorld` smart contract on our behalf. Note that in this example there is no dependency on RPC providers, as we simply build all transaction data, its required `sponsorSignature` and send to Gelato Relay API. `sponsorSignature` is required by `sponsor` in order for Gelato to securely credit payments, but in this example we do not enforce any payment to be made as it is a testnet. In this way, interacting with a blockchain is simplified to sending a `POST` request to a web server.
#### Backend example
```ts
import { Wallet, utils } from "ethers";
import { GelatoRelaySDK } from "@gelatonetwork/gelato-relay-sdk";
const forwardRequestExample = async () => {
// Goerli
const chainId = 5;
// HELLO WORLD smart contract on Goerli
const target = "0x8580995EB790a3002A55d249e92A8B6e5d0b384a";
const NATIVE_TOKEN = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
// Create Mock wallet
const wallet = Wallet.createRandom();
const sponsor = await wallet.getAddress();
console.log(`Mock PK: ${await wallet._signingKey().privateKey}`);
console.log(`Mock wallet address: ${sponsor}`);
// abi encode for HelloWorld.sayHiVanilla(address _feeToken)
const data = `0x4b327067000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeaeeeeeeeeeeeeeeeee`;
// Async Gas Tank payment model (won't be enforced on testnets, hence no need to deposit into Gelato's Gas Tank smart contract)
const paymentType = 1;
// Maximum fee that sponsor is willing to pay worth of NATIVE_TOKEN
const maxFee = "1000000000000000000";
// Gas limit
const gas = "200000";
// We do not enforce smart contract nonces to simplify the example.
// In reality, this decision depends whether or not target address already implements
// replay protection. (More info in the docs)
const sponsorNonce = 0;
const enforceSponsorNonce = false;
// Only relevant when enforceSponsorNonce=true
const enforceSponsorNonceOrdering = false;
// Build ForwardRequest object
const forwardRequest = GelatoRelaySDK.forwardRequest(
chainId,
target,
data,
NATIVE_TOKEN,
paymentType,
maxFee,
gas,
sponsorNonce,
enforceSponsorNonce,
sponsor
);
// Get EIP-712 hash (aka digest) of forwardRequest
const digest = GelatoRelaySDK.getForwardRequestDigestToSign(forwardRequest);
// Sign digest using Mock private key
const sponsorSignature: utils.BytesLike = utils.joinSignature(
await wallet._signingKey().signDigest(digest)
);
// Send forwardRequest and its sponsorSignature to Gelato Relay API
await GelatoRelaySDK.sendForwardRequest(forwardRequest, sponsorSignature);
console.log("ForwardRequest submitted!");
};
forwardRequestExample();
```
1. Check if the Gelato Multichain Relay supports a given ChainId
#### Frontend example
```typescript
const chainSupported = await RelaySDK.isChainSupported(chainId);
if (!chainSupported) {
console.log("ChainId not supported");
return;
}
Using [ReactJS](https://reactjs.org/) and [Wagmi](https://wagmi.sh/).
Generate the payload using `getForwardRequestWalletPayloadToSign` method than sign it using `signTypedDataAsync`
```ts
import { useSignTypedData } from 'wagmi';
const { signTypedDataAsync } = useSignTypedData();
// Get transaction data (use forwardRequest from the example above)
const generatedParams = GelatoRelaySDK.getForwardRequestWalletPayloadToSign(forwardRequest);
// Sign it on Metamask
const sponsorSignature = await signTypedDataAsync(generatedParams);
// Send forwardRequest and its sponsorSignature to Gelato Relay API
const requestId = await GelatoRelaySDK.sendForwardRequest(forwardRequest, sponsorSignature);
console.log("ForwardRequest submitted!", requestId);
```
2. Estimate the execution price using the Relay Multichain Oracle
## Payment Types
```typescript
// Check if the Relay has an oracle on this ChainId
const isActiveOracle = await RelaySDK.isOracleActive(chainId);
if (!isActiveOracle) {
console.log("Oracle is not active on this network");
return;
}
Upon sending messages and signatures to Gelato Relay API, Gelato Executors will acknowledge and execute them as soon as they are ready, hence paying gas fees in native token. Gelato Executors can have their fee costs refunded, plus a small fraction as incentive, in one of the following options:
// Estimates the transaction cost in the defined token for the inputted gasLimit
// The paymentTokenAddress is the address of the token used to pay transaction fees
const estimatedExecutionFeeInToken: BigNumber = await RelaySDK.getEstimatedFee(
chainId,
paymentTokenAddress,
gasLimit,
isHighPriority // If we want to get a high priority fee
);
`Synchronous Payment (Type 0)`: This means that the `target` smart contract will pay Gelato Relay's smart contract as the call is forwarded. Payment can be done in `feeToken`, where it is expected to be a whitelisted payment token.
`Asynchronous Gas Tank Payment (Type 1)`: This means that the `sponsor` must hold a balance in one of Gelato's Gas Tank smart contracts. The balance could even be held on a different `chainId` than the one the transaction is being relayed on (as defined by `sponsorChainId`). An event is emitted to tell Gelato how much to charge in the future, which shall be acknowledged in an off-chain accounting system. A `sponsorSignature` is expected in order to ensure that the sponsor agrees on being charged up to a `maxFee` amount.
`Synchronous Gas Tank Payment (Type 2)`: Similarly to `Type 1`, but `sponsor` is expected to hold a balance with Gelato on the same `chainId` where the transaction is executed. Fee deduction happens during the transaction. A `sponsorSignature` is expected in order to ensure that the sponsor agrees on being charged up to a `maxFee` amount.
`Synchronous Pull Fee Payment (Type 3)`: In this scenario a `sponsor` pre-approves the appropriate Gelato Relay's smart contract to spend tokens up so some maximum allowance value. During execution of the transaction, Gelato will credit due fees using `IERC20(feeToken).transferFrom(...)` in order to pull fees from his/her account. A `sponsorSignature` is expected in order to ensure that the sponsor agrees on being charged up to a `maxFee` amount.
Note that payment of type 0 is the simplest one, as it requires no `sponsor` signature to be provided, but it assumes that the `target` smart contract refunds `msg.sender` due amount of fees in `feeToken`. This may require changes to the internal logic of `target` smart contract.
## Request Types
```ts
type ForwardCall = {
chainId: number;
target: string;
data: BytesLike;
feeToken: string;
gas: string;
};
```
If you are estimating the transaction cost on Optimism, you have to use the
function getEstimatedFee with the GasLimit on L1 as follows:
`ForwardCall` is designed to handle payments of type 0, as it requires no signatures.
```typescript
const estimatedExecutionFeeInToken: BigNumber = await RelaySDK.getEstimatedFee(
chainId,
paymentTokenAddress,
gasLimit,
isHighPriority // If we want to get a high priority fee
gasLimitL1 // Estimated Gas Limit on L1
);
```ts
type ForwardRequest = {
chainId: number;
target: string;
data: BytesLike;
feeToken: string;
paymentType: number;
maxFee: string;
gas: string;
sponsor: string;
sponsorChainId: number;
nonce: number;
enforceSponsorNonce: boolean;
enforceSponsorNonceOrdering: boolean;
};
```
3. Get supported payment tokens by chain id
`ForwardRequest` is designed to handle payments of type 1, 2 and 3, in cases where all meta-transaction related logic (or other kinds of replay protection mechanisms such as hash based commitments) is already implemented inside `target` smart contract. The `sponsor` is still required to EIP-712 sign this request, in order to ensure the integrity of payments. Optionally, `nonce` may or may not be enforced, by setting `enforceSponsorNonce`. Some dApps may not need to rely on a nonce for `ForwardRequest` if they already implement strong forms of replay protection.
```typescript
// Get Payment Token Addresses
const paymentTokensAdresses: string[] = await RelaySDK.getPaymentTokens(
chainId
);
```ts
type MetaTxRequest = {
chainId: number;
target: string;
data: BytesLike;
feeToken: string;
paymentType: number;
maxFee: string;
gas: string;
user: string;
sponsor: string;
sponsorChainId: number;
nonce: number;
deadline: number;
};
```
4. Submit transaction:
If you want to submit a transaction using the Gelato Multichain Relayer, the transaction should pay to the Gelato contract
to execute, otherwise the transaction will revert.
`MetaTxRequest` is designed to handle payments of type 1, 2 and 3, in cases where the `target` contract does not have any meta-transaction nor replay protection logic. In this case, the appropriate Gelato Relay's smart contract already verifies `user` and `sponsor` signatures. `user` is the EOA address that wants to interact with the dApp, while `sponsor` is the account that pays fees.
```typescript
import { BigNumber } from "ethers";
import { Interface } from "ethers/lib/utils";
## Sending ForwardCall
// Generate the function data
const contractInterface = new Interface(contractABI);
const data = contractInterface.encodeFunctionData("functionToCall", [args]);
### ForwardCall are for payments of Type 0.
const relayTx = await RelaySDK.sendRelayTransaction(
chainId,
destAddress,
data,
paymentTokenAddress
);
console.log(`RelayerTransactionId = ${relayTx.taskId}`);
ForwardCall requests require no signatures and can be submitted by calling the following method in Gelato Relay SDK:
```ts
/**
*
* @param {number} chainId - Chain ID.
* @param {string} target - Address of dApp's smart contract to call.
* @param {string} data - Payload for `target`.
* @param {string} feeToken - paymentToken for Gelato Executors. Use `0xeee...` for native token.
* @param {string} gas - Gas limit.
* @returns {PromiseLike<string>} taskId - Task ID.
*/
const sendCallRequest = async (
chainId: number,
target: string,
data: string,
feeToken: string,
gas: string
): Promise<string>;
```
5. Check your transaction status:
Upon Promise resolution, we get a unique `taskId` that identifies our request. `taskId` can then be used to query Gelato Status API in order to retrieve more information.
```typescript
const status = await RelaySDK.getTaskStatus(taskId);
if (status) {
const state = (status as TransactionStatus).taskState;
switch (state) {
case TaskState.CheckPending:
console.log(`> Task pending relayer verification`);
break;
case TaskState.ExecPending:
console.log(`> Task queued for execution`);
break;
case TaskState.ExecSuccess:
console.log(`> Task successfully executed, tx hash: ${status.execution?.transactionHash}`);
break;
case TaskState.ExecReverted:
console.log(`> Task was reverted with message: ${status.lastCheck?.message}`);
break;
case TaskState.Cancelled:
console.log(`> Task was cancelled with message: ${status.lastCheck?.message}`);
break;
default:
console.log(`> Task status: ${state}`);
}
## Sending ForwardRequest
### ForwardRequest are for payments of Type 1, 2 or 3.
Firstly, we build a `ForwardRequest` object using the following method:
```ts
/**
*
* @param {number} chainId - Chain ID.
* @param {string} target - Address of dApp's smart contract to call.
* @param {string} data - Payload for `target`.
* @param {string} feeToken - paymentToken for Gelato Executors. Use `0xeee...` for native token.
* @param {number} paymentType - Type identifier for Gelato's payment. Can be 1, 2 or 3.
* @param {string} maxFee - Maximum fee sponsor is willing to pay Gelato Executors.
* @param {string} gas - Gas limit.
* @param {number} nonce - Smart contract nonce for sponsor to sign.
* Can be 0 if enforceSponsorNonce is always false.
* @param {boolean} enforceSponsorNonce - Whether or not to enforce replay protection using sponsor's nonce.
* @param {string} sponsor - EOA address that pays Gelato Executors.
* @param {number} [sponsorChainId] - Chain ID of where sponsor holds a Gas Tank balance with Gelato.
* Relevant for paymentType=1. Defaults to `chainId` if not provided.
* @param {boolean} [enforceSponsorNonceOrdering] - Whether or not ordering matters for concurrently submitted transactions.
* Defaults to `true` if not provided.
* @returns {ForwardRequest}
*/
const forwardRequest = (
chainId: number,
target: string,
data: BytesLike,
feeToken: string,
paymentType: number,
maxFee: string,
gas: string,
nonce: number,
enforceSponsorNonce: boolean,
sponsor: string,
sponsorChainId?: number,
enforceSponsorNonceOrdering?: boolean
): ForwardRequest;
```
## Examples
Then we send `request` to Gelato Relay API. `sponsorSignature` is the EIP-712 signature from `sponsor`. Upon Promise resolution, we get a unique `taskId` that identifies our request. `taskId` can then be used to query Gelato Status API in order to retrieve more information.
Check out our tutorial repository [relay-sdk-hello-world](https://github.com/gelatodigital/relay-sdk-hello-world) for more in-depth examples.
<br/><br/>
```ts
/**
*
* @param {ForwardRequest} request - ForwardRequest to be relayed by Gelato Executors.
* @param {string} sponsorSignature - EIP-712 signature of sponsor (who pays Gelato Executors).
* @returns {PromiseLike<string>} taskId - Task ID.
*/
const sendForwardRequest = async (
request: ForwardRequest,
sponsorSignature: BytesLike
): Promise<string>;
```
## Supported Chains
## Sending MetaTxRequest
These are the chain Ids supported by the Gelato Multichain Relay:
### MetaTxRequest are for payments of Type 1, 2 or 3.
```typescript
MAINNET: 1,
ROPSTEN: 3,
RINKEBY: 4,
GOERLI: 5,
OPTIMISM: 10,
BSC: 56,
XDAI: 100,
MATIC: 137,
FANTOM: 250,
MOONBEAM: 1284,
ARBITRUM: 42161,
AVALANCHE: 43114
Firstly we create `MetaTxRequest` object using the following SDK's method:
```ts
/**
*
* @param {number} chainId - Chain ID.
* @param {string} target - Address of dApp's smart contract to call.
* @param {string} data - Payload for `target`.
* @param {string} feeToken - paymentToken for Gelato Executors. Use `0xeee...` for native token.
* @param {number} paymentType - Type identifier for Gelato's payment. Can be 1, 2 or 3.
* @param {string} maxFee - Maximum fee sponsor is willing to pay Gelato Executors.
* @param {string} gas - Gas limit.
* @param {string} user - EOA of dApp's user
* @param {number} nonce - user's smart contract nonce.
* @param {string} [sponsor] - EOA that pays Gelato Executors.
* @param {number} [sponsorChainId] - Chain ID where sponsor holds a balance with Gelato.
* Relevant for paymentType=1.
* @param {number} [deadline] - Deadline for executing MetaTxRequest, UNIX timestamp in seconds.
* Can also be 0 (not enforced).
* @returns {MetaTxRequest}
*/
const metaTxRequest = (
chainId: number,
target: string,
data: BytesLike,
feeToken: string,
paymentType: number,
maxFee: string,
gas: string,
user: string,
nonce: number,
sponsor?: string,
sponsorChainId?: number,
deadline?: number
): MetaTxRequest;
```
## Gelato Contract Addresses
Then we send `request` to Gelato Relay API. `userSignature` is the EIP-712 signature from dApp's user. If `sponsorSignature` is not passed, we assume `sponsor` is also the `user`, so that we set it equal to `sponsorSignature`. Upon Promise resolution, we get a unique `taskId` that identifies our request. `taskId` can then be used to query Gelato Status API in order to retrieve more information.
| Chain | Contract Address |
| --------- | ------------------------------------------ |
| MAINNET | 0x3CACa7b48D0573D793d3b0279b5F0029180E83b6 |
| ROPSTEN | 0xCc4CcD69D31F9FfDBD3BFfDe49c6aA886DaB98d9 |
| RINKEBY | 0x0630d1b8C2df3F0a68Df578D02075027a6397173 |
| GOERLI | 0x683913B3A32ada4F8100458A3E1675425BdAa7DF |
| KOVAN | 0xDf592cB2d32445F8e831d211AB20D3233cA41bD8 |
| OPTIMISM | 0x01051113D81D7d6DA508462F2ad6d7fD96cF42Ef |
| BSC | 0x7C5c4Af1618220C090A6863175de47afb20fa9Df |
| XDAI | 0x29b6603D17B9D8f021EcB8845B6FD06E1Adf89DE |
| MATIC | 0x7598e84B2E114AB62CAB288CE5f7d5f6bad35BbA |
| MUMBAI | 0x25aD59adbe00C2d80c86d01e2E05e1294DA84823 |
| FANTOM | 0xebA27A2301975FF5BF7864b99F55A4f7A457ED10 |
| MOONBEAM | 0x91f2A140cA47DdF438B9c583b7E71987525019bB |
| ARBITRUM | 0x4775aF8FEf4809fE10bf05867d2b038a4b5B2146 |
| AVALANCHE | 0x7C5c4Af1618220C090A6863175de47afb20fa9Df |
| BOBA | 0x91f2A140cA47DdF438B9c583b7E71987525019bB |
| CRONOS | 0x91f2A140cA47DdF438B9c583b7E71987525019bB |
```ts
/**
*
* @param {MetaTxRequest} request - MetaTxRequest to be relayed by Gelato Executors.
* @param {string} userSignature - EIP-712 signature from user:
* EOA that interacts with target dApp's address.
* @param {string} sponsorSignature - EIP-712 signature from sponsor:
* EOA that pays Gelato Executors, could be same as user.
* @returns {PromiseLike<string>} taskId - Task ID.
*/
const sendMetaTxRequest = async (
request: MetaTxRequest,
userSignature: BytesLike,
sponsorSignature?: BytesLike
): Promise<string>;
```
## RelayTransit Contract Addresses
## Querying Task Status
| Chain | Contract Address |
| --------- | ------------------------------------------ |
| MAINNET | 0x9B077C59fDe7de5AdCeF8093Bc38B61d43FC7007 |
| ROPSTEN | 0xE2Fc8F14B6cEb1AD8165623E02953eDB100288bE |
| RINKEBY | 0x7084d869F0C120957E40D762Ebe3104474D5248f |
| GOERLI | 0xCDdE9992Fb66038Dd8419b56149a75CC79Df133C |
| KOVAN | 0xb34758F24fFEf132dc5831C2Cd9A0a5e120CD564 |
| OPTIMISM | 0xe8a5eE73f3c8F1Cd55915f6Eb5Fc7df4206f3C78 |
| BSC | 0x43728A95386D64384C76Afd416Dcc8118869BA6c |
| XDAI | 0x62B1a88CCc6BC5e6FF91FB2FCD29Ab4F819b35C6 |
| MATIC | 0xE2Fc8F14B6cEb1AD8165623E02953eDB100288bE |
| MUMBAI | 0x24D677f8A59A486BfC6d87E9453C4f1fEfcB0958 |
| FANTOM | 0xFbf1CA2be769b79BE01e48F509107dcACb9ae11b |
| MOONBEAM | 0x36225733276425f5DbA88977Aef45f042BACB953 |
| ARBITRUM | 0x0ae392879A228B2484D9B1F80A5D0B7080FE79C2 |
| AVALANCHE | 0xa120a7d4EaF1910D38bc934D756DF507943a4C5a |
| BOBA | 0x4efaEe0fAD71A451c6Ca621df5AeFc5c01668a26 |
| CRONOS | 0x62B1a88CCc6BC5e6FF91FB2FCD29Ab4F819b35C6 |
Once a task is submitted to Gelato Relay API, we can use its `taskId` in order to query Gelato Status API as follows:
```ts
/**
*
* @param taskId - Task ID.
* @returns {PromiseLike<TransactionStatus | undefined}
*/
const getStatus = async (
taskId: string
): Promise<TransactionStatus | undefined>;
```
`getStatus` returns `undefined` in case any error has occurred, otherwise it returns an object of type `TransactionStatus` defined as follows:
```ts
interface TransactionStatus {
service: string; // Name of Gelato Service
chain: string; // Chain ID
taskId: string; // taskId
taskState: TaskState;
created_at: Date; // JS Date object
lastCheck?: Check;
execution?: Execution;
lastExecution: Date; // JS Date object
}
// TransactionStatus.taskState is of type:
enum TaskState {
CheckPending = "CheckPending",
ExecPending = "ExecPending",
ExecSuccess = "ExecSuccess",
ExecReverted = "ExecReverted",
WaitingForConfirmation = "WaitingForConfirmation",
Blacklisted = "Blacklisted",
Cancelled = "Cancelled",
NotFound = "NotFound",
}
// TransactionStatus.lastCheck is optional of type:
interface Check {
taskState: TaskState;
message?: string;
payload?: Payload;
reason?: string;
}
// TransactionStatus.lastExecution is optional of type:
interface Execution {
status: string;
transactionHash: string;
blockNumber: number;
created_at: Date;
}
```
## Estimating maxFee
`maxFee` denotes the maximum fee denominated in `feeToken` a `sponsor` is willing to pay, and is one of the required parameters in both `ForwardRequest` and `MetaTxRequest`. Thanks to `sponsorSignature` and smart contract logic, Gelato Executors will be strongly disencouraged to over-charge transaction sponsors. Moreover, `maxFee` also serves as a buffer to protect against gas price volatility spikes, meaning that transactions will still get mined on time and reliably under said adversarial circumstances. At execution time, Gelato will charge the fair fee according to actual gas cost estimates and gas price used, not the whole `maxFee`. In the future, staked Gelato Executors will have a strong incentive to play by the fair rules described in this paragraph even if there is no way for the smart contract to enforce this rule (for instance, payments of Type 1 which use an Off-chain accounting system), as doing otherwise will result in their fee revenues not being paid by the Gelato DAO, and possibly have some or all of their GEL stake slashed.
Below is an example on how to use Gelato Relay SDK in order to calculate suitable `maxFee` values:
```ts
const estimateMaxFee = async (
chainId: number,
feeToken: string,
gasLimit: number
): Promise<string | undefined> => {
try {
// First we query all currently whitelisted feeTokens
const whitelistedFeeTokens: string[] = (
await GelatoRelaySDK.getFeeTokens(chainId)
).map((token) => {
return token.toLowerCase();
});
console.log(
`Whitelisted fee tokens for chainId ${chainId}: ${JSON.stringify(
whitelistedFeeTokens
)}`
);
if (!whitelistedFeeTokens.includes(feeToken.toLowerCase())) {
throw new Error(`feeToken ${feeToken} not whitelisted`);
}
// Add a constant buffer to gasLimit, since the tx will be routed through
// Gelato's smart contracts
const totalGasLimit = gasLimit + GelatoRelaySDK.GELATO_GAS_BUFFER;
// Estimate maxFee
const maxFee = await GelatoRelaySDK.getMaxFeeEstimate(
chainId,
feeToken,
totalGasLimit
);
console.log(`maxFee estimate for feeToken ${feeToken}: ${maxFee}`);
return maxFee;
} catch (error) {
const errorMsg = (error as Error).message ?? String(error);
console.log(`estimateMaxFee: Failed with error: ${errorMsg}`);
return undefined;
}
};
async function main() {
// Can use GelatoRelaySDK.isChainSupported(chainId) to see if it is supported
const chainId = 4;
// Native token
const feeToken = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
// gasLimit of the transaction being relayed.
// Note that, by construction, this is an upper bound on the actual gas cost,
// hence suitable for estimating a maxFee
const gasLimit = 100000;
await estimateMaxFee(chainId, feeToken, gasLimit);
}
main();
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc