quickstart.md

Quickstart

Execute your first cross-chain transaction in under 5 minutes.

Relay is a multichain payments network. You define the Intent (what the user wants), and Relay handles the Execution (how to get there).

Follow this 5-step flow to integrate Relay into your application:

Step 1: Configure

To see how fast and simple Relay makes transacting cross-chain, let’s bridge real assets between inexpensive L2s—Base and Arbitrum.

Prerequisites:

API key Provisioning

Create an API key in the Relay Dashboard to raise your rate limits.
See API keys and Rate Limits for usage and limits.

Chain Configuration

For chain metadata we recommend querying the chains API in your application. This will return some valuable information about the chain, we've provided a sample below:

{
  "chains": [{
      "id": 10,
      "name": "optimism",
      "displayName": "Optimism",
      "httpRpcUrl": "https://optimism.publicnode.com",
      "wsRpcUrl": "wss://optimism.publicnode.com",
      "explorerUrl": "https://optimistic.etherscan.io",
      "explorerName": "Optimism Etherscan",
      "depositEnabled": true,
      "tokenSupport": "All",
      "disabled": false,
      "partialDisableLimit": 0,
      "blockProductionLagging": false,
      "currency": {
          "id": "eth",
          "symbol": "ETH",
          "name": "Ether",
          "address": "0x0000000000000000000000000000000000000000",
          "decimals": 18,
          "supportsBridging": true
      },
      "withdrawalFee": 1,
      "depositFee": 0,
      "surgeEnabled": false,
      "featuredTokens": [
          {
            "id": "eth",
            "symbol": "ETH",
            "name": "Ether",
            "address": "0x0000000000000000000000000000000000000000",
            "decimals": 18,
            "supportsBridging": true,
            "metadata": {
                "logoURI": "https://assets.relay.link/icons/1/light.png"
            }
          }
      ],
      "erc20Currencies": [
          {
            "id": "sipher",
            "symbol": "SIPHER",
            "name": "Sipher",
            "address": "0xb94944669f7967e16588e55ac41be0d5ef399dcd",
            "decimals": 18,
            "supportsBridging": true,
            "withdrawalFee": 1,
            "depositFee": 0,
            "surgeEnabled": false
          }
      ],
      "solverCurrencies": [
        {
          "id": "sipher",
          "symbol": "SIPHER",
          "name": "Sipher",
          "address": "0xb94944669f7967e16588e55ac41be0d5ef399dcd",
          "decimals": 18
        }
      ],
      "iconUrl": "https://assets.relay.link/icons/10/light.png",
      "contracts": {
        "multicall3": "0xca11bde05977b3631167028862be2a173976ca11",
        "multicaller": "0x0000000000002bdbf1bf3279983603ec279cc6df",
        "onlyOwnerMulticaller": "0xb90ed4c123843cbfd66b11411ee7694ef37e6e72",
        "relayReceiver": "0xa5f565650890fba1824ee0f21ebbbf660a179934",
        "erc20Router": "0xf5042e6ffac5a625d4e7848e0b01373d8eb9e222",
        "approvalProxy": "0xbbbfd134e9b44bfb5123898ba36b01de7ab93d98",
        "v3": {
          "erc20Router": "0xb92fe925dc43a0ecde6c8b1a2709c170ec4fff4f",
          "approvalProxy": "0xccc88a9d1b4ed6b0eaba998850414b24f1c315be"
        }
      },
      "vmType": "evm",
      "baseChainId": 1,
      "solverAddresses": [
          "0xf70da97812cb96acdf810712aa562db8dfa3dbef"
      ],
      "tags": [],
      "protocol": {
          "v2": {
            "chainId": "optimism",
            "depository": "0x4cd00e387622c35bddb9b4c962c136462338bc31"
          }
      }
  }]
}

The endpoint exposes a vast amount of chain metadata but the important things to note are:

Step 2: Quote

Every action in Relay starts with a Quote.

The quote endpoint handles all of your use cases, whether it’s a bridge, swap, or cross-chain call. It calculates fees, finds the best route, and generates the transaction data.

Request

As an example, let’s consider the scenario of bridging 0.0001 ETH from Base (Chain ID 8453) to Arbitrum One (Chain ID 42161):
Note: the requestId will be unique to every request.

curl -X POST "https://api.relay.link/quote/v2" \
-H "Content-Type: application/json" \
-d '{
  "user": "YOUR_WALLET_ADDRESS",
  "originChainId": 8453,
  "destinationChainId": 42161,
  "originCurrency": "0x0000000000000000000000000000000000000000",
  "destinationCurrency": "0x0000000000000000000000000000000000000000",
  "amount": "100000000000000",
  "tradeType": "EXACT_INPUT"
}'
{
  "steps": [
    {
      "id": "deposit",
      "action": "Confirm transaction in your wallet",
      "description": "Deposit funds to the relayer to execute the bridge",
      "kind": "transaction",
      "requestId": "0x8a9b3c...",
      "items": [
        {
          "status": "incomplete",
          "data": {
            "from": "YOUR_WALLET_ADDRESS",
            "to": "0xf70da97812cb96acdf810712aa562db8dfa3dbef",
            "data": "0x00fad611...",
            "value": "100000000000000",
            "chainId": 8453,
            "gas": "150000",
            "maxFeePerGas": "100000000",
            "maxPriorityFeePerGas": "100000000"
          },
          "check": {
            "endpoint": "/intents/status?requestId=0x8a9b3c...",
            "method": "GET"
          }
        }
      ],
      "depositAddress": "" 
    }
  ],
  "fees": {
    "gas": {
      "amount": "21000",
      "currency": {
        "chainId": 8453,
        "address": "0x0000000000000000000000000000000000000000",
        "symbol": "ETH",
        "name": "Ether",
        "decimals": 18
      },
      "amountUsd": "0.01"
    },
    "relayer": {
      "amount": "5000000000000",
      "currency": {
        "chainId": 8453,
        "address": "0x0000000000000000000000000000000000000000",
        "symbol": "ETH",
        "name": "Ether",
        "decimals": 18
      },
      "amountUsd": "0.02"
    }
  },
  "details": {
    "operation": "bridge",
    "sender": "YOUR_WALLET_ADDRESS",
    "recipient": "YOUR_WALLET_ADDRESS",
    "timeEstimate": 15,
    "currencyIn": {
      "amount": "100000000000000",
      "currency": {
        "chainId": 8453,
        "address": "0x0000000000000000000000000000000000000000",
        "symbol": "ETH",
        "decimals": 18
      }
    },
    "currencyOut": {
      "amount": "95000000000000",
      "currency": {
        "chainId": 42161,
        "address": "0x0000000000000000000000000000000000000000",
        "symbol": "ETH",
        "decimals": 18
      }
    },
    "totalImpact": {
      "usd": "-0.02",
      "percent": "-0.50"
    },
    "rate": "0.95"
  }
}

Step 3: Execute

The quote endpoint returns a steps array. Think of this as a recipe your application must follow. You need to iterate through these steps and prompt the user to sign or submit them.

The Logic

For a simple ETH bridge, the steps array contains a single transaction item. To execute it:

The Script (Node.js / Viem example)

Copy the script below to execute the transaction returned by the Quote in Step 2. You'll need to add the wallet connection logic using your preferred provider.

// npm install viem
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';

// 1. Setup Wallet (Base)
// Initialize your wallet using a provider or your preferred method
const account = {}
const client = createWalletClient({
  account,
  chain: base,
  transport: http()
});

// 2. The Quote from Step 2 (Paste JSON response)
const quote = { /* PASTE_FULL_JSON_RESPONSE_HERE */ };

async function execute() {
  console.log("🚀 Starting Execution...");

// Iterate through steps (usually just 1 for ETH bridge)
  for (const step of quote.steps) {
    const item = step.items[0]
    if (step.kind === 'transaction') {
      console.log(`Submitting Transaction...`);
      const hash = await client.sendTransaction({
        to: item.data.to,
        data: item.data.data,
        value: BigInt(item.data.value),
        chain: base
      });
      console.log(`✅ Bridge Initiated: ${hash}`);
      console.log(`requestId: ${step.requestId}`);
    }
  }
}

execute();

Step 4: Monitor

Once you submit the transaction, the Relay Solver detects the deposit and fills the request on the destination chain.

Use the status endpoint with the requestId located inside each step object in your quote response to track status and confirm success. You can also use the check.endpoint property inside the step item object as the endpoint for checking the status of the request.
Note: Replace with the requestId returned in your quote

curl "https://api.relay.link/intents/status/v3?requestId=0x20538510fd9eab7a90c3e54418f8f477bfef24d83c11955a8ca835e6154b59d3"
{
  "status": "success",
  "inTxHashes": [
    "0x9421772820b92c239162341a17994b4ad8706c974af2ebf88084a1b3b614d328"
  ],
  "txHashes": [
    "0xef2a71eb2ddd952b31f7b552e133d3af048e4be30a568f2bea54a36d8f3b12cd"
  ],
  "updatedAt": 1767385462193,
  "originChainId": 8453,
  "destinationChainId": 56
}

Step 5: Optimize

You have successfully executed your first cross-chain transaction with Relay! Check out some of the advanced features we offer to customize the experience: