Quoting Swaps
The getSwapQuote function computes the output amount for a swap by solving the torus invariant. It handles tick crossings automatically.
Usage
import { getSwapQuote } from '@taurus-swap/sdk';
const quote = await getSwapQuote(poolState, {
tokenInIndex: 0, // Selling USDC
tokenOutIndex: 1, // Buying USDT
amountIn: 100_000_000n // 100 USDC (microunits)
});
console.log('Output:', quote.amountOut);
console.log('Price impact:', quote.priceImpact);
console.log('Fee:', quote.fee);SwapQuote Type
interface SwapQuote {
// Output
amountOut: bigint; // Amount of output token (microunits)
// Pricing
priceImpact: number; // Price impact as decimal (0.0014 = 0.14%)
effectivePrice: number; // Output/Input ratio
// Fees
fee: bigint; // Fee amount (in input token microunits)
feeBps: number; // Fee in basis points
// Path info
ticksCrossed: number; // Number of ticks crossed
segments: TradeSegment[]; // Trade path segments
// Validation
minOut: bigint; // Minimum output after slippage
}
interface TradeSegment {
amountIn: bigint;
amountOut: bigint;
tickCrossedId: number; // 0 if no crossing
newTickState: number;
}Field Descriptions
Output
amountOut— The exact output amount in microunits. Use this for the user's "You will receive" display.
Pricing
priceImpact— How much the trade moves the price. 0.0014 means 0.14% price slippage from mid-price.effectivePrice— The actual exchange rate: amountOut / amountIn. For stablecoin swaps, this should be close to 1.0.
Fees
fee— The fee amount in input token microunits. Deducted before the trade is computed.feeBps— Fee in basis points. 30 = 0.3%.
Path Info
ticksCrossed— Number of tick boundaries crossed. More crossings = more complex transaction.segments— The trade path. Each segment is a portion of the trade between crossings.
Validation
minOut— amountOut minus slippage tolerance. Pass this to the transaction builder.
Full Example with Slippage
const quote = await getSwapQuote(poolState, {
tokenInIndex: 0,
tokenOutIndex: 1,
amountIn: 100_000_000n
});
// Apply slippage tolerance (0.5% = 50 bps)
const SLIPPAGE_BPS = 50;
const minOut = quote.amountOut * (10000n - BigInt(SLIPPAGE_BPS)) / 10000n;
console.log(`Expected output: ${quote.amountOut} USDT`);
console.log(`Minimum output: ${minOut} USDT (${SLIPPAGE_BPS} bps slippage)`);
console.log(`Price impact: ${(quote.priceImpact * 100).toFixed(2)}%`);
// Warn if price impact is high
if (quote.priceImpact > 0.01) { // > 1%
alert('High price impact! Consider splitting into smaller trades.');
}Debouncing Quotes
In a React UI, debounce user input to avoid excessive quote requests:
import { useState, useEffect, useCallback } from 'react';
import { getSwapQuote, debounce } from '@taurus-swap/sdk';
function SwapForm({ poolState }: { poolState: PoolState }) {
const [amountIn, setAmountIn] = useState('');
const [quote, setQuote] = useState<SwapQuote | null>(null);
const fetchQuote = useCallback(
debounce(async (input: string) => {
if (!input || !poolState) return;
const amountIn = parseAmountToMicrounits(input, 6);
const q = await getSwapQuote(poolState, {
tokenInIndex: 0,
tokenOutIndex: 1,
amountIn
});
setQuote(q);
}, 300),
[poolState]
);
useEffect(() => {
fetchQuote(amountIn);
}, [amountIn, fetchQuote]);
return (
<input
value={amountIn}
onChange={(e) => setAmountIn(e.target.value)}
placeholder="Amount in"
/>
{quote && <div>You receive: {formatAmount(quote.amountOut)}</div>}
);
}Handling Stale State
Quotes are valid only for the pool state they were computed from. If the pool changes between quote and execution, the transaction may fail:
try {
const { txGroup } = await buildSwapTransactionGroup(
algodClient,
POOL_APP_ID,
account,
{
...tradeParams,
claimedOut: quote.amountOut,
minOut: quote.minOut
}
);
await sendTransaction(txGroup);
} catch (err) {
if (err.message.includes('invariant check failed')) {
// Pool state changed - re-quote and retry
const freshQuote = await getSwapQuote(freshPoolState, tradeParams);
// Retry with fresh quote...
}
}Large Trades
For trades that cross many ticks, the quote includes a trade recipe:
const quote = await getSwapQuote(poolState, {
tokenInIndex: 0,
tokenOutIndex: 1,
amountIn: 1_000_000_000n // 1000 USDC - large trade
});
console.log(`Crossing ${quote.ticksCrossed} ticks`);
console.log('Trade segments:', quote.segments);
// Use swap_with_crossings instead of swap
const method = quote.ticksCrossed > 0
? 'swap_with_crossings'
: 'swap';Note: The SDK automatically selects the correct method when you use buildSwapTransactionGroup. You don't need to handle this manually.