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
demoSteps
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
demoimport { 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
demoimport { 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
demoimport { 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
demoimport { 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.
import { Hooks } from 'tempo.ts/wagmi'
const { data: metadata } = Hooks.token.useGetMetadata({
token: '0x20c0000000000000000000000000000000000001', // AlphaUSD
})
console.log('Token:', metadata?.symbol)
Token: AlphaUSDconsole.log('Quote Token:', metadata?.quoteToken) // returns `pathUSD` address Quote Token: 0x20c0000000000000000000000000000000000000Flip 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.
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_000For 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.