DeepBook Predict
DeepBook Predict is an expiry-based prediction market protocol on Sui. It lets applications build markets where users mint and redeem binary positions or vertical ranges against oracle-driven prices. Liquidity providers supply quote assets to a shared vault and receive PLP LP shares in return.
The protocol runs on Sui Testnet and is documented from the predict-testnet-4-16 branch of the DeepBookV3 repository. There is no dedicated Predict TypeScript SDK yet, so you build Predict transactions directly with the Sui TypeScript SDK against the protocol's Move entry points, as the quickstart below shows.
DeepBook Predict smart contracts might change before Mainnet deployment. Treat the current package IDs, object layouts, and entry points as Testnet integration targets. All package IDs and source references on these pages are pinned to the predict-testnet-4-16 branch and change at Mainnet launch.
Quickstart: mint a binary position
This quickstart installs the Sui TypeScript SDK, funds a Testnet account, creates a PredictManager, and mints one binary position. These samples live in the examples/deepbook-predict package, which CI type-checks with tsc --noEmit against @mysten/sui version 2.22.1. This document does not execute them against Testnet, so run the manual verification steps before you rely on them.
1. Install the SDK
Install the Sui TypeScript SDK. You do not need a Predict-specific package.
- npm
- Yarn
- pnpm
npm install @mysten/sui
yarn add @mysten/sui
pnpm add @mysten/sui
2. Request Testnet tokens
You need two assets on Testnet, from two separate sources. Neither one substitutes for the other:
- SUI for gas: Every transaction on this page pays gas in SUI, including the ones that only move DUSDC. Request SUI from a Sui Testnet faucet, which lists the browser, Discord, and cURL routes.
- DUSDC as the quote asset: Predict denominates deposits, mints, and vault supplies in DUSDC. Request DUSDC and other Predict assets through the DeepBook Predict Testnet token request form. DUSDC never pays gas, so an address that holds DUSDC but no SUI cannot submit a Predict transaction.
How much SUI to hold
Keep at least 1 SUI on the address as a working reserve. That covers many Predict transactions with headroom, because a single faucet request supplies well above the cost of one transaction. The quickstart transactions cost more than a plain transfer: creating and sharing a PredictManager writes new objects, so it pays storage on top of computation. Sui refunds part of the storage cost as a rebate when you delete objects, so a session costs less in total than the sum of its gas budgets.
Treat 1 SUI as a starting reserve, not a budget. Before you rely on a fixed gas budget in your own code, measure the real cost of each transaction with a dry run, then set the budget with margin for variable costs such as shared object contention. See Gas Fees for the fee formula and budget rules.
Request more SUI
Check your balance with sui client gas before you request. Faucets rate-limit per address and per IP, so request only when the balance actually runs low. If the browser faucet rate-limits you, use the Discord or cURL routes under alternative methods for getting SUI tokens. When you finish testing, return unused Testnet SUI to the faucet pool.
3. Set the configuration block
Keep every onchain ID in one place. These values are Testnet-only and come from the Contract Information page. They change at Mainnet launch, so never inline them elsewhere. The record keys on network, and you resolve it once at startup, which is the switch point when you add another environment. See Manage configuration across networks for what changes per network and which Testnet behavior you cannot assume carries to Mainnet.
export type PredictNetwork = 'testnet' | 'mainnet';
export type PredictConfig = {
network: PredictNetwork;
fullnodeUrl: string;
packageId: string;
predictObjectId: string;
quoteType: string;
serverUrl: string;
};
// Testnet IDs pinned to the `predict-testnet-4-16` branch. These change at
// Mainnet launch. Source: Contract Information page.
const TESTNET: PredictConfig = {
network: 'testnet',
fullnodeUrl: 'https://fullnode.testnet.sui.io:443',
packageId: '0xf5ea2b3749c65d6e56507cc35388719aadb28f9cab873696a2f8687f5c785138',
predictObjectId: '0xc8736204d12f0a7277c86388a68bf8a194b0a14c5538ad13f22cbd8e2a38028a',
// DeepBook Test USDC (DUSDC), 6 decimals.
quoteType:
'0xe95040085976bfd54a1a07225cd46c8a2b4e8e2b6732f140a0fc49850ba73e1a::dusdc::DUSDC',
serverUrl: 'https://predict-server.testnet.mystenlabs.com',
};
// DeepBook Predict has no Mainnet deployment yet, so there is no Mainnet entry
// to select. Add one at launch: every value differs from Testnet, including the
// quote asset, which is a test coin on Testnet and a real asset on Mainnet.
const CONFIGS: Partial<Record<PredictNetwork, PredictConfig>> = {
testnet: TESTNET,
};
export function predictConfigFor(network: PredictNetwork): PredictConfig {
const config = CONFIGS[network];
if (!config) {
throw new Error(`DeepBook Predict has no ${network} deployment.`);
}
return config;
}
// Resolve once at startup and pass the result down, rather than reading the
// network in each module. The examples target Testnet.
export const PREDICT = predictConfigFor('testnet');
// Oracle ID, expiry, and strike are NOT hardcoded. Read a live oracle from the
// Predict server before minting: GET /predicts/:predict_id/oracles.
export type ActiveOracle = {
oracleId: string; // object ID of the OracleSVI
expiry: number; // ms timestamp
strike: number; // fixed-point strike, per oracle scale
};
Set up a client and a signer next. The following example uses the gRPC client, which matches the rest of the DeepBook SDK docs.
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
import { PREDICT } from './config.js';
export function getKeypair(privateKey: string): Ed25519Keypair {
const { secretKey } = decodeSuiPrivateKey(privateKey);
return Ed25519Keypair.fromSecretKey(secretKey);
}
export const client = new SuiGrpcClient({
network: PREDICT.network,
baseUrl: PREDICT.fullnodeUrl,
});
4. Create a PredictManager
Each user creates one PredictManager and reuses it. The create_manager function shares the manager as a new object, so you read its ID from the transaction effects. Because create_manager shares the manager during this transaction, you deposit into it and mint from it in a later transaction, not the same one.
import { Transaction } from '@mysten/sui/transactions';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { client } from './client.js';
import { PREDICT } from './config.js';
// Creates and shares a PredictManager, then returns its object ID.
export async function createManager(signer: Ed25519Keypair): Promise<string> {
const tx = new Transaction();
tx.moveCall({ target: `${PREDICT.packageId}::predict::create_manager` });
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer,
include: { effects: true, objectTypes: true },
});
// Wait for finality before acting on the result, so later reads reflect it.
await client.waitForTransaction({ result });
if (result.$kind === 'FailedTransaction') {
// The transaction is onchain and the sender paid gas. Do not retry it.
const { status } = result.FailedTransaction;
throw new Error(
`create_manager aborted: ${status.success ? 'unknown' : JSON.stringify(status.error)}`,
);
}
const objectTypes = result.Transaction?.objectTypes ?? {};
const managerId = result.Transaction?.effects?.changedObjects?.find(
(obj) =>
obj.idOperation === 'Created' &&
objectTypes[obj.objectId]?.includes('PredictManager'),
)?.objectId;
if (!managerId) {
throw new Error('Could not find created PredictManager in effects');
}
return managerId;
}
5. Mint your first binary position
Read a live oracle from the Predict server, then deposit DUSDC and mint one binary position in a single transaction. A binary position is keyed by oracle, expiry, strike, and direction. This example mints an up position with market_key::up.
import { Transaction } from '@mysten/sui/transactions';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { client } from './client.js';
import { PREDICT, type ActiveOracle } from './config.js';
// Deposits DUSDC into the manager and mints one binary "up" position, in a
// single PTB. The deposit is sourced from the signer's DUSDC wherever it sits,
// whether that is an address balance or several separate coin objects.
export async function mintBinaryUp(params: {
signer: Ed25519Keypair;
managerId: string;
oracle: ActiveOracle;
depositAmount: bigint; // DUSDC base units (6 decimals)
quantity: bigint; // position quantity
}) {
const { signer, managerId, oracle, depositAmount, quantity } = params;
const tx = new Transaction();
// 1. Source the deposit amount in DUSDC and deposit it into the manager.
const deposit = tx.coin({ balance: depositAmount, type: PREDICT.quoteType });
tx.moveCall({
target: `${PREDICT.packageId}::predict_manager::deposit`,
typeArguments: [PREDICT.quoteType],
arguments: [tx.object(managerId), deposit],
});
// 2. Build the MarketKey for an "up" binary position.
const key = tx.moveCall({
target: `${PREDICT.packageId}::market_key::up`,
arguments: [
tx.pure.id(oracle.oracleId),
tx.pure.u64(oracle.expiry),
tx.pure.u64(oracle.strike),
],
});
// 3. Mint the position, paying from the manager's deposited balance.
tx.moveCall({
target: `${PREDICT.packageId}::predict::mint`,
typeArguments: [PREDICT.quoteType],
arguments: [
tx.object(PREDICT.predictObjectId),
tx.object(managerId),
tx.object(oracle.oracleId),
key,
tx.pure.u64(quantity),
tx.object.clock(),
],
});
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer,
include: { effects: true },
});
// Wait for finality before acting on the result, so later reads reflect it.
await client.waitForTransaction({ result });
if (result.$kind === 'FailedTransaction') {
// The transaction is onchain and the sender paid gas. Do not retry it.
const { status } = result.FailedTransaction;
throw new Error(
`mint aborted: ${status.success ? 'unknown' : JSON.stringify(status.error)}`,
);
}
return result.Transaction;
}
The mint succeeds only when the oracle is live, the quote asset is accepted, the market key matches the oracle, and the manager holds enough deposited DUSDC. For preview amounts, call get_trade_amounts before you mint. The end-to-end Testnet tutorial covers previews, vertical ranges, redemption, and the liquidity provider flow.
Verify on Testnet
The samples above pass compile checks but this page does not execute them. To confirm them end to end on Testnet:
- Fund a Testnet address with SUI, then confirm a nonzero balance with
sui client gas. - Request DUSDC through the token request form, then confirm your DUSDC balance with
sui client balance. - Run
createManager, then confirm the returned ID resolves withsui client object MANAGER_ID. - Fetch a live oracle:
curl https://predict-server.testnet.mystenlabs.com/predicts/PREDICT_OBJECT_ID/oracles. Confirm at least one oracle reports an active lifecycle state. - Run
mintBinaryUpwith that oracle, adepositAmountat or above the mint cost, and a smallquantity. Confirm the effects report a success status and aPositionMintedevent.
Key features
DeepBook Predict provides the following capabilities:
- Binary positions: Mint directional positions keyed by oracle, expiry, strike, and direction.
- Vertical ranges: Mint bounded range positions keyed by oracle, expiry, lower strike, and higher strike.
- Oracle-based pricing:
OracleSVIobjects track spot, forward, SVI parameters, lifecycle status, and settlement prices. - Shared manager accounts: Each user reuses one
PredictManagerto hold quote balances, positions, and range quantities. - Vault liquidity: Liquidity providers supply accepted quote assets to the vault and receive
PLPshares that represent a proportional claim on vault value. - Indexed data path: Applications read render-ready market, vault, portfolio, and history data from the public Predict server.
Testnet Workflow
End-to-end DeepBook Predict walkthrough on Sui Testnet: oracle context, PredictManager setup, minting binary and vertical range positions, redemption and settlement, and the liquidity provider vault flow.
Design
Learn about DeepBook Predict design, including Predict, PredictManager, OracleSVI, Vault, and PLP.