Skip to content

Relayer Reference

The Ryze Relayer is an intent-based transaction execution service. Instead of users submitting on-chain transactions directly, they sign an intent (an EIP-712 typed message) and the relayer batches and executes it on their behalf -- handling gas, oracle price data, and batching for efficiency.

Base URLs

EnvironmentBase URL
Mainnethttps://mainnet.relayer.ryze.pro/api/v1
Testnethttps://sepolia.relayer.ryze.pro/api/v1

Endpoints

MethodPathDescription
POST/intents/submitSubmit a signed intent (swap, join, exit)
GET/intents/:intentIdGet intent execution status
GET/healthService health check

Intent Types

All intents go through the same /intents/submit endpoint. The type field determines the operation:

TypeDescriptionGuide
swapToken-to-token swap (single or multi-hop)Submit Swap
joinSingle-asset liquidity depositSubmit Join
joinProportionalMulti-asset proportional liquidity depositSubmit Proportional Join
exitProportionalProportional liquidity withdrawalSubmit Exit

How It Works

1. User gets a quote from the Router
2. User approves the MultiHopRouter to spend their tokens (ERC-20 approve)
3. User signs an EIP-712 intent message with their wallet
4. Frontend POSTs the signed intent to the Relayer
5. Relayer validates signature + nonce, queues the intent
6. Relayer batches intents, fetches oracle prices, executes on-chain
7. Frontend polls for status until confirmed

Authentication

No API keys. The relayer authenticates via EIP-712 signatures -- each intent must be signed by the user's wallet, proving they authorized the operation.

The signature field is a single hex string:

  • EOA wallets -- the 65-byte ECDSA signature (r‖s‖v) returned by signTypedData, submitted as-is.
  • Smart-contract wallets (ERC-1271) -- e.g. Safe multisigs: submit the wallet's contract signature bytes. The relayer (and the router on-chain) validate via isValidSignature(bytes32,bytes).

The legacy { "v": …, "r": …, "s": … } object format is still accepted for backward compatibility.

Smart-contract wallets can also skip the relayer entirely for liquidity operations: the router exposes caller-authorized joinSingle, joinProportional, and exitProportional functions that need no off-chain signature (the caller pays gas and the Pyth verification fee; no intent fee is charged).

Rate Limiting

  • 100 requests per minute per IP address
  • Returns HTTP 429 when exceeded

Common Prerequisites

Before submitting any intent:

1. Token Approval

The user must approve the MultiHopRouter contract to spend their input tokens:

javascript
import { erc20Abi } from 'viem';

const MULTIHOP_ROUTER = '0x8e20A1534a204DE569E9d62D410c19795b81DF70';

const hash = await walletClient.writeContract({
  address: tokenAddress,
  abi: erc20Abi,
  functionName: 'approve',
  args: [MULTIHOP_ROUTER, amountIn], // or MaxUint256 for unlimited
});
await publicClient.waitForTransactionReceipt({ hash });

2. Read Nonce

Each intent type has its own nonce counter on the contract. Read the current nonce before signing:

javascript
// For swaps
const nonce = await publicClient.readContract({
  address: MULTIHOP_ROUTER,
  abi: routerAbi,
  functionName: 'swapNonces',
  args: [userAddress],
});

// For single joins
const nonce = await publicClient.readContract({
  address: MULTIHOP_ROUTER,
  abi: routerAbi,
  functionName: 'joinNonces',
  args: [userAddress],
});

// For proportional joins
const nonce = await publicClient.readContract({
  address: MULTIHOP_ROUTER,
  abi: routerAbi,
  functionName: 'joinProportionalNonces',
  args: [userAddress],
});

// For exits
const nonce = await publicClient.readContract({
  address: MULTIHOP_ROUTER,
  abi: routerAbi,
  functionName: 'exitProportionalNonces',
  args: [userAddress],
});

3. EIP-712 Domain

All intent types share this domain:

javascript
const domain = {
  name: 'MultiHopRouter',
  version: '1',
  chainId: 8453, // Base mainnet (84532 for testnet)
  verifyingContract: '0x8e20A1534a204DE569E9d62D410c19795b81DF70',
};

Error Format

json
{
  "success": false,
  "status": "error",
  "message": "Verification failed: nonce mismatch: expected 1, got 0 (hint: use 1 for your next intent)"
}
CodeCommon Causes
400Invalid signature, nonce mismatch, expired deadline, bad path
429Rate limit exceeded
503Service unhealthy