<!-- tempo-docs-context -->
> Source: [/docs/guide/stablecoin-dex/executing-swaps](https://tempo.xyz/developers/docs/guide/stablecoin-dex/executing-swaps.md)
> Section: [Tempo EVM](https://tempo.xyz/developers/docs/development.md). Build on Tempo EVM: wallets and keys, transactions and fees, TIP-20 Tokens, contracts, exchange, network details, nodes, protocol specifications, and changelog.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

<span id="executing-swaps-on-the-tempo-stablecoin-dex" />

# Swap stablecoins

Swap stablecoins against existing orders in the Stablecoin DEX orderbook. Get a quote and set a slippage limit before submitting the transaction. The examples use AlphaUSD and BetaUSD on Moderato testnet.

**Interactive demo: Execute a Swap**

1. Connect
2. Add funds
3. Make swaps

Source: [tempoxyz/examples/tree/main/examples/exchange](https://github.com/tempoxyz/examples/tree/main/examples/exchange)

## Swap implementation steps

::::steps
### Set up your swap client

Ensure that you have set up your client by following the [guide](https://tempo.xyz/developers/docs/sdk/typescript).

<span id="stablecoin-swap-best-practices" />

<span id="always-get-quotes-before-swapping" />

### Get a price quote

Before executing a swap, get a quote to see the expected price.

:::code-group
```tsx twoslash [Buy.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
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? // [!code hl]
  const { data: quote, error } = Hooks.dex.useBuyQuote({ // [!code hl]
    tokenIn: alphaUsd, // [!code hl]
    tokenOut: betaUsd, // [!code hl]
    amountOut: amount, // [!code hl]
  }) // [!code hl]

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return <div>Quote: {formatUnits(quote, 6)}</div>
}
```

```tsx twoslash [Sell.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
import { formatUnits, parseUnits } from 'viem'

const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'

function Sell() {
  const amount = parseUnits('10', 6)

  // How much BetaUSD will I receive for 10 AlphaUSD? // [!code hl]
  const { data: quote, error } = Hooks.dex.useSellQuote({ // [!code hl]
    tokenIn: alphaUsd, // [!code hl]
    tokenOut: betaUsd, // [!code hl]
    amountIn: amount, // [!code hl]
  }) // [!code hl]

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return <div>Quote: {formatUnits(quote, 6)}</div>
}
```
:::

<span id="set-appropriate-slippage-protection" />

### Calculate slippage tolerance

Set appropriate slippage based on your quote to protect against unfavorable price movements.

:::code-group
```tsx twoslash [Buy.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
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, error } = Hooks.dex.useBuyQuote({
    tokenIn: alphaUsd,
    tokenOut: betaUsd,
    amountOut: amount,
  })

  // [!code ++] Calculate 0.5% slippage tolerance 
  const slippageBps = 50n // [!code ++]
  const maxAmountIn = quote // [!code ++]
    ? (quote * (10_000n + slippageBps) + 9_999n) / 10_000n // [!code ++]
    : 0n // [!code ++]

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return (
    <div>
      <div>Quote: {formatUnits(quote, 6)}</div>
      <div>Max input (0.5% slippage): {formatUnits(maxAmountIn, 6)}</div> {/* [!code ++] */}
    </div>
  )
}
```

```tsx twoslash [Sell.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
import { formatUnits, parseUnits } from 'viem'

const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'

function Sell() {
  const amount = parseUnits('10', 6)

  // How much BetaUSD will I receive for 10 AlphaUSD?
  const { data: quote, error } = Hooks.dex.useSellQuote({
    tokenIn: alphaUsd,
    tokenOut: betaUsd,
    amountIn: amount,
  })

  // [!code ++] Calculate 0.5% slippage tolerance
  const slippageBps = 50n // [!code ++]
  const minAmountOut = quote // [!code ++]
    ? quote * (10_000n - slippageBps) / 10_000n // [!code ++]
    : 0n // [!code ++]

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return (
    <div>
      <div>Quote: {formatUnits(quote, 6)}</div>
      <div>Min output (0.5% slippage): {formatUnits(minAmountOut, 6)}</div> {/* [!code ++] */}
    </div>
  )
}
```
:::

### Approve stablecoin spend

To execute a swap, you need to approve the Stablecoin DEX contract to spend the token you're using to fund the swap.

:::code-group
```tsx twoslash [Buy.tsx]
// @noErrors
import { Actions, Addresses } from 'viem/tempo' // [!code ++]
import { Hooks } from 'wagmi/tempo'
import { formatUnits, parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi' // [!code ++]

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, error } = Hooks.dex.useBuyQuote({
    tokenIn: alphaUsd,
    tokenOut: betaUsd,
    amountOut: amount,
  })

  // Calculate 0.5% slippage tolerance
  const slippageBps = 50n
  const maxAmountIn = quote
    ? (quote * (10_000n + slippageBps) + 9_999n) / 10_000n
    : 0n

  const sendCalls = useSendCallsSync() // [!code ++]

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return (
    <div>
      <div>Quote: {formatUnits(quote, 6)}</div>
      <div>Max input (0.5% slippage): {formatUnits(maxAmountIn, 6)}</div>
      <button type="button" disabled={sendCalls.isPending} onClick={() => { // [!code ++]
        const calls = [ // [!code ++]
          Actions.token.approve.call({ // [!code ++]
            amount: maxAmountIn, // Approve the max amount with slippage // [!code ++]
            spender: Addresses.stablecoinDex, // [!code ++]
            token: alphaUsd, // [!code ++]
          }), // [!code ++]
        ] // [!code ++]
        sendCalls.sendCallsSync({ calls }) // [!code ++]
      }}> {/* [!code ++] */}
        Approve Spend {/* [!code ++] */}
      </button> {/* [!code ++] */}
    </div>
  )
}
```

```tsx twoslash [Sell.tsx]
// @noErrors
import { Actions, Addresses } from 'viem/tempo' // [!code ++]
import { Hooks } from 'wagmi/tempo'
import { formatUnits, parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi' // [!code ++]

const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'

function Sell() {
  const amount = parseUnits('10', 6)

  // How much BetaUSD will I receive for 10 AlphaUSD?
  const { data: quote, error } = Hooks.dex.useSellQuote({
    tokenIn: alphaUsd,
    tokenOut: betaUsd,
    amountIn: amount,
  })

  // Calculate 0.5% slippage tolerance
  const slippageBps = 50n
  const minAmountOut = quote
    ? quote * (10_000n - slippageBps) / 10_000n
    : 0n

  const sendCalls = useSendCallsSync() // [!code ++]

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return (
    <div>
      <div>Quote: {formatUnits(quote, 6)}</div>
      <div>Min output (0.5% slippage): {formatUnits(minAmountOut, 6)}</div>
      <button type="button" disabled={sendCalls.isPending} onClick={() => { // [!code ++]
        const calls = [ // [!code ++]
          Actions.token.approve.call({ // [!code ++]
            amount, // Approve the exact amount being sold // [!code ++]
            spender: Addresses.stablecoinDex, // [!code ++]
            token: alphaUsd, // [!code ++]
          }), // [!code ++]
        ] // [!code ++]
        sendCalls.sendCallsSync({ calls }) // [!code ++]
      }}> {/* [!code ++] */}
        Approve Spend {/* [!code ++] */}
      </button> {/* [!code ++] */}
    </div>
  )
}
```
:::

### Execute a swap

Batch the token approval with the swap in a single transaction for better UX.

:::code-group
```tsx twoslash [Buy.tsx]
// @noErrors
import { Actions, Addresses } from 'viem/tempo'
import { Hooks } from 'wagmi/tempo'
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, error } = Hooks.dex.useBuyQuote({
    tokenIn: alphaUsd,
    tokenOut: betaUsd,
    amountOut: amount,
  })

  // Calculate 0.5% slippage tolerance
  const slippageBps = 50n
  const maxAmountIn = quote
    ? (quote * (10_000n + slippageBps) + 9_999n) / 10_000n
    : 0n

  const sendCalls = useSendCallsSync()

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return (
    <div>
      <div>Quote: {formatUnits(quote, 6)}</div>
      <div>Max input (0.5% slippage): {formatUnits(maxAmountIn, 6)}</div>
      <button type="button" disabled={sendCalls.isPending} onClick={() => {
        const calls = [
          Actions.token.approve.call({
            amount: maxAmountIn, // Approve the max amount with slippage
            spender: Addresses.stablecoinDex,
            token: alphaUsd,
          }),
          Actions.dex.buy.call({ // [!code ++]
            amountOut: amount, // [!code ++]
            maxAmountIn, // [!code ++]
            tokenIn: alphaUsd, // [!code ++]
            tokenOut: betaUsd, // [!code ++]
          }), // [!code ++]
        ]
        sendCalls.sendCallsSync({ calls })
      }}>
        Execute Swap
      </button>
    </div>
  )
}
```

```tsx twoslash [Sell.tsx]
// @noErrors
import { Actions, Addresses } from 'viem/tempo'
import { Hooks } from 'wagmi/tempo'
import { formatUnits, parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi'

const alphaUsd = '0x20c0000000000000000000000000000000000001'
const betaUsd = '0x20c0000000000000000000000000000000000002'

function Sell() {
  const amount = parseUnits('10', 6)

  // How much BetaUSD will I receive for 10 AlphaUSD?
  const { data: quote, error } = Hooks.dex.useSellQuote({
    tokenIn: alphaUsd,
    tokenOut: betaUsd,
    amountIn: amount,
  })

  // Calculate 0.5% slippage tolerance
  const slippageBps = 50n
  const minAmountOut = quote
    ? quote * (10_000n - slippageBps) / 10_000n
    : 0n

  const sendCalls = useSendCallsSync()

  if (error) return <div>{error.message}</div>
  if (quote === undefined) return <div>Loading quote…</div>

  return (
    <div>
      <div>Quote: {formatUnits(quote, 6)}</div>
      <div>Min output (0.5% slippage): {formatUnits(minAmountOut, 6)}</div>
      <button type="button" disabled={sendCalls.isPending} onClick={() => {
        const calls = [
          Actions.token.approve.call({
            amount, // Approve the exact amount being sold
            spender: Addresses.stablecoinDex,
            token: alphaUsd,
          }),
          Actions.dex.sell.call({ // [!code ++]
            amountIn: amount, // [!code ++]
            minAmountOut, // [!code ++]
            tokenIn: alphaUsd, // [!code ++]
            tokenOut: betaUsd, // [!code ++]
          }), // [!code ++]
        ]
        sendCalls.sendCallsSync({ calls })
      }}>
        Execute Swap
      </button>
    </div>
  )
}
```
:::
::::

## Stablecoin swap 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:

```tsx
import { Hooks } from 'wagmi/tempo'
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 === undefined) {
    return <div>Loading quote...</div>
  }

  return <div>Quote: {quote.toString()}</div>
}
```

## Stablecoin swap learning resources

* [DEX balances](https://tempo.xyz/developers/docs/protocol/exchange/exchange-balance) — Learn about how the Stablecoin DEX interacts with your balances
* [Swap Execution Details](https://tempo.xyz/developers/docs/protocol/exchange/executing-swaps) — Learn about the technical details of swap execution
