Help us improve
Share bugs, ideas, or general feedback.
From sui-dev-agents
Integrates DeepBook V3 — SUI's native CLOB DEX, margin trading, prediction markets, and DEEP-token fee mechanics. Use for order books, limit/market orders, leverage, TPSL, flash loans, or any on-chain trading on SUI.
npx claudepluginhub first-mover-tw/sui-dev-agents --plugin sui-dev-agentsHow this skill is triggered — by the user, by Claude, or both
Slash command
/sui-dev-agents:sui-deepbookThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Canonical CLOB DEX, margin engine, and prediction-market substrate on SUI.**
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Share bugs, ideas, or general feedback.
Canonical CLOB DEX, margin engine, and prediction-market substrate on SUI.
Targets: @mysten/deepbook-v3 1.4.1 (^1.3), @mysten/sui 2.17.0 (^2.16). Tested: 2026-06-03.
Predict section re-verified against
deepbookv3@predict-testnet-4-16source 2026-05-30 — Predict is a separatedeepbook_predictMove package, not part of the npm SDK.
Compatibility notes: Use @mysten/deepbook-v3 (V3 — current). The legacy @mysten/deepbook / clob_v2 packages are deprecated and not what you want.
V3 is a clean break from V2. If you've used V2 (deepbook::clob_v2, AccountCap, custodian), forget the mental model:
| Concern | V2 (legacy) | V3 (current) |
|---|---|---|
| Account model | AccountCap per pool, custodian-owned funds | BalanceManager — one shared object holds all your funds, scoped via TradeCap / DepositCap / WithdrawCap |
| Fees | Paid in base/quote | Paid in DEEP (or whitelisted alternative via payWithDeep: false on supported pools) |
| Pool creation | Permissioned | Permissionless (createPermissionlessPool) — burn DEEP as creation fee |
| Margin / leverage | n/a | First-class: MarginManager, MarginPool, liquidations, Pyth oracles |
| Order primitives | place_limit_order only | Limit + Market + IOC + FOK + Post-Only + Self-matching policies + TPSL conditional orders |
| Move modules | deepbook::clob_v2 | deepbook::pool, deepbook::balance_manager, margin::* |
Do not mix V2 and V3 examples in the same codebase. The Move modules, object types, and SDK packages are entirely separate.
┌─────────────────┐ ┌──────────────┐
│ BalanceManager │◄────────┤ TradeCap │ (delegate trading without giving up funds)
│ (shared obj) │ └──────────────┘
│ • Base coins │
│ • Quote coins │ ┌──────────────┐
│ • DEEP │◄────────┤ TradeProof │ (per-tx capability, generated from cap)
└────────┬────────┘ └──────────────┘
│
│ attached to every order via TradeProof
▼
┌─────────────────┐
│ Pool │ baseCoin / quoteCoin, tick_size, lot_size, min_size
│ (shared obj) │ CLOB matching engine, DEEP fee escrow
└─────────────────┘
Mental model: BalanceManager is your wallet; Pool is the order book. Every order references a BalanceManager via a TradeProof. You can grant TradeCap to a market-making bot (up to ~1,000 authorized traders per BM) without exposing withdrawal rights.
Fee economics: Paying with DEEP gives a fee discount (canonically ~20% — verify current rate); DEEP stakers earn maker rebates and vote on per-pool fee parameters.
Pool internals: A Pool is split into Book (matching), State (governance/fee params), and Vault (settlement). PoolRegistry enforces a single pool per (Base, Quote) pair — no fragmented liquidity.
Client choice (read this — do not skip): @mysten/sui v2 removed SuiClient and getFullnodeUrl. Use SuiGrpcClient from @mysten/sui/grpc. JSON-RPC is deprecated (full removal April 2026). Any code you write using new SuiClient(...) or getFullnodeUrl(...) is wrong on the current SDK and will not type-check.
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { DeepBookClient } from '@mysten/deepbook-v3';
import { Transaction } from '@mysten/sui/transactions';
const suiClient = new SuiGrpcClient({
network: 'mainnet',
baseUrl: 'https://fullnode.mainnet.sui.io:443',
});
const dbClient = new DeepBookClient({
client: suiClient,
address: '0xYOUR_ADDRESS',
network: 'mainnet',
// Optional: register your own BalanceManager so SDK helpers resolve by key
balanceManagers: {
MY_BM: { address: '0xYOUR_BALANCE_MANAGER_ID' },
},
});
The SDK ships mainnet/testnet pool maps (SUI_USDC, DEEP_USDC, DEEP_SUI, …) and package IDs — you don't hard-code them.
// @check:skip — fragment, continues from Quick Start §1
const tx = new Transaction();
tx.add(dbClient.balanceManager.createAndShareBalanceManager());
// Sign + execute, then grab the new shared object ID from object changes
// and feed it back into DeepBookClient as `balanceManagers.MY_BM.address`.
If you want to delegate trading: use createBalanceManagerWithOwner(owner) and mint a TradeCap separately (balanceManager.mintTradeCap).
// @check:skip — fragment, continues from Quick Start §1
const tx = new Transaction();
tx.add(dbClient.balanceManager.depositIntoManager('MY_BM', 'SUI', 1.5));
tx.add(dbClient.balanceManager.depositIntoManager('MY_BM', 'DEEP', 10)); // fee fuel
Quantities are human-readable (1.5 SUI, not 1_500_000_000 MIST). The SDK applies coin scalar from its CoinMap.
// @check:skip — fragment, continues from Quick Start §1
import { OrderType, SelfMatchingOptions } from '@mysten/deepbook-v3';
const tx = new Transaction();
tx.add(
dbClient.deepBook.placeLimitOrder({
poolKey: 'SUI_USDC',
balanceManagerKey: 'MY_BM',
clientOrderId: '1001', // your tracking ID
price: 2.15, // quote per base, human units
quantity: 10, // base units, human
isBid: true, // true = buy SUI
orderType: OrderType.POST_ONLY, // maker-only; cancels if it would cross
selfMatchingOption: SelfMatchingOptions.CANCEL_TAKER,
payWithDeep: true, // DEEP fee path (cheapest on supported pools)
}),
);
PlaceLimitOrderParams (from @mysten/deepbook-v3):
poolKey, balanceManagerKey — string keys into your configured mapsclientOrderId — string; surfaces in events for your reconciliationprice, quantity — number | bigint, human units (SDK rescales)isBid — true buy base / false sell baseexpiration? — epoch ms; defaults to MAX_TIMESTAMPorderType? — NO_RESTRICTION | IMMEDIATE_OR_CANCEL | FILL_OR_KILL | POST_ONLYselfMatchingOption? — SELF_MATCHING_ALLOWED | CANCEL_TAKER | CANCEL_MAKERpayWithDeep? — true (default) uses DEEP fee path// @check:skip — fragment, continues from §4
tx.add(
dbClient.deepBook.placeMarketOrder({
poolKey: 'SUI_USDC',
balanceManagerKey: 'MY_BM',
clientOrderId: '2001',
quantity: 5,
isBid: true,
payWithDeep: true,
}),
);
// @check:skip — fragment, continues from §4
tx.add(dbClient.deepBook.cancelOrder('SUI_USDC', 'MY_BM', orderId));
tx.add(dbClient.deepBook.cancelAllOrders('SUI_USDC', 'MY_BM'));
tx.add(dbClient.deepBook.modifyOrder('SUI_USDC', 'MY_BM', orderId, newQuantity));
// @check:skip — fragment, continues from Quick Start §1
// Top-of-book + depth
const mid = await dbClient.midPrice('SUI_USDC');
const { bids, asks } = await dbClient.getLevel2Range('SUI_USDC', 2.0, 2.30, true);
// Account view
const balances = await dbClient.checkManagerBalance('MY_BM', 'SUI');
const openOrders = await dbClient.accountOpenOrders('SUI_USDC', 'MY_BM');
// Quote a hypothetical fill
const out = await dbClient.getQuoteQuantityOut('SUI_USDC', 10);
All read methods are on the DeepBookClient instance and are async (Promise<...>). They route through devInspect / RPC — no signing needed.
Since SUI v1.47, DeepBook is not an implicit dependency. Pin it explicitly:
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/mainnet" }
DeepBook = { git = "https://github.com/MystenLabs/deepbookv3.git", subdir = "packages/deepbook", rev = "main" }
Token = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-system", rev = "framework/mainnet" }
Minimal Move call (most teams should use the SDK instead — direct Move integration is for protocol composability):
use deepbook::pool::Pool;
use deepbook::balance_manager::{BalanceManager, TradeProof};
use token::deep::DEEP;
use sui::clock::Clock;
public fun place_bid<Base, Quote>(
pool: &mut Pool<Base, Quote>,
manager: &mut BalanceManager,
proof: &TradeProof,
client_order_id: u64,
price: u64, // scaled, see FLOAT_SCALAR
quantity: u64, // scaled to base coin decimals
expire_timestamp: u64,
clock: &Clock,
ctx: &mut TxContext,
) {
deepbook::pool::place_limit_order<Base, Quote>(
pool,
manager,
proof,
client_order_id,
0, // NO_RESTRICTION
0, // SELF_MATCHING_ALLOWED
price,
quantity,
true, // is_bid
true, // pay_with_deep
expire_timestamp,
clock,
ctx,
);
}
DeepBook Margin adds leverage on top of any CLOB pool via separate objects. The SDK exposes a full surface but the high-level moving parts are:
MarginPool — per-asset lending pool. LPs deposit base/quote, borrowers pay interest.MarginManager — a leveraged position; analogous to BalanceManager but with debt.MarginRegistry — global registry of supported margin pools.PoolProxy — wraps a regular DeepBook Pool so margin orders route through it without bypassing CLOB matching.SuiPythClient + mainnetPythConfigs.MarginTPSL — conditional take-profit / stop-loss orders that auto-fire when oracle price crosses a trigger.Two-transaction flow: (A) create + initialize + share the margin manager once, (B) in later txs reference it by managerKey to deposit / borrow / trade.
// @check:skip — fragment, continues from Quick Start §1
// === Transaction A: one-time setup ===
const txA = new Transaction();
const { manager, initializer } = dbClient.marginManager.newMarginManagerWithInitializer('SUI_USDC')(txA);
txA.add(dbClient.marginManager.depositDuringInitialization({
manager,
poolKey: 'SUI_USDC',
coinType: 'USDC',
amount: 1000, // human units
}));
txA.add(dbClient.marginManager.shareMarginManager('SUI_USDC', manager, initializer));
// → register the resulting shared object as 'MY_MM' in your config map
// === Transaction B: borrow + place margin order ===
const tx = new Transaction();
// 1. Borrow against the collateral (use borrowBase / borrowQuote, not generic borrow)
tx.add(dbClient.marginManager.borrowQuote('MY_MM', 3000)); // 3x leverage on quote (USDC)
// 2. Place a margin limit order through the pool proxy
tx.add(
dbClient.poolProxy.placeMarginLimitOrder({
poolKey: 'SUI_USDC',
marginManagerKey: 'MY_MM',
clientOrderId: 'm-1',
price: 2.15,
quantity: 1500,
isBid: true,
payWithDeep: true,
}),
);
// 5. Optional: attach a stop-loss
tx.add(
dbClient.marginTPSL.addConditionalOrder({
marginManagerKey: 'MY_MM',
poolKey: 'SUI_USDC',
triggerPrice: 1.90,
isStopLoss: true,
// ... order params for the unwind leg
}),
);
Health & liquidation: read margin state with dbClient.getMarginManagerState('MY_MM') → returns assets, debts, and a health factor. Below 1.0 → liquidatable via marginLiquidations.
PRICE_INFO_OBJECT_MAX_AGE_MS). Stale feeds → reverted orders. Always refresh in the same PTB.borrow() returns shares, not a fixed amount.Off-chain REST service for historical and aggregate data (trades, volume, OHLCV, orderbook snapshots) that you can't cheaply derive from RPC. There is no SDK wrapper — fetch directly:
// Mainnet base: https://deepbook-indexer.mainnet.mystenlabs.com
// Predict (testnet): https://predict-server.testnet.mystenlabs.com
// Common endpoints (canonical names — verify exact query-param spelling against current docs):
// GET /pools — all pools + metadata (tick_size, lot_size)
// GET /summary — per-pool 24h price/volume/quote summary
// GET /book_depth?pool_id=... — live L2 depth snapshot
// GET /ohlcv?pool_id=...&interval=... — candles
// GET /historical_volume?... — volume by pool or balance manager
const summary = await fetch(
'https://deepbook-indexer.mainnet.mystenlabs.com/summary',
).then(r => r.json());
When to use the indexer vs. SDK queries:
getLevel2Range) — it's live RPCaccountOpenOrders)Endpoint surface evolves; canonical reference is https://docs.sui.io/onchain-finance/deepbookv3/deepbookv3-indexer. Use
sui_docs_queryfor the current list before hard-coding.
Expiry-based prediction-market protocol. It is NOT the CLOB. Predict is a separate Move package (deepbook_predict, currently on the predict-testnet-4-16 branch) that only borrows deepbook::math — it has no Pool, no BalanceManager, no order book, no maker/taker. Every trade is priced against a shared LP vault (the protocol is your counterparty), using Block Scholes' OracleSVI volatility model. If you find yourself reaching for placeLimitOrder / TradeProof here, you're in the wrong mental model.
As of 2026-05, Predict is testnet-only and experimental. Verify mainnet availability before wiring it into production.
| Object | Role |
|---|---|
Predict | Shared root. Holds the vault balances, pricing/risk/treasury config, quote-asset allowlist, oracle strike grids, and the PLP treasury cap. Treat as the "market root". |
PredictManager | Per-user account. Holds the user's quote balances plus their position & range quantities. One per user, reused. Analogous in spirit to a BalanceManager but a completely different type/module. |
OracleSVI | Market state for one (underlying, expiry). Carries spot, forward, SVI params, activation status, settlement price. Created/updated by a Block Scholes operator via OracleSVICap. |
PLP | LP share token (a Coin<PLP>), minted when you supply quote into the vault. |
Registry / AdminCap | Admin wiring (create Predict, create oracles, set spreads/limits). Not user-facing. |
Positions and ranges are NOT objects. They are internal balances inside PredictManager, keyed by:
(oracle_id, expiry, strike, is_up) → a MarketKey(oracle_id, expiry, lower_strike, higher_strike) → a RangeKeyThere is no "position NFT" to find. Read them from the manager object or the indexed server.
Predict package: 0xf5ea2b3749c65d6e56507cc35388719aadb28f9cab873696a2f8687f5c785138
Predict object: 0xc8736204d12f0a7277c86388a68bf8a194b0a14c5538ad13f22cbd8e2a38028a
Quote asset: ...::dusdc::DUSDC (testnet faucet stablecoin, 6 decimals)
Public server: https://predict-server.testnet.mystenlabs.com
deepbook_predict::predict)All trade fns are generic over <Quote> and take human-irrelevant scaled u64s (Move layer):
create_manager(ctx): ID — make a PredictManager (shared). One per user.mint<Quote>(predict, manager, oracle, key: MarketKey, quantity, clock, ctx) — buy a directional position; debits quote from the manager, emits PositionMinted.redeem<Quote>(predict, manager, oracle, key, quantity, clock, ctx) — sell; payout into the manager. redeem_permissionless<Quote>(...) for settled oracles (anyone can call).mint_range<Quote>(predict, manager, oracle, key: RangeKey, quantity, clock, ctx) / redeem_range<Quote>(...) — vertical ranges.supply<Quote>(predict, coin, clock, ctx): Coin<PLP> — LP in, get shares.withdraw<Quote>(predict, lp_coin, clock, ctx): Coin<Quote> — burn shares, quote out (subject to a withdrawal rate-limiter + vault-availability check).get_trade_amounts(...) -> (cost, payout), get_range_trade_amounts(...), ask_bounds(oracle_id) -> (min, max).There is no dedicated @mysten/deepbook-predict SDK. Build PTBs with @mysten/codegen-generated bindings, or raw moveCall:
// @check:skip — references deployment IDs/types you supply at runtime
import { Transaction } from '@mysten/sui/transactions';
const PKG = '0xf5ea2b...'; // predict package id
const PREDICT = '0xc87362...'; // Predict shared object
const DUSDC = '0x<pkg>::dusdc::DUSDC';
const CLOCK = '0x6';
// LP: supply quote → PLP shares (real flow from scripts/transactions/predict/deposit.ts)
const tx = new Transaction();
const lp = tx.moveCall({
target: `${PKG}::predict::supply`,
typeArguments: [DUSDC],
arguments: [tx.object(PREDICT), coin /* Coin<DUSDC> */, tx.object(CLOCK)],
});
tx.transferObjects([lp], tx.pure.address(myAddress));
// Trade: buy a directional position (manager + oracle + MarketKey built upstream)
tx.moveCall({
target: `${PKG}::predict::mint`,
typeArguments: [DUSDC],
arguments: [tx.object(PREDICT), tx.object(MANAGER), tx.object(ORACLE), marketKey, tx.pure.u64(qty), tx.object(CLOCK)],
});
active → live spot/SVI updates (prices update more often than SVI) → settled (frozen on the first post-expiry price push; emits OracleSettled) → optionally compacted (storage optimization). Mints require an active oracle; after settlement only redeems work (and redeem_permissionless opens up). Don't assume an oracle is tradeable just because it exists — check status.
predict-server — your default render backend (indexed, paginated). Key endpoints:
GET /predicts/:id/state, /predicts/:id/oracles, /oracles/:id/state, /oracles/:id/ask-bounds/predicts/:id/vault/summary, /vault/performance?range=ALL/managers, /managers/:id/summary, /managers/:id/positions/summary, /managers/:id/pnl?range=ALL/oracles/:id/prices[/latest], /oracles/:id/svi[/latest], /positions/{minted,redeemed}, /ranges/{minted,redeemed}, /lp/{supplies,withdrawals}, /trades/:oracle_idoracle::Oracle{PricesUpdated,SVIUpdated,Settled,Activated}.❌ Treating Predict like the CLOB. No Pool/BalanceManager/TradeProof/limit orders. Counterparty is the PLP vault; price comes from OracleSVI + a utilization spread.
❌ Looking for a position object. Positions/ranges are balances inside PredictManager. Read the manager, not a dangling NFT.
❌ Scanning chain as your primary backend. Use predict-server for lists/history/PnL; chain reads are slow and hard to paginate.
❌ Assuming zero server lag post-tx. Confirm the tx, then refresh server endpoints — it's low-lag, not instant.
❌ Using stale testnet package IDs. Predict redeploys; pull the current package/object IDs (server /status, or the repo's scripts/config/constants.ts) instead of hard-coding.
clientOrderId as your reconciliation key. It echoes back in events and order objects; the on-chain orderId is generated and not predictable.getQuoteQuantityOut / getBaseQuantityOut to compute expected slippage; show the user the worst-case fill.OrderType.POST_ONLY for market-making strategies to avoid accidentally crossing the spread and paying taker fees.tx.add(...) composition pattern is built for this.CANCEL_TAKER (default-allowed self-matches waste fees).❌ Using SuiClient / getFullnodeUrl (v1 SDK)
@mysten/sui v2 (current); imports fail at type-check, RPC client is wrong shape.import { SuiGrpcClient } from '@mysten/sui/grpc'; construct with { network, baseUrl }. The DeepBook SDK is built against the gRPC client, not the legacy JSON-RPC one.❌ Importing Pyth from @pythnetwork/pyth-sui-js
MarginManagerContract expects; extra dependency.import { SuiPythClient, SuiPriceServiceConnection } from '@mysten/deepbook-v3' — the DeepBook SDK re-exports the Pyth pieces wired to its own config (mainnetPythConfigs, testnetPythConfigs).❌ Mixing V2 (clob_v2) examples with V3 imports
clob_v2::place_limit_order doesn't exist on the V3 deployment; LLMs hallucinate this constantly.deepbook::pool::place_limit_order + BalanceManager + TradeProof. No AccountCap, no custodian_v2.❌ Forgetting DEEP for fees
checkManagerBalance(bm, 'DEEP') before placing; or set payWithDeep: false on pools that support whitelisted fee tokens.❌ Hard-coding pool / package IDs
mainnetPools / testnetPools / mainnetPackageIds from the SDK; if you must override, do it via DeepBookClient constructor options.❌ Confusing human vs. scaled units
1_500_000_000 to the SDK when it expects 1.5.coin.scalar internally. Move modules take scaled units. Know which layer you're at.❌ Treating BalanceManager like a per-pool AccountCap
❌ Querying orderbook depth from the indexer
getLevel2Range / midPrice. Indexer → historical + aggregates only.❌ Building margin without refreshing Pyth in the same PTB
EPriceTooOld.pythClient.updatePriceFeeds(...) (or SDK equivalent) in the same Transaction as the margin op.❌ Assuming TPSL is your private executor
Need current contract addresses, indexer endpoints, or Predict launch status?
// @check:skip — sui_docs_query is an agent tool, not real TS API
const info = await sui_docs_query({
type: 'docs',
target: 'deepbook',
query: 'v3 mainnet contract-information balance manager package id',
});
Reference URLs (canonical, check for updates):
One BalanceManager, many pools, DEEP fuels the engine.