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

Pricing

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 cancelled.