> ## Documentation Index
> Fetch the complete documentation index at: https://docs.relay.link/llms.txt
> Use this file to discover all available pages before exploring further.

# Fast Fill

> Accelerate the destination fill of a cross-chain request

Fast Fill is a feature that allows you to accelerate the destination fill of a cross-chain request. This is useful if you want to speed up the completion of a bridge or swap operation before it's landed onchain.

## Requirements

Before you can start fast filling requests, you need:

1. **An API key** — Required to authenticate your fast fill requests. [Request an API key](/references/api/api-keys#how-to-get-an-api-key).
2. **Enterprise Partnership** — Reach out to the Relay team to become an Enterprise Partner. Learn more about the [Enterprise Partner Program](/resources/enterprise).
3. **A Linked Funding Address** — A wallet address must be linked to your API key. This is the address that will fund your app balance. [Reach out](https://forms.gle/XNeELYavjwoJwPEf7) to the Relay team to link your wallet address.
4. **Sufficient App Balance** — Your app balance must have enough funds to cover fast fills and fee sponsorship. When a fast fill is triggered, a hold is placed against your app balance for the fill amount. This hold is released once the user's deposit lands onchain. While holds are active, they reduce the balance available for new fast fills and claims, but do not block [fee sponsorship](/features/fee-sponsorship) deductions.

Once you're set up, you can begin fast filling requests.

***

## How to use it?

To Fast Fill a request you simply need to call the [Fast Fill API](/references/api/fast-fill) with the request ID of the request you want to fast fill after you've submitted it onchain but before it finalizes. When a fast fill is triggered, the transaction is instantly filled on the destination chain and a hold is placed against your app balance for the fill amount. Once the user's deposit lands onchain and Relay indexes it, the hold is released.

### Example

This example demonstrates the full fast fill flow: getting a quote, submitting the transaction onchain, calling the fast fill API, and monitoring the status.

<CodeGroup>
  ```typescript SDK expandable theme={null}
  import { getClient, createClient } from "@relayprotocol/relay-sdk";
  import { createWalletClient, createPublicClient, http } from "viem";
  import { base } from "viem/chains";

  // 1. Setup Wallet - Initialize your wallet using your preferred method
  const account = {}; // Your wallet account (e.g., privateKeyToAccount, or injected wallet)
  const wallet = createWalletClient({
    account,
    chain: base,
    transport: http(),
  });

  const publicClient = createPublicClient({
    chain: base,
    transport: http(),
  });

  // 2. Initialize the Relay client
  createClient({
    baseApiUrl: "https://api.relay.link",
    source: "YOUR_APP_NAME",
  });

  // 3. Get a quote using the SDK
  const quote = await getClient().actions.getQuote({
    chainId: 8453, // Base
    toChainId: 42161, // Arbitrum
    currency: "0x0000000000000000000000000000000000000000", // ETH
    toCurrency: "0x0000000000000000000000000000000000000000", // ETH
    amount: "100000000000000", // 0.0001 ETH
    tradeType: "EXACT_INPUT",
    wallet,
  });

  const requestId = quote.steps[0].requestId;
  console.log(`Request ID: ${requestId}`);

  // 4. Execute the quote and fast fill once the transaction is submitted
  let txHash: string;

  await getClient().actions.execute({
    quote,
    wallet,
    onProgress: async ({ currentStep, currentStepItem, txHashes }) => {
      // Once transaction is submitted, trigger fast fill immediately
      if (txHashes && txHashes.length > 0 && !txHash) {
        txHash = txHashes[0];
        console.log(`Transaction submitted: ${txHash}`);

        // 5. Call Fast Fill immediately after submitting (before waiting for confirmation)
        const fastFillResult = await getClient().actions.fastFill({
          requestId,
        });
        console.log("Fast fill initiated:", fastFillResult);
      }

      // Monitor progress
      if (currentStep && currentStepItem) {
        console.log(`Step: ${currentStep.action}, Status: ${currentStepItem.status}`);
      }
    },
  });

  console.log("Bridge completed successfully!");
  ```

  ```typescript API expandable theme={null}
  import { createWalletClient, createPublicClient, http, type Hex } from "viem";
  import { base } from "viem/chains";

  // 1. Setup Wallet - Initialize your wallet using your preferred method
  const account = {}; // Your wallet account (e.g., privateKeyToAccount, or injected wallet)
  const walletClient = createWalletClient({
    account,
    chain: base,
    transport: http(),
  });

  const publicClient = createPublicClient({
    chain: base,
    transport: http(),
  });

  const API_KEY = "YOUR_API_KEY"; // Required for fast fill

  // 2. Get a quote from the Relay API
  const quoteResponse = await fetch("https://api.relay.link/quote/v2", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      user: account.address,
      originChainId: 8453, // Base
      destinationChainId: 42161, // Arbitrum
      originCurrency: "0x0000000000000000000000000000000000000000", // ETH
      destinationCurrency: "0x0000000000000000000000000000000000000000", // ETH
      amount: "100000000000000", // 0.0001 ETH
      tradeType: "EXACT_INPUT",
    }),
  });

  const quote = await quoteResponse.json();
  const step = quote.steps[0];
  const item = step.items[0];
  const requestId = step.requestId;

  console.log(`Request ID: ${requestId}`);

  // 3. Submit the transaction on-chain
  const txHash = await walletClient.sendTransaction({
    to: item.data.to as Hex,
    data: item.data.data as Hex,
    value: BigInt(item.data.value),
  });

  console.log(`Transaction submitted: ${txHash}`);

  // 4. Call the Fast Fill API immediately after submitting (before waiting for receipt)
  // This accelerates the fill on the destination chain
  const fastFillResponse = await fetch("https://api.relay.link/fast-fill", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      requestId,
    }),
  });

  const fastFillResult = await fastFillResponse.json();
  console.log("Fast fill initiated:", fastFillResult);

  // 5. Now wait for the transaction receipt (origin chain confirmation)
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
  console.log(`Origin transaction confirmed in block ${receipt.blockNumber}`);

  // 6. Poll the status API to confirm the fill completed
  const checkStatus = async (): Promise<any> => {
    const statusResponse = await fetch(
      `https://api.relay.link/intents/status/v3?requestId=${requestId}`,
      {
        headers: { "Authorization": `Bearer ${API_KEY}` },
      }
    );
    return statusResponse.json();
  };

  // Poll until success
  let status = await checkStatus();
  while (status.status !== "success" && status.status !== "failure") {
    console.log(`Status: ${status.status}`);
    await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second
    status = await checkStatus();
  }

  if (status.status === "success") {
    console.log("Bridge completed successfully!");
    console.log(`Destination tx: ${status.txHashes?.[0]}`);
  } else {
    console.error("Bridge failed:", status);
  }
  ```
</CodeGroup>

<Info>
  You can use the **`maxFillAmountUsd`** parameter to set a maximum USD value for a fast fill request. If the request's value exceeds this limit, the fast fill will not be executed. This is useful for managing risk and controlling exposure, especially when dealing with volatile assets or large transaction volumes.
</Info>

***

## Funding Your App Balance

There are two ways to deposit funds to your app balance:

### Option 1: Use the Relay App UI

The simplest way to deposit funds is through the [Relay App Balance UI](https://www.relay.link/app-balance). This provides a user-friendly interface for managing your balance.

### Option 2: Direct On-Chain Deposit

You can programmatically deposit to your app balance by sending a transaction on Base to the Relay solver. This method involves appending specific calldata in place of the request ID to identify the deposit.

#### How It Works

When you transfer funds to the solver using specific calldata, Relay treats it as a deposit to your app balance. This method uses a fixed 12-character prefix and suffix (`012345abcdef`) with the middle portion specifying which address to credit:

**Calldata Format:**

```
0x[prefix][address-to-credit][suffix]
```

* **Prefix:** `012345abcdef`
* **Address to Credit:** The wallet address to deposit funds for (use `0000000000000000000000000000000000000000` for `msg.sender`)
* **Suffix:** `012345abcdef`

#### Examples

| Calldata                                                             | Behavior                                             |
| -------------------------------------------------------------------- | ---------------------------------------------------- |
| `0x012345abcdef0000000000000000000000000000000000000000012345abcdef` | Credits `msg.sender`                                 |
| `0x012345abcdefd5c0d17ccb9071d27a4f7ed8255f59989b9aee0d012345abcdef` | Credits `0xd5c0d17ccb9071d27a4f7ed8255f59989b9aee0d` |

<Tip>
  The ability to specify a different address is useful for building auto-topup systems or having more granular control over which accounts receive deposits.
</Tip>

#### Solver Address

Deposits should be sent to the Relay solver on Base:

| Network | Address                                      |
| ------- | -------------------------------------------- |
| Base    | `0xf70da97812cb96acdf810712aa562db8dfa3dbef` |

#### TypeScript Example

```typescript expandable theme={null}
import { erc20Abi, encodeFunctionData, createWalletClient } from 'viem'
import { base } from 'viem/chains'

const BASE_USDC_ADDRESS = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' as const
const RELAY_BASE_SOLVER_ADDRESS = '0xf70da97812cb96acdf810712aa562db8dfa3dbef' as const
const REQUEST_ID_PREFIX = '012345abcdef'

const walletClient = createWalletClient({
  chain: base,
  transport: custom(window.ethereum!),
})

const [userAddress] = await walletClient.getAddresses()

const amountInWei = '100000000' // 100 USDC

// Encode the transfer function call
const transferData = encodeFunctionData({
  abi: erc20Abi,
  functionName: 'transfer',
  args: [RELAY_BASE_SOLVER_ADDRESS, amountInWei]
})

// Add custom calldata to credit the wallet address
const customCalldata =
  `${REQUEST_ID_PREFIX}${userAddress.slice(2)}${REQUEST_ID_PREFIX}` as `0x${string}`

const hash = await walletClient.sendTransaction({
  to: BASE_USDC_ADDRESS,
  data: `${transferData}${customCalldata}`,
  account: userAddress,
  chain: base
})
```

***

## Checking Your App Balance

Verify your available balance using the [Get App Fee Balances](/references/api/get-app-fee-balances) API:

<CodeGroup>
  ```bash Request theme={null}
  curl --location 'https://api.relay.link/app-fees/{your-wallet-address}/balances'
  ```

  ```json Response theme={null}
  {
    "currency": {
      "chainId": 8453,
      "address": "0x0000000000000000000000000000000000000000",
      "symbol": "USDC",
      "name": "USDC",
      "decimals": 6
    },
    "amount": "75021651210714015",
    "amountFormatted": "0.075021651210714015",
    "amountUsd": "116.235557",
    "minimumAmount": "75021651210714015"
  }
  ```
</CodeGroup>

***

## Caveats

* Slippage may lead to a surplus or shortage in your app balance. If you have a good estimate of the final amount you can use the **`solverInputCurrencyAmount`** parameter to specify the exact amount of input currency you want to use for the fill, thus minimizing slippage.
* We recommend protecting your API key on the backend by not exposing it to the client.
* Fast Fill holds, outstanding fast fills that are waiting to be indexed on the destination chain, reduce the balance available for new fast fills and claims, but do not block fee sponsorship.
