Sui.

Post

Share your knowledge.

article banner.
harry phan.
Apr 30, 2025
Article

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 token
  • deepbook: 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
  1. 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
2
Share
Comments
.

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

290Posts417Answers
Sui.X.Peera.

Earn Your Share of 1000 Sui

Gain Reputation Points & Get Rewards for Helping the Sui Community Grow.

Reward CampaignMay
We use cookies to ensure you get the best experience on our website.
More info