# Get a fee quote from a relayer

> Ask a relayer what it'll cost to submit your transfer or withdrawal. The quote carries a signed fee commitment with an expiry.

## What this lets you do

Ask a [relayer](/operations/relaying) how much it'll cost to submit your private [transfer](/operations/transfer) or [withdrawal](/operations/withdraw) on-chain. The relayer returns a signed quote: a commitment that, if you submit before it expires, they'll relay your transaction at the named fee.

## Constraints & limits

-   **Quote expiry is short (typically 60 to 90 seconds).** Slow proof generation can outlast the quote. The SDK does not auto-retry, so request a fresh quote with `prepareTransfer` or `prepareWithdraw` and submit again. Handle both `FeeCommitmentExpired` and relayer-side rejections.
-   **The quote binds the fee, not the transfer.** The signed commitment covers the fee asset, fee amount, fee-split data, and expiration. Changing the asset invalidates the quote, while the transfer's recipient and amount are shielded and can change without re-quoting.
-   **Signed by the relayer.** The signature is what makes the quote binding. Don't trust unsigned "estimates" from a relayer, because only signed quotes give you the fee commitment.
-   **One quote per relayer.** If you want to compare across relayers, request from each independently. The SDK supports multiple `RelayerInfo` entries.

## What it unlocks next

-   [Submit via relayer](submit-via-relayer), since the standard flow uses the quote you just got.
-   Show the user the fee before they commit to generating the proof, which is a courtesy they'll appreciate when fees are surprisingly high.
-   Compare quotes across multiple relayers and pick the cheapest.

## How to use it

```ts
const quote = await relayerInteractor.getTransferQuote(relayers[0], {
    asset: tokenId,    // chainId comes from the relayer config, not the params
    commit: true,
});

console.log(`Relayer fee: ${formatUnits(BigInt(quote.feeAmount), decimals)} ${symbol}`);
console.log(`Valid until: ${new Date(quote.feeCommitment.expiration).toISOString()}`);
```

```ts
const quote = await relayerInteractor.getWithdrawalQuote(relayers[0], {
    asset: tokenId,                // chainId comes from the relayer config, not the params
    amount: withdrawAmount,
    recipient: publicDestination,
    extraGas: false,
    commit: true,
});

console.log(`Relayer fee: ${formatUnits(BigInt(quote.feeAmount), decimals)} ${symbol}`);
console.log(`Valid until: ${new Date(quote.feeCommitment.expiration).toISOString()}`);
```

Use these methods when you want a fee preview before preparing the full operation. Normal flows fetch a quote inside `prepareTransfer()` and `prepareWithdraw()` anyway. The chain comes from the relayer config rather than the params, and quote expiration is in milliseconds.

## Behind the scenes

SDK call `relayerInteractor.getTransferQuote(relayer, params)`, or `getWithdrawalQuote` for a withdrawal, invoked automatically by `prepareTransfer` and `prepareWithdraw`
Relayer endpoint `POST {relayer.url}/v1/quote/{chainType}/{chainId}/transfer`
What's signed The relayer signs the `feeCommitment`, covering the fee asset, the amount fields, the encoded fee-split `data` (recipient, fee recipient, fee amount, native gas), and the expiration. This `signedRelayerCommitment` is the binding signature.
