Skip to content

Providing Liquidity

Add liquidity for a token pair by placing orders on the Stablecoin DEX. You can provide liquidity on the buy or sell side of the orderbook, with limit or flip orders. To learn more about order types see the documentation on order types.

In this guide you will learn how to place buy and sell orders to provide liquidity on the Stablecoin DEX orderbook.

Demo

Place an Order

demo
1
Create an account, or use an existing one.
2
Add testnet funds to your account.
3
Approve spend and place buy order for 100 AlphaUSD
4
Query order details
pnpx gitpick tempoxyz/tempo-ts/tree/main/examples/exchange

Steps

Set up your client

Ensure that you have set up your client by following the guide.

Approve spend

To place an order, you need to approve the Stablecoin DEX contract to spend the order's "spend" token.

Approve Spend

demo
1
Create an account, or use an existing one.
2
Approve the Stablecoin DEX to spend pathUSD
ApproveSpend.tsx
import { Addresses, Hooks } from 'tempo.ts/wagmi'
import { parseUnits } from 'viem'
 
const pathUsd = '0x20c0000000000000000000000000000000000000'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
 
function ApproveSpend(props: { orderType: 'buy' | 'sell' }) {
  const { orderType } = props
  // buying AlphaUSD requires we spend pathUSD 
  const spendToken = orderType === 'buy' ? pathUsd : alphaUsd 

  const { mutate: approve } = Hooks.token.useApproveSync() 
 
  return (
    <button type="button" onClick={() => {
      approve({ 
        amount: parseUnits('100', 6), 
        spender: Addresses.stablecoinExchange, 
        token: spendToken, 
      }) 
  }}>
      Approve Spend
    </button>
  )
}

Place order

Once the spend is approved, you can place an order by calling the place action on the Stablecoin DEX.

Place Order

demo
1
Create an account, or use an existing one.
2
Approve spend and place buy order for 100 AlphaUSD
PlaceOrder.tsx
import { Actions, Addresses } from 'tempo.ts/viem'
import { parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi'
 
const pathUsd = '0x20c0000000000000000000000000000000000000'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
 
function PlaceOrder(props: { orderType: 'buy' | 'sell' }) {
  const { orderType } = props
  // buying AlphaUSD requires we spend pathUSD
  const spendToken = orderType === 'buy' ? pathUsd : alphaUsd
 
  const sendCalls = useSendCallsSync() 
 
  return (
    <button type="button" onClick={() => {
      const calls = [ 
        Actions.token.approve.call({ 
          spender: Addresses.stablecoinExchange, 
          amount: parseUnits('100', 6), 
          token: spendToken, 
        }), 
        Actions.dex.place.call({ 
          token: alphaUsd, 
          amount: parseUnits('100', 6), 
          type: orderType, 
          tick: 0, 
        }), 
      ] 
      sendCalls.sendCallsSync({ calls }) 
    }}>
      Place Order
    </button>
  )
}

View order details

After placing an order, you can query its details to see the current state, including the amount filled and remaining using Hooks.dex.useOrder.

View Order

demo
1
Create an account, or use an existing one.
2
Add testnet funds to your account.
3
Approve spend and place buy order for 100 AlphaUSD
4
Query order details
QueryOrder.tsx
import { Hooks } from 'tempo.ts/wagmi'
 
const orderId = 123n
 
const { data: order, refetch } = Hooks.dex.useOrder({
  orderId,
})
 
console.log('Type:', order?.isBid ? 'Buy' : 'Sell')
console.log('Amount:', order?.amount.toString())
console.log('Remaining:', order?.remaining.toString())
console.log('Tick:', order?.tick)
console.log('Is flip order:', order?.isFlip)

For more details on querying orders, see the Hooks.dex.useOrder documentation.

Recipes

Cancel order

Cancel an order using its order ID.

When you cancel an order, any remaining funds are credited to your exchange balance (not directly to your wallet). To move funds back to your wallet, you can withdraw them to your wallet.

Place and Cancel an Order

demo
1
Create an account, or use an existing one.
2
Add testnet funds to your account.
3
Approve spend and place buy order for 100 AlphaUSD
4
Cancel the order
pnpx gitpick tempoxyz/tempo-ts/tree/main/examples/exchange
ManageOrder.tsx
import { Actions, Addresses } from 'tempo.ts/viem'
import { Hooks } from 'tempo.ts/wagmi'
import { parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi'
 
const pathUsd = '0x20c0000000000000000000000000000000000000'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
 
function ManageOrder() {
  const sendCalls = useSendCallsSync()
  const cancelOrder = Hooks.dex.useCancelSync() 
 
  const placeOrder = () => {
    const calls = [
      Actions.token.approve.call({
        spender: Addresses.stablecoinExchange,
        amount: parseUnits('100', 6),
        token: pathUsd,
      }),
      Actions.dex.place.call({
        token: alphaUsd,
        amount: parseUnits('100', 6),
        type: 'buy',
        tick: 0,
      }),
    ]
    sendCalls.sendCallsSync({ calls })
  }
 
  return (
    <>
      <button type="button" onClick={placeOrder}>
        Place Order
      </button>
      <form onSubmit={
        (event) => {
          event.preventDefault()
          const formData = new FormData(event.target as HTMLFormElement)
          const orderId = BigInt(formData.get('orderId') as string)
 
          cancelOrder.mutate({ orderId }) 
        }
      }>
        <input type="text" name="orderId" placeholder="Order ID" />
        <button
          type="submit"
          disabled={cancelOrder.isPending}
        > 
          {cancelOrder.isPending ? 'Canceling...' : 'Cancel Order'}
        </button> 
      </form>
    </>
  )
}

Determining quote token

Each token has a designated quote token that it trades against on the DEX. For most stablecoins, this will be pathUSD.

Use the token.useGetMetadata hook to retrieve a token's quote token.

example.ts
import { Hooks } from 'tempo.ts/wagmi'
 
const { data: metadata } = Hooks.token.useGetMetadata({ 
  token: '0x20c0000000000000000000000000000000000001', // AlphaUSD 
}) 
 
console.log('Token:', metadata?.symbol)
Token: AlphaUSD
console.log('Quote Token:', metadata?.quoteToken) // returns `pathUSD` address
Quote Token: 0x20c0000000000000000000000000000000000000

Flip order

Flip orders automatically switch between buy and sell sides when filled, providing continuous liquidity. Use viem's dex.placeFlip to create a flip order call.

PlaceFlipOrder.tsx
import { Actions, Addresses } from 'tempo.ts/viem'
import { parseUnits } from 'viem'
import { useSendCallsSync } from 'wagmi'
 
const pathUsd = '0x20c0000000000000000000000000000000000000'
const alphaUsd = '0x20c0000000000000000000000000000000000001'
 
function PlaceFlipOrder(props: { orderType: 'buy' | 'sell' }) {
  const { orderType } = props
  // buying AlphaUSD requires we spend pathUSD
  const spendToken = orderType === 'buy' ? pathUsd : alphaUsd
 
  const sendCalls = useSendCallsSync()
 
  return (
    <button type="button" onClick={() => {
      const calls = [
        Actions.token.approve.call({
          spender: Addresses.stablecoinExchange,
          amount: parseUnits('100', 6),
          token: spendToken,
        }),
        Actions.dex.placeFlip.call({ 
          token: alphaUsd,
          amount: parseUnits('100', 6),
          type: orderType,
          tick: 0,
        }),
      ]
      sendCalls.sendCallsSync({ calls })
    }}>
      Place Flip Order
    </button>
  )
}

Place order at specific price

Ticks represent prices relative to the quote token (usually pathUSD). The formula is:

tick = (price - 1) * 100_000

For example, price $1.0000 → tick = 0, price $0.9990 → tick = -10, and price $1.0010 → tick = 10.

Use the Tick utility to convert between prices and ticks:

import { Actions, Tick } from 'tempo.ts/viem'
import { parseUnits } from 'viem'
 
const alphaUsd = '0x20c0000000000000000000000000000000000001'
 
// buy order at $0.9990 (tick: -10) 
const buyCall = Actions.dex.place.call({ 
  token: alphaUsd, 
  amount: parseUnits('100', 6), 
  type: 'buy', 
  tick: Tick.fromPrice('0.9990'), // -10 
}) 
 
// sell order at $1.0010 (tick: 10) 
const sellCall = Actions.dex.place.call({ 
  token: alphaUsd, 
  amount: parseUnits('100', 6), 
  type: 'sell', 
  tick: Tick.fromPrice('1.0010'), // 10 
}) 

For more details including tick precision, limits, and calculation examples, see Understanding Ticks.

Best practices

Batch calls

You can batch the calls to approve spend and place the order in a single transaction for efficiency. See the guide on batch transactions for more details.

Learning resources