@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.
Files changed (250) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/PREDICT.md +389 -61
  3. package/dist/contracts/account/account.d.mts +23 -23
  4. package/dist/contracts/account/account.d.mts.map +1 -1
  5. package/dist/contracts/account/account_registry.d.mts +13 -13
  6. package/dist/contracts/deepbook/account.d.mts +18 -18
  7. package/dist/contracts/deepbook/balances.d.mts +4 -4
  8. package/dist/contracts/deepbook/deep_price.d.mts +3 -3
  9. package/dist/contracts/deepbook/order.d.mts +12 -12
  10. package/dist/contracts/deepbook_predict/admin.d.mts +4 -4
  11. package/dist/contracts/deepbook_predict/builder_code.d.mts +11 -11
  12. package/dist/contracts/deepbook_predict/builder_code_events.d.mts +10 -10
  13. package/dist/contracts/deepbook_predict/config_events.d.mts +93 -68
  14. package/dist/contracts/deepbook_predict/config_events.d.mts.map +1 -1
  15. package/dist/contracts/deepbook_predict/config_events.mjs +45 -1
  16. package/dist/contracts/deepbook_predict/config_events.mjs.map +1 -1
  17. package/dist/contracts/deepbook_predict/deps/std/type_name.mjs +17 -0
  18. package/dist/contracts/deepbook_predict/deps/std/type_name.mjs.map +1 -0
  19. package/dist/contracts/deepbook_predict/expiry_market.d.mts +652 -235
  20. package/dist/contracts/deepbook_predict/expiry_market.d.mts.map +1 -1
  21. package/dist/contracts/deepbook_predict/expiry_market.mjs +652 -186
  22. package/dist/contracts/deepbook_predict/expiry_market.mjs.map +1 -1
  23. package/dist/contracts/deepbook_predict/lp_book.mjs +1 -1
  24. package/dist/contracts/deepbook_predict/market_lifecycle_cap.d.mts +5 -5
  25. package/dist/contracts/deepbook_predict/market_manager.d.mts +27 -27
  26. package/dist/contracts/deepbook_predict/order_events.d.mts +50 -50
  27. package/dist/contracts/deepbook_predict/order_events.d.mts.map +1 -1
  28. package/dist/contracts/deepbook_predict/order_events.mjs +3 -1
  29. package/dist/contracts/deepbook_predict/order_events.mjs.map +1 -1
  30. package/dist/contracts/deepbook_predict/pause_cap.d.mts +5 -5
  31. package/dist/contracts/deepbook_predict/plp.d.mts +184 -82
  32. package/dist/contracts/deepbook_predict/plp.d.mts.map +1 -1
  33. package/dist/contracts/deepbook_predict/plp.mjs +126 -7
  34. package/dist/contracts/deepbook_predict/plp.mjs.map +1 -1
  35. package/dist/contracts/deepbook_predict/pool_accounting.mjs +1 -1
  36. package/dist/contracts/deepbook_predict/pool_valuation_cap.d.mts +5 -5
  37. package/dist/contracts/deepbook_predict/predict_account.d.mts +14 -14
  38. package/dist/contracts/deepbook_predict/pricing.d.mts +91 -58
  39. package/dist/contracts/deepbook_predict/pricing.d.mts.map +1 -1
  40. package/dist/contracts/deepbook_predict/pricing.mjs +30 -3
  41. package/dist/contracts/deepbook_predict/pricing.mjs.map +1 -1
  42. package/dist/contracts/deepbook_predict/pricing_config.mjs.map +1 -1
  43. package/dist/contracts/deepbook_predict/protocol_config.d.mts +400 -92
  44. package/dist/contracts/deepbook_predict/protocol_config.d.mts.map +1 -1
  45. package/dist/contracts/deepbook_predict/protocol_config.mjs +451 -61
  46. package/dist/contracts/deepbook_predict/protocol_config.mjs.map +1 -1
  47. package/dist/contracts/deepbook_predict/range_codec.d.mts +2 -2
  48. package/dist/contracts/deepbook_predict/registry.d.mts +28 -28
  49. package/dist/contracts/deepbook_predict/strike_exposure.mjs +1 -1
  50. package/dist/contracts/deepbook_predict/strike_payout_tree.mjs +17 -12
  51. package/dist/contracts/deepbook_predict/strike_payout_tree.mjs.map +1 -1
  52. package/dist/contracts/deepbook_predict/vault_events.d.mts +154 -106
  53. package/dist/contracts/deepbook_predict/vault_events.d.mts.map +1 -1
  54. package/dist/contracts/deepbook_predict/vault_events.mjs +57 -1
  55. package/dist/contracts/deepbook_predict/vault_events.mjs.map +1 -1
  56. package/dist/contracts/deepbook_predict_math/config-arguments.d.mts +10 -0
  57. package/dist/contracts/deepbook_predict_math/config-arguments.d.mts.map +1 -0
  58. package/dist/contracts/deepbook_predict_math/lazer_price.d.mts +106 -0
  59. package/dist/contracts/deepbook_predict_math/lazer_price.d.mts.map +1 -0
  60. package/dist/contracts/deepbook_predict_math/lazer_price.mjs +125 -0
  61. package/dist/contracts/deepbook_predict_math/lazer_price.mjs.map +1 -0
  62. package/dist/contracts/deepbook_predict_math/math.d.mts +284 -0
  63. package/dist/contracts/deepbook_predict_math/math.d.mts.map +1 -0
  64. package/dist/contracts/deepbook_predict_math/math.mjs +364 -0
  65. package/dist/contracts/deepbook_predict_math/math.mjs.map +1 -0
  66. package/dist/contracts/deepbook_predict_orders/config-arguments.d.mts +13 -0
  67. package/dist/contracts/deepbook_predict_orders/config-arguments.d.mts.map +1 -0
  68. package/dist/contracts/deepbook_predict_orders/delayed_execution_config.d.mts +215 -0
  69. package/dist/contracts/deepbook_predict_orders/delayed_execution_config.d.mts.map +1 -0
  70. package/dist/contracts/deepbook_predict_orders/delayed_execution_config.mjs +215 -0
  71. package/dist/contracts/deepbook_predict_orders/delayed_execution_config.mjs.map +1 -0
  72. package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.mjs +87 -0
  73. package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.mjs.map +1 -0
  74. package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.mjs +52 -0
  75. package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.mjs.map +1 -0
  76. package/dist/contracts/deepbook_predict_orders/deps/fixed_math/i64.mjs +25 -0
  77. package/dist/contracts/deepbook_predict_orders/deps/fixed_math/i64.mjs.map +1 -0
  78. package/dist/contracts/deepbook_predict_orders/deps/sui/balance.mjs +21 -0
  79. package/dist/contracts/deepbook_predict_orders/deps/sui/balance.mjs.map +1 -0
  80. package/dist/contracts/deepbook_predict_orders/deps/sui/table.mjs +39 -0
  81. package/dist/contracts/deepbook_predict_orders/deps/sui/table.mjs.map +1 -0
  82. package/dist/contracts/deepbook_predict_orders/desk.d.mts +187 -0
  83. package/dist/contracts/deepbook_predict_orders/desk.d.mts.map +1 -0
  84. package/dist/contracts/deepbook_predict_orders/desk.mjs +261 -0
  85. package/dist/contracts/deepbook_predict_orders/desk.mjs.map +1 -0
  86. package/dist/contracts/deepbook_predict_orders/order_queue.d.mts +1042 -0
  87. package/dist/contracts/deepbook_predict_orders/order_queue.d.mts.map +1 -0
  88. package/dist/contracts/deepbook_predict_orders/order_queue.mjs +849 -0
  89. package/dist/contracts/deepbook_predict_orders/order_queue.mjs.map +1 -0
  90. package/dist/contracts/deepbook_predict_orders/queue.d.mts +683 -0
  91. package/dist/contracts/deepbook_predict_orders/queue.d.mts.map +1 -0
  92. package/dist/contracts/deepbook_predict_orders/queue.mjs +912 -0
  93. package/dist/contracts/deepbook_predict_orders/queue.mjs.map +1 -0
  94. package/dist/contracts/deepbook_predict_orders/queue_events.d.mts +195 -0
  95. package/dist/contracts/deepbook_predict_orders/queue_events.d.mts.map +1 -0
  96. package/dist/contracts/deepbook_predict_orders/queue_events.mjs +187 -0
  97. package/dist/contracts/deepbook_predict_orders/queue_events.mjs.map +1 -0
  98. package/dist/contracts/deepbook_sessions/session_config.d.mts +8 -8
  99. package/dist/contracts/deepbook_sessions/sessions.d.mts +163 -28
  100. package/dist/contracts/deepbook_sessions/sessions.d.mts.map +1 -1
  101. package/dist/contracts/deepbook_sessions/sessions.mjs +234 -5
  102. package/dist/contracts/deepbook_sessions/sessions.mjs.map +1 -1
  103. package/dist/deployments/mainnet.mjs +7 -4
  104. package/dist/deployments/mainnet.mjs.map +1 -1
  105. package/dist/deployments/testnet.mjs +7 -4
  106. package/dist/deployments/testnet.mjs.map +1 -1
  107. package/dist/predict/bindings/expiry-market.d.mts +77 -0
  108. package/dist/predict/bindings/expiry-market.d.mts.map +1 -0
  109. package/dist/predict/bindings/expiry-market.mjs +139 -0
  110. package/dist/predict/bindings/expiry-market.mjs.map +1 -0
  111. package/dist/predict/bindings/protocol-config.d.mts +39 -0
  112. package/dist/predict/bindings/protocol-config.d.mts.map +1 -0
  113. package/dist/predict/bindings/protocol-config.mjs +90 -0
  114. package/dist/predict/bindings/protocol-config.mjs.map +1 -0
  115. package/dist/predict/bindings/rename.mjs +9 -0
  116. package/dist/predict/bindings/rename.mjs.map +1 -0
  117. package/dist/predict/client.d.mts +595 -16
  118. package/dist/predict/client.d.mts.map +1 -1
  119. package/dist/predict/client.mjs +986 -10
  120. package/dist/predict/client.mjs.map +1 -1
  121. package/dist/predict/config/generated.d.mts +22 -1
  122. package/dist/predict/config/generated.d.mts.map +1 -1
  123. package/dist/predict/config/generated.mjs +30 -1
  124. package/dist/predict/config/generated.mjs.map +1 -1
  125. package/dist/predict/config/mainnet.mjs +11 -3
  126. package/dist/predict/config/mainnet.mjs.map +1 -1
  127. package/dist/predict/config/testnet.mjs +11 -3
  128. package/dist/predict/config/testnet.mjs.map +1 -1
  129. package/dist/predict/config/types.d.mts +50 -1
  130. package/dist/predict/config/types.d.mts.map +1 -1
  131. package/dist/predict/cost.d.mts +38 -11
  132. package/dist/predict/cost.d.mts.map +1 -1
  133. package/dist/predict/cost.mjs +37 -11
  134. package/dist/predict/cost.mjs.map +1 -1
  135. package/dist/predict/decode.d.mts +251 -1
  136. package/dist/predict/decode.d.mts.map +1 -1
  137. package/dist/predict/decode.mjs +342 -4
  138. package/dist/predict/decode.mjs.map +1 -1
  139. package/dist/predict/errors.d.mts +69 -6
  140. package/dist/predict/errors.d.mts.map +1 -1
  141. package/dist/predict/errors.mjs +277 -4
  142. package/dist/predict/errors.mjs.map +1 -1
  143. package/dist/predict/index.d.mts +21 -10
  144. package/dist/predict/index.mjs +24 -12
  145. package/dist/predict/queue-id.d.mts +13 -0
  146. package/dist/predict/queue-id.d.mts.map +1 -0
  147. package/dist/predict/queue-id.mjs +19 -0
  148. package/dist/predict/queue-id.mjs.map +1 -0
  149. package/dist/predict/queue.d.mts +505 -0
  150. package/dist/predict/queue.d.mts.map +1 -0
  151. package/dist/predict/queue.mjs +774 -0
  152. package/dist/predict/queue.mjs.map +1 -0
  153. package/dist/predict/reads/balances.mjs +1 -1
  154. package/dist/predict/reads/markets.mjs +46 -5
  155. package/dist/predict/reads/markets.mjs.map +1 -1
  156. package/dist/predict/reads/pool.mjs +1 -1
  157. package/dist/predict/reads/pricing.d.mts +1 -1
  158. package/dist/predict/reads/queue.d.mts +105 -0
  159. package/dist/predict/reads/queue.d.mts.map +1 -0
  160. package/dist/predict/reads/queue.mjs +445 -0
  161. package/dist/predict/reads/queue.mjs.map +1 -0
  162. package/dist/predict/ticks.d.mts +9 -1
  163. package/dist/predict/ticks.d.mts.map +1 -1
  164. package/dist/predict/ticks.mjs +18 -1
  165. package/dist/predict/ticks.mjs.map +1 -1
  166. package/dist/predict/tx/authed.mjs +1 -1
  167. package/dist/predict/tx/common.d.mts.map +1 -1
  168. package/dist/predict/tx/common.mjs +12 -1
  169. package/dist/predict/tx/common.mjs.map +1 -1
  170. package/dist/predict/tx/queue.d.mts +220 -0
  171. package/dist/predict/tx/queue.d.mts.map +1 -0
  172. package/dist/predict/tx/queue.mjs +399 -0
  173. package/dist/predict/tx/queue.mjs.map +1 -0
  174. package/dist/predict/tx/trade.d.mts.map +1 -1
  175. package/dist/predict/tx/trade.mjs +61 -43
  176. package/dist/predict/tx/trade.mjs.map +1 -1
  177. package/dist/sessions.d.mts +90 -2
  178. package/dist/sessions.d.mts.map +1 -1
  179. package/dist/sessions.mjs +107 -2
  180. package/dist/sessions.mjs.map +1 -1
  181. package/dist/transactions/balanceManager.d.mts +12 -12
  182. package/dist/transactions/balanceManager.d.mts.map +1 -1
  183. package/dist/transactions/deepbook.d.mts +20 -20
  184. package/dist/transactions/deepbook.d.mts.map +1 -1
  185. package/dist/transactions/deepbookAdmin.d.mts +4 -4
  186. package/dist/transactions/deepbookAdmin.d.mts.map +1 -1
  187. package/dist/transactions/marginAdmin.d.mts +7 -7
  188. package/dist/transactions/marginAdmin.d.mts.map +1 -1
  189. package/dist/transactions/marginLiquidations.d.mts +3 -3
  190. package/dist/transactions/marginMaintainer.d.mts +5 -5
  191. package/dist/transactions/marginMaintainer.d.mts.map +1 -1
  192. package/dist/transactions/marginManager.d.mts +32 -32
  193. package/dist/transactions/marginManager.d.mts.map +1 -1
  194. package/dist/transactions/marginPool.d.mts +18 -18
  195. package/dist/transactions/marginRegistry.d.mts +16 -16
  196. package/dist/transactions/marginTPSL.d.mts +10 -10
  197. package/dist/transactions/marginTPSL.d.mts.map +1 -1
  198. package/dist/transactions/poolProxy.d.mts +8 -8
  199. package/dist/transactions/poolProxy.d.mts.map +1 -1
  200. package/package.json +4 -4
  201. package/src/contracts/deepbook_predict/config_events.ts +39 -0
  202. package/src/contracts/deepbook_predict/deps/std/type_name.ts +24 -0
  203. package/src/contracts/deepbook_predict/expiry_market.ts +960 -169
  204. package/src/contracts/deepbook_predict/order_events.ts +3 -1
  205. package/src/contracts/deepbook_predict/plp.ts +150 -9
  206. package/src/contracts/deepbook_predict/pricing.ts +46 -7
  207. package/src/contracts/deepbook_predict/pricing_config.ts +3 -1
  208. package/src/contracts/deepbook_predict/protocol_config.ts +648 -33
  209. package/src/contracts/deepbook_predict/strike_payout_tree.ts +25 -21
  210. package/src/contracts/deepbook_predict/vault_events.ts +65 -0
  211. package/src/contracts/deepbook_predict_math/config-arguments.ts +6 -0
  212. package/src/contracts/deepbook_predict_math/lazer_price.ts +196 -0
  213. package/src/contracts/deepbook_predict_math/math.ts +553 -0
  214. package/src/contracts/deepbook_predict_orders/config-arguments.ts +11 -0
  215. package/src/contracts/deepbook_predict_orders/delayed_execution_config.ts +430 -0
  216. package/src/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.ts +108 -0
  217. package/src/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.ts +58 -0
  218. package/src/contracts/deepbook_predict_orders/deps/fixed_math/i64.ts +21 -0
  219. package/src/contracts/deepbook_predict_orders/deps/sui/balance.ts +19 -0
  220. package/src/contracts/deepbook_predict_orders/deps/sui/table.ts +37 -0
  221. package/src/contracts/deepbook_predict_orders/desk.ts +419 -0
  222. package/src/contracts/deepbook_predict_orders/order_flow.ts +19 -0
  223. package/src/contracts/deepbook_predict_orders/order_queue.ts +1670 -0
  224. package/src/contracts/deepbook_predict_orders/queue.ts +1394 -0
  225. package/src/contracts/deepbook_predict_orders/queue_events.ts +189 -0
  226. package/src/contracts/deepbook_sessions/sessions.ts +355 -4
  227. package/src/deployments/mainnet.ts +7 -2
  228. package/src/deployments/testnet.ts +7 -2
  229. package/src/deployments/types.ts +14 -1
  230. package/src/predict/bindings/expiry-market.ts +127 -0
  231. package/src/predict/bindings/protocol-config.ts +59 -0
  232. package/src/predict/bindings/rename.ts +14 -0
  233. package/src/predict/client.ts +2076 -13
  234. package/src/predict/config/generated.ts +50 -0
  235. package/src/predict/config/mainnet.ts +16 -2
  236. package/src/predict/config/testnet.ts +16 -2
  237. package/src/predict/config/types.ts +51 -1
  238. package/src/predict/cost.ts +62 -14
  239. package/src/predict/decode.ts +691 -2
  240. package/src/predict/errors.ts +391 -14
  241. package/src/predict/index.ts +87 -6
  242. package/src/predict/queue-id.ts +22 -0
  243. package/src/predict/queue.ts +1231 -0
  244. package/src/predict/reads/markets.ts +30 -0
  245. package/src/predict/reads/queue.ts +606 -0
  246. package/src/predict/ticks.ts +35 -0
  247. package/src/predict/tx/common.ts +25 -1
  248. package/src/predict/tx/queue.ts +525 -0
  249. package/src/predict/tx/trade.ts +80 -49
  250. 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((m) => Number(m.expiryMs) > Date.now() + 30_000 && !m.mintPaused);
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 — quoting and minting take the same descriptor.
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
- underlying: 'BTC',
73
- expiryMs,
74
- strike: 'reference',
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 receipt from the execution result (execute with events included):
78
- const receipt = client.predict.decode.mint(mintResult);
79
- receipt.orderId; // PERSIST THIS — needed to redeem/claim later
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`. Market-resolving builders
193
- (`mint`/`mintAmount`/`mintCost`/`redeem`/`claimSettled`) are async: they resolve the market object
194
- from `{ underlying, expiryMs, strike, side }` via the on-chain registry (cached per client).
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()`, `positions(owner)` (chain-only enumeration of open positions),
205
- `hasPosition(owner, marketId, orderId)`. All reads run over the client's `simulateTransaction`; no
206
- indexer required.
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`). Pass
221
- `config: toGeneratedConfig(cfg)` — the flat config slice the bindings resolve the shared objects
222
- against — and give owner-authorized calls `auth: tx.add(generateAuth(cfg))`, the hot-potato `Auth`
223
- the account calls consume. The account itself (create, deposit, share) is
224
- `@mysten/deepbook-v3/account`'s `accountRegistryMoveCalls` / `accountMoveCalls`. Also exported:
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), plus the components they are built from. See
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: cost.SHIPPED_FEE_POLICY, // or the market's own MarketCreated snapshot
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 — use the market's `MarketCreated` event, or
393
- `cost.SHIPPED_FEE_POLICY` only for a market created under that template.
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` | `14a7e8f8` | Circle native USDC — `0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC` |
418
- | `testnet` | `deepbook-predict-testnet` | `4c78adac` | `a928bd2d` | mintable test coin, displays as `DUSDC` — `0xc028557a1ed49e42ed091e115aedefd70a442b184c18fbec5c48d5b6c0b8c184::usdc::USDC` |
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
- Testnet uses Predict and Sessions **v2** from deepbookv3 PR #1311. Mainnet remains **v1**.
433
- `packages.predict` and `sessionsPackageId` are the current Move-call targets; `packages.predictV1`
434
- and `sessionsPackageIdV1` retain the original IDs for existing struct types, events and
435
- dynamic-field keys. Custom upgraded configs must supply both IDs. The v1 fallback is only for custom
436
- deployments that have never been upgraded. A type first introduced in a later version uses that
437
- version's defining ID (for example, `MintRange` was introduced in v2).
438
-
439
- **All-in budget mint (v2 only):** `spend` caps the debit including all trade fees, and `minQuantity`
440
- is the minimum payout quantity accepted. It may spend less than the budget because of lot rounding,
441
- balance limits or the contract's sizing constraints. Network gas is separate. `mintAmount` retains
442
- its existing premium-only budget semantics.
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 new entrypoints require the v2 packages;
460
- do not use them with the recorded v1 Mainnet deployment.
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
- - **Positions are enumerable on-chain**: `read.positions(owner)` lists every open position (market +
469
- order id) straight from the account's position table — one round trip warm, no indexer. Persisting
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.