Post
Share your knowledge.

Build a DEX on Sui Using DeepBook: A Practical Guide for Move Developers
Welcome to the next level of Sui Move development. In this hands-on guide, we're diving deep into DeepBook — the powerful CLOB (Central Limit Order Book) engine in the Sui ecosystem to show you how to build a DEX from scratch. Whether you're prototyping DeFi apps or exploring token mechanics, this tutorial will walk you through smart contract creation, interaction, and testing using DeepBook's latest modules.
Introduction: Why DeepBook Matters
If you're familiar with DeFi protocols like Uniswap or dYdX, you'll know how essential a performant, on-chain order book is. DeepBook brings that capability to Sui with a natively composable design. It enables limit orders, market orders, liquidity pools, and custodial accounts — all wrapped in Move modules.
This article follows up on our previous intro to DeepBook and gets fully practical: we'll show you how to mint tokens, create liquidity pools, deposit/withdraw assets, and execute both limit and market orders.
Setting Up Your Project
Start by creating a new Move project:
$ sui move new howtosui_deepbook
We'll build two modules:
usdt
: a custom quote asset tokendeepbook
: our interaction logic with DeepBook modules
USDT Token Module
module howtosui::usdt {
use sui::coin::{Coin, TreasuryCap, Self};
public struct USDT has drop {}
fun init(witness: USDT, ctx: &mut TxContext) {
let (treasury, metadata) = coin::create_currency(witness, 6, b"USDT", b"", b"", option::none(), ctx);
transfer::public_freeze_object(metadata);
transfer::public_transfer(treasury, tx_context::sender(ctx))
}
public entry fun mint(treasury_cap: &mut TreasuryCap<USDT>, amount: u64, recipient: address, ctx: &mut TxContext) {
treasury_cap.mint_and_transfer(amount, recipient, ctx)
}
public entry fun burn(treasury_cap: &mut TreasuryCap<USDT>, coin: Coin<USDT>) {
treasury_cap.burn(coin);
}
}
DeepBook Module Integration
module howtosui::deepbook {
use deepbook::clob_v2 as deepbook;
use deepbook::custodian_v2 as custodian;
use sui::coin::{Coin, Self};
use sui::clock::Clock;
const FLOAT_SCALING: u64 = 1_000_000_000;
public fun new_pool<Base, Quote>(payment: &mut Coin<SUI>, ctx: &mut TxContext) {
let fee = coin::balance_mut(payment).split(100 * FLOAT_SCALING);
let coin = coin::from_balance(fee, ctx);
deepbook::create_pool<Base, Quote>(1 * FLOAT_SCALING, 1, coin, ctx);
}
public fun new_custodian_account(ctx: &mut TxContext) {
transfer::public_transfer(deepbook::create_account(ctx), tx_context::sender(ctx));
}
public fun make_base_deposit<Base, Quote>(pool: &mut deepbook::Pool<Base, Quote>, coin: Coin<Base>, account_cap: &custodian::AccountCap) {
deepbook::deposit_base(pool, coin, account_cap);
}
public fun make_quote_deposit<Base, Quote>(pool: &mut deepbook::Pool<Base, Quote>, coin: Coin<Quote>, account_cap: &custodian::AccountCap) {
deepbook::deposit_quote(pool, coin, account_cap);
}
public fun withdraw_base<Base, Quote>(pool: &mut deepbook::Pool<Base, Quote>, quantity: u64, account_cap: &custodian::AccountCap, ctx: &mut TxContext) {
let base = deepbook::withdraw_base(pool, quantity, account_cap, ctx);
transfer::public_transfer(base, tx_context::sender(ctx));
}
public fun place_limit_order<Base, Quote>(
pool: &mut deepbook::Pool<Base, Quote>,
client_order_id: u64,
price: u64,
quantity: u64,
self_matching_prevention: u8,
is_bid: bool,
expire_timestamp: u64,
restriction: u8,
clock: &Clock,
account_cap: &custodian::AccountCap,
ctx: &mut TxContext
): (u64, u64, bool, u64) {
deepbook::place_limit_order(pool, client_order_id, price, quantity, self_matching_prevention, is_bid, expire_timestamp, restriction, clock, account_cap, ctx)
}
public fun place_base_market_order<Base, Quote>(
pool: &mut deepbook::Pool<Base, Quote>,
account_cap: &custodian::AccountCap,
base_coin: Coin<Base>,
client_order_id: u64,
is_bid: bool,
clock: &Clock,
ctx: &mut TxContext
) {
let quote_coin = coin::zero<Quote>(ctx);
let quantity = coin::value(&base_coin);
place_market_order(pool, account_cap, client_order_id, quantity, is_bid, base_coin, quote_coin, clock, ctx);
}
fun place_market_order<Base, Quote>(
pool: &mut deepbook::Pool<Base, Quote>,
account_cap: &custodian::AccountCap,
client_order_id: u64,
quantity: u64,
is_bid: bool,
base_coin: Coin<Base>,
quote_coin: Coin<Quote>,
clock: &Clock,
ctx: &mut TxContext
) {
let (base, quote) = deepbook::place_market_order(pool, account_cap, client_order_id, quantity, is_bid, base_coin, quote_coin, clock, ctx);
transfer::public_transfer(base, tx_context::sender(ctx));
transfer::public_transfer(quote, tx_context::sender(ctx));
}
}
Environment Setup: Localnet Testing
Run your validator locally:
$ sui client switch --env localnet
Create two accounts:
$ sui client new-address ed25519 yasmine
$ sui client new-address ed25519 yoyo
Fund both via local faucet.
Deploy & Interact
4.1 Publish Modules
$ sui client publish --gas-budget 100000000
Export key objects like PACKAGE_ID, TREASURY_CAP_ID, POOL_ID, etc.
4.2 Mint Quote Token (USDT)
$ sui client call --function mint ... 1000000000 <address>
4.3 Create Pool
$ sui client call --function new_pool --args <payment_coin_id>
4.4 Create Custodian Account
$ sui client call --function new_custodian_account
4.5 Deposit Assets
$ sui client call --function make_base_deposit
$ sui client call --function make_quote_deposit
4.6 Place Limit Orders
$ sui client call --function place_limit_order --args <price> <quantity> <expire>
4.7 Execute Market Orders
$ sui client call --function place_base_market_order
- Wrap-Up
With DeepBook, Sui offers a fully on-chain, composable, and efficient orderbook engine suitable for high-performance DeFi protocols. From token minting to order execution, every component is programmable and testable via Move. This guide gives you the baseline to build your own trading platforms, liquidity strategies, or even complex DAO-governed DeFi ecosystems on Sui.
Stay tuned for Part 3, where we dive into event parsing, order history tracking, and frontend integration using the Sui SDK. Let’s keep BUIDLing
- Sui
- SDKs and Developer Tools
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.