@mysten/deepbook-v3 2.6.4 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +153 -0
- package/PREDICT.md +389 -61
- package/dist/contracts/account/account.d.mts +23 -23
- package/dist/contracts/account/account.d.mts.map +1 -1
- package/dist/contracts/account/account_registry.d.mts +13 -13
- package/dist/contracts/deepbook/account.d.mts +18 -18
- package/dist/contracts/deepbook/balances.d.mts +4 -4
- package/dist/contracts/deepbook/deep_price.d.mts +3 -3
- package/dist/contracts/deepbook/order.d.mts +12 -12
- package/dist/contracts/deepbook_predict/admin.d.mts +4 -4
- package/dist/contracts/deepbook_predict/builder_code.d.mts +11 -11
- package/dist/contracts/deepbook_predict/builder_code_events.d.mts +10 -10
- package/dist/contracts/deepbook_predict/config_events.d.mts +93 -68
- package/dist/contracts/deepbook_predict/config_events.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/config_events.mjs +45 -1
- package/dist/contracts/deepbook_predict/config_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/deps/std/type_name.mjs +17 -0
- package/dist/contracts/deepbook_predict/deps/std/type_name.mjs.map +1 -0
- package/dist/contracts/deepbook_predict/expiry_market.d.mts +652 -235
- package/dist/contracts/deepbook_predict/expiry_market.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/expiry_market.mjs +652 -186
- package/dist/contracts/deepbook_predict/expiry_market.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/lp_book.mjs +1 -1
- package/dist/contracts/deepbook_predict/market_lifecycle_cap.d.mts +5 -5
- package/dist/contracts/deepbook_predict/market_manager.d.mts +27 -27
- package/dist/contracts/deepbook_predict/order_events.d.mts +50 -50
- package/dist/contracts/deepbook_predict/order_events.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/order_events.mjs +3 -1
- package/dist/contracts/deepbook_predict/order_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pause_cap.d.mts +5 -5
- package/dist/contracts/deepbook_predict/plp.d.mts +184 -82
- package/dist/contracts/deepbook_predict/plp.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/plp.mjs +126 -7
- package/dist/contracts/deepbook_predict/plp.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pool_accounting.mjs +1 -1
- package/dist/contracts/deepbook_predict/pool_valuation_cap.d.mts +5 -5
- package/dist/contracts/deepbook_predict/predict_account.d.mts +14 -14
- package/dist/contracts/deepbook_predict/pricing.d.mts +91 -58
- package/dist/contracts/deepbook_predict/pricing.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/pricing.mjs +30 -3
- package/dist/contracts/deepbook_predict/pricing.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pricing_config.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/protocol_config.d.mts +400 -92
- package/dist/contracts/deepbook_predict/protocol_config.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/protocol_config.mjs +451 -61
- package/dist/contracts/deepbook_predict/protocol_config.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/range_codec.d.mts +2 -2
- package/dist/contracts/deepbook_predict/registry.d.mts +28 -28
- package/dist/contracts/deepbook_predict/strike_exposure.mjs +1 -1
- package/dist/contracts/deepbook_predict/strike_payout_tree.mjs +17 -12
- package/dist/contracts/deepbook_predict/strike_payout_tree.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/vault_events.d.mts +154 -106
- package/dist/contracts/deepbook_predict/vault_events.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/vault_events.mjs +57 -1
- package/dist/contracts/deepbook_predict/vault_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict_math/config-arguments.d.mts +10 -0
- package/dist/contracts/deepbook_predict_math/config-arguments.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.d.mts +106 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.mjs +125 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_math/math.d.mts +284 -0
- package/dist/contracts/deepbook_predict_math/math.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_math/math.mjs +364 -0
- package/dist/contracts/deepbook_predict_math/math.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/config-arguments.d.mts +13 -0
- package/dist/contracts/deepbook_predict_orders/config-arguments.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.d.mts +215 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.mjs +215 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.mjs +87 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.mjs +52 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/fixed_math/i64.mjs +25 -0
- package/dist/contracts/deepbook_predict_orders/deps/fixed_math/i64.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/balance.mjs +21 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/balance.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/table.mjs +39 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/table.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/desk.d.mts +187 -0
- package/dist/contracts/deepbook_predict_orders/desk.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/desk.mjs +261 -0
- package/dist/contracts/deepbook_predict_orders/desk.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.d.mts +1042 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.mjs +849 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue.d.mts +683 -0
- package/dist/contracts/deepbook_predict_orders/queue.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue.mjs +912 -0
- package/dist/contracts/deepbook_predict_orders/queue.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.d.mts +195 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.mjs +187 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.mjs.map +1 -0
- package/dist/contracts/deepbook_sessions/session_config.d.mts +8 -8
- package/dist/contracts/deepbook_sessions/sessions.d.mts +163 -28
- package/dist/contracts/deepbook_sessions/sessions.d.mts.map +1 -1
- package/dist/contracts/deepbook_sessions/sessions.mjs +234 -5
- package/dist/contracts/deepbook_sessions/sessions.mjs.map +1 -1
- package/dist/deployments/mainnet.mjs +7 -4
- package/dist/deployments/mainnet.mjs.map +1 -1
- package/dist/deployments/testnet.mjs +7 -4
- package/dist/deployments/testnet.mjs.map +1 -1
- package/dist/predict/bindings/expiry-market.d.mts +77 -0
- package/dist/predict/bindings/expiry-market.d.mts.map +1 -0
- package/dist/predict/bindings/expiry-market.mjs +139 -0
- package/dist/predict/bindings/expiry-market.mjs.map +1 -0
- package/dist/predict/bindings/protocol-config.d.mts +39 -0
- package/dist/predict/bindings/protocol-config.d.mts.map +1 -0
- package/dist/predict/bindings/protocol-config.mjs +90 -0
- package/dist/predict/bindings/protocol-config.mjs.map +1 -0
- package/dist/predict/bindings/rename.mjs +9 -0
- package/dist/predict/bindings/rename.mjs.map +1 -0
- package/dist/predict/client.d.mts +595 -16
- package/dist/predict/client.d.mts.map +1 -1
- package/dist/predict/client.mjs +986 -10
- package/dist/predict/client.mjs.map +1 -1
- package/dist/predict/config/generated.d.mts +22 -1
- package/dist/predict/config/generated.d.mts.map +1 -1
- package/dist/predict/config/generated.mjs +30 -1
- package/dist/predict/config/generated.mjs.map +1 -1
- package/dist/predict/config/mainnet.mjs +11 -3
- package/dist/predict/config/mainnet.mjs.map +1 -1
- package/dist/predict/config/testnet.mjs +11 -3
- package/dist/predict/config/testnet.mjs.map +1 -1
- package/dist/predict/config/types.d.mts +50 -1
- package/dist/predict/config/types.d.mts.map +1 -1
- package/dist/predict/cost.d.mts +38 -11
- package/dist/predict/cost.d.mts.map +1 -1
- package/dist/predict/cost.mjs +37 -11
- package/dist/predict/cost.mjs.map +1 -1
- package/dist/predict/decode.d.mts +251 -1
- package/dist/predict/decode.d.mts.map +1 -1
- package/dist/predict/decode.mjs +342 -4
- package/dist/predict/decode.mjs.map +1 -1
- package/dist/predict/errors.d.mts +69 -6
- package/dist/predict/errors.d.mts.map +1 -1
- package/dist/predict/errors.mjs +277 -4
- package/dist/predict/errors.mjs.map +1 -1
- package/dist/predict/index.d.mts +21 -10
- package/dist/predict/index.mjs +24 -12
- package/dist/predict/queue-id.d.mts +13 -0
- package/dist/predict/queue-id.d.mts.map +1 -0
- package/dist/predict/queue-id.mjs +19 -0
- package/dist/predict/queue-id.mjs.map +1 -0
- package/dist/predict/queue.d.mts +505 -0
- package/dist/predict/queue.d.mts.map +1 -0
- package/dist/predict/queue.mjs +774 -0
- package/dist/predict/queue.mjs.map +1 -0
- package/dist/predict/reads/balances.mjs +1 -1
- package/dist/predict/reads/markets.mjs +46 -5
- package/dist/predict/reads/markets.mjs.map +1 -1
- package/dist/predict/reads/pool.mjs +1 -1
- package/dist/predict/reads/pricing.d.mts +1 -1
- package/dist/predict/reads/queue.d.mts +105 -0
- package/dist/predict/reads/queue.d.mts.map +1 -0
- package/dist/predict/reads/queue.mjs +445 -0
- package/dist/predict/reads/queue.mjs.map +1 -0
- package/dist/predict/ticks.d.mts +9 -1
- package/dist/predict/ticks.d.mts.map +1 -1
- package/dist/predict/ticks.mjs +18 -1
- package/dist/predict/ticks.mjs.map +1 -1
- package/dist/predict/tx/authed.mjs +1 -1
- package/dist/predict/tx/common.d.mts.map +1 -1
- package/dist/predict/tx/common.mjs +12 -1
- package/dist/predict/tx/common.mjs.map +1 -1
- package/dist/predict/tx/queue.d.mts +220 -0
- package/dist/predict/tx/queue.d.mts.map +1 -0
- package/dist/predict/tx/queue.mjs +399 -0
- package/dist/predict/tx/queue.mjs.map +1 -0
- package/dist/predict/tx/trade.d.mts.map +1 -1
- package/dist/predict/tx/trade.mjs +61 -43
- package/dist/predict/tx/trade.mjs.map +1 -1
- package/dist/sessions.d.mts +90 -2
- package/dist/sessions.d.mts.map +1 -1
- package/dist/sessions.mjs +107 -2
- package/dist/sessions.mjs.map +1 -1
- package/dist/transactions/balanceManager.d.mts +12 -12
- package/dist/transactions/balanceManager.d.mts.map +1 -1
- package/dist/transactions/deepbook.d.mts +20 -20
- package/dist/transactions/deepbook.d.mts.map +1 -1
- package/dist/transactions/deepbookAdmin.d.mts +4 -4
- package/dist/transactions/deepbookAdmin.d.mts.map +1 -1
- package/dist/transactions/marginAdmin.d.mts +7 -7
- package/dist/transactions/marginAdmin.d.mts.map +1 -1
- package/dist/transactions/marginLiquidations.d.mts +3 -3
- package/dist/transactions/marginMaintainer.d.mts +5 -5
- package/dist/transactions/marginMaintainer.d.mts.map +1 -1
- package/dist/transactions/marginManager.d.mts +32 -32
- package/dist/transactions/marginManager.d.mts.map +1 -1
- package/dist/transactions/marginPool.d.mts +18 -18
- package/dist/transactions/marginRegistry.d.mts +16 -16
- package/dist/transactions/marginTPSL.d.mts +10 -10
- package/dist/transactions/marginTPSL.d.mts.map +1 -1
- package/dist/transactions/poolProxy.d.mts +8 -8
- package/dist/transactions/poolProxy.d.mts.map +1 -1
- package/package.json +4 -4
- package/src/contracts/deepbook_predict/config_events.ts +39 -0
- package/src/contracts/deepbook_predict/deps/std/type_name.ts +24 -0
- package/src/contracts/deepbook_predict/expiry_market.ts +960 -169
- package/src/contracts/deepbook_predict/order_events.ts +3 -1
- package/src/contracts/deepbook_predict/plp.ts +150 -9
- package/src/contracts/deepbook_predict/pricing.ts +46 -7
- package/src/contracts/deepbook_predict/pricing_config.ts +3 -1
- package/src/contracts/deepbook_predict/protocol_config.ts +648 -33
- package/src/contracts/deepbook_predict/strike_payout_tree.ts +25 -21
- package/src/contracts/deepbook_predict/vault_events.ts +65 -0
- package/src/contracts/deepbook_predict_math/config-arguments.ts +6 -0
- package/src/contracts/deepbook_predict_math/lazer_price.ts +196 -0
- package/src/contracts/deepbook_predict_math/math.ts +553 -0
- package/src/contracts/deepbook_predict_orders/config-arguments.ts +11 -0
- package/src/contracts/deepbook_predict_orders/delayed_execution_config.ts +430 -0
- package/src/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.ts +108 -0
- package/src/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.ts +58 -0
- package/src/contracts/deepbook_predict_orders/deps/fixed_math/i64.ts +21 -0
- package/src/contracts/deepbook_predict_orders/deps/sui/balance.ts +19 -0
- package/src/contracts/deepbook_predict_orders/deps/sui/table.ts +37 -0
- package/src/contracts/deepbook_predict_orders/desk.ts +419 -0
- package/src/contracts/deepbook_predict_orders/order_flow.ts +19 -0
- package/src/contracts/deepbook_predict_orders/order_queue.ts +1670 -0
- package/src/contracts/deepbook_predict_orders/queue.ts +1394 -0
- package/src/contracts/deepbook_predict_orders/queue_events.ts +189 -0
- package/src/contracts/deepbook_sessions/sessions.ts +355 -4
- package/src/deployments/mainnet.ts +7 -2
- package/src/deployments/testnet.ts +7 -2
- package/src/deployments/types.ts +14 -1
- package/src/predict/bindings/expiry-market.ts +127 -0
- package/src/predict/bindings/protocol-config.ts +59 -0
- package/src/predict/bindings/rename.ts +14 -0
- package/src/predict/client.ts +2076 -13
- package/src/predict/config/generated.ts +50 -0
- package/src/predict/config/mainnet.ts +16 -2
- package/src/predict/config/testnet.ts +16 -2
- package/src/predict/config/types.ts +51 -1
- package/src/predict/cost.ts +62 -14
- package/src/predict/decode.ts +691 -2
- package/src/predict/errors.ts +391 -14
- package/src/predict/index.ts +87 -6
- package/src/predict/queue-id.ts +22 -0
- package/src/predict/queue.ts +1231 -0
- package/src/predict/reads/markets.ts +30 -0
- package/src/predict/reads/queue.ts +606 -0
- package/src/predict/ticks.ts +35 -0
- package/src/predict/tx/common.ts +25 -1
- package/src/predict/tx/queue.ts +525 -0
- package/src/predict/tx/trade.ts +80 -49
- package/src/sessions.ts +206 -1
package/PREDICT.md
CHANGED
|
@@ -45,41 +45,35 @@ const withdrawTx = client.predict.tx.withdraw(myAddress, 100); // $100
|
|
|
45
45
|
// Pick a market. `read.markets()` lists ACTIVE markets — live and not yet settled — which
|
|
46
46
|
// includes a market past its expiry that nobody has settled yet; quoting against one aborts.
|
|
47
47
|
// Expiries are absolute timestamps, so never hardcode one: filter on `expiryMs`, leaving
|
|
48
|
-
// room to quote, sign and land (and clear the pre-expiry no-trade window).
|
|
48
|
+
// room to quote, sign and land (and clear the pre-expiry no-trade window). A window's reference
|
|
49
|
+
// price is set only once the window opens, so a market listed ahead of its window has
|
|
50
|
+
// `referencePrice: null`, and `strike: 'reference'` throws for it until then.
|
|
49
51
|
const markets = await client.predict.read.markets();
|
|
50
52
|
// -> [{ id, expiryMs, tickSize, admissionTickSize, mintPaused, referencePrice }, ...]
|
|
51
|
-
const tradeable = markets.filter(
|
|
53
|
+
const tradeable = markets.filter(
|
|
54
|
+
(m) => Number(m.expiryMs) > Date.now() + 30_000 && !m.mintPaused && m.referencePrice != null,
|
|
55
|
+
);
|
|
52
56
|
const expiryMs = tradeable[0].expiryMs;
|
|
53
57
|
|
|
54
|
-
// Describe the position once and reuse it
|
|
58
|
+
// Describe the position once and reuse it: pricing, planning and ordering take the same descriptor.
|
|
55
59
|
const desc = { underlying: 'BTC', expiryMs, strike: 'reference', side: 'up' } as const;
|
|
56
60
|
|
|
57
|
-
// Quote before you trade: dry-runs your exact mint, real fees, real account.
|
|
58
|
-
const q = await client.predict.read.quoteMint(myAddress, desc, { quantity: 50 });
|
|
59
|
-
q.entryProbability; // your fill (0..1 per $1 payout)
|
|
60
|
-
q.cost; // exact all-in debit
|
|
61
|
-
|
|
62
|
-
// Trade. `maxCost` is your ceiling on the all-in debit — pass the quote plus a buffer,
|
|
63
|
-
// rounded to 6 decimals, since raw amounts are integers at that scale.
|
|
64
|
-
const mintTx = await client.predict.tx.mint(myAddress, desc, {
|
|
65
|
-
quantity: 50,
|
|
66
|
-
maxCost: Math.ceil(q.cost * 1.01 * 1e6) / 1e6,
|
|
67
|
-
});
|
|
68
|
-
// -> sign & execute any of these with your wallet / dapp-kit / signer
|
|
69
|
-
|
|
70
61
|
// Anonymous board price (no account needed): both sides of any strike.
|
|
71
|
-
const { up, down } = await client.predict.read.price(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
62
|
+
const { up, down } = await client.predict.read.price(desc);
|
|
63
|
+
|
|
64
|
+
// Trade. Orders are queued: placed now and filled about a second later at Pyth's price, within
|
|
65
|
+
// the plan's slippage, or refunded. `planMint` quotes the order at the current price and turns
|
|
66
|
+
// the slippage (cents per contract, never a percentage) into the limits the enqueue carries.
|
|
67
|
+
// Once the price moves, the reference strike can leave the market's entry band, and `planMint`
|
|
68
|
+
// then throws `entry-band`: see Queued orders for picking a strike near the money.
|
|
69
|
+
const plan = await client.predict.read.planMint(myAddress, desc, { amount: 10, slippageCents: 10 });
|
|
70
|
+
plan.accepting; // false, with plan.refusal, when the enqueue would be refused now
|
|
71
|
+
const { transaction } = await client.predict.tx.enqueuePlan(myAddress, desc, plan);
|
|
72
|
+
// -> sign & execute any of these with your wallet / dapp-kit / signer
|
|
76
73
|
|
|
77
|
-
// Decode the
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
receipt.entryProbability; // your fill price (0..1 per $1 payout)
|
|
81
|
-
receipt.premium; // exact cost breakdown
|
|
82
|
-
receipt.fees;
|
|
74
|
+
// Decode the enqueue from the execution result (execute with events included).
|
|
75
|
+
const { recordId } = client.predict.decode.enqueue(result); // PERSIST THIS: sell or follow the order
|
|
76
|
+
const outcome = await client.predict.read.waitForOutcome(desc, recordId); // 'filled' or 'refunded'
|
|
83
77
|
|
|
84
78
|
// Read: one market's live state (+ NAV) and the pool.
|
|
85
79
|
const market = await client.predict.read.market({ underlying: 'BTC', expiryMs });
|
|
@@ -87,6 +81,303 @@ console.log(market?.nav, market?.tickSize, market?.mintPaused);
|
|
|
87
81
|
const pool = await client.predict.read.pool();
|
|
88
82
|
```
|
|
89
83
|
|
|
84
|
+
> **Immediate trades retire with delayed execution.** Until a network's cutover,
|
|
85
|
+
> `read.executionMode()` is `'immediate'` and orders fill in the transaction: quote with
|
|
86
|
+
> `read.quoteMint`, trade with `tx.mint` (`quantity` and a `maxCost` ceiling), and decode with
|
|
87
|
+
> `decode.mint`, whose `orderId` redeems or claims the position. `mint`, `mintAmount`, `mintCost`
|
|
88
|
+
> and `redeem` work only while the config calls a pre-v4 Predict package. Predict v4 always aborts
|
|
89
|
+
> them (`EDelayedExecutionRequired`), and the version watermark bump to 4 retires the older
|
|
90
|
+
> packages. From then on orders are queued: see [Queued orders](#queued-orders-delayed-execution).
|
|
91
|
+
> Branch on `read.executionMode()` rather than a release date.
|
|
92
|
+
|
|
93
|
+
## Queued orders (delayed execution)
|
|
94
|
+
|
|
95
|
+
With delayed execution (Predict v4, DBU-885) an order is placed now and filled later, at Pyth's
|
|
96
|
+
signed price for its τ: the Pyth Lazer channel tick at or before placement + the policy delay (800
|
|
97
|
+
ms on the 200 ms channel at launch). A keeper, or anyone running the open filler, commits the price
|
|
98
|
+
and resolves the order: a fill, or a refund with a reason code. A filled mint stays in the market's
|
|
99
|
+
queue as an **Open record**, not in the account. Sell it early with `enqueueSell`, or let the
|
|
100
|
+
queue's settlement walk pay it at settlement.
|
|
101
|
+
|
|
102
|
+
Delayed execution spans three packages. Predict (upgraded to v4) keeps the markets, pricing, cash
|
|
103
|
+
and settlement. The order-flow package `deepbook_predict_orders` holds the queue: each market has
|
|
104
|
+
one `MarketQueue`, at an ID derived from the package's single `QueueRegistry` and the market
|
|
105
|
+
(`client.predict.queueIdFor(marketId)`, or `deriveQueueId(registry, market)`), and its single
|
|
106
|
+
`OrderDesk` holds the policy (delay, order fee, capacities). The math library
|
|
107
|
+
`deepbook_predict_math` holds the pure pricing math. Every queued-order call goes to
|
|
108
|
+
`deepbook_predict_orders`, while a fill still emits Predict's `OrderMinted` or `LiveOrderRedeemed`.
|
|
109
|
+
|
|
110
|
+
> Both the Testnet and Mainnet configs record delayed execution. On a network without a record the
|
|
111
|
+
> queued surface throws `PredictInputError`. Pass a `config` with
|
|
112
|
+
> `packages.predictDelayedExecution`, `packages.predictOrders`, `objects.orderDesk` and
|
|
113
|
+
> `objects.queueRegistry` set (a localnet publish) to use it there. Until a network's version
|
|
114
|
+
> watermark reaches 4, `read.executionMode()` returns `'awaiting-cutover'` and Predict's admission
|
|
115
|
+
> refuses enqueues.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { snapStrike } from '@mysten/deepbook-v3/predict';
|
|
119
|
+
|
|
120
|
+
// Which path is live? 'immediate' | 'awaiting-cutover' | 'delayed' | 'unsupported' | 'retired'.
|
|
121
|
+
const mode = await client.predict.read.executionMode();
|
|
122
|
+
|
|
123
|
+
// The market's queue: the "pricing delayed" gate, τ / deadline / cutoff preview, the order fee,
|
|
124
|
+
// and the largest mint the market's spare cash takes now.
|
|
125
|
+
const queue = await client.predict.read.queue(desc, myAddress);
|
|
126
|
+
queue.stuck; // show "pricing delayed" and stop offering orders
|
|
127
|
+
queue.acceptingMints; // and queue.acceptingSells: one side can be full while the other is open
|
|
128
|
+
queue.refusal.mint; // the preflight code a mint would get now, or null
|
|
129
|
+
queue.maxMint.budget.maxRaw; // "Max right now" for a budget mint, raw USDC
|
|
130
|
+
|
|
131
|
+
// A strike near the money. Admission refuses an entry price outside the market's band, which each
|
|
132
|
+
// market snapshots at creation (`read.feePolicy`): 0.25–0.75 on Mainnet, and 0.15–0.85 on Testnet
|
|
133
|
+
// markets created since 2026-10-13. Once the price moves away from a window's reference, the
|
|
134
|
+
// reference strike can sit outside it.
|
|
135
|
+
const pricer = await client.predict.read.pricer(desc);
|
|
136
|
+
const atm = snapStrike(pricer.strikeAtProbability(0.5)!, tradeable[0].admissionTickSize);
|
|
137
|
+
const atmDesc = { ...desc, strike: atm };
|
|
138
|
+
|
|
139
|
+
// Plan, then queue. `planMint` quotes the order at the current price and turns the slippage into
|
|
140
|
+
// the limits the enqueue carries. Slippage is cents per contract, never a percentage: a contract
|
|
141
|
+
// pays $1, so 10¢ lets a 42¢ contract fill at up to 52¢, fees included.
|
|
142
|
+
const plan = await client.predict.read.planMint(myAddress, atmDesc, {
|
|
143
|
+
amount: 10,
|
|
144
|
+
slippageCents: 10,
|
|
145
|
+
});
|
|
146
|
+
const { transaction, preview } = await client.predict.tx.enqueuePlan(myAddress, atmDesc, plan);
|
|
147
|
+
preview.timing.tauMs; // when it prices
|
|
148
|
+
preview.totalDebit; // budget + order fee, debited at enqueue. Unused budget comes back at the fill
|
|
149
|
+
|
|
150
|
+
// After execution (with events included): the record ID is the handle for everything else.
|
|
151
|
+
// Persist it. `waitForOutcome` keeps polling a record the fullnode doesn't show yet.
|
|
152
|
+
const { recordId } = client.predict.decode.enqueue(result);
|
|
153
|
+
const outcome = await client.predict.read.waitForOutcome(atmDesc, recordId);
|
|
154
|
+
outcome.order?.view; // 'filled' (an Open record holding the position) or 'refunded' (with a reason)
|
|
155
|
+
|
|
156
|
+
// Sell an Open record early: plan it, then queue the sell with the plan's floors.
|
|
157
|
+
const sellPlan = await client.predict.read.planSell(myAddress, desc, {
|
|
158
|
+
recordId,
|
|
159
|
+
quantity: 50,
|
|
160
|
+
slippageCents: 10,
|
|
161
|
+
});
|
|
162
|
+
const sell = await client.predict.tx.enqueuePlan(myAddress, desc, sellPlan);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The plan and preview types are exported (`MintPlan`, `SellPlan`, `PlanMintOptions`,
|
|
166
|
+
`PlanSellOptions`, `SlippageOptions`, `QueuedOrderPlan`, `QueuedOrderPreview`), so form state can be
|
|
167
|
+
typed without `ReturnType`.
|
|
168
|
+
|
|
169
|
+
#### After expiry: showing the result
|
|
170
|
+
|
|
171
|
+
At expiry a keeper settles the market, pays every Open record its settled payout (the full quantity
|
|
172
|
+
in range, 0 out of range) into the owner's account, and cleans the records up. On Testnet all of
|
|
173
|
+
that lands within about a second of expiry. So by the time an app looks:
|
|
174
|
+
|
|
175
|
+
- `read.order` returns `null` and `waitForOutcome` ends `'gone'` for a filled record. After expiry
|
|
176
|
+
that means the market paid it out, not that the order was lost.
|
|
177
|
+
- `read.market`, `read.price` and the quotes abort `ELivePricingExpired`.
|
|
178
|
+
- `read.settlement` still works. Keep each filled record's `position.orderId` (from
|
|
179
|
+
`waitForOutcome`, `read.order` or `decode.queuedFills`) and pass it to `cost.settledPayout`.
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { cost } from '@mysten/deepbook-v3/predict';
|
|
183
|
+
|
|
184
|
+
const s = await client.predict.read.settlement(desc);
|
|
185
|
+
if (s.settled) {
|
|
186
|
+
const payoutRaw = cost.settledPayout(orderId, s.settlementPriceRaw!, s.tickSizeRaw);
|
|
187
|
+
const won = payoutRaw > 0n; // payoutRaw is raw USDC, already in the account's balance
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The payout also arrives as an `OpenRecordSettled` event (`decode.openRecordPayouts`) in the keeper's
|
|
192
|
+
transaction, which an indexer serves. If the payout walk skipped a record
|
|
193
|
+
(`OpenRecordPayoutSkipped`), the record stays Open until `tx.payOpen` pays it.
|
|
194
|
+
|
|
195
|
+
#### A purchase form
|
|
196
|
+
|
|
197
|
+
`read.planMint(owner, market, opts)` returns everything a purchase form shows, for a visitor without
|
|
198
|
+
an account too (the quote then comes from the account-free `quote_mint`, which leaves out an
|
|
199
|
+
account's builder fee). An account whose balance covers the order is quoted at its own pricing, and
|
|
200
|
+
a budget that pricing refuses is never planned from the account-free quote. `amount` plans an all-in
|
|
201
|
+
spend and is the whole debit by default, order fee included (`orderFee: 'exclusive'` charges the fee
|
|
202
|
+
on top). `quantity` plans an exact payout instead.
|
|
203
|
+
|
|
204
|
+
| Form field | Plan field |
|
|
205
|
+
| ------------------------------ | ----------------------------------------------------------------------------- |
|
|
206
|
+
| Lower / upper bound | `snapStrike(price, market.admissionTickSize, 'down' \| 'up')` before planning |
|
|
207
|
+
| Trade balance | `balance.available` (null without an account), `balance.covers` |
|
|
208
|
+
| Purchase presets, "Max" | `maxNow`: the most the market's spare cash and the balance take now |
|
|
209
|
+
| Payout multiple | `payoutMultiple` (at the current price, order fee included) |
|
|
210
|
+
| Potential payout | `potentialPayout`, and `minPayout` at the worst price |
|
|
211
|
+
| Price per contract | `pricePerContract`, and `worstPricePerContract` (unsubsidized, plus slippage) |
|
|
212
|
+
| Max slippage | `slippageCents` in, `slippage.cents` out (`'auto'` sizes it from the model) |
|
|
213
|
+
| Order fee | `orderFee`, read from the order desk every time |
|
|
214
|
+
| "Pricing in about a second" | `timing.tauMs`, `timing.deadlineMs` |
|
|
215
|
+
| Disabled button and its reason | `accepting`, `refusal` (the preflight code a mint would get now) |
|
|
216
|
+
|
|
217
|
+
A budget plan's fill buys what the budget buys at τ and is refunded with the order fee returned when
|
|
218
|
+
that is below `minPayout`. An exact plan's fill is refunded when the entry probability or the all-in
|
|
219
|
+
cost passes its cap. The limits are sized from the price without the fee subsidy, because enqueue
|
|
220
|
+
admission checks the order without it and the subsidy can run out before the fill. A budget plan's
|
|
221
|
+
payout floor is also checked with an exact quote at that quantity, so it never asks for more than
|
|
222
|
+
admission buys. The quote, the payout multiple and `pricePerContract` show the subsidized price the
|
|
223
|
+
fill is expected to charge. A budget plan needs a premium of at least 1 USDC, so a smaller budget,
|
|
224
|
+
or an amount the order fee takes whole, is refused with `min-premium`. `planSell` returns the sell
|
|
225
|
+
side: `proceeds`, `net` (after the order fee, negative when the fee is above the proceeds),
|
|
226
|
+
`minProceeds` and `minNet` at the worst price, and the `enqueueSell` options. A `slippageCents` of
|
|
227
|
+
0, or a few cents, is accepted but leaves the price little room to move between the quote and τ.
|
|
228
|
+
Such an order is often refused at placement (`EOrderFailsLimits`, by the build's dry run or on
|
|
229
|
+
chain, where gas is spent) or refunded at the fill, and a refund keeps the order fee. `'auto'` sizes
|
|
230
|
+
the room from the model.
|
|
231
|
+
|
|
232
|
+
- **Preflight, typed.** Each `enqueue*` builder reads the market once and refuses, with a
|
|
233
|
+
`PredictPreflightError` and a `code`, an order the queue or protocol gates would abort: `not-live`
|
|
234
|
+
(the watermark isn't raised, or Predict doesn't allowlist the order-flow package yet), `no-queue`
|
|
235
|
+
(the market's `MarketQueue` isn't created yet), `retired` (a Predict upgrade raised the watermark
|
|
236
|
+
above the Predict code this SDK calls, or the desk's version floor retired the order-flow package
|
|
237
|
+
it calls), `paused`, `stuck`, `past-cutoff`, `queue-full`, `account-cap`, `fee` (prompt a top-up:
|
|
238
|
+
a mint needs a balance above the order fee, a sell at least the fee), `market-cash`,
|
|
239
|
+
`min-premium`, `entry-band`, `below-min-sell`, `record-not-open`, `not-record-owner`. A plan's
|
|
240
|
+
`accepting` and `refusal` run the same preflight on the plan's order, so the form's button never
|
|
241
|
+
enables an order its enqueue refuses. A mint plan also refuses `fee` when the balance doesn't
|
|
242
|
+
cover `totalDebit`, `min-premium` when a budget buys less than the minimum premium without the fee
|
|
243
|
+
subsidy, and `cost-above-payout` when the unsubsidized cost is above the payout, or for a budget,
|
|
244
|
+
about the payout. `tx.enqueuePlan` takes the descriptor a mint plan was planned with, or the
|
|
245
|
+
coordinates `planSell` took for a sell plan. It throws a refused plan's code, and `fee` when the
|
|
246
|
+
balance now escrows less than the plan's budget. It also throws a `PredictInputError` when called
|
|
247
|
+
with another owner, market, strike, side or record than the plan's `target`, since the plan's
|
|
248
|
+
limits fit only that order, and when the order fee rose since the plan, since the plan's debit and
|
|
249
|
+
a sell's net assume its fee. A plan made with `strike: 'reference'` is refused once the reference
|
|
250
|
+
strike moves. When the chain refuses to quote a plan, `planMint` throws a typed refusal where it
|
|
251
|
+
can tell why: `entry-band` for a strike outside the market's entry band, `min-premium` for an
|
|
252
|
+
order whose premium is below 1 USDC. The probability can still leave the band between plan and
|
|
253
|
+
placement, which the chain refuses with `EOrderFailsLimits`. A plan on a market past its expiry
|
|
254
|
+
throws `past-cutoff`, since the chain has no live price to quote. `planSell` throws
|
|
255
|
+
`record-not-open` for a record that isn't Open, and a `PredictInputError` for more than the record
|
|
256
|
+
holds, since the chain can't quote either. Two admission conditions are checked only on chain, at
|
|
257
|
+
placement: the market's SVI age under the order desk's `svi_max_age_ms`, and room in the payout
|
|
258
|
+
tree for a new strike's boundary nodes. A refused order never fails the rest of a transaction. The
|
|
259
|
+
order's own price limits are checked only on chain, at placement (`EOrderFailsLimits`), and the
|
|
260
|
+
preview runs on the local clock, so near the cutoff the chain can still refuse: decode that with
|
|
261
|
+
`describePredictError`. `EOrderFailsLimits` also covers admission: an entry price outside the
|
|
262
|
+
market's band, or a premium below the minimum. `planMint` throws `entry-band` when the strike's
|
|
263
|
+
price is outside the band, before any plan exists, so pick a strike with
|
|
264
|
+
`pricer.strikeAtProbability` and `snapStrike` rather than offering one far from the money.
|
|
265
|
+
- **Pricing aborts.** Every quote, plan and enqueue loads the market's live pricer, which aborts in
|
|
266
|
+
Predict's `pricing` module while an oracle input is missing or stale
|
|
267
|
+
(`EBlockScholesPriceUnavailable`, `EBlockScholesPriceStale`, and the SVI and Pyth forms). These
|
|
268
|
+
clear once the oracles write again, usually within seconds, and `describePredictError` gives each
|
|
269
|
+
a "try again" text. The plan's quote can pass and the enqueue still abort, so a submitted order
|
|
270
|
+
can fail this way too: offer a retry rather than an error page.
|
|
271
|
+
- **Plans are snapshots.** A plan's quote, limits, fee and gates are read once, when it is made, and
|
|
272
|
+
the SDK never expires a plan. `tx.enqueuePlan` reads the gates and the balance again and refuses a
|
|
273
|
+
refused plan, a smaller escrow, a fee rise, another target or a moved reference strike, but it
|
|
274
|
+
keeps the plan's limits. Every enqueue the facade builds starts with
|
|
275
|
+
`queueTx.assertOrderFeeAtMost`, which aborts the transaction (`option::EOPTION_NOT_SET`, described
|
|
276
|
+
by `describePredictError`) when the desk's fee rose between building and execution, since the
|
|
277
|
+
enqueue charges the fee at execution and takes no fee bound. An old plan still places at the old
|
|
278
|
+
price's limits, which then fill or refund at τ, so plan again when the price has moved or the user
|
|
279
|
+
has waited. The timing preview (`tauMs`, `deadlineMs`, `beforeCutoff`) runs on the device clock,
|
|
280
|
+
and the chain's clock decides, so a skewed device clock shows the wrong countdown and can let an
|
|
281
|
+
order past the cutoff preflight. The market's oracle objects (the Pyth feed and the Block Scholes
|
|
282
|
+
stores) come from the config, which pins them per deployment: a feed re-bound on chain aborts
|
|
283
|
+
`EWrongPythFeed` or `EWrongBlockScholesValueStore` until the SDK, or a `config` override, records
|
|
284
|
+
the new one. A session key's raw `SessionsContract` call skips the facade's preflight and plan
|
|
285
|
+
binding, so check the plan's `accepting` and send the plan's own strike and limits.
|
|
286
|
+
- **Order states.** `read.order(s)` returns each record with `queue.orderView`: `placed` (with
|
|
287
|
+
`awaitingPrice` once τ passes), `priced` (the committed price and a countdown to the deadline),
|
|
288
|
+
then `filled` or `refunded`. A filler that commits a price and resolves the order in one
|
|
289
|
+
transaction moves it from `placed` straight to `filled`, so a UI can't count on seeing `priced`.
|
|
290
|
+
Report "Filled" only from the record or the `QueuedOrderFilled` event. For an indexer or event
|
|
291
|
+
feed, `decode.queueEvents` + `queue.reduceOrderEvents` build the same states.
|
|
292
|
+
- **Refunds.** Keepers refund an unfinished order at its deadline (τ + 5 s). Offer "Refund my order"
|
|
293
|
+
(`tx.refund(m)`) only when `view.canRequestRefund` is true, 5 s past the deadline. It needs no
|
|
294
|
+
account or Pyth key and works during a freeze. Never prepend it to other transactions.
|
|
295
|
+
`queue.REFUND_REASONS` maps each reason to its text and fee treatment: reasons 1 and 2 keep the
|
|
296
|
+
order fee, the rest return it, 8 means the market couldn't pay at the fill, and 9 means the
|
|
297
|
+
account's receive address couldn't take USDC (it is on USDC's deny list, or USDC is paused).
|
|
298
|
+
- **Parked funds.** Nothing sends USDC to a denied address. A fill for a denied receive address is
|
|
299
|
+
refused (reason 9), and a refund or change the address can't take stays in its record
|
|
300
|
+
(`RecordFundsParked`, `view.parkedRaw`). Once the address is clear, `tx.claimParked(m, recordId)`
|
|
301
|
+
sends it there. A settled Open record whose payout was skipped (short of cash, or a denied
|
|
302
|
+
address) is paid with `tx.payOpen(m, recordId)`. Both are permissionless: anyone can send them,
|
|
303
|
+
and the USDC goes only to the record's own receive address. Each queue call that can send USDC
|
|
304
|
+
reads Sui's shared `DenyList` (`0x403`) read-only, which the builders add on their own.
|
|
305
|
+
- **Big sells.** A sell's cash need above spare cash sets `preview.needsFunding`. By default the
|
|
306
|
+
builder adds `rebalance_expiry_cash` after the enqueue so the market is funded at once
|
|
307
|
+
(`fundMarket: 'auto' | 'always' | 'never'`). A sell still uncovered at the fill is refunded in
|
|
308
|
+
full and its position returns to an Open record.
|
|
309
|
+
- **Positions.** A filled mint is an Open record in the market's queue, not a position in the
|
|
310
|
+
account, so `read.positions(owner)` doesn't list it. The SDK has no indexer client, so the app
|
|
311
|
+
supplies record IDs from its enqueue receipts or its indexer, and reads them with `read.orders`.
|
|
312
|
+
`claimSettled` still pays positions minted into the account before delayed execution. Pending
|
|
313
|
+
refunds and proceeds sent to the account show in `read.pendingFunds(owner)` (already counted in
|
|
314
|
+
`read.balance`).
|
|
315
|
+
- **The open filler.** `tx.fill(m, { payloads })` verifies signed Lazer payloads with the current
|
|
316
|
+
Lazer package (read from Lazer's `State` per call), commits them and resolves up to `maxOrders`
|
|
317
|
+
records. Anyone with Lazer access can run one.
|
|
318
|
+
- **Settlement.** After Predict's `try_settle`, the queue's `settle_step` refunds the orders still
|
|
319
|
+
waiting (reason 5) and then pays each Open record its settled payout to the account's wrapper
|
|
320
|
+
address (`OpenRecordSettled`, 0 for a loser). One call per transaction until it returns
|
|
321
|
+
`queue.SETTLE_PHASE.DONE`. DONE means the walk reached the last record: a record the market
|
|
322
|
+
couldn't pay stays Open with `OpenRecordPayoutSkipped`, for a later `pay_open`. `settle_step` is
|
|
323
|
+
permissionless, so its refund events carry whoever sent the transaction as `sender`.
|
|
324
|
+
- **Pure helpers** in the `queue` namespace: the cash-need formulas (ported 1:1 from
|
|
325
|
+
`deepbook_predict_math::math`), `maxMintNow`, `previewTiming`, `orderCutoffMs`, and
|
|
326
|
+
`slippageBand`, a heuristic `Δp ≈ k · φ(Φ⁻¹(p)) · √(h / T)` for sizing `maxProbability` /
|
|
327
|
+
`minProbability` that still needs product sign-off. `queueTx` has the thunks for composing an
|
|
328
|
+
enqueue into your own PTB (`queueTx.enqueueExactCost(toOrdersConfig(cfg), …)`), plus the keeper's
|
|
329
|
+
`createQueue` (registry, desk and market), `commit`, `resolve`, `refund`, `adminRefund`,
|
|
330
|
+
`settleStep`, `payOpen`, `claimParked` and `cleanup`. `SessionsContract` has the `enqueue*`
|
|
331
|
+
session wrappers, which take the `orderDesk` and the `queueRegistry` and need Sessions v3, which
|
|
332
|
+
`getSessionsConfig` records on both networks.
|
|
333
|
+
|
|
334
|
+
#### Queued orders from a session key
|
|
335
|
+
|
|
336
|
+
A session key trades the owner's account, so plan against the owner and send the plan's raw limits
|
|
337
|
+
through the `SessionsContract` wrapper. The session key signs, sends and pays its own gas, and
|
|
338
|
+
`decode.enqueue` and `waitForOutcome` work as they do for an owner's enqueue.
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
342
|
+
import { binaryRangeTicks, priceToRaw } from '@mysten/deepbook-v3/predict';
|
|
343
|
+
import { SessionsContract, getSessionsConfig } from '@mysten/deepbook-v3/sessions';
|
|
344
|
+
|
|
345
|
+
const sessions = new SessionsContract(getSessionsConfig('testnet'));
|
|
346
|
+
const { objects, underlyings } = client.predict.cfg;
|
|
347
|
+
const target = {
|
|
348
|
+
expiryMarketId: tradeable[0].id,
|
|
349
|
+
wrapperId: sessions.deriveAccountWrapperId(owner),
|
|
350
|
+
orderDesk: objects.orderDesk!,
|
|
351
|
+
queueRegistry: objects.queueRegistry!,
|
|
352
|
+
protocolConfig: objects.protocolConfig,
|
|
353
|
+
oracleRegistry: objects.oracleRegistry,
|
|
354
|
+
pythFeed: underlyings.BTC.pythFeed,
|
|
355
|
+
blockScholesValueStore: underlyings.BTC.blockScholesValueStore,
|
|
356
|
+
blockScholesSviStore: underlyings.BTC.blockScholesSviStore,
|
|
357
|
+
};
|
|
358
|
+
const plan = await client.predict.read.planMint(owner, atmDesc, { amount: 10, slippageCents: 10 });
|
|
359
|
+
const { lowerTick, higherTick } = binaryRangeTicks(
|
|
360
|
+
priceToRaw(atm),
|
|
361
|
+
'up',
|
|
362
|
+
priceToRaw(tradeable[0].tickSize),
|
|
363
|
+
);
|
|
364
|
+
const tx = new Transaction();
|
|
365
|
+
tx.add(
|
|
366
|
+
sessions.enqueueExactCost({
|
|
367
|
+
...target,
|
|
368
|
+
lowerTick,
|
|
369
|
+
higherTick,
|
|
370
|
+
maxCost: plan.raw.budget,
|
|
371
|
+
minQuantity: plan.raw.minQuantity,
|
|
372
|
+
}),
|
|
373
|
+
);
|
|
374
|
+
// Sell an Open record the same way: `enqueueRedeemOpen` with the record's quantity and
|
|
375
|
+
// `planSell(owner, …).raw.minProbability` / `.raw.minProceeds`.
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
A revoked or expired key aborts `sessions::ESessionNotAuthorized`, which `describePredictError`
|
|
379
|
+
explains along with the other Sessions and account aborts.
|
|
380
|
+
|
|
90
381
|
## ⚠ Slippage defaults are UNCAPPED
|
|
91
382
|
|
|
92
383
|
`mint` mirrors the chain's semantics: when you omit `maxCost` and `maxProbability`, the mint is
|
|
@@ -189,9 +480,12 @@ const tx = await client.predict.tx.mint(
|
|
|
189
480
|
|
|
190
481
|
- **`client.predict.tx`** — `createManager`, `deposit`, `withdraw`, `mint`, `mintAmount`,
|
|
191
482
|
`mintCost`, `redeem`, `claimSettled`, `supplyPlp`, `withdrawPlp`, `cancelSupplyPlp`,
|
|
192
|
-
`cancelWithdrawPlp`, `setBuilderCode`, `unsetBuilderCode
|
|
193
|
-
|
|
194
|
-
|
|
483
|
+
`cancelWithdrawPlp`, `setBuilderCode`, `unsetBuilderCode`, and for queued orders `enqueuePlan`,
|
|
484
|
+
`enqueueMint`, `enqueueMintAmount`, `enqueueMintCost`, `enqueueSell`, `refund`, `claimParked`,
|
|
485
|
+
`payOpen`, `fill` (see [Queued orders](#queued-orders-delayed-execution)). Market-resolving
|
|
486
|
+
builders (`mint`/`mintAmount`/`mintCost`/`redeem`/`claimSettled`) are async: they resolve the
|
|
487
|
+
market object from `{ underlying, expiryMs, strike, side }` via the on-chain registry (cached per
|
|
488
|
+
client).
|
|
195
489
|
- **`client.predict.read`** — `markets()` (summaries of the pool's **active** markets — live and not
|
|
196
490
|
yet settled, so a market past expiry that nobody has settled is still listed and quoting against
|
|
197
491
|
it aborts; filter on `expiryMs` and `mintPaused` before trading: id, expiry, tick size, admission
|
|
@@ -201,27 +495,42 @@ const tx = await client.predict.tx.mint(
|
|
|
201
495
|
`quoteMint(owner, m, opts)` / `quoteMintCost(owner, m, opts)` / `quoteRedeem(owner, m, opts)`
|
|
202
496
|
(exact dry-run quotes: real fees from the real code path — and they throw the same typed errors
|
|
203
497
|
the real trade would, so a quote doubles as preflight), `balance(owner)`, `plpBalance(owner)`,
|
|
204
|
-
`pool()`, `
|
|
205
|
-
|
|
206
|
-
|
|
498
|
+
`pool()`, `feePolicy(m)` (the market's fee snapshot, for `cost`), `settlement(m)` (the settlement
|
|
499
|
+
price, which still reads after expiry, when `market` and the quotes abort), `positions(owner)`
|
|
500
|
+
(chain-only enumeration of open positions), `hasPosition(owner, marketId, orderId)`, and for
|
|
501
|
+
queued orders `executionMode()`, `queue(m)`, `planMint(owner, m, opts)`,
|
|
502
|
+
`planSell(owner, m, opts)`, `order(m, id)`, `orders(m, ids)`, `waitForOutcome(m, id)`,
|
|
503
|
+
`quoteSell(owner, m, opts)`, `pendingFunds(owner)`, `lazerPackages()`. All reads run over the
|
|
504
|
+
client's `simulateTransaction`; no indexer required.
|
|
207
505
|
- **`client.predict.decode`** — pure execution-result decoders (no network): `mint`, `redeem`,
|
|
208
506
|
`claim`, `createManager`, `deposit`, `withdraw`, `plpRequest`, `plpCancel`, `builderCode`. Each
|
|
209
507
|
singular form throws unless exactly one matching event is present; `mints`, `redeems` and `claims`
|
|
210
508
|
are the plural forms for batched PTBs and return every receipt (the other decoders have no
|
|
211
509
|
plural). Execute transactions with events included and pass the result; receipts come back in SDK
|
|
212
510
|
units with raw bigints alongside. Decoding uses the events' canonical BCS bytes, so it is
|
|
213
|
-
transport-independent.
|
|
511
|
+
transport-independent. The queue decoders (`enqueue`, `queueEvents`, `cohortCommits`,
|
|
512
|
+
`queuedFills`, `queuedRefunds`, `openRecordPayouts`, `marketPayoutsCompleted`, `queueOps`) match
|
|
513
|
+
the order-flow package's `queue_events` against its original ID
|
|
514
|
+
(`packages.predictOrdersV1 ?? predictOrders`). `expiryPnlRealized` matches against
|
|
515
|
+
`packages.predictDelayedExecution`, the Predict version that introduced it, and `policyUpdates`
|
|
516
|
+
decodes the desk's `DelayedExecutionPolicyUpdated` and Predict's `FlushOperatorUpdated` and
|
|
517
|
+
`OrderFlowUpdated`. `realizedPnlRaw` sums `expiryPnlRealized` receipts into the pool's gross
|
|
518
|
+
realized P&L.
|
|
214
519
|
- **PTB composition** — each `client.predict.tx.*` builder returns a finished `Transaction`, so to
|
|
215
520
|
put a Predict call into a PTB you are building, use the generated move-call bindings `/predict`
|
|
216
521
|
exports: one namespace of transaction thunks per Predict module (`plpMoveCalls`,
|
|
217
522
|
`expiryMarketMoveCalls`, `predictAccountMoveCalls`, `protocolConfigMoveCalls`,
|
|
218
523
|
`registryMoveCalls`, `builderCodeMoveCalls`, `marketManagerMoveCalls`, `pricingMoveCalls`,
|
|
219
524
|
`rangeCodecMoveCalls`, `adminMoveCalls` and the cap modules) plus the event layouts
|
|
220
|
-
(`vaultEvents`, `orderEvents`, `configEvents`, `builderCodeEvents`).
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
525
|
+
(`vaultEvents`, `orderEvents`, `configEvents`, `builderCodeEvents`). The order-flow package's
|
|
526
|
+
bindings are `queueMoveCalls`, `deskMoveCalls`, `orderQueueMoveCalls`,
|
|
527
|
+
`delayedExecutionConfigMoveCalls` and `queueEvents`, and the math library's are
|
|
528
|
+
`predictMathMoveCalls` and `lazerPriceMoveCalls`. Pass `config: toGeneratedConfig(cfg)` — the flat
|
|
529
|
+
config slice the bindings resolve the shared objects against, or `toOrdersConfig(cfg)` for the
|
|
530
|
+
order-flow package, which adds it and its desk — and give owner-authorized calls
|
|
531
|
+
`auth: tx.add(generateAuth(cfg))`, the hot-potato `Auth` the account calls consume. The account
|
|
532
|
+
itself (create, deposit, share) is `@mysten/deepbook-v3/account`'s `accountRegistryMoveCalls` /
|
|
533
|
+
`accountMoveCalls`. Also exported:
|
|
225
534
|
`loadLivePricer(toGeneratedConfig(cfg), { expiryMarketId, ...cfg.underlyings[sym] })` — the
|
|
226
535
|
`pricer` every live trade call borrows, which the `/sessions` Predict wrappers take as a PTB
|
|
227
536
|
result — and `deriveAccountWrapperId(cfg, owner)`.
|
|
@@ -248,8 +557,8 @@ const tx = await client.predict.tx.mint(
|
|
|
248
557
|
|
|
249
558
|
- **`cost`** — the deployed FEE math as an exact integer port, so an all-in quote costs no chain
|
|
250
559
|
call: `mintCost` (what a mint debits), `mintCostForBudget` (the `mint_exact_cost` budget search),
|
|
251
|
-
`redeemLiveProceeds` (what a live close credits),
|
|
252
|
-
below.
|
|
560
|
+
`redeemLiveProceeds` (what a live close credits), `settledPayout` (what an order pays at a
|
|
561
|
+
settlement price), plus the components they are built from. See below.
|
|
253
562
|
|
|
254
563
|
- **Typed errors** — invalid inputs throw `PredictInputError` before the chain sees them; failed
|
|
255
564
|
simulations throw `PredictMoveError` with the decoded Move abort (`module`, `code`, `abortName`).
|
|
@@ -308,7 +617,7 @@ import { cost } from '@mysten/deepbook-v3/predict';
|
|
|
308
617
|
|
|
309
618
|
const pricer = await client.predict.read.pricer({ underlying: 'BTC', expiryMs });
|
|
310
619
|
const shape = {
|
|
311
|
-
fees:
|
|
620
|
+
fees: await client.predict.read.feePolicy({ underlying: 'BTC', expiryMs }), // the market's own
|
|
312
621
|
expiryMs,
|
|
313
622
|
probabilities: { pricer, lower: 105_000, upper: null }, // an UP order at $105k
|
|
314
623
|
};
|
|
@@ -389,8 +698,10 @@ a zero charge or rebate. The congestion rate defaults to zero (disabled in the s
|
|
|
389
698
|
when enabled, supply `penaltyRate`, calculated by `cost.congestionPenaltyRate` from the market's
|
|
390
699
|
gas-price EWMA and the transaction's gas price. Supply `builderCode`, `feeIncentiveBalance` and, for
|
|
391
700
|
account-capped budget sizing, `accountBalance` to reflect the account being quoted. The fee
|
|
392
|
-
**policy** is a per-market snapshot taken at creation
|
|
393
|
-
`cost.SHIPPED_FEE_POLICY`
|
|
701
|
+
**policy** is a per-market snapshot taken at creation: read it with `read.feePolicy(market)`, one
|
|
702
|
+
object read. Don't use `cost.SHIPPED_FEE_POLICY` for a live market. It is the code default, and
|
|
703
|
+
neither recorded deployment's template matches it: both charge about twice its trading fee, ramp the
|
|
704
|
+
fee to 3× over the last 60 s and admit entries in 25%–75%.
|
|
394
705
|
|
|
395
706
|
Invalid raw domains (including negative amounts/rates, probabilities outside `[0, 1e9]`, and invalid
|
|
396
707
|
lot sizes) throw `PredictInputError` before arithmetic. Supplied book totals must also be
|
|
@@ -414,8 +725,8 @@ initial deployment; subsequent package upgrades come from `Published.toml`:
|
|
|
414
725
|
|
|
415
726
|
| Network | Deployment | Chain id | Source commit | `quoteCoinType` |
|
|
416
727
|
| --------- | -------------------------- | ---------- | ------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
417
|
-
| `mainnet` | `deepbook-predict-mainnet` | `35834a8a` | `
|
|
418
|
-
| `testnet` | `deepbook-predict-testnet` | `4c78adac` | `
|
|
728
|
+
| `mainnet` | `deepbook-predict-mainnet` | `35834a8a` | `7b169bde` | Circle native USDC — `0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC` |
|
|
729
|
+
| `testnet` | `deepbook-predict-testnet` | `4c78adac` | `4d752fb8` | mintable test coin, displays as `DUSDC` — `0xc028557a1ed49e42ed091e115aedefd70a442b184c18fbec5c48d5b6c0b8c184::usdc::USDC` |
|
|
419
730
|
|
|
420
731
|
Object ids for both are baked into the SDK — `MAINNET_CONFIG` / `TESTNET_CONFIG`, with
|
|
421
732
|
`MAINNET_DEPLOYMENT` / `TESTNET_DEPLOYMENT` and `MAINNET_UNITS` / `TESTNET_UNITS` alongside — and
|
|
@@ -429,17 +740,32 @@ Move-call targets resolve from the config's package ids, so a deployment of your
|
|
|
429
740
|
passing `config` — `predict({ network, config })` or
|
|
430
741
|
`new PredictClient({ client, network, config })` — and `network` is then not consulted.
|
|
431
742
|
|
|
432
|
-
|
|
433
|
-
`
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
743
|
+
Mainnet runs Predict **v4** and Testnet Predict **v5**, both built from the same sources, with
|
|
744
|
+
`deepbook_predict_orders` and `deepbook_predict_math` at v1 on both. Sessions is **v3** on both. The
|
|
745
|
+
Published.toml records are in deepbookv3 through PR #1365. `packages.predict` and
|
|
746
|
+
`sessionsPackageId` are the current Move-call targets; `packages.predictV1` and
|
|
747
|
+
`sessionsPackageIdV1` retain the original IDs for existing struct types, events and dynamic-field
|
|
748
|
+
keys. Custom upgraded configs must supply both IDs. The v1 fallback is only for custom deployments
|
|
749
|
+
that have never been upgraded. A type first introduced in a later version uses that version's
|
|
750
|
+
defining ID, and version numbers do not line up across networks, so check the defining ID on each
|
|
751
|
+
one. For example, `MintRange` was introduced in v2 on both networks, and
|
|
752
|
+
`vault_events::UsdcAddedToPlp` is defined by Mainnet v3 (`0x08fa3ef1…`) and Testnet v3
|
|
753
|
+
(`0xb5155d4c…`), neither of them the current call target. The types and events delayed execution
|
|
754
|
+
added are defined by Mainnet v4 and Testnet v5, which the configs record as
|
|
755
|
+
`packages.predictDelayedExecution`.
|
|
756
|
+
|
|
757
|
+
**Adding USDC to the pool without minting PLP:** `plpMoveCalls.addUsdcToPlp` wraps
|
|
758
|
+
`add_usdc_to_plp`, which pays a `Coin<USDC>` into the pool's idle cash and mints nothing in return.
|
|
759
|
+
Any caller can use it, and the whole amount accrues to existing PLP holders. The chain rejects the
|
|
760
|
+
contribution when the pool has no PLP supply yet, the payment is under 10 USDC, a flush is in
|
|
761
|
+
flight, or pool cash after the contribution would exceed 10 USDC per PLP. `client.predict` has no
|
|
762
|
+
builder or decoder for this entrypoint. Match `UsdcAddedToPlp` against its defining ID, not
|
|
763
|
+
`predictV1`.
|
|
764
|
+
|
|
765
|
+
**All-in budget mint (v2 and later):** `spend` caps the debit including all trade fees, and
|
|
766
|
+
`minQuantity` is the minimum payout quantity accepted. It may spend less than the budget because of
|
|
767
|
+
lot rounding, balance limits or the contract's sizing constraints. Network gas is separate.
|
|
768
|
+
`mintAmount` retains its existing premium-only budget semantics.
|
|
443
769
|
|
|
444
770
|
```ts
|
|
445
771
|
const quote = await client.predict.read.quoteMintCost(myAddress, desc, {
|
|
@@ -456,8 +782,8 @@ const tx = await client.predict.tx.mintCost(myAddress, desc, {
|
|
|
456
782
|
`read.quoteMintCost` simulates the actual budget mint with the owner's current balance and fees; it
|
|
457
783
|
requires an existing funded account. Sessions callers can compose `SessionsContract.mintExactCost`
|
|
458
784
|
with a live pricer using raw Move units. The generated `expiryMarketMoveCalls` also exposes
|
|
459
|
-
`quoteMintExactCostForAccount` for lower-level PTBs. These
|
|
460
|
-
|
|
785
|
+
`quoteMintExactCostForAccount` for lower-level PTBs. These entrypoints require v2 or later. Both
|
|
786
|
+
recorded deployments qualify, but a custom deployment still on v1 does not.
|
|
461
787
|
|
|
462
788
|
An expired market stays in `read.markets()` until someone settles it — the list is the pool's
|
|
463
789
|
live-and-not-yet-settled set, not a tradeable set. On either network, check `expiryMs` against the
|
|
@@ -465,8 +791,10 @@ clock (and `mintPaused`) before quoting rather than assuming the list is tradeab
|
|
|
465
791
|
|
|
466
792
|
## Notes
|
|
467
793
|
|
|
468
|
-
- **
|
|
469
|
-
order id) straight from the account's position table — one round trip warm, no indexer.
|
|
794
|
+
- **Account positions are enumerable on-chain**: `read.positions(owner)` lists every open position
|
|
795
|
+
(market + order id) straight from the account's position table — one round trip warm, no indexer.
|
|
796
|
+
With delayed execution a filled order is an Open record in the market's queue instead, which this
|
|
797
|
+
list doesn't include (see [Queued orders](#queued-orders-delayed-execution)). Persisting
|
|
470
798
|
`decode.mint(result).orderId` and applying `decode.redeem(result).replacementOrderId` is still the
|
|
471
799
|
fastest hot path, with `read.positions` as the fresh-start/recovery source and `read.hasPosition`
|
|
472
800
|
as the cheap validator.
|