Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Quotes and Fees

Read this page after Send a Transaction. It explains the quote on a prepared transfer and what your interface should check before execution.

Pricing is owned and signed by the Mirage API. The SDK does not calculate fees, gas budgets, or reward amounts locally. It requests a quote and uses the returned service fee, funding requirements, and sealed authorization exactly as given.

A prepared transfer carries that quote on .fees. All amounts are bigint values in raw token units.

const prepared = await prepareTransfer({ /* ... */ });
const { fees } = prepared;
 
fees.serviceFee;     // one public { asset, amount } quote
fees.rewardAsset;    // escrow reward denomination
fees.rewardAmount;   // the complete reward pot
fees.depositByAsset; // exact principal plus reward funding, keyed by asset
fees.msgValue;       // exact native amount supplied at deployment

serviceFee is an AssetAmount, so read the number from serviceFee.amount and its denomination from serviceFee.asset.

console.log(
  `Service fee: ${formatUnits(fees.serviceFee.amount, token.decimals)} ${token.symbol}`,
);

Funding requirements

depositByAsset is the exact amount of each asset the quote requires, covering principal plus the reward pot. ERC-20 entries are what the approval step approves; the native entry is sent as msgValue during deployment.

for (const [asset, amount] of Object.entries(fees.depositByAsset)) {
  const balance = await getTokenBalance(asset, account, publicClient);
  if (balance < amount) {
    throw new Error(`Insufficient balance for ${asset}`);
  }
}

Approvals are for the exact quoted amount, not an unbounded allowance. assetRequirements remains available as a per-asset view of the transfer and escrow amounts.

Quotes are locked once approval begins

refreshFees re-requests a quote, and updateTransfers replaces amounts and recipients while keeping the prepared row layout.

const fresh = await prepared.refreshFees();
const updated = await prepared.updateTransfers(newRows);

Both throw INVALID_STAGE once an approval has been broadcast, a checkpoint exists, or the escrow is deployed. From that point, the deployed constructor is bound to a specific quote, and the transfer must proceed with it or be canceled.