<!--
Sitemap:
- [Interop SDK Documentation](/index): Build multichain TypeScript apps with interoperable addresses, cross-chain quotes, transfer execution, and order tracking across providers.
- [Install Interop SDK](/installation): Install @wonderland/interop-addresses and @wonderland/interop-cross-chain, then choose the package that fits your multichain app.
- [Addresses Module](/addresses/): Parse, encode, and resolve chain-aware addresses that combine an account, chain, and optional ENS name into one unambiguous identifier.
- [Addresses: Getting Started](/addresses/getting-started): Parse an interoperable address and extract its components — go from a human-readable name like vitalik.eth@eip155:1 to address and chain ID.
- [Addresses: Concepts](/addresses/concepts): How EIP-7930, ERC-7828, and CAIP-350 combine address and chain into a single, unambiguous, validated identifier for multichain apps.
- [Parsing an Interoperable Name](/addresses/example): Walkthrough for wallet developers — extract the raw address and chain ID from an interop address so legacy contracts keep working.
- [Addresses: Advanced Usage](/addresses/advanced-usage): Advanced patterns for interoperable addresses — checksums, validation, error handling, and round-trip conversions between formats.
- [Addresses: API Reference](/addresses/api): Function signatures and types for the interop-addresses package — high-level helpers, name-layer methods, and binary-layer primitives.
- [Cross-Chain Module](/cross-chain/): One open source integration for cross-chain actions — compare quotes across providers, execute orders, and track completion.
- [Cross-Chain: Getting Started](/cross-chain/getting-started): Execute a cross-chain token transfer end-to-end — create a provider, fetch a quote, send the transaction, and track the order to completion.
- [Cross-Chain: Concepts](/cross-chain/concepts): The intent-based architecture behind the cross-chain package and how the SDK unifies heterogeneous bridge providers behind a common interface.
- [Supported Providers](/cross-chain/providers): Supported cross-chain providers (Across, Relay, OIF, Bungee, LiFi Intents) and how to configure each via createCrossChainProvider.
- [Across Provider](/cross-chain/across-provider): Configure and use the Across Protocol provider for cross-chain token transfers via the Across bridge infrastructure.
- [Relay Provider](/cross-chain/relay-provider): Configure and use the Relay Protocol provider for cross-chain transfers, including opt-in gasless execution via EIP-3009 signatures.
- [OIF Provider](/cross-chain/oif-provider): Direct integration with any OIF-compliant solver — submission modes, resource locks, and configuration for Open Intents Framework backends.
- [Bungee Provider](/cross-chain/bungee-provider): Cross-chain token transfers via Bungee — onchain transactions, gasless permit2 flow, and tier-based API access for sandbox or production.
- [LiFi Intents Provider](/cross-chain/lifi-intents-provider): Cross-chain transfers through the LI.FI intent solver marketplace, where competing solvers fulfill deposits at the best available rate.
- [Cross-Chain: Full Example](/cross-chain/example): End-to-end example of executing a cross-chain transfer — setup, quote, approval handling, transaction submission, and order tracking.
- [Cross-Chain: Frontend Integration](/cross-chain/frontend-integration): Wire the cross-chain SDK into a React/Next.js app with wagmi v2 — a useCrossChainSwap hook covering quotes, approvals, and submission.
- [Order Tracking](/cross-chain/order-tracking): Track cross-chain orders from initiation to completion via OIF OrderStatus events, with both onchain and offchain observation strategies.
- [Cross-Chain: Advanced Usage](/cross-chain/advanced-usage): Aggregator patterns for cross-chain transfers — multi-provider quote fetching, sorting strategies, timeouts, and built-in order tracking.
- [Cross-Chain: API Reference](/cross-chain/api): Function signatures and types for the interop-cross-chain package — providers, aggregator, approval service, and order tracking.
-->

# Relay Provider

The Relay Protocol provider enables cross-chain token transfers using the Relay bridge infrastructure.

**Status**: Active (mainnet + testnet)

## Configuration

| Field             | Type     | Required | Description                                                                                                                                                         |
| ----------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `baseUrl`         | string   | No       | Custom API base URL (overrides isTestnet)                                                                                                                           |
| `isTestnet`       | boolean  | No       | Use testnet API (default: false)                                                                                                                                    |
| `providerId`      | string   | No       | Custom provider identifier (default: "relay")                                                                                                                       |
| `apiKey`          | string   | No       | Relay API key for authentication                                                                                                                                    |
| `submissionModes` | string\[] | No       | Execution modes: `["user-transaction"]`, `["gasless"]`, or both (default: `["user-transaction"]`). Controls whether quotes request permit-based (gasless) execution |

:::info\[Gasless is opt-in — the default is `["user-transaction"]` only]

`submissionModes` defaults to `["user-transaction"]`. To enable gasless execution, explicitly opt in:

```typescript
submissionModes: ["user-transaction", "gasless"];
```

When both modes are configured, quotes are fetched in parallel and the aggregator handles either order type seamlessly, so opting in has no extra cost. For Relay, tokens that support EIP-3009 (e.g. USDC) are **fully gasless** — the quote returns only a signature step. Other ERC-20 tokens may still require a one-time approval transaction alongside the signature step.

:::

Notes:

* `baseUrl` overrides the URL derived from `isTestnet`.
* When `apiKey` is provided, it is sent as the `x-api-key` header on all requests.

## Creating the Provider

```ts twoslash
import { createCrossChainProvider } from "@wonderland/interop-cross-chain";

// Relay config is optional - defaults to mainnet
// Mainnet: https://api.relay.link
// Testnet: https://api.testnets.relay.link
const relayProvider = createCrossChainProvider("relay", { isTestnet: true });

// With API key
const relayWithKey = createCrossChainProvider("relay", {
    apiKey: "your-api-key",
});
```

## Getting Quotes

By default, the provider fetches quotes for the `"user-transaction"` mode only. To enable gasless execution, configure `submissionModes` to include `"gasless"` — e.g. `["user-transaction", "gasless"]`. When multiple modes are configured, quotes are fetched in parallel and if a mode is not available for the requested route, only the successful mode's quote is returned.

```typescript
const quotes = await relayProvider.getQuotes({
    user: "0xYourAddress",
    input: {
        chainId: 11155111,
        assetAddress: "0xInputTokenAddress",
        amount: "1000000000000000000", // 1 token (in wei)
    },
    output: {
        chainId: 84532,
        assetAddress: "0xOutputTokenAddress",
        recipient: "0xRecipientAddress",
    },
    swapType: "exact-input",
});

const quote = quotes[0]; // Select the first quote
```

## Fees

After getting a quote, you can inspect the standardized fee breakdown via `quote.fees`:

```typescript
const quote = quotes[0];

console.log(quote.fees?.bridgeFee); // { amount, amountUsd, token }
console.log(quote.fees?.bridgeFeePct); // percentage (wei-encoded, 1e18 = 100%)
console.log(quote.fees?.originGas); // origin chain gas estimate
```

See the [API reference](/cross-chain/api#quotefees) for the full `QuoteFees` type.

## Executing Transactions

Relay quotes always contain transaction steps. After getting a quote, execute the transaction:

```typescript
import { getTransactionSteps } from "@wonderland/interop-cross-chain";

const step = getTransactionSteps(quote.order)[0];
const hash = await walletClient.sendTransaction({
    to: step.transaction.to,
    data: step.transaction.data,
    value: step.transaction.value ? BigInt(step.transaction.value) : undefined,
    gas: step.transaction.gas ? BigInt(step.transaction.gas) : undefined,
});
console.log("Transaction sent:", hash);
```

## Permit Flow (Gasless)

When `submissionModes` includes `"gasless"`, the quote requests permit-based execution. Tokens supporting EIP-3009 (e.g. USDC) return only a signature step (fully gasless). Other ERC-20 tokens may still require a one-time approval transaction alongside the signature step. The user signs the EIP-712 typed data payload and submits it to Relay via `submitOrder`:

:::note
Only EIP-712 signature steps (Permit2, EIP-3009) are currently supported. If the Relay API returns an EIP-191 signature step, a `ProviderGetQuoteFailure` is thrown.
:::

```typescript
import { createCrossChainProvider, getSignatureSteps } from "@wonderland/interop-cross-chain";

const relayProvider = createCrossChainProvider("relay", { submissionModes: ["gasless"] });

const quotes = await relayProvider.getQuotes({
    user: "0xYourAddress",
    input: { chainId: 1, assetAddress: "0xUSDC", amount: "1000000" },
    output: { chainId: 10, assetAddress: "0xUSDC" },
});

const quote = quotes[0];

// The quote contains EIP-712 signature steps
const step = getSignatureSteps(quote.order)[0];
const { domain, types, primaryType, message } = step.signaturePayload;
const signature = await walletClient.signTypedData({ domain, types, primaryType, message });

// Submit the signed permit
const result = await relayProvider.submitOrder(quote, signature);
console.log("Order ID:", result.orderId);
```

## Tracking

Relay tracking is fully API-based — it does not require RPC URLs. The SDK polls the Relay API (`/intents/status/v3`) at 5-second intervals until the order is finalized or fails.

To start tracking, you need two values:

* **`orderId`** — found at `quote.tracking.orderId`. This is the identifier Relay uses to look up the order status.
* **`openTxHash`** — the bridge transaction hash from the [execution step](#executing-transactions) (not the approval hash).

```typescript
const orderId = quote.tracking?.orderId;
const tracker = executor.prepareTracking("relay");

for await (const item of tracker.watchOrder({
    orderId,
    openTxHash: hash, // from the execution step above
    originChainId: 11155111,
    destinationChainId: 84532,
})) {
    // Handle tracking updates
}
```

## Transaction Notification

Transaction notification is automatic — when tracking starts, the pre-tracker calls Relay's [transaction indexing](https://docs.relay.link/references/api/api_guides/transaction-indexing) via `POST /transactions/index`, accelerating the indexing process before transaction validation completes. No manual step is required.

## Next Step

See a complete working example: [Full Example](/cross-chain/example)

## References

* [Relay Protocol Documentation](https://docs.relay.link/)
* [API Reference](/cross-chain/api) — full type definitions for quotes, fees, and orders
* [Concepts](/cross-chain/concepts) — how intent-based transfers work
