Executing Swaps
Execute swaps between stablecoins on the exchange. Swaps execute immediately against existing orders in the orderbook, providing instant liquidity for cross-stablecoin payments.
By the end of this guide you will be able to execute swaps, get price quotes, and manage slippage protection.
Execute a Swap
demoSteps
Set up your client
Ensure that you have set up your client by following the guide.
Get a price quote
Before executing a swap, get a quote to see the expected price.
import { Hooks } from 'tempo.ts/wagmi'
import { formatUnits, parseUnits } from 'viem'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'
function Buy() {
const amount = parseUnits('10', 6)
// How much AlphaUSD do I need to spend to receive 10 BetaUSD?
const { data: quote } = Hooks.dex.useBuyQuote({
tokenIn: alphaUsd,
tokenOut: betaUsd,
amountOut: amount,
})
return <div>Quote: {formatUnits(quote, 6)}</div>
}Calculate slippage tolerance
Set appropriate slippage based on your quote to protect against unfavorable price movements.
import { Hooks } from 'tempo.ts/wagmi'
import { formatUnits, parseUnits } from 'viem'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'
function Buy() {
const amount = parseUnits('10', 6)
// How much AlphaUSD do I need to spend to receive 10 BetaUSD?
const { data: quote } = Hooks.dex.useBuyQuote({
tokenIn: alphaUsd,
tokenOut: betaUsd,
amountOut: amount,
})
// Calculate 0.5% slippage tolerance
const slippageTolerance = 0.005
const maxAmountIn = quote
? quote * BigInt(Math.floor((1 + slippageTolerance) * 1000)) / 1000n
: 0n
return (
<div>
<div>Quote: {formatUnits(quote, 6)}</div>
<div>Max input (0.5% slippage): {formatUnits(maxAmountIn, 6)}</div> // [!code ++]
</div>
)
}Approve Spend
To execute a swap, you need to approve the Stablecoin DEX contract to spend the token you're using to fund the swap.
import { Actions, Addresses } from 'tempo.ts/viem'
import { Hooks } from 'tempo.ts/wagmi'
import { formatUnits, parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'
function Buy() {
const amount = parseUnits('10', 6)
// How much AlphaUSD do I need to spend to receive 10 BetaUSD?
const { data: quote } = Hooks.dex.useBuyQuote({
tokenIn: alphaUsd,
tokenOut: betaUsd,
amountOut: amount,
})
// Calculate 0.5% slippage tolerance
const slippageTolerance = 0.005
const maxAmountIn = quote
? quote * BigInt(Math.floor((1 + slippageTolerance) * 1000)) / 1000n
: 0n
const sendCalls = useSendCallsSync()
return (
<div>
<div>Quote: {formatUnits(quote, 6)}</div>
<div>Max input (0.5% slippage): {formatUnits(maxAmountIn, 6)}</div>
<button type="button" onClick={() => {
const calls = [
Actions.token.approve.call({
amount: maxAmountIn, // Approve the max amount with slippage
spender: Addresses.stablecoinExchange,
token: alphaUsd,
}),
]
sendCalls.sendCallsSync({ calls })
}}> // [!code ++]
Approve Spend // [!code ++]
</button> // [!code ++]
</div>
)
}Execute a swap
Batch the token approval with the swap in a single transaction for better UX.
import { Actions, Addresses } from 'tempo.ts/viem'
import { Hooks } from 'tempo.ts/wagmi'
import { formatUnits, parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'
function Buy() {
const amount = parseUnits('10', 6)
// How much AlphaUSD do I need to spend to receive 10 BetaUSD?
const { data: quote } = Hooks.dex.useBuyQuote({
tokenIn: alphaUsd,
tokenOut: betaUsd,
amountOut: amount,
})
// Calculate 0.5% slippage tolerance
const slippageTolerance = 0.005
const maxAmountIn = quote
? quote * BigInt(Math.floor((1 + slippageTolerance) * 1000)) / 1000n
: 0n
const sendCalls = useSendCallsSync()
return (
<div>
<div>Quote: {formatUnits(quote, 6)}</div>
<div>Max input (0.5% slippage): {formatUnits(maxAmountIn, 6)}</div>
<button type="button" onClick={() => {
const calls = [
Actions.token.approve.call({
amount: maxAmountIn, // Approve the max amount with slippage
spender: Addresses.stablecoinExchange,
token: alphaUsd,
}),
Actions.dex.buy.call({
amountOut: amount,
maxAmountIn,
tokenIn: alphaUsd,
tokenOut: betaUsd,
}),
]
sendCalls.sendCallsSync({ calls })
}}>
Execute Swap
</button>
</div>
)
}Recipes
Handling insufficient liquidity
Quote requests will fail with an InsufficientLiquidity error if there isn't enough liquidity in the orderbook to satisfy the requested amount.
Handle this error when fetching quotes:
import { Hooks } from 'tempo.ts/wagmi'
import { parseUnits } from 'viem'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'
function Swap() {
const amount = parseUnits('10', 6)
const { data: quote, error } = Hooks.dex.useSellQuote({
tokenIn: alphaUsd,
tokenOut: betaUsd,
amountIn: amount,
})
if (error) {
if (error.message.includes('InsufficientLiquidity')) {
return <div>Not enough liquidity available. Try a smaller amount.</div>
}
return <div>Error: {error.message}</div>
}
if (!quote) {
return <div>Loading quote...</div>
}
return <div>Quote: {quote.toString()}</div>
}Best Practices
Always get quotes before swapping
Query the expected price before executing a swap to ensure you're getting a fair rate and to set appropriate slippage protection.
Set appropriate slippage protection
Use minAmountOut or maxAmountIn to protect against unfavorable price movements between quoting and execution.