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

# Fast fill

> A transfer that lands in seconds. BRDG asks every venue with a fast lane, checks what the wallet can pay for, and builds the one that delivers the most.

A fast fill lands in seconds. The venue's solver pays the user on the destination from its own liquidity right away, instead of waiting for the source chain to finalise. BRDG aggregates every venue with a fast lane and ranks them by what the user receives, like the ordinary quote.

There are two kinds of fast lane:

* **Gasless.** The user signs one EIP-712 message and a relayer sends the source transaction and pays its gas. The gas is charged in the token you send and is already taken off every quoted amount. Relay's relayer submits Relay fast fills. Across fast fills are sponsored by BRDG: BRDG's relayer submits the deposit to Across's `SpokePoolPeriphery`, and the user's signed USDC covers that gas plus the platform fee in the same transaction. The quote shows this as one `Fast fill fee` line, and BRDG refuses any amount where that fee would exceed 5%.
* **Sent by the user.** Mayan Swift is a solver fill too, usually about 3 seconds, but the user sends the source transaction and pays its gas. BRDG offers it only when the wallet can: see [the gas check](#the-gas-check).

A fast fill is never private. Fast fill and `privacy: true` cannot be combined.

## How BRDG aggregates fast fills

1. `POST /fastfill/quote` asks only the venues with a fast lane: Relay, Across and Mayan. Every other venue is left out silently.
2. Each venue quotes its fast form only: Relay its gasless permit order where the token has one, otherwise its ordinary solver fill sent by the user (native tokens, and every Solana source); Across the sponsored deposit; Mayan its Swift route (never its slower CCTP or Wormhole routes). A venue that has no fast form for the pair answers `no_route`.
3. BRDG reads the `sender`'s native balance on the source chain once, and refuses any row the user sends (Mayan, or Relay without a permit) that the wallet cannot pay gas for.
4. The answers are ranked by what the user receives, exactly as in `POST /bridge/quote`. `best` is the winner, and `rejected` lists every venue that did not quote, with its reason.

### The gas check

A row the user sends needs gas on the source chain. BRDG compares `sender`'s native balance with the venue's own gas estimate for that route (on Solana, the rent the swap accounts need). If the balance is short, the row is refused with `insufficient_gas` and appears in `rejected`. If the venue gives no estimate, any balance at all passes. If the balance cannot be read, nothing is refused and the wallet itself refuses a send it cannot afford. Gasless rows are never checked.

## Supported

| | Support |
| - | - |
| Venues | Relay (gasless where the token has a permit, else sent by the user), Across (gasless, sponsored by BRDG) and Mayan Swift (sent by the user), ranked against each other by what the user receives |
| Source chains | Relay: the EVM chains it serves (Ethereum, Base, Arbitrum, Optimism, Polygon and others) and Solana. Across: Ethereum, Base, Arbitrum, Optimism and Polygon. Mayan: EVM chains and Solana |
| Source tokens | Relay: USDC with one signature; other ERC-20 tokens (WETH, USDT, cbBTC and more) after a one-time `approve` to Permit2, which the wallet sends and pays gas for once; native tokens and Solana tokens as one ordinary transaction. Across: native USDC only. Mayan: tokens and native SOL that Swift accepts |
| Destinations | Any chain and token the winning venue delivers to, Solana and `hypercore` included. See [Hyperliquid](#hyperliquid) |
| Wallets | Standard wallets (EOAs). Smart contract wallets are refused with `smart_wallet_unsupported` on the gasless lane |

## Hyperliquid

`toChain: "hypercore"` works on the fast lane, with both kinds of Hyperliquid route ranked together exactly as in [`POST /bridge/quote`](https://docs.brdg.now/concepts/hyperliquid):

* **Direct.** The venue credits the Hyperliquid account straight from the source chain. Relay and Mayan Swift both do, and a direct Relay row needs no gas from the user where the token has a permit.
* **Through Arbitrum.** The venue delivers USDC to Arbitrum and BRDG's relayer credits the account. The row carries `postStep: { kind: "hypercore_deposit", chain: "arbitrum", vm: "evm" }`, and your user signs nothing after the source step - whether that step was a signature or a transaction. The relayer charges its gas plus 10 cents, capped at \$1, already inside the quoted output.

The Hyperliquid minimum applies here as everywhere: a row that would credit less than 1 USDC, or less than 5.10 USDC into an account with no history, is listed in `rejected` with `code: "below_min"` and the amount it would have delivered.

A `hypercore` **source** quotes but no venue serves it fast yet, so the table comes back empty with `emptyReason: "no_fast_fill_route"` and Relay's own reason in `rejected`. Use [`POST /bridge/quote`](https://docs.brdg.now/api-reference/quote/quote) to bridge out of Hyperliquid.

## How it works

**1. Quote**

`POST /fastfill/quote` asks only the venues with a fast fill lane and ranks them by what the user receives.

**2. Build**

`POST /fastfill/build` returns `steps` for the winner. On the gasless lane the last step is `{ vm: "sign", scheme: "eip712", payload }`: sign `payload.domain`, `payload.types`, `payload.primaryType` and `payload.message` with the wallet in `payload.owner`, using `eth_signTypedData_v4`. Do not sign `payload.venueSubmit`; it is the venue's own handle. Any other step (an `approve`, a Relay order without a permit, or a Mayan order, as `vm: "evm"` or `vm: "svm"`) is an ordinary transaction: send it and wait for it to be mined. A Solana step arrives already signed by Mayan's own keys, so add the wallet's signature without changing the blockhash or adding instructions.

**3. Submit**

A signature goes to `POST /fastfill/transfers/{id}/submit` with `{ signature }`. BRDG checks that it belongs to `owner` and covers exactly the built message, then hands it to the venue. A transaction goes to [`POST /bridge/transfers/{id}/submit`](https://docs.brdg.now/api-reference/quote/submit) with the step's own `step` (`approve` or `main`).

**4. Track**

[`GET /bridge/transfers/{id}`](https://docs.brdg.now/api-reference/quote/transfer), like any transfer. If the submit answered `txHash: null`, the relayer holds the signature and has not broadcast yet; BRDG keeps tracking it and fills in `sourceTxHash` when the venue reports it.

## Script

This script sends 10 USDC from Base to Arbitrum on whichever fast lane wins. On the gasless lane it spends no ETH; if Mayan wins, the wallet sends one transaction. It uses the [TypeScript project](https://docs.brdg.now/guides/typescript-setup.md); save it as `src/fast-fill.ts` and run `npx tsx src/fast-fill.ts`.

```typescript src/fast-fill.ts theme={null}
import type { Hex } from 'viem';
import { account, brdg, signEvmStep } from './evm';

const API = 'https://api.brdg.now/v1';

async function post<T>(path: string, body: unknown): Promise<T> {
  const response = await fetch(`${API}${path}`, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify(body),
  });
  const json = await response.json();
  if (!response.ok) throw new Error(`${json.error.code}: ${json.error.message}`);
  return json as T;
}

async function main() {
  // 1. Quote. Only fast fill venues compete; Mayan only if the wallet holds gas.
  const quote = await post<any>('/fastfill/quote', {
    fromChain: 'base',
    toChain: 'arbitrum',
    fromToken: 'USDC',
    toToken: 'USDC',
    amountAtomic: '10000000',
    sender: account.address,
  });
  if (!quote.best) throw new Error(quote.emptyReason ?? 'no fast fill route');
  console.log(`${quote.best.venue} delivers ${quote.best.amountOutAtomic} in ~${quote.best.estimatedSeconds}s`);

  // 2. Build
  const build = await post<any>('/fastfill/build', { decisionId: quote.decisionId });

  // 3. Transactions first: a one time approve to Permit2, or the Mayan order itself
  for (const step of build.steps) {
    if (step.vm !== 'evm') continue;
    const hash = await signEvmStep(step);
    await brdg.submitTransfer(build.transferId, { txHash: hash, step: step.step });
  }

  // 4. On the gasless lane, sign the message. No transaction, no gas.
  const sign = build.steps.find((step: any) => step.vm === 'sign');
  if (sign) {
    const { domain, types, primaryType, message } = sign.payload;
    const signature: Hex = await account.signTypedData({ domain, types, primaryType, message });

    // 5. Submit the signature
    const submitted = await post<any>(`/fastfill/transfers/${build.transferId}/submit`, { signature });
    console.log(submitted.status, submitted.txHash);
  }

  // 6. Wait for delivery
  const transfer = await brdg.waitForTransfer(build.transferId, {
    onUpdate: (t) => console.log(t.status),
  });
  console.log(transfer.status, transfer.receivedAmountAtomic);
}

main().catch((e) => { console.error(e); process.exit(1); });
```

## Errors

| Code | Status | Meaning and what to do |
| - | - | - |
| `fast_fill_not_private` | 400 | `privacy: true` was sent. A fast fill is never private. |
| `not_fast_fill` | 409 | The `decisionId` or transfer did not come from a fast fill quote. Use the ordinary build and submit. |
| `signature_mismatch` | 400 | The signature is not `owner`'s over this build's message. Nothing was sent. Sign `payload` again with the wallet in `owner`. |
| `smart_wallet_unsupported` | 400 | The signature came from a smart contract wallet. Use a standard wallet, or the ordinary route. |
| `fast_fill_already_signed` | 409 | This transfer already has a different signature. Submit that one again. |
| `submit_in_progress` | 409 | Another submit for this transfer is running. Retry after `retryAfterMs`. |
| `fast_fill_refused` | 409 | The venue refused the signature and nothing was sent. Quote and build again. |
| `fast_fill_unknown_result` | 502 | The venue did not answer and may hold the signature. Submit the same signature again; it is never sent twice. |
| `insufficient_gas` | in `rejected` | A venue the user sends (Mayan) was skipped because `sender` cannot pay the source gas. Fund the wallet, or take a gasless row. |
| `fast_fill_submit` | 409 | A transfer submit was sent for a fast fill's message. Use `POST /fastfill/transfers/{id}/submit`. |
| `build_expired` | 409 | The message expired before it was signed. Quote and build again. |

## Fees and referrals

The [platform fee](https://docs.brdg.now/concepts/fees.md) works exactly as it does on `POST /bridge/quote` and is already inside every output amount. Both referral fields are accepted here too:

| Field | On a fast fill |
| - | - |
| `referralCode` | Your user's BRDG code. 10% off the platform fee and points for the code's owner, exactly as on the ordinary quote. |
| `referralWallet` + `referralBps` | Your own [integrator share](https://docs.brdg.now/concepts/referrals.md), both or neither, `0` to `15`. Paid on rows the user sends; `0` on rows the venue relays. |

A fast fill the venue relays is gasless: the user signs a message and the venue's relayer sends the source transaction, so there is nothing of the user's for an integrator payout to ride in. Those rows come back with `referralFeeAmountAtomic: "0"` and `fees.referral: null`, rather than quoting a share that would never be paid. A fast fill the user sends (Mayan Swift, and Relay on native and Solana sources) pays your share in that transaction like any other transfer.

## Endpoints used

| Step | Endpoint |
| - | - |
| Quote | [`POST /fastfill/quote`](https://docs.brdg.now/api-reference/fastfill/quote) |
| Build | [`POST /fastfill/build`](https://docs.brdg.now/api-reference/fastfill/build) |
| Approve, first time only | [`POST /bridge/transfers/{id}/submit`](https://docs.brdg.now/api-reference/quote/submit) |
| Submit the signature | [`POST /fastfill/transfers/{id}/submit`](https://docs.brdg.now/api-reference/fastfill/submit) |
| Track | [`GET /bridge/transfers/{id}`](https://docs.brdg.now/api-reference/quote/transfer) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.