> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://viem.sh/api/mcp` to find what you need.

# `withRelay`

Connects to a remote Tempo relay or applies relay plugins directly to a transport.

* [View Guide](https://docs.tempo.xyz/guide/payments/sponsor-user-fees)
* [View Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction)

In remote mode, `withRelay` forwards every `eth_fillTransaction` request to the relay and preserves the request's
`feePayer` value so the relay can decide whether to sponsor the transaction. It also forwards
owner approvals, config and operation reads, and operation-aware transaction lookups. The relay
can therefore own the shared account store instead of each client.

* `feePayer: true` asks the relay to sponsor the transaction.
* If `feePayer` is omitted, `undefined`, or `null`, that value is forwarded as-is.
* An explicit `feePayer` address is preserved.

Transaction and receipt lookups query the default transport first. If no result exists,
Viem asks the relay whether the hash identifies an account operation and routes a
matching operation lookup through the relay. Other lookups retain the default result.

## Usage

### Remote Mode

:::code-group
```ts twoslash [example.ts]
import { privateKeyToAccount } from 'viem/accounts'
import { createClient, http, withRelay } from 'viem/tempo'

// See https://viem.sh/tempo/guides/relay/run for instructions on running a relay.
const client = createClient({
  account: privateKeyToAccount('0x...'),
  testnet: true,
  transport: withRelay(
    http(),                             // ← Default Transport
    http('https://relay.example.com'),  // ← Relay Transport // [!code hl]
  ),
})

// Regular transaction
const receipt1 = await client.sendTransactionSync({
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
})

// Sponsored transaction // [!code hl]
const receipt2 = await client.sendTransactionSync({ // [!code hl]
  feePayer: true, // [!code hl]
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb', // [!code hl]
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
// [!include ~/snippets/tempo/viem.config.ts:setup]
```
:::

#### Example Relay Service

Connect to a relay configured with the
[fee-payer plugin](/tempo/relay/plugins/fee-payer) to sponsor requests.

:::code-group
```ts twoslash [client.ts]
import { privateKeyToAccount } from 'viem/accounts'
import { createClient, http, withRelay } from 'viem/tempo'

// See https://viem.sh/tempo/guides/relay/run for instructions on running a relay.
const client = createClient({
  account: privateKeyToAccount('0x...'),
  testnet: true,
  transport: withRelay(
    http(),
    http('http://localhost:3000'),
  ),
})

const hash = await client.sendTransactionSync({
  feePayer: true,
  to: '0x0000000000000000000000000000000000000000',
})
```
:::

### Local Mode

```ts twoslash
import { createClient, http } from 'viem'
import { tempo } from 'viem/chains'
import { Relay, Store, withRelay } from 'viem/tempo'

const client = createClient({
  chain: tempo,
  transport: withRelay(http(), { // [!code focus]
    plugins: [Relay.accounts({ store: Store.memory() })], // [!code focus]
  }), // [!code focus]
})
```

Local plugins wrap the default transport directly. See the [available plugins](/tempo/guides/relay/connect#connect-to-a-local-relay)
for sponsorship, fee-token resolution, simulation, and account coordination.
Memory storage is process-local; clients for independent owners must share persistent atomic
storage.

## Return Type

Remote mode returns `Transport<'relay', { accounts: true }>`, plus `keyAuthorization: true`
when that option is set. Local mode preserves the default transport's attributes and RPC
schema. It advertises account coordination when an accounts plugin or the underlying
transport provides it, and key authorization storage when a key authorization plugin
is configured.

## Parameters

### defaultTransport

* **Type:** `Transport`

The execution transport. Local mode wraps this transport directly. Remote mode
uses it for ordinary requests and broadcasting with the `sign-only` policy.

### relayTransport

* **Type:** `Transport | Transport.withRelay.LocalOptions`

Pass a transport to connect to a remote relay, or an options object to run plugins
locally. Plugins run in array order; an empty array forwards requests unchanged.
Local options also accept `resolveTokens`, shared by fee selection and sponsorship.

### parameters.keyAuthorization

* **Type:** `boolean`
* **Default:** `false`

Available only in remote mode. Set to `true` when the relay runs the
[Key Authorization plugin](/tempo/relay/plugins/key-authorization), so
[`accessKey.signAuthorization`](/tempo/actions/accessKey.signAuthorization) saves
signed authorizations to the relay.

```ts twoslash
import { createClient, http } from 'viem'
import { tempo } from 'viem/chains'
import { withRelay } from 'viem/tempo'

const client = createClient({
  chain: tempo,
  transport: withRelay(http(), http('https://relay.example.com'), {
    keyAuthorization: true, // [!code focus]
  }),
})
```

### parameters.policy

* **Type:** `'sign-only' | 'sign-and-broadcast'`
* **Default:** `'sign-only'`

Available only in remote mode. For sponsored uncoordinated transactions,
`sign-only` requests a signature from the relay and broadcasts through the default
transport. `sign-and-broadcast` submits through the relay. Coordinated account
submissions always use the relay.
