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

# `Relay.funding`

Infers requested token balances and discovers omitted funding sources before filling a transaction with gas, fees, and a nonce.

## Usage

```ts
import { createClient, http, parseUnits } from 'viem'
import { tempo } from 'viem/chains'
import { Addresses, tempoActions, Relay, withRelay } from 'viem/tempo'
import { account } from './account'
import { store } from './store'

const client = createClient({
  account,
  chain: tempo,
  transport: withRelay(http(), { plugins: [Relay.funding({ store })] }),
}).extend(tempoActions())

// Infer the required balance and discover sources before signing.
await client.token.transferSync({
  amount: parseUnits('50', 6),
  requireFunds: true,
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
  token: Addresses.pathUsd,
})
```

The account must hold a fee token or use a fee payer. Funding supplies application balances, not transaction fees.

## Compose with Other Plugins

Funding works independently. Add `feePayer` for sponsorship, `feeToken` for fee-token selection, or `simulate` for a preview that includes funding source execution.

```ts
import { http } from 'viem'
import { Relay, Store, withRelay } from 'viem/tempo'
import { sponsor } from './sponsor'

const store = Store.memory()
const transport = withRelay(http(), {
  plugins: [
    Relay.funding({ store }),
    Relay.feePayer({ account: sponsor }),
    Relay.feeToken(),
    Relay.simulate({ store }),
  ],
  resolveTokens: async (chainId) => [
    '0x20c0000000000000000000000000000000000000',
    '0x20c0000000000000000000000000000000000001',
  ],
})
```

Place funding before fee-payer sponsorship so it resolves requirements even for fully prepared transactions. Place multisig coordination first when needed. The shared `resolveTokens` callback runs at most once per request and chain, even when fee selection and funding inference both need it. Sharing a store also shares cached token metadata between fee selection and simulation.

Known transfer and burn calls skip inference simulation and token resolution. An owner transfer with omitted sources needs one discovery `eth_call` followed by the requested RPC. Explicit requirements and sources skip discovery too. `simulate` adds a separate preview of the final funded transaction; inference uses temporary balances and cannot substitute for that preview.

## Parameters

### getRoute

* **Type:** `({ chainId, token, transaction }) => Route | undefined | Promise<Route | undefined>`

`transaction` is the unsigned RPC request. Use `transaction.from` to select routes for the funding account; it contains an address, not a local signer.

Optional callback returning ordered source configurations and `slippageBps` for a chain and output token. The token address is checksummed. Return `undefined` to reject discovery for that pair. Explicit sources bypass the callback.

By default, mainnet and testnet use Viem's known tokens with the same currency as the output, excluding the output itself. Localnet uses PathUSD, AlphaUSD, BetaUSD, and ThetaUSD. Inputs have no source-specific cap. Unknown output tokens and other chains, including Zones, require a custom callback.

```ts
import { http } from 'viem'
import { Addresses, FundingSource, Relay, withRelay } from 'viem/tempo'
import { store } from './store'

withRelay(http(), {
  plugins: [
    Relay.funding({
      store,
      getRoute: async ({ chainId, token }) => {
        if (chainId !== 42431 || token !== Addresses.pathUsd) return undefined
        return {
          slippageBps: 100,
          sources: [FundingSource.dex({ tokenIn: Addresses.alphaUsd })],
        }
      },
    }),
  ],
})
```

Explicit transaction slippage takes precedence over the route default. If both are omitted, slippage is zero. Each requirement has its own aggregate tolerance. Known tokens are discovery inputs, not a guarantee of balances, liquidity, or deployed funding support.

The transport passes the client's configured chain ID to the handler. The handler uses the explicit request-option chain ID or the transaction's chain ID and rejects conflicts. When neither is supplied, it defaults to Tempo mainnet (4217). Discovery and filling receive the resolved chain ID in request options.

### policyId

* **Type:** `bigint`

Default policy selected when key authorization specifies `fundingPolicy: true`. The handler checks that the policy exists on the requested chain. Explicit policy IDs and inline policies bypass default selection.

```ts
import { http } from 'viem'
import { Relay, withRelay } from 'viem/tempo'
import { store } from './store'

withRelay(http(), { plugins: [Relay.funding({ policyId: 1n, store })] })
```

The policy must already exist. Supply its current rules through `policyRules` or register them in the store for automatic funding. Its administrators can update the rules that apply to attached access keys.

### policyRules

* **Type:** `FundingPolicy.Rules`

Fallback policy rules for access-key funding when the request and store do not supply them. The handler verifies their hash against the policy's current onchain commitment before using and caching them. A mismatch rejects the request.

```ts
import { http } from 'viem'
import { Addresses, FundingSource, Store, Relay, withRelay } from 'viem/tempo'

withRelay(http(), {
  plugins: [
    Relay.funding({
      policyId: 1n,
      policyRules: {
        maxSlippageBps: 0,
        sources: {
          [Addresses.pathUsd]: [
            FundingSource.dex({ tokenIn: Addresses.alphaUsd }),
          ],
        },
      },
      store: Store.memory(),
    }),
  ],
})
```

Request-supplied rules take precedence, followed by registered rules matching the current commitment, then configured rules. Update the configured rules or register new rules when the policy changes. This option does not create a policy or change owner funding routes.

### store

* **Type:** `Store.Store`

Optional store for funding policy rules. Defaults to an in-memory store. Use a long-lived persistent store to retain rules across restarts. Rules are keyed by chain, policy contract, and rules hash; each request still reads the policy's current commitment.

```ts
import { http } from 'viem'
import { Relay, withRelay } from 'viem/tempo'
import { store } from './store'

withRelay(http(), { plugins: [Relay.funding({ store })] })
```

### tokens

* **Type:** `readonly Address[]`

Additional TIP-20 output tokens to include in the first inference simulation. The shared `resolveTokens` callback supplies additional candidates, defaulting to known tokens on the selected chain. Missing tokens can be discovered through insufficient-balance retries. This option does not configure funding sources or grant access-key permissions.

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

const store = Store.memory()
// ---cut---

withRelay(http(), {
  plugins: [
    Relay.funding({
      store,
      tokens: ['0x20c0000000000000000000000000000000000004'], // [!code focus]
    }),
  ],
})
```

## Behavior

Funding resolution applies to `eth_fillTransaction`, `eth_call`, and `eth_estimateGas`. Calls and estimates use their requested block and state overrides for discovery and leave onchain balances unchanged.

Set `requireFunds: true` to infer requirements from the transaction calls. Partial entries such as `{ sources }` or `{ token, sources }` are also supported.

Omitted token and amount fields are resolved from recognized single-transfer, burn, or exact-input DEX calldata when possible, including zero amounts. For `true`, recognized transfer and burn batches also skip simulation. Other calls use simulation, including swaps that may spend internal DEX balances.

Explicit fields always take precedence. When simulation finds multiple tokens, each partial entry must specify its token. A missing or ambiguous match fails; supply both `token` and `amount` to resolve it.

When simulation is needed, the transport runs the complete batch with temporary sender balances for known and configured TIP-20 tokens. If a TIP-20 reports an insufficient balance, the transport adds or increases that token's override and retries from the same block state. Discovery stops after 16 attempts, a repeated failure without execution progress, or an unrelated error.

Successful simulation logs determine each token's peak cumulative outflow minus inflow. Sending 100 tokens, receiving 90 back, then sending 20 requires a starting balance of 100, even though net spending is only 30. Each inferred amount is a total target balance; funding sources supply the shortfall after existing funds.

Inference stops at the first successful simulation. The transport then discovers sources and forwards the concrete requirements for the requested RPC operation. Simulations do not change onchain state.

:::warning
Inference is intended for fixed-amount TIP-20 operations. Supply explicit token and amount requirements for balance-dependent calls, including “spend everything,” or when simulation cannot infer the intended operation. Missing approvals, permissions, funding routes, and source liquidity still cause failure. Multisig transactions require explicit requirements and sources.
:::

* Omitted `requireFunds` and `[]` perform no automatic funding.
* Omitted `sources` use the output token's configured route. A missing route fails.
* Explicit sources, including `[]`, retain their order, caps, and data.
* Discovery precedes gas estimation and signing. Discovery does not reserve funds.
* Filling errors are propagated. Incomplete requirements cannot fall back to signing.

## Return Value

A relay plugin for `withRelay`, `Relay.create`, or `Relay.handleRequest`. Local `withRelay` transports retain their original metadata and advertise `funding: true`.
