@mysten/deepbook-v3 2.0.1 → 2.1.3

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 (272) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/PREDICT.md +256 -0
  3. package/README.md +116 -0
  4. package/dist/account.d.mts +139 -0
  5. package/dist/account.d.mts.map +1 -0
  6. package/dist/account.mjs +181 -0
  7. package/dist/account.mjs.map +1 -0
  8. package/dist/bcs/integers.mjs +23 -0
  9. package/dist/bcs/integers.mjs.map +1 -0
  10. package/dist/contracts/account/account.d.mts +382 -0
  11. package/dist/contracts/account/account.d.mts.map +1 -0
  12. package/dist/contracts/account/account.mjs +443 -0
  13. package/dist/contracts/account/account.mjs.map +1 -0
  14. package/dist/contracts/account/account_events.d.mts +41 -0
  15. package/dist/contracts/account/account_events.d.mts.map +1 -0
  16. package/dist/contracts/account/account_events.mjs +72 -0
  17. package/dist/contracts/account/account_events.mjs.map +1 -0
  18. package/dist/contracts/account/account_registry.d.mts +210 -0
  19. package/dist/contracts/account/account_registry.d.mts.map +1 -0
  20. package/dist/contracts/account/account_registry.mjs +263 -0
  21. package/dist/contracts/account/account_registry.mjs.map +1 -0
  22. package/dist/contracts/account/config-arguments.d.mts +10 -0
  23. package/dist/contracts/account/config-arguments.d.mts.map +1 -0
  24. package/dist/contracts/account/deps/sui/bag.mjs +44 -0
  25. package/dist/contracts/account/deps/sui/bag.mjs.map +1 -0
  26. package/dist/contracts/deepbook/account.d.mts +18 -18
  27. package/dist/contracts/deepbook/balances.d.mts +4 -4
  28. package/dist/contracts/deepbook/deep_price.d.mts +3 -3
  29. package/dist/contracts/deepbook/deep_price.d.mts.map +1 -1
  30. package/dist/contracts/deepbook/order.d.mts +12 -12
  31. package/dist/contracts/deepbook_predict/builder_code_events.mjs +38 -0
  32. package/dist/contracts/deepbook_predict/builder_code_events.mjs.map +1 -0
  33. package/dist/contracts/deepbook_predict/config-arguments.d.mts +13 -0
  34. package/dist/contracts/deepbook_predict/config-arguments.d.mts.map +1 -0
  35. package/dist/contracts/deepbook_predict/deps/fixed_math/i64.mjs +25 -0
  36. package/dist/contracts/deepbook_predict/deps/fixed_math/i64.mjs.map +1 -0
  37. package/dist/contracts/deepbook_predict/deps/sui/balance.mjs +25 -0
  38. package/dist/contracts/deepbook_predict/deps/sui/balance.mjs.map +1 -0
  39. package/dist/contracts/deepbook_predict/deps/sui/coin.mjs +24 -0
  40. package/dist/contracts/deepbook_predict/deps/sui/coin.mjs.map +1 -0
  41. package/dist/contracts/deepbook_predict/deps/sui/table.mjs +39 -0
  42. package/dist/contracts/deepbook_predict/deps/sui/table.mjs.map +1 -0
  43. package/dist/contracts/deepbook_predict/deps/sui/vec_set.mjs +26 -0
  44. package/dist/contracts/deepbook_predict/deps/sui/vec_set.mjs.map +1 -0
  45. package/dist/contracts/deepbook_predict/ewma.mjs +29 -0
  46. package/dist/contracts/deepbook_predict/ewma.mjs.map +1 -0
  47. package/dist/contracts/deepbook_predict/expiry_cash.mjs +27 -0
  48. package/dist/contracts/deepbook_predict/expiry_cash.mjs.map +1 -0
  49. package/dist/contracts/deepbook_predict/expiry_market.mjs +367 -0
  50. package/dist/contracts/deepbook_predict/expiry_market.mjs.map +1 -0
  51. package/dist/contracts/deepbook_predict/lp_book.mjs +92 -0
  52. package/dist/contracts/deepbook_predict/lp_book.mjs.map +1 -0
  53. package/dist/contracts/deepbook_predict/market_manager.mjs +59 -0
  54. package/dist/contracts/deepbook_predict/market_manager.mjs.map +1 -0
  55. package/dist/contracts/deepbook_predict/order.mjs +26 -0
  56. package/dist/contracts/deepbook_predict/order.mjs.map +1 -0
  57. package/dist/contracts/deepbook_predict/order_events.mjs +84 -0
  58. package/dist/contracts/deepbook_predict/order_events.mjs.map +1 -0
  59. package/dist/contracts/deepbook_predict/plp.mjs +284 -0
  60. package/dist/contracts/deepbook_predict/plp.mjs.map +1 -0
  61. package/dist/contracts/deepbook_predict/pool_accounting.mjs +58 -0
  62. package/dist/contracts/deepbook_predict/pool_accounting.mjs.map +1 -0
  63. package/dist/contracts/deepbook_predict/predict_account.mjs +106 -0
  64. package/dist/contracts/deepbook_predict/predict_account.mjs.map +1 -0
  65. package/dist/contracts/deepbook_predict/pricing.mjs +80 -0
  66. package/dist/contracts/deepbook_predict/pricing.mjs.map +1 -0
  67. package/dist/contracts/deepbook_predict/range_codec.mjs +41 -0
  68. package/dist/contracts/deepbook_predict/range_codec.mjs.map +1 -0
  69. package/dist/contracts/deepbook_predict/registry.mjs +55 -0
  70. package/dist/contracts/deepbook_predict/registry.mjs.map +1 -0
  71. package/dist/contracts/deepbook_predict/strike_exposure.mjs +65 -0
  72. package/dist/contracts/deepbook_predict/strike_exposure.mjs.map +1 -0
  73. package/dist/contracts/deepbook_predict/strike_exposure_config.mjs +33 -0
  74. package/dist/contracts/deepbook_predict/strike_exposure_config.mjs.map +1 -0
  75. package/dist/contracts/deepbook_predict/strike_payout_tree.mjs +72 -0
  76. package/dist/contracts/deepbook_predict/strike_payout_tree.mjs.map +1 -0
  77. package/dist/contracts/deepbook_predict/vault_events.mjs +184 -0
  78. package/dist/contracts/deepbook_predict/vault_events.mjs.map +1 -0
  79. package/dist/contracts/deepbook_sessions/config-arguments.d.mts +10 -0
  80. package/dist/contracts/deepbook_sessions/config-arguments.d.mts.map +1 -0
  81. package/dist/contracts/deepbook_sessions/deps/sui/vec_map.mjs +37 -0
  82. package/dist/contracts/deepbook_sessions/deps/sui/vec_map.mjs.map +1 -0
  83. package/dist/contracts/deepbook_sessions/session_config.d.mts +63 -0
  84. package/dist/contracts/deepbook_sessions/session_config.d.mts.map +1 -0
  85. package/dist/contracts/deepbook_sessions/session_config.mjs +82 -0
  86. package/dist/contracts/deepbook_sessions/session_config.mjs.map +1 -0
  87. package/dist/contracts/deepbook_sessions/sessions.d.mts +275 -0
  88. package/dist/contracts/deepbook_sessions/sessions.d.mts.map +1 -0
  89. package/dist/contracts/deepbook_sessions/sessions.mjs +443 -0
  90. package/dist/contracts/deepbook_sessions/sessions.mjs.map +1 -0
  91. package/dist/contracts/utils/index.d.mts +18 -1
  92. package/dist/contracts/utils/index.d.mts.map +1 -1
  93. package/dist/deployments/index.d.mts +31 -0
  94. package/dist/deployments/index.d.mts.map +1 -0
  95. package/dist/deployments/index.mjs +30 -0
  96. package/dist/deployments/index.mjs.map +1 -0
  97. package/dist/deployments/testnet.d.mts +14 -0
  98. package/dist/deployments/testnet.d.mts.map +1 -0
  99. package/dist/deployments/testnet.mjs +73 -0
  100. package/dist/deployments/testnet.mjs.map +1 -0
  101. package/dist/deployments/types.d.mts +36 -0
  102. package/dist/deployments/types.d.mts.map +1 -0
  103. package/dist/index.mjs +0 -1
  104. package/dist/predict/client.d.mts +255 -0
  105. package/dist/predict/client.d.mts.map +1 -0
  106. package/dist/predict/client.mjs +436 -0
  107. package/dist/predict/client.mjs.map +1 -0
  108. package/dist/predict/config/generated.d.mts +29 -0
  109. package/dist/predict/config/generated.d.mts.map +1 -0
  110. package/dist/predict/config/generated.mjs +16 -0
  111. package/dist/predict/config/generated.mjs.map +1 -0
  112. package/dist/predict/config/index.d.mts +10 -0
  113. package/dist/predict/config/index.d.mts.map +1 -0
  114. package/dist/predict/config/index.mjs +13 -0
  115. package/dist/predict/config/index.mjs.map +1 -0
  116. package/dist/predict/config/testnet.d.mts +17 -0
  117. package/dist/predict/config/testnet.d.mts.map +1 -0
  118. package/dist/predict/config/testnet.mjs +26 -0
  119. package/dist/predict/config/testnet.mjs.map +1 -0
  120. package/dist/predict/config/types.d.mts +55 -0
  121. package/dist/predict/config/types.d.mts.map +1 -0
  122. package/dist/predict/decode.d.mts +162 -0
  123. package/dist/predict/decode.d.mts.map +1 -0
  124. package/dist/predict/decode.mjs +175 -0
  125. package/dist/predict/decode.mjs.map +1 -0
  126. package/dist/predict/errors.d.mts +42 -0
  127. package/dist/predict/errors.d.mts.map +1 -0
  128. package/dist/predict/errors.mjs +37 -0
  129. package/dist/predict/errors.mjs.map +1 -0
  130. package/dist/predict/index.d.mts +18 -0
  131. package/dist/predict/index.mjs +14 -0
  132. package/dist/predict/pricing.d.mts +73 -0
  133. package/dist/predict/pricing.d.mts.map +1 -0
  134. package/dist/predict/pricing.mjs +129 -0
  135. package/dist/predict/pricing.mjs.map +1 -0
  136. package/dist/predict/reads/balances.mjs +41 -0
  137. package/dist/predict/reads/balances.mjs.map +1 -0
  138. package/dist/predict/reads/inspect.d.mts +8 -0
  139. package/dist/predict/reads/inspect.d.mts.map +1 -0
  140. package/dist/predict/reads/inspect.mjs +37 -0
  141. package/dist/predict/reads/inspect.mjs.map +1 -0
  142. package/dist/predict/reads/markets.mjs +130 -0
  143. package/dist/predict/reads/markets.mjs.map +1 -0
  144. package/dist/predict/reads/parse.mjs +20 -0
  145. package/dist/predict/reads/parse.mjs.map +1 -0
  146. package/dist/predict/reads/pool.mjs +26 -0
  147. package/dist/predict/reads/pool.mjs.map +1 -0
  148. package/dist/predict/reads/positions.d.mts +12 -0
  149. package/dist/predict/reads/positions.d.mts.map +1 -0
  150. package/dist/predict/reads/positions.mjs +77 -0
  151. package/dist/predict/reads/positions.mjs.map +1 -0
  152. package/dist/predict/reads/pricing.d.mts +20 -0
  153. package/dist/predict/reads/pricing.d.mts.map +1 -0
  154. package/dist/predict/reads/pricing.mjs +43 -0
  155. package/dist/predict/reads/pricing.mjs.map +1 -0
  156. package/dist/predict/ticks.d.mts +11 -0
  157. package/dist/predict/ticks.d.mts.map +1 -0
  158. package/dist/predict/ticks.mjs +21 -0
  159. package/dist/predict/ticks.mjs.map +1 -0
  160. package/dist/predict/tx/authed.mjs +18 -0
  161. package/dist/predict/tx/authed.mjs.map +1 -0
  162. package/dist/predict/tx/common.d.mts +18 -0
  163. package/dist/predict/tx/common.d.mts.map +1 -0
  164. package/dist/predict/tx/common.mjs +52 -0
  165. package/dist/predict/tx/common.mjs.map +1 -0
  166. package/dist/predict/tx/trade.d.mts +15 -0
  167. package/dist/predict/tx/trade.d.mts.map +1 -0
  168. package/dist/predict/tx/trade.mjs +86 -0
  169. package/dist/predict/tx/trade.mjs.map +1 -0
  170. package/dist/predict/units.d.mts +11 -0
  171. package/dist/predict/units.d.mts.map +1 -0
  172. package/dist/predict/units.mjs +44 -0
  173. package/dist/predict/units.mjs.map +1 -0
  174. package/dist/queries/accountQueries.mjs +0 -1
  175. package/dist/queries/accountQueries.mjs.map +1 -1
  176. package/dist/queries/orderQueries.mjs +0 -1
  177. package/dist/queries/orderQueries.mjs.map +1 -1
  178. package/dist/queries/registryQueries.mjs +0 -1
  179. package/dist/queries/registryQueries.mjs.map +1 -1
  180. package/dist/sessions.d.mts +244 -0
  181. package/dist/sessions.d.mts.map +1 -0
  182. package/dist/sessions.mjs +291 -0
  183. package/dist/sessions.mjs.map +1 -0
  184. package/dist/transactions/balanceManager.d.mts +12 -12
  185. package/dist/transactions/balanceManager.d.mts.map +1 -1
  186. package/dist/transactions/deepbook.d.mts +20 -20
  187. package/dist/transactions/deepbook.d.mts.map +1 -1
  188. package/dist/transactions/deepbookAdmin.d.mts +4 -4
  189. package/dist/transactions/marginAdmin.d.mts +7 -7
  190. package/dist/transactions/marginLiquidations.d.mts +3 -3
  191. package/dist/transactions/marginMaintainer.d.mts +5 -5
  192. package/dist/transactions/marginManager.d.mts +32 -32
  193. package/dist/transactions/marginPool.d.mts +18 -18
  194. package/dist/transactions/marginRegistry.d.mts +16 -16
  195. package/dist/transactions/marginTPSL.d.mts +10 -10
  196. package/dist/transactions/poolProxy.d.mts +8 -8
  197. package/package.json +25 -4
  198. package/src/account.ts +239 -0
  199. package/src/bcs/integers.ts +35 -0
  200. package/src/contracts/account/account.ts +706 -0
  201. package/src/contracts/account/account_events.ts +64 -0
  202. package/src/contracts/account/account_registry.ts +468 -0
  203. package/src/contracts/account/config-arguments.ts +8 -0
  204. package/src/contracts/account/deps/sui/bag.ts +42 -0
  205. package/src/contracts/deepbook_predict/admin.ts +44 -0
  206. package/src/contracts/deepbook_predict/builder_code.ts +155 -0
  207. package/src/contracts/deepbook_predict/builder_code_events.ts +34 -0
  208. package/src/contracts/deepbook_predict/config-arguments.ts +11 -0
  209. package/src/contracts/deepbook_predict/config_events.ts +140 -0
  210. package/src/contracts/deepbook_predict/deps/fixed_math/i64.ts +21 -0
  211. package/src/contracts/deepbook_predict/deps/sui/balance.ts +25 -0
  212. package/src/contracts/deepbook_predict/deps/sui/coin.ts +20 -0
  213. package/src/contracts/deepbook_predict/deps/sui/table.ts +37 -0
  214. package/src/contracts/deepbook_predict/deps/sui/vec_set.ts +22 -0
  215. package/src/contracts/deepbook_predict/ewma.ts +26 -0
  216. package/src/contracts/deepbook_predict/ewma_config.ts +28 -0
  217. package/src/contracts/deepbook_predict/expiry_cash.ts +24 -0
  218. package/src/contracts/deepbook_predict/expiry_market.ts +1549 -0
  219. package/src/contracts/deepbook_predict/lp_book.ts +105 -0
  220. package/src/contracts/deepbook_predict/market_lifecycle_cap.ts +75 -0
  221. package/src/contracts/deepbook_predict/market_manager.ts +218 -0
  222. package/src/contracts/deepbook_predict/order.ts +24 -0
  223. package/src/contracts/deepbook_predict/order_events.ts +129 -0
  224. package/src/contracts/deepbook_predict/pause_cap.ts +68 -0
  225. package/src/contracts/deepbook_predict/plp.ts +987 -0
  226. package/src/contracts/deepbook_predict/pool_accounting.ts +79 -0
  227. package/src/contracts/deepbook_predict/predict_account.ts +180 -0
  228. package/src/contracts/deepbook_predict/pricing.ts +124 -0
  229. package/src/contracts/deepbook_predict/pricing_config.ts +41 -0
  230. package/src/contracts/deepbook_predict/protocol_config.ts +1066 -0
  231. package/src/contracts/deepbook_predict/range_codec.ts +53 -0
  232. package/src/contracts/deepbook_predict/registry.ts +694 -0
  233. package/src/contracts/deepbook_predict/strike_exposure.ts +77 -0
  234. package/src/contracts/deepbook_predict/strike_exposure_config.ts +46 -0
  235. package/src/contracts/deepbook_predict/strike_payout_tree.ts +89 -0
  236. package/src/contracts/deepbook_predict/vault_events.ts +222 -0
  237. package/src/contracts/deepbook_sessions/config-arguments.ts +8 -0
  238. package/src/contracts/deepbook_sessions/deps/sui/vec_map.ts +33 -0
  239. package/src/contracts/deepbook_sessions/session_config.ts +130 -0
  240. package/src/contracts/deepbook_sessions/sessions.ts +663 -0
  241. package/src/contracts/propbook/block_scholes_store.ts +842 -0
  242. package/src/contracts/propbook/deps/sui/table.ts +37 -0
  243. package/src/contracts/propbook/oracle_lane.ts +170 -0
  244. package/src/contracts/propbook/pyth_feed.ts +414 -0
  245. package/src/contracts/propbook/registry.ts +596 -0
  246. package/src/deployments/index.ts +73 -0
  247. package/src/deployments/testnet.ts +107 -0
  248. package/src/deployments/types.ts +81 -0
  249. package/src/index.ts +5 -0
  250. package/src/predict/client.ts +941 -0
  251. package/src/predict/config/generated.ts +39 -0
  252. package/src/predict/config/index.ts +25 -0
  253. package/src/predict/config/testnet.ts +27 -0
  254. package/src/predict/config/types.ts +52 -0
  255. package/src/predict/decode.ts +476 -0
  256. package/src/predict/errors.ts +83 -0
  257. package/src/predict/index.ts +94 -0
  258. package/src/predict/pricing.ts +199 -0
  259. package/src/predict/reads/balances.ts +55 -0
  260. package/src/predict/reads/inspect.ts +78 -0
  261. package/src/predict/reads/markets.ts +222 -0
  262. package/src/predict/reads/parse.ts +30 -0
  263. package/src/predict/reads/pool.ts +37 -0
  264. package/src/predict/reads/positions.ts +144 -0
  265. package/src/predict/reads/pricing.ts +79 -0
  266. package/src/predict/ticks.ts +42 -0
  267. package/src/predict/tx/authed.ts +20 -0
  268. package/src/predict/tx/common.ts +92 -0
  269. package/src/predict/tx/trade.ts +183 -0
  270. package/src/predict/units.ts +49 -0
  271. package/src/sessions.ts +471 -0
  272. package/dist/types/bcs.mjs +0 -7
@@ -0,0 +1,222 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Transaction } from '@mysten/sui/transactions';
4
+ import { type GeneratedConfig } from '../config/generated.js';
5
+ import { type UnderlyingConfig } from '../config/index.js';
6
+ import { PredictMoveError } from '../errors.js';
7
+ import { POS_INF_TICK } from '../ticks.js';
8
+ import { loadLivePricer, type MarketFeeds } from '../tx/trade.js';
9
+ import * as expiryMarket from '../../contracts/deepbook_predict/expiry_market.js';
10
+ import * as plp from '../../contracts/deepbook_predict/plp.js';
11
+ import * as pricing from '../../contracts/deepbook_predict/pricing.js';
12
+ import * as rangeCodec from '../../contracts/deepbook_predict/range_codec.js';
13
+ import * as registry from '../../contracts/deepbook_predict/registry.js';
14
+ import { inspectReturns, type ReadClient } from './inspect.js';
15
+ import { parseOptionalId, parseOptionalU64, parseU64LE, parseVectorOfIds } from './parse.js';
16
+
17
+ // On-chain ids of the pool's active (live, not-yet-settled) expiry markets.
18
+ // `plp::active_expiry_markets(vault)` — see packages/predict/sources/plp/plp.move:179.
19
+ export async function activeMarketIds(
20
+ client: ReadClient,
21
+ config: GeneratedConfig,
22
+ ): Promise<string[]> {
23
+ const tx = new Transaction();
24
+ tx.add(plp.activeExpiryMarkets({ config }));
25
+ const [cmd0] = await inspectReturns(client, tx);
26
+ return parseVectorOfIds(cmd0[0]);
27
+ }
28
+
29
+ // The expiry market id for one underlying at one expiry, or null if none exists.
30
+ // `registry::expiry_market_id(registry, propbook_underlying_id: u32, expiry: u64):
31
+ // Option<ID>` — see packages/predict/sources/registry/registry.move:53.
32
+ export async function expiryMarketId(
33
+ client: ReadClient,
34
+ config: GeneratedConfig,
35
+ underlying: UnderlyingConfig,
36
+ expiryMs: bigint,
37
+ ): Promise<string | null> {
38
+ const tx = new Transaction();
39
+ tx.add(
40
+ registry.expiryMarketId({
41
+ config,
42
+ arguments: { propbookUnderlyingId: underlying.propbookUnderlyingId, expiry: expiryMs },
43
+ }),
44
+ );
45
+ const [cmd0] = await inspectReturns(client, tx);
46
+ return parseOptionalId(cmd0[0]);
47
+ }
48
+
49
+ export interface MarketState {
50
+ expiryMs: bigint;
51
+ tickSizeRaw: bigint;
52
+ /**
53
+ * The COARSER raw-price step new finite mint boundaries must align to
54
+ * (`expiry_market::admission_tick_size`). A numeric strike must be a whole
55
+ * multiple of this — the fine `tickSizeRaw` grid alone is not sufficient — or
56
+ * the chain aborts `EInvalidAdmissionTick`. The market's reference tick is the
57
+ * one finite boundary allowed to bypass it.
58
+ */
59
+ admissionTickSizeRaw: bigint;
60
+ mintPaused: boolean;
61
+ /**
62
+ * The reference fine-grid tick (Polymarket-style anchor strike: derived
63
+ * on-chain from the exact previous-window oracle observation), or null while
64
+ * the keeper has not seeded it. Reference PRICE raw = tick * tickSizeRaw.
65
+ */
66
+ referenceTickRaw: bigint | null;
67
+ }
68
+
69
+ // The per-market state getters, in fixed order. `expiry_market::{expiry,
70
+ // tick_size, mint_paused, reference_tick}` — see
71
+ // packages/predict/sources/expiry_market.move:{101,177,259,187}. reference_tick
72
+ // returns Option (no abort risk). settlement is read separately via
73
+ // `settlementPrice` (its own non-batched getter below).
74
+ const STATE_FNS = [
75
+ expiryMarket.expiry,
76
+ expiryMarket.tickSize,
77
+ expiryMarket.admissionTickSize,
78
+ expiryMarket.mintPaused,
79
+ expiryMarket.referenceTick,
80
+ ] as const;
81
+
82
+ function parseStateAt(cmds: Uint8Array[][], base: number): MarketState {
83
+ return {
84
+ expiryMs: parseU64LE(cmds[base][0]),
85
+ tickSizeRaw: parseU64LE(cmds[base + 1][0]),
86
+ admissionTickSizeRaw: parseU64LE(cmds[base + 2][0]),
87
+ mintPaused: (cmds[base + 3][0][0] ?? 0) !== 0, // BCS bool: 1 byte
88
+ referenceTickRaw: parseOptionalU64(cmds[base + 4][0]),
89
+ };
90
+ }
91
+
92
+ export async function marketState(
93
+ client: ReadClient,
94
+ config: GeneratedConfig,
95
+ marketId: string,
96
+ ): Promise<MarketState> {
97
+ const [state] = await marketStates(client, config, [marketId]);
98
+ return state;
99
+ }
100
+
101
+ // Batched marketState for N markets in ONE PTB (STATE_FNS.length commands per
102
+ // market, same order). Returns states aligned with `marketIds`.
103
+ export async function marketStates(
104
+ client: ReadClient,
105
+ config: GeneratedConfig,
106
+ marketIds: readonly string[],
107
+ ): Promise<MarketState[]> {
108
+ if (marketIds.length === 0) return [];
109
+ const tx = new Transaction();
110
+ for (const id of marketIds) {
111
+ for (const fn of STATE_FNS) {
112
+ tx.add(fn({ config, arguments: { market: id } }));
113
+ }
114
+ }
115
+ const cmds = await inspectReturns(client, tx);
116
+ return marketIds.map((_, i) => parseStateAt(cmds, STATE_FNS.length * i));
117
+ }
118
+
119
+ // Anonymous both-sides pricing for one strike: the chain's own probability for
120
+ // (strike, +inf] and (-inf, strike]. Deployed `pricing::range_price` takes typed
121
+ // `range_codec::Strike`s (NOT raw u64) — each boundary is built via
122
+ // `range_codec::strike_from_tick(tick, tick_size)`, which maps tick 0 → -inf,
123
+ // POS_INF_TICK → +inf, and any finite tick → tick*tick_size. `range_price` is a
124
+ // public fun on the deployed package. Both sides read the SAME pricer in one PTB, so
125
+ // `down` is the chain's number, not 1 − up.
126
+ export async function rangePrices(
127
+ client: ReadClient,
128
+ config: GeneratedConfig,
129
+ marketId: string,
130
+ feeds: MarketFeeds,
131
+ strikeRaw: bigint,
132
+ tickSizeRaw: bigint,
133
+ ): Promise<{ upRaw: bigint; downRaw: bigint }> {
134
+ const tx = new Transaction();
135
+ const pricer = tx.add(loadLivePricer(config, { expiryMarketId: marketId, ...feeds }));
136
+ // strikeRaw is a whole tick multiple (the caller validates divisibility), so the
137
+ // finite boundary is `strike_from_tick(strikeRaw / tickSize, tickSize)`.
138
+ const strikeTick = strikeRaw / tickSizeRaw;
139
+ const mkStrike = (tick: bigint) =>
140
+ tx.add(rangeCodec.strikeFromTick({ config, arguments: { tick, tickSize: tickSizeRaw } }));
141
+ const strike = mkStrike(strikeTick);
142
+ const posInf = mkStrike(POS_INF_TICK);
143
+ const negInf = mkStrike(0n);
144
+ // UP: (strike, +inf], then DOWN: (-inf, strike] — the last two commands.
145
+ tx.add(pricing.rangePrice({ config, arguments: { pricer, lower: strike, higher: posInf } }));
146
+ tx.add(pricing.rangePrice({ config, arguments: { pricer, lower: negInf, higher: strike } }));
147
+ const cmds = await inspectReturns(client, tx);
148
+ return {
149
+ upRaw: parseU64LE(cmds[cmds.length - 2][0]),
150
+ downRaw: parseU64LE(cmds[cmds.length - 1][0]),
151
+ };
152
+ }
153
+
154
+ // Fresh single read of the reference tick — used by mint-at-reference, which
155
+ // must not trust a cached state (the reference is unset early in a window
156
+ // until the keeper seeds it).
157
+ export async function referenceTick(
158
+ client: ReadClient,
159
+ config: GeneratedConfig,
160
+ marketId: string,
161
+ ): Promise<bigint | null> {
162
+ const tx = new Transaction();
163
+ tx.add(expiryMarket.referenceTick({ config, arguments: { market: marketId } }));
164
+ const [cmd0] = await inspectReturns(client, tx);
165
+ return parseOptionalU64(cmd0[0]);
166
+ }
167
+
168
+ // The recorded settlement price, or null while the market is unsettled.
169
+ //
170
+ // On the deployed package `expiry_market::settlement_price` is public and
171
+ // `destroy_some`s the stored Option — callable here only because simulate runs with
172
+ // checksEnabled:false, and it aborts in std::option (EOPTION_NOT_SET) when the
173
+ // market has not settled; we map exactly that abort (and the public
174
+ // EMarketNotSettled variant, should a future package guard it directly) to null.
175
+ // (A non-aborting `try_settlement_price` also exists on-chain if this ever wants to
176
+ // drop the abort-catch.)
177
+ export async function settlementPrice(
178
+ client: ReadClient,
179
+ config: GeneratedConfig,
180
+ marketId: string,
181
+ ): Promise<bigint | null> {
182
+ const tx = new Transaction();
183
+ tx.add(expiryMarket.settlementPrice({ config, arguments: { market: marketId } }));
184
+ try {
185
+ const [cmd0] = await inspectReturns(client, tx);
186
+ return parseU64LE(cmd0[0]);
187
+ } catch (e) {
188
+ if (
189
+ e instanceof PredictMoveError &&
190
+ (e.module === 'option' ||
191
+ (e.module === 'expiry_market' && e.abortName === 'EMarketNotSettled'))
192
+ ) {
193
+ return null;
194
+ }
195
+ throw e;
196
+ }
197
+ }
198
+
199
+ // A market's current NAV mark (the per-expiry recoverable value the flush prices
200
+ // against). Loads a fresh live pricer, then reads `current_nav(market, &pricer)` —
201
+ // see packages/predict/sources/expiry_market.move:236. `Pricer` has copy+drop, so
202
+ // the unconsumed borrow is fine in a read-only inspect.
203
+ export async function currentNav(
204
+ client: ReadClient,
205
+ config: GeneratedConfig,
206
+ marketId: string,
207
+ underlying: UnderlyingConfig,
208
+ ): Promise<bigint> {
209
+ const tx = new Transaction();
210
+ const pricer = tx.add(
211
+ loadLivePricer(config, {
212
+ expiryMarketId: marketId,
213
+ pythFeed: underlying.pythFeed,
214
+ blockScholesValueStore: underlying.blockScholesValueStore,
215
+ blockScholesSviStore: underlying.blockScholesSviStore,
216
+ }),
217
+ );
218
+ tx.add(expiryMarket.currentNav({ config, arguments: { market: marketId, pricer } }));
219
+ const cmds = await inspectReturns(client, tx);
220
+ // current_nav is the last command; load_live_pricer precedes it.
221
+ return parseU64LE(cmds[cmds.length - 1][0]);
222
+ }
@@ -0,0 +1,30 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // BCS decoders for the return values of on-chain reads, built on the
4
+ // `@mysten/sui/bcs` codec so the read layer decodes exactly the on-chain Move ABI
5
+ // (u64 LE, vector<ID>, Option) with no hand-rolled byte walking. Round-tripped
6
+ // against `@mysten/sui/bcs` in tests/reads.test.ts.
7
+
8
+ import { bcs } from '@mysten/sui/bcs';
9
+
10
+ // BCS u64 → bigint. `bcs.u64()` parses to a decimal string.
11
+ export function parseU64LE(bytes: Uint8Array): bigint {
12
+ return BigInt(bcs.u64().parse(bytes));
13
+ }
14
+
15
+ // BCS vector<ID> / vector<address> → full-length 0x lowercase ids
16
+ // (`bcs.Address` already yields normalized ids).
17
+ export function parseVectorOfIds(bytes: Uint8Array): string[] {
18
+ return bcs.vector(bcs.Address).parse(bytes);
19
+ }
20
+
21
+ // BCS Option<u64>: None → null, Some(x) → x.
22
+ export function parseOptionalU64(bytes: Uint8Array): bigint | null {
23
+ const v = bcs.option(bcs.u64()).parse(bytes);
24
+ return v == null ? null : BigInt(v);
25
+ }
26
+
27
+ // BCS Option<ID>: None → null, Some(id) → normalized 0x id.
28
+ export function parseOptionalId(bytes: Uint8Array): string | null {
29
+ return bcs.option(bcs.Address).parse(bytes);
30
+ }
@@ -0,0 +1,37 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Transaction } from '@mysten/sui/transactions';
4
+ import { type GeneratedConfig } from '../config/generated.js';
5
+ import * as plp from '../../contracts/deepbook_predict/plp.js';
6
+ import { inspectReturns, type ReadClient } from './inspect.js';
7
+ import { parseU64LE } from './parse.js';
8
+
9
+ export interface PoolStats {
10
+ plpTotalSupply: bigint;
11
+ idleBalance: bigint;
12
+ supplyRequestsPending: bigint;
13
+ withdrawRequestsPending: bigint;
14
+ }
15
+
16
+ // The pool's four u64 vault stats batched into one PTB (command order fixed below).
17
+ // `plp::{plp_total_supply, idle_balance, supply_requests_pending,
18
+ // withdraw_requests_pending}(vault)` — see
19
+ // packages/predict/sources/plp/plp.move:{164,149,169,174}.
20
+ export async function poolStats(client: ReadClient, config: GeneratedConfig): Promise<PoolStats> {
21
+ const tx = new Transaction();
22
+ for (const fn of [
23
+ plp.plpTotalSupply,
24
+ plp.idleBalance,
25
+ plp.supplyRequestsPending,
26
+ plp.withdrawRequestsPending,
27
+ ]) {
28
+ tx.add(fn({ config }));
29
+ }
30
+ const cmds = await inspectReturns(client, tx);
31
+ return {
32
+ plpTotalSupply: parseU64LE(cmds[0][0]),
33
+ idleBalance: parseU64LE(cmds[1][0]),
34
+ supplyRequestsPending: parseU64LE(cmds[2][0]),
35
+ withdrawRequestsPending: parseU64LE(cmds[3][0]),
36
+ };
37
+ }
@@ -0,0 +1,144 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { bcs } from '@mysten/sui/bcs';
4
+ import type { ClientWithCoreApi } from '@mysten/sui/client';
5
+ import { deriveDynamicFieldID, normalizeSuiAddress } from '@mysten/sui/utils';
6
+ import { type GeneratedConfig } from '../config/generated.js';
7
+ import { deriveAccountWrapperIdFrom } from '../tx/common.js';
8
+ import { AccountWrapper } from '../../account.js';
9
+ import { PositionKey, PredictData } from '../../contracts/deepbook_predict/predict_account.js';
10
+
11
+ // ============================================================================
12
+ // Chain-only position enumeration.
13
+ //
14
+ // Every open position is tracked under the owner's account:
15
+ // `predict_account::PredictData.positions` is a
16
+ // `Table<PositionKey{expiry_market_id, order_id}, Position>` — and Table
17
+ // entries are dynamic fields, so the KEYS (everything redeem/claim need)
18
+ // arrive directly from a dynamic-field listing. No indexer, no simulation.
19
+ //
20
+ // The walk (all parsing is exact BCS via `include: {content: true}`; the account
21
+ // and PredictData struct layouts come from the generated `contracts/*` MoveStructs
22
+ // so they can't drift from the deployed `account`/`predict_account` sources):
23
+ // 1. wrapper object (id derived client-side) → account UID
24
+ // 2. derived DataKey<PredictApp> field object → positions Table id
25
+ // 3. listDynamicFields(table) → PositionKey per entry
26
+ // Steps 1-2 resolve ids that are immutable once created — cache them per
27
+ // owner (the facade does) and steady state is ONE call per page of positions.
28
+ // ============================================================================
29
+
30
+ // sui::dynamic_field::Field<DataKey<PredictApp>, PredictData>. DataKey is
31
+ // source-empty, but Move inserts a hidden `dummy_field: bool` into empty
32
+ // structs — so the name occupies ONE zero byte between id and value (and the
33
+ // same byte is the derived-field key, below). The `value` uses the generated
34
+ // `PredictData` layout so it tracks the deployed struct.
35
+ const PredictDataFieldBcs = bcs.struct('Field<DataKey,PredictData>', {
36
+ id: bcs.Address,
37
+ name: bcs.bool(), // DataKey's hidden dummy_field
38
+ value: PredictData,
39
+ });
40
+
41
+ /** One open position — the coordinates redeem/claim/hasPosition take. */
42
+ export interface OpenPosition {
43
+ marketId: string;
44
+ orderId: bigint;
45
+ }
46
+
47
+ /** Resolved-once ids for an owner's position store (cache these). */
48
+ export interface PositionsHandle {
49
+ accountUid: string;
50
+ /** Null until the account's Predict data exists (first trade/builder-code). */
51
+ positionsTableId: string | null;
52
+ /** Open-position count at resolution time (from the Table's size). */
53
+ positionCount: bigint;
54
+ }
55
+
56
+ async function contentOf(client: ClientWithCoreApi, objectId: string): Promise<Uint8Array | null> {
57
+ try {
58
+ const { object } = await client.core.getObject({ objectId, include: { content: true } });
59
+ return object.content ?? null;
60
+ } catch (e) {
61
+ // Only a genuinely absent object means "no positions" (never-onboarded
62
+ // owner, or no Predict data yet). Anything else — transport failures,
63
+ // rate limits — must surface, not silently read as an empty portfolio.
64
+ if (/not.?found|does not exist|deleted|NOT_FOUND/i.test(String(e))) return null;
65
+ throw e;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Resolve the immutable id chain for an owner's positions: wrapper → account
71
+ * UID → PredictData → positions Table. Returns null when the owner has never
72
+ * created a Predict account.
73
+ */
74
+ export async function resolvePositionsTable(
75
+ client: ClientWithCoreApi,
76
+ config: GeneratedConfig,
77
+ owner: string,
78
+ ): Promise<PositionsHandle | null> {
79
+ const wrapperContent = await contentOf(client, deriveAccountWrapperIdFrom(config, owner));
80
+ if (!wrapperContent) return null;
81
+ const accountUid = normalizeSuiAddress(AccountWrapper.parse(wrapperContent).account.account_id);
82
+
83
+ // The PredictData field id is derivable — no listing needed for this hop.
84
+ const dataFieldId = deriveDynamicFieldID(
85
+ accountUid,
86
+ `${config.accountPackageId}::account::DataKey<${config.predictPackageId}::predict_account::PredictApp>`,
87
+ new Uint8Array([0]), // DataKey's hidden dummy_field: bool = false
88
+ );
89
+ const fieldContent = await contentOf(client, dataFieldId);
90
+ if (!fieldContent) return { accountUid, positionsTableId: null, positionCount: 0n };
91
+
92
+ const data = PredictDataFieldBcs.parse(fieldContent).value;
93
+ return {
94
+ accountUid,
95
+ positionsTableId: normalizeSuiAddress(data.positions.id),
96
+ positionCount: data.positions.size,
97
+ };
98
+ }
99
+
100
+ /**
101
+ * List open positions from a resolved positions Table: one call per page,
102
+ * keys parsed from the dynamic-field NAMES (no per-entry fetches).
103
+ */
104
+ export async function positionsFromTable(
105
+ client: ClientWithCoreApi,
106
+ positionsTableId: string,
107
+ opts: { limit?: number; maxPages?: number } = {},
108
+ ): Promise<OpenPosition[]> {
109
+ const limit = opts.limit ?? 1000;
110
+ const maxPages = opts.maxPages ?? 10;
111
+ const out: OpenPosition[] = [];
112
+ let cursor: string | undefined = undefined;
113
+ for (let page = 0; page < maxPages; page++) {
114
+ const res = await client.core.listDynamicFields({
115
+ parentId: positionsTableId,
116
+ limit,
117
+ cursor,
118
+ });
119
+ for (const entry of res.dynamicFields) {
120
+ const key = PositionKey.parse(entry.name.bcs);
121
+ out.push({
122
+ marketId: normalizeSuiAddress(key.expiry_market_id),
123
+ orderId: key.order_id,
124
+ });
125
+ }
126
+ if (!res.hasNextPage || !res.cursor) return out;
127
+ cursor = res.cursor;
128
+ }
129
+ throw new Error(
130
+ `positions listing exceeded ${maxPages} pages (${out.length} so far) — raise maxPages`,
131
+ );
132
+ }
133
+
134
+ /** Convenience: resolve + list in one call (uncached; the facade caches). */
135
+ export async function positions(
136
+ client: ClientWithCoreApi,
137
+ config: GeneratedConfig,
138
+ owner: string,
139
+ opts: { limit?: number; maxPages?: number } = {},
140
+ ): Promise<OpenPosition[]> {
141
+ const handle = await resolvePositionsTable(client, config, owner);
142
+ if (!handle?.positionsTableId) return [];
143
+ return positionsFromTable(client, handle.positionsTableId, opts);
144
+ }
@@ -0,0 +1,79 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Transaction } from '@mysten/sui/transactions';
4
+ import { type GeneratedConfig } from '../config/generated.js';
5
+ import { Pricer } from '../../contracts/deepbook_predict/pricing.js';
6
+ import type { PricerInputs, Svi } from '../pricing.js';
7
+ import { loadLivePricer, type MarketFeeds } from '../tx/trade.js';
8
+ import { inspectReturns, type ReadClient } from './inspect.js';
9
+
10
+ // The chain's fixed-point scales for the rolled `PricingSVI` (see the generated
11
+ // `Pricer`/`PricingSVI` struct): forward and rho/m/sigma at 1e9; the rolled `a`/`b` land
12
+ // at 1e18 (roll_down multiplies the 1e9 raw by an extra 1e9). Converting to `number`
13
+ // (float) is deliberate — this is a display pricer; a is a variance ~O(1e-2), so f64's
14
+ // ~15 significant digits are ample and, per pricing.ts, more precise than the chain's
15
+ // fixed point on the short-dated surfaces this prices.
16
+ const FORWARD_SCALE = 1e9;
17
+ const AB_SCALE = 1e18;
18
+ const RMS_SCALE = 1e9; // rho, m, sigma
19
+
20
+ const i64 = (v: { magnitude: string | number | bigint; is_negative: boolean }): number =>
21
+ (v.is_negative ? -1 : 1) * Number(v.magnitude);
22
+
23
+ /** A resolved pricer snapshot read from the chain: the decimal forward + rolled SVI the
24
+ * client-side math consumes, plus the oracle source timestamps behind it (ms; for
25
+ * staleness display — Pyth is 0 when no usable spot existed). The Block-Scholes entries are
26
+ * batch ENVELOPE times (what freshness and the SVI roll-down anchor on), not model times. */
27
+ export interface PricerSnapshot extends PricerInputs {
28
+ sources: {
29
+ pythSpotMs: number;
30
+ blockScholesSpotMs: number;
31
+ blockScholesForwardMs: number;
32
+ blockScholesSviMs: number;
33
+ };
34
+ }
35
+
36
+ // Decode a `Pricer` (already forward-resolved + roll-down-applied on-chain) into decimal
37
+ // `PricerInputs`. Signed fields (`a`, `rho`, `m`) carry the magnitude/flag pair the chain
38
+ // uses; `b`/`sigma` are non-negative.
39
+ function decodePricer(pricer: ReturnType<typeof Pricer.parse>): PricerSnapshot {
40
+ const s = pricer.svi;
41
+ const svi: Svi = {
42
+ a: ((s.a_is_negative ? -1 : 1) * Number(s.a_magnitude)) / AB_SCALE,
43
+ b: Number(s.b) / AB_SCALE,
44
+ rho: i64(s.rho) / RMS_SCALE,
45
+ m: i64(s.m) / RMS_SCALE,
46
+ sigma: Number(s.sigma) / RMS_SCALE,
47
+ };
48
+ return {
49
+ forward: Number(pricer.forward) / FORWARD_SCALE,
50
+ svi,
51
+ sources: {
52
+ pythSpotMs: Number(pricer.pyth_spot_source_timestamp_ms),
53
+ blockScholesSpotMs: Number(pricer.block_scholes_spot_source_timestamp_ms),
54
+ blockScholesForwardMs: Number(pricer.block_scholes_forward_source_timestamp_ms),
55
+ blockScholesSviMs: Number(pricer.block_scholes_svi_source_timestamp_ms),
56
+ },
57
+ };
58
+ }
59
+
60
+ // Read one live pricer snapshot for `marketId`: a single simulate of
61
+ // `load_live_pricer` — the chain reads the oracle feeds, picks the forward
62
+ // (Pyth-vs-Block-Scholes admin policy + freshness), and rolls the SVI down to now, then
63
+ // returns the whole `Pricer` by value (copy+drop), whose BCS we decode. One round trip;
64
+ // then a `boardPricer` prices every strike locally.
65
+ //
66
+ // `load_live_pricer` ABORTS (a typed PredictMoveError) when the market is expired, a feed
67
+ // is stale, or the surface fails the pricing-safe envelope — i.e. exactly when the chain
68
+ // itself cannot quote. Callers surface that the same way `read.price` does.
69
+ export async function readPricerSnapshot(
70
+ client: ReadClient,
71
+ config: GeneratedConfig,
72
+ marketId: string,
73
+ feeds: MarketFeeds,
74
+ ): Promise<PricerSnapshot> {
75
+ const tx = new Transaction();
76
+ tx.add(loadLivePricer(config, { expiryMarketId: marketId, ...feeds }));
77
+ const [cmd0] = await inspectReturns(client, tx);
78
+ return decodePricer(Pricer.parse(cmd0[0]));
79
+ }
@@ -0,0 +1,42 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { PredictInputError } from './errors.js';
4
+
5
+ const TICK_BITS = 30n;
6
+
7
+ /** +inf sentinel tick: the upper bound of an UP range. */
8
+ export const POS_INF_TICK = (1n << TICK_BITS) - 1n;
9
+
10
+ export type Side = 'up' | 'down';
11
+
12
+ // Convert a raw binary-range strike to the `(lower_tick, higher_tick)` pair the
13
+ // `mint` entrypoint takes directly (there is no standalone packed range key).
14
+ // An UP order is `(strike, +inf)` -> lower_tick = strike/tick_size, higher_tick =
15
+ // POS_INF_TICK; a DOWN order is `(-inf, strike)` -> lower_tick = 0 (neg-inf),
16
+ // higher_tick = strike/tick_size.
17
+ export function binaryRangeTicks(
18
+ strikeRaw: bigint,
19
+ side: Side,
20
+ tickSize: bigint,
21
+ ): { lowerTick: bigint; higherTick: bigint } {
22
+ // Anything not exactly 'up' used to fall through to DOWN, byte-identical to a real
23
+ // down mint — no build error, no simulate error, no chain abort. `side` arrives from UI
24
+ // state, JSON, or a DB column at runtime, where the literal type does not protect.
25
+ if (side !== 'up' && side !== 'down') {
26
+ throw new PredictInputError(`side must be 'up' or 'down', got ${JSON.stringify(side)}`);
27
+ }
28
+ const tick = strikeRaw / tickSize;
29
+ if (tick * tickSize !== strikeRaw) {
30
+ throw new PredictInputError(`strike ${strikeRaw} is not a whole tick multiple of ${tickSize}`);
31
+ }
32
+ if (tick <= 0n || tick >= POS_INF_TICK) {
33
+ throw new PredictInputError(
34
+ `strike tick ${tick} outside the finite tick domain (1..POS_INF_TICK-1)`,
35
+ );
36
+ }
37
+ const isUp = side === 'up';
38
+ return {
39
+ lowerTick: isUp ? tick : 0n,
40
+ higherTick: isUp ? POS_INF_TICK : tick,
41
+ };
42
+ }
@@ -0,0 +1,20 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { accountMoveCalls as account } from '../../account.js';
4
+ import * as plp from '../../contracts/deepbook_predict/plp.js';
5
+ import * as predictAccount from '../../contracts/deepbook_predict/predict_account.js';
6
+ import { withAuth } from './common.js';
7
+
8
+ // Every owner-authorized single call in this SDK, declared rather than written: `withAuth`
9
+ // prepends the `generate_auth` command and fills the generated `auth` argument, so each of these
10
+ // takes exactly its generated options minus that slot. Command order is always auth → call, the
11
+ // call consuming the hot potato. The builder-code pair lives in the PREDICT package's
12
+ // `predict_account` module, not the account package.
13
+ export const depositFunds = withAuth(account.depositFunds);
14
+ export const withdrawFunds = withAuth(account.withdrawFunds);
15
+ export const requestSupply = withAuth(plp.requestSupply);
16
+ export const requestWithdraw = withAuth(plp.requestWithdraw);
17
+ export const cancelSupplyRequest = withAuth(plp.cancelSupplyRequest);
18
+ export const cancelWithdrawRequest = withAuth(plp.cancelWithdrawRequest);
19
+ export const setBuilderCode = withAuth(predictAccount.setBuilderCode);
20
+ export const unsetBuilderCode = withAuth(predictAccount.unsetBuilderCode);
@@ -0,0 +1,92 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import type { Transaction, TransactionArgument, TransactionResult } from '@mysten/sui/transactions';
4
+ import { toGeneratedConfig, type GeneratedConfig } from '../config/generated.js';
5
+ import type { PredictConfig } from '../config/index.js';
6
+ import { AccountContract, accountMoveCalls as account } from '../../account.js';
7
+
8
+ // Predict's accounts ARE the shared on-chain account primitive (`packages/account`), so the
9
+ // builders live in `@mysten/deepbook-v3/account` and this is the thin adapter that drives them with
10
+ // Predict's deployed ids. The generated thunks are still used directly by `withAuth` below, which
11
+ // wraps Predict's own entrypoints too — those take the same `Auth` hot potato.
12
+ export function accountContract(cfg: PredictConfig): AccountContract {
13
+ return new AccountContract({
14
+ accountPackageId: cfg.packages.account,
15
+ accountRegistry: cfg.objects.accountRegistry,
16
+ });
17
+ }
18
+
19
+ /**
20
+ * Owner authority is a hot-potato `Auth` minted from the tx sender (`ctx` is implicit in a PTB)
21
+ * and consumed by the very next account-loading call (`load_account_mut` inside `deposit_funds` /
22
+ * `withdraw_funds` / `mint` / …). It resolves to owner auth for whoever signs the transaction.
23
+ * See `packages/account/sources/account.move`.
24
+ */
25
+ export function generateAuth(cfg: PredictConfig): (tx: Transaction) => TransactionResult {
26
+ return account.generateAuth({ config: toGeneratedConfig(cfg) });
27
+ }
28
+
29
+ // The shape every generated binding shares: options in, one PTB command out.
30
+ type GeneratedCall<Options> = (options: Options) => (tx: Transaction) => TransactionResult;
31
+
32
+ // The generated options of a call that consumes the hot-potato `Auth`. Codegen types
33
+ // `arguments` as the named form OR a positional tuple; only the named form is used here.
34
+ interface AuthCallOptions {
35
+ arguments: { auth: TransactionArgument } | readonly unknown[];
36
+ config?: object;
37
+ package?: string;
38
+ }
39
+
40
+ // The named-`arguments` arm of such an options type (the tuple arm has no `auth` property).
41
+ type NamedArguments<Options extends AuthCallOptions> = Extract<
42
+ Options['arguments'],
43
+ { auth: TransactionArgument }
44
+ >;
45
+
46
+ /**
47
+ * The options {@link withAuth} leaves to the caller: the generated ones, minus the `auth`
48
+ * argument it supplies itself, with the projected config required (it is what mints the auth).
49
+ */
50
+ export type WithAuthOptions<Options extends AuthCallOptions> = Omit<
51
+ Options,
52
+ 'arguments' | 'config'
53
+ > & {
54
+ config: GeneratedConfig;
55
+ arguments: Omit<NamedArguments<Options>, 'auth'>;
56
+ };
57
+
58
+ /**
59
+ * Every owner-authorized call in this SDK is the same two commands — mint the hot-potato `Auth`,
60
+ * then make the generated call that consumes it. This lifts a generated binding into that pair,
61
+ * so such a builder is declared rather than written: `withAuth(account.depositFunds)` takes
62
+ * `deposit_funds`'s own options with the `auth` slot already filled.
63
+ */
64
+ export function withAuth<Options extends AuthCallOptions>(
65
+ call: GeneratedCall<Options>,
66
+ ): (options: WithAuthOptions<Options>) => (tx: Transaction) => TransactionResult {
67
+ return (options) => (tx) => {
68
+ const auth = tx.add(account.generateAuth({ config: options.config }));
69
+ // The one unchecked step: with `Options` still generic, TS cannot see that putting `auth`
70
+ // back makes the arguments whole again. Callers get the fully checked type above.
71
+ return tx.add(
72
+ call({ ...options, arguments: { ...options.arguments, auth } } as unknown as Options),
73
+ );
74
+ };
75
+ }
76
+
77
+ // The derivation must agree with on-chain `derive_address`, so it is owned in one place:
78
+ // `@mysten/deepbook-v3/account`. This projects Predict's config onto that contract.
79
+ export function deriveAccountWrapperIdFrom(
80
+ config: Pick<GeneratedConfig, 'accountRegistry' | 'accountPackageId'>,
81
+ owner: string,
82
+ ): string {
83
+ return new AccountContract({
84
+ accountPackageId: config.accountPackageId,
85
+ accountRegistry: config.accountRegistry,
86
+ }).deriveAccountWrapperId(owner);
87
+ }
88
+
89
+ /** The deterministic id of an owner's canonical account wrapper — no chain read needed. */
90
+ export function deriveAccountWrapperId(cfg: PredictConfig, owner: string): string {
91
+ return deriveAccountWrapperIdFrom(toGeneratedConfig(cfg), owner);
92
+ }