@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
@@ -4,9 +4,23 @@ import { fromBase64, normalizeSuiAddress } from '@mysten/sui/utils';
4
4
  import type { PredictConfig } from './config/index.js';
5
5
  import { accountEvents } from '../account.js';
6
6
  import * as builderCodeEvents from '../contracts/deepbook_predict/builder_code_events.js';
7
+ import * as configEvents from '../contracts/deepbook_predict/config_events.js';
7
8
  import * as orderEvents from '../contracts/deepbook_predict/order_events.js';
8
9
  import * as vaultEvents from '../contracts/deepbook_predict/vault_events.js';
10
+ import * as queueEvents from '../contracts/deepbook_predict_orders/queue_events.js';
9
11
  import { PredictInputError } from './errors.js';
12
+ import {
13
+ isMintKind,
14
+ isSellKind,
15
+ orderKindName,
16
+ policyFromBcs,
17
+ refundReason,
18
+ type DelayedExecutionPolicy,
19
+ type HeldPosition,
20
+ type OrderKindName,
21
+ type RefundReasonInfo,
22
+ } from './queue.js';
23
+ import { decodeOrderRange } from './cost.js';
10
24
  import { fromRaw } from './units.js';
11
25
 
12
26
  // ============================================================================
@@ -20,7 +34,7 @@ import { fromRaw } from './units.js';
20
34
  // Decoding uses each event's BCS bytes, not its `json`: the client typings
21
35
  // warn the JSON rendering varies across transports (JSON-RPC/gRPC/GraphQL),
22
36
  // while BCS is canonical. Layouts come from the GENERATED event MoveStructs
23
- // (src/contracts/{deepbook_predict,account}/*_events.ts), whose field order
37
+ // (src/contracts/{deepbook_predict,deepbook_predict_orders,account}/*_events.ts), whose field order
24
38
  // mirrors the deployed Move — regenerate the bindings if the package changes.
25
39
  // ============================================================================
26
40
 
@@ -51,7 +65,9 @@ function eventBytes(e: DecodableEvent): Uint8Array | null {
51
65
 
52
66
  // Match by defining package + module + struct name. Events are typed by the
53
67
  // package version that introduced their struct, not the latest Move-call target.
54
- // All events decoded here were introduced in v1.
68
+ // The pre-queue events were introduced in v1 (`predictV1`); the Predict events the
69
+ // delayed-execution upgrade added in `predictDelayedExecution`; and the queue events
70
+ // in the order-flow companion's original ID (`predictOrdersV1 ?? predictOrders`).
55
71
  function matches(e: DecodableEvent, pkg: string, module: string, name: string): boolean {
56
72
  const tag = e.eventType ?? e.type;
57
73
  if (tag) {
@@ -473,4 +489,677 @@ export function decodeBuilderCodeSets(
473
489
  }));
474
490
  }
475
491
 
492
+ // --- delayed execution (DBU-885) ---------------------------------------------
493
+ //
494
+ // Delayed execution spans two packages. The queue events and the desk's
495
+ // `DelayedExecutionPolicyUpdated` belong to the order-flow companion,
496
+ // `deepbook_predict_orders` (`queue_events`), typed by its ORIGINAL ID. A fill also emits
497
+ // Predict's `OrderMinted` or `LiveOrderRedeemed` (v1 layouts, `decodeMints`/`decodeRedeems`),
498
+ // so match events by type, never by the package a transaction called. The Predict events the
499
+ // delayed-execution upgrade added (`ExpiryPnlRealized`, `FlushOperatorUpdated`,
500
+ // `OrderFlowUpdated`) are typed by `packages.predictDelayedExecution`.
501
+
502
+ /**
503
+ * The defining package of the Predict types and events the delayed-execution upgrade added.
504
+ * Throws rather than guessing: matching against the latest package would silently decode nothing
505
+ * once the package is upgraded again.
506
+ */
507
+ export function delayedExecutionOrigin(cfg: PredictConfig): string {
508
+ const pkg = cfg.packages.predictDelayedExecution;
509
+ if (!pkg) {
510
+ throw new PredictInputError(
511
+ `delayed execution isn't recorded for ${cfg.network} in this SDK version: pass a ` +
512
+ '`config` whose `packages.predictDelayedExecution` names the package that introduced it',
513
+ );
514
+ }
515
+ return pkg;
516
+ }
517
+
518
+ /**
519
+ * The original ID of the order-flow companion (`deepbook_predict_orders`), which types the queue
520
+ * events. Throws while the config doesn't record the companion.
521
+ */
522
+ export function predictOrdersOrigin(cfg: PredictConfig): string {
523
+ const pkg = cfg.packages.predictOrdersV1 ?? cfg.packages.predictOrders;
524
+ if (!pkg) {
525
+ throw new PredictInputError(
526
+ `the order-flow package isn't recorded for ${cfg.network} in this SDK version: pass a ` +
527
+ '`config` whose `packages.predictOrders` names `deepbook_predict_orders`',
528
+ );
529
+ }
530
+ return pkg;
531
+ }
532
+
533
+ function side(kind: number): 'mint' | 'sell' | 'unknown' {
534
+ return isMintKind(kind) ? 'mint' : isSellKind(kind) ? 'sell' : 'unknown';
535
+ }
536
+
537
+ function heldPosition(
538
+ p: {
539
+ order_id: bigint;
540
+ root_id: bigint;
541
+ opened_at_ms: bigint;
542
+ },
543
+ lotSize: bigint,
544
+ ): HeldPosition | null {
545
+ return p.order_id === 0n
546
+ ? null
547
+ : {
548
+ orderId: p.order_id,
549
+ rootId: p.root_id,
550
+ openedAtMs: p.opened_at_ms,
551
+ quantityRaw: decodeOrderRange(p.order_id, lotSize).quantity,
552
+ };
553
+ }
554
+
555
+ /** The market's cash figures after the call, as the queue events report them. */
556
+ export interface QueueCashFigures {
557
+ marketCash: bigint;
558
+ requiredCash: bigint;
559
+ waitingCashNeed: bigint;
560
+ }
561
+
562
+ /** `OrderEnqueued`: the trader's own receipt for a queued mint or sell. Drives "Placed". */
563
+ export interface EnqueueReceipt {
564
+ type: 'enqueued';
565
+ marketId: string;
566
+ /** The record ID: what `read.order`, `quoteSell` and `enqueueSell` take. Persist it. */
567
+ recordId: bigint;
568
+ accountId: string;
569
+ kind: number;
570
+ kindName: OrderKindName;
571
+ side: 'mint' | 'sell' | 'unknown';
572
+ request: {
573
+ lowerTick: bigint;
574
+ higherTick: bigint;
575
+ quantity: bigint;
576
+ maxPremium: bigint;
577
+ minQuantity: bigint;
578
+ maxCost: bigint;
579
+ maxProbability: bigint;
580
+ minProbability: bigint;
581
+ minProceeds: bigint;
582
+ };
583
+ /** The position a sell moved into the record. Null for a mint. */
584
+ position: HeldPosition | null;
585
+ timing: {
586
+ placedAtMs: bigint;
587
+ earliestPriceMs: bigint;
588
+ tauMs: bigint;
589
+ deadlineMs: bigint;
590
+ cutoffMs: bigint;
591
+ pythChannel: number;
592
+ };
593
+ /** The Open record a sell took its position from. Null for a mint. */
594
+ sourceRecordId: bigint | null;
595
+ builderCodeId: string | null;
596
+ referrerAccountId: string | null;
597
+ /** USDC escrowed for the premium and fees (0 for a sell). */
598
+ budget: number;
599
+ orderFee: number;
600
+ cash: QueueCashFigures;
601
+ /** `onchain_timestamp_ms`: the placement transaction's clock. */
602
+ timestampMs: bigint;
603
+ raw: { budget: bigint; orderFee: bigint; cashNeed: bigint; subsidyBound: bigint };
604
+ /** The volatility snapshot the fill prices with, as the generated layout parses it. */
605
+ vol: (typeof queueEvents.OrderEnqueued)['$inferType']['vol'];
606
+ }
607
+
608
+ /** `CohortCommitted`: a price attached to the records `firstRecordId..=lastRecordId`. Drives "Priced". */
609
+ export interface CohortCommitReceipt {
610
+ type: 'cohort-committed';
611
+ marketId: string;
612
+ tauMs: bigint;
613
+ /** The update's envelope: τ, or the backup tick one channel tick later. */
614
+ tickMs: bigint;
615
+ firstRecordId: bigint;
616
+ /** Inclusive. */
617
+ lastRecordId: bigint;
618
+ /** The committed price of the cohort's first order as a float: `spotRaw / 1e9`. */
619
+ price: number;
620
+ /** The committed price, normalized to 1e9. */
621
+ spotRaw: bigint;
622
+ /** That price's own update time, in µs. */
623
+ generationUs: bigint;
624
+ pythSourceId: number;
625
+ pythChannel: number;
626
+ /** Who committed: a keeper, or any third-party filler. */
627
+ sender: string;
628
+ /** `onchain_timestamp_ms`. */
629
+ timestampMs: bigint;
630
+ }
631
+
632
+ /** `QueuedOrderFilled`. Report "Filled" only from this event (or the record). */
633
+ export interface QueuedFillReceipt {
634
+ type: 'filled';
635
+ marketId: string;
636
+ recordId: bigint;
637
+ accountId: string;
638
+ kind: number;
639
+ side: 'mint' | 'sell' | 'unknown';
640
+ /** Filled quantity (mint) or closed quantity (sell). */
641
+ quantity: number;
642
+ /** Cost paid (mint) or proceeds before the order fee (sell). */
643
+ amount: number;
644
+ fees: {
645
+ trading: number;
646
+ builder: number;
647
+ referral: number;
648
+ order: number;
649
+ subsidyUsed: number;
650
+ inventoryImpact: number;
651
+ };
652
+ tauMs: bigint;
653
+ tickMs: bigint;
654
+ /** The record's position now: a mint's new position, a partial sell's remainder, or null. */
655
+ position: HeldPosition | null;
656
+ sender: string;
657
+ timestampMs: bigint;
658
+ cash: QueueCashFigures;
659
+ raw: {
660
+ quantity: bigint;
661
+ amount: bigint;
662
+ tradingFee: bigint;
663
+ builderFee: bigint;
664
+ referralFee: bigint;
665
+ orderFee: bigint;
666
+ subsidyUsed: bigint;
667
+ inventoryImpact: bigint;
668
+ };
669
+ }
670
+
671
+ /**
672
+ * `QueuedOrderRefunded`, from whichever path refunded the order: resolve, a deadline refund, an
673
+ * admin refund, or the settlement drain (`settle_step`, reason 5). `sender` is always the
674
+ * transaction's sender.
675
+ */
676
+ export interface QueuedRefundReceipt {
677
+ type: 'refunded';
678
+ marketId: string;
679
+ recordId: bigint;
680
+ accountId: string;
681
+ kind: number;
682
+ side: 'mint' | 'sell' | 'unknown';
683
+ reason: RefundReasonInfo;
684
+ escrowReturned: number;
685
+ orderFeeReturned: number;
686
+ subsidyReturned: number;
687
+ /** True when a sell's record went back to Open holding its position. */
688
+ positionReturned: boolean;
689
+ sender: string;
690
+ timestampMs: bigint;
691
+ cash: QueueCashFigures;
692
+ raw: { escrowReturned: bigint; orderFeeReturned: bigint; subsidyReturned: bigint };
693
+ }
694
+
695
+ /**
696
+ * `OpenRecordSettled` (paid, 0 for a loser) or `OpenRecordPayoutSkipped` (stays Open, for a later
697
+ * `pay_open`), from `settle_step`'s payout walk or `pay_open`.
698
+ */
699
+ export interface OpenRecordPayoutReceipt {
700
+ type: 'open-record-settled' | 'open-record-payout-skipped';
701
+ marketId: string;
702
+ recordId: bigint;
703
+ accountId: string;
704
+ orderId: bigint;
705
+ payout: number;
706
+ /** True for `OpenRecordPayoutSkipped`: the market couldn't pay it yet. */
707
+ skipped: boolean;
708
+ timestampMs: bigint;
709
+ raw: { payout: bigint };
710
+ }
711
+
712
+ /** `MarketPayoutsCompleted`: the settlement payout walk is done. */
713
+ export interface MarketPayoutsCompletedReceipt {
714
+ type: 'market-payouts-completed';
715
+ marketId: string;
716
+ timestampMs: bigint;
717
+ }
718
+
719
+ /**
720
+ * `RecordFundsParked`: a record kept USDC it couldn't send to its receive address (on USDC's deny
721
+ * list, or USDC paused). `RecordFundsClaimed`: `claim_parked` sent a record's parked funds.
722
+ */
723
+ export interface RecordFundsReceipt {
724
+ type: 'record-funds-parked' | 'record-funds-claimed';
725
+ marketId: string;
726
+ recordId: bigint;
727
+ accountId: string;
728
+ receiveAddress: string;
729
+ /** Parked: this call's parked change or refund. Claimed: everything the record had parked. */
730
+ amount: number;
731
+ timestampMs: bigint;
732
+ raw: { amount: bigint };
733
+ }
734
+
735
+ /** Queue housekeeping events, for ops and alerts. */
736
+ export type QueueOpsReceipt = {
737
+ type: 'queued-orders-cleaned';
738
+ marketId: string;
739
+ recordIds: bigint[];
740
+ timestampMs: bigint;
741
+ };
742
+
743
+ /** Delayed-execution admin events, for the multisig scripts and monitors. */
744
+ export type PolicyUpdateReceipt =
745
+ | {
746
+ /**
747
+ * The companion desk's `DelayedExecutionPolicyUpdated`, from every policy setter with the
748
+ * full post-state. The desk's `init` at publish emits none: the launch policy is only the
749
+ * desk's state.
750
+ */
751
+ type: 'policy-updated';
752
+ deskId: string;
753
+ policy: DelayedExecutionPolicy;
754
+ timestampMs: bigint;
755
+ }
756
+ | { type: 'flush-operator-updated'; operator: string; added: boolean; timestampMs: bigint }
757
+ | {
758
+ /** Predict's `OrderFlowUpdated`: an order-flow witness allowlisted or removed. */
759
+ type: 'order-flow-updated';
760
+ /** The witness type, as Move's `type_name` renders it (no `0x` prefix). */
761
+ orderFlow: string;
762
+ enabled: boolean;
763
+ timestampMs: bigint;
764
+ };
765
+
766
+ /** Every delayed-execution order event, tagged, in chain order. Feed it to `queue.reduceOrderEvents`. */
767
+ export type QueueEvent =
768
+ | EnqueueReceipt
769
+ | CohortCommitReceipt
770
+ | QueuedFillReceipt
771
+ | QueuedRefundReceipt
772
+ | OpenRecordPayoutReceipt
773
+ | MarketPayoutsCompletedReceipt
774
+ | RecordFundsReceipt
775
+ | QueueOpsReceipt;
776
+
777
+ const cashOf = (e: { market_cash: bigint; required_cash: bigint; waiting_cash_need: bigint }) => ({
778
+ marketCash: e.market_cash,
779
+ requiredCash: e.required_cash,
780
+ waitingCashNeed: e.waiting_cash_need,
781
+ });
782
+
783
+ function enqueueReceipt(
784
+ e: (typeof queueEvents.OrderEnqueued)['$inferType'],
785
+ lotSize: bigint,
786
+ ): EnqueueReceipt {
787
+ return {
788
+ type: 'enqueued',
789
+ marketId: normalizeSuiAddress(e.expiry_market_id),
790
+ recordId: e.record_id,
791
+ accountId: normalizeSuiAddress(e.account_id),
792
+ kind: e.kind,
793
+ kindName: orderKindName(e.kind),
794
+ side: side(e.kind),
795
+ request: {
796
+ lowerTick: e.request.lower_tick,
797
+ higherTick: e.request.higher_tick,
798
+ quantity: e.request.quantity,
799
+ maxPremium: e.request.max_premium,
800
+ minQuantity: e.request.min_quantity,
801
+ maxCost: e.request.max_cost,
802
+ maxProbability: e.request.max_probability,
803
+ minProbability: e.request.min_probability,
804
+ minProceeds: e.request.min_proceeds,
805
+ },
806
+ position: heldPosition(e.position, lotSize),
807
+ timing: {
808
+ placedAtMs: e.timing.placed_at_ms,
809
+ earliestPriceMs: e.timing.earliest_price_ms,
810
+ tauMs: e.timing.tau_ms,
811
+ deadlineMs: e.timing.deadline_ms,
812
+ cutoffMs: e.timing.cutoff_ms,
813
+ pythChannel: e.timing.pyth_channel,
814
+ },
815
+ sourceRecordId: e.source_record_id ?? null,
816
+ builderCodeId: optId(e.builder_code_id),
817
+ referrerAccountId: optId(e.referrer_account_id),
818
+ budget: fromRaw(e.budget, 6),
819
+ orderFee: fromRaw(e.order_fee, 6),
820
+ cash: cashOf(e),
821
+ timestampMs: e.onchain_timestamp_ms,
822
+ raw: {
823
+ budget: e.budget,
824
+ orderFee: e.order_fee,
825
+ cashNeed: e.cash_need,
826
+ subsidyBound: e.subsidy_bound,
827
+ },
828
+ vol: e.vol,
829
+ };
830
+ }
831
+
832
+ function cohortCommitReceipt(
833
+ e: (typeof queueEvents.CohortCommitted)['$inferType'],
834
+ ): CohortCommitReceipt {
835
+ return {
836
+ type: 'cohort-committed',
837
+ marketId: normalizeSuiAddress(e.expiry_market_id),
838
+ tauMs: e.tau_ms,
839
+ tickMs: e.tick_ms,
840
+ firstRecordId: e.first_record_id,
841
+ lastRecordId: e.last_record_id,
842
+ price: fromRaw(e.spot, 9),
843
+ spotRaw: e.spot,
844
+ generationUs: e.generation_us,
845
+ pythSourceId: e.pyth_source_id,
846
+ pythChannel: e.pyth_channel,
847
+ sender: normalizeSuiAddress(e.sender),
848
+ timestampMs: e.onchain_timestamp_ms,
849
+ };
850
+ }
851
+
852
+ function fillReceipt(
853
+ e: (typeof queueEvents.QueuedOrderFilled)['$inferType'],
854
+ lotSize: bigint,
855
+ ): QueuedFillReceipt {
856
+ return {
857
+ type: 'filled',
858
+ marketId: normalizeSuiAddress(e.expiry_market_id),
859
+ recordId: e.record_id,
860
+ accountId: normalizeSuiAddress(e.account_id),
861
+ kind: e.kind,
862
+ side: side(e.kind),
863
+ quantity: fromRaw(e.quantity, 6),
864
+ amount: fromRaw(e.amount, 6),
865
+ fees: {
866
+ trading: fromRaw(e.trading_fee, 6),
867
+ builder: fromRaw(e.builder_fee, 6),
868
+ referral: fromRaw(e.referral_fee, 6),
869
+ order: fromRaw(e.order_fee, 6),
870
+ subsidyUsed: fromRaw(e.subsidy_used, 6),
871
+ inventoryImpact: fromRaw(e.inventory_impact, 6),
872
+ },
873
+ tauMs: e.tau_ms,
874
+ tickMs: e.tick_ms,
875
+ position: heldPosition(e.position, lotSize),
876
+ sender: normalizeSuiAddress(e.sender),
877
+ timestampMs: e.onchain_timestamp_ms,
878
+ cash: cashOf(e),
879
+ raw: {
880
+ quantity: e.quantity,
881
+ amount: e.amount,
882
+ tradingFee: e.trading_fee,
883
+ builderFee: e.builder_fee,
884
+ referralFee: e.referral_fee,
885
+ orderFee: e.order_fee,
886
+ subsidyUsed: e.subsidy_used,
887
+ inventoryImpact: e.inventory_impact,
888
+ },
889
+ };
890
+ }
891
+
892
+ function refundReceipt(
893
+ e: (typeof queueEvents.QueuedOrderRefunded)['$inferType'],
894
+ ): QueuedRefundReceipt {
895
+ return {
896
+ type: 'refunded',
897
+ marketId: normalizeSuiAddress(e.expiry_market_id),
898
+ recordId: e.record_id,
899
+ accountId: normalizeSuiAddress(e.account_id),
900
+ kind: e.kind,
901
+ side: side(e.kind),
902
+ reason: refundReason(e.reason),
903
+ escrowReturned: fromRaw(e.escrow_returned, 6),
904
+ orderFeeReturned: fromRaw(e.order_fee_returned, 6),
905
+ subsidyReturned: fromRaw(e.subsidy_returned, 6),
906
+ positionReturned: e.position_returned,
907
+ sender: normalizeSuiAddress(e.sender),
908
+ timestampMs: e.onchain_timestamp_ms,
909
+ cash: cashOf(e),
910
+ raw: {
911
+ escrowReturned: e.escrow_returned,
912
+ orderFeeReturned: e.order_fee_returned,
913
+ subsidyReturned: e.subsidy_returned,
914
+ },
915
+ };
916
+ }
917
+
918
+ function payoutReceipt(
919
+ skipped: boolean,
920
+ ): (e: (typeof queueEvents.OpenRecordSettled)['$inferType']) => OpenRecordPayoutReceipt {
921
+ return (e) => ({
922
+ type: skipped ? 'open-record-payout-skipped' : 'open-record-settled',
923
+ marketId: normalizeSuiAddress(e.expiry_market_id),
924
+ recordId: e.record_id,
925
+ accountId: normalizeSuiAddress(e.account_id),
926
+ orderId: e.order_id,
927
+ payout: fromRaw(e.payout, 6),
928
+ skipped,
929
+ timestampMs: e.onchain_timestamp_ms,
930
+ raw: { payout: e.payout },
931
+ });
932
+ }
933
+
934
+ function recordFundsReceipt(
935
+ type: RecordFundsReceipt['type'],
936
+ ): (e: (typeof queueEvents.RecordFundsParked)['$inferType']) => RecordFundsReceipt {
937
+ return (e) => ({
938
+ type,
939
+ marketId: normalizeSuiAddress(e.expiry_market_id),
940
+ recordId: e.record_id,
941
+ accountId: normalizeSuiAddress(e.account_id),
942
+ receiveAddress: normalizeSuiAddress(e.receive_address),
943
+ amount: fromRaw(e.amount, 6),
944
+ timestampMs: e.onchain_timestamp_ms,
945
+ raw: { amount: e.amount },
946
+ });
947
+ }
948
+
949
+ // Each order event the queue emits: its struct name, generated layout and receipt mapping.
950
+ // One table drives both the per-type decoders and `decodeQueueEvents`, so they can't disagree.
951
+ const QUEUE_EVENT_DECODERS: readonly {
952
+ name: string;
953
+ layout: { parse(bytes: Uint8Array): unknown };
954
+ // `lotSize` is the config's position lot, which decodes a held position's quantity.
955
+ map: (e: never, lotSize: bigint) => QueueEvent;
956
+ }[] = [
957
+ { name: 'OrderEnqueued', layout: queueEvents.OrderEnqueued, map: enqueueReceipt },
958
+ { name: 'CohortCommitted', layout: queueEvents.CohortCommitted, map: cohortCommitReceipt },
959
+ { name: 'QueuedOrderFilled', layout: queueEvents.QueuedOrderFilled, map: fillReceipt },
960
+ { name: 'QueuedOrderRefunded', layout: queueEvents.QueuedOrderRefunded, map: refundReceipt },
961
+ { name: 'OpenRecordSettled', layout: queueEvents.OpenRecordSettled, map: payoutReceipt(false) },
962
+ {
963
+ name: 'OpenRecordPayoutSkipped',
964
+ layout: queueEvents.OpenRecordPayoutSkipped,
965
+ map: payoutReceipt(true),
966
+ },
967
+ {
968
+ name: 'MarketPayoutsCompleted',
969
+ layout: queueEvents.MarketPayoutsCompleted,
970
+ map: (e: (typeof queueEvents.MarketPayoutsCompleted)['$inferType']) => ({
971
+ type: 'market-payouts-completed',
972
+ marketId: normalizeSuiAddress(e.expiry_market_id),
973
+ timestampMs: e.onchain_timestamp_ms,
974
+ }),
975
+ },
976
+ {
977
+ name: 'RecordFundsParked',
978
+ layout: queueEvents.RecordFundsParked,
979
+ map: recordFundsReceipt('record-funds-parked'),
980
+ },
981
+ {
982
+ name: 'RecordFundsClaimed',
983
+ layout: queueEvents.RecordFundsClaimed,
984
+ map: recordFundsReceipt('record-funds-claimed'),
985
+ },
986
+ {
987
+ name: 'QueuedOrdersCleaned',
988
+ layout: queueEvents.QueuedOrdersCleaned,
989
+ map: (e: (typeof queueEvents.QueuedOrdersCleaned)['$inferType']) => ({
990
+ type: 'queued-orders-cleaned',
991
+ marketId: normalizeSuiAddress(e.expiry_market_id),
992
+ recordIds: [...e.record_ids],
993
+ timestampMs: e.onchain_timestamp_ms,
994
+ }),
995
+ },
996
+ ];
997
+
998
+ function eventPayload(e: DecodableEvent, module: string, name: string): Uint8Array {
999
+ const bytes = eventBytes(e);
1000
+ if (!bytes) {
1001
+ throw new PredictInputError(
1002
+ `${module}::${name} event has no BCS payload — execute/simulate with events included`,
1003
+ );
1004
+ }
1005
+ return bytes;
1006
+ }
1007
+
1008
+ /**
1009
+ * Every delayed-execution order event in a result, tagged with `type`, in event order: the
1010
+ * companion's `queue_events`, matched against its original ID. The app's single entry point for
1011
+ * the queue: pass the list to `queue.reduceOrderEvents`.
1012
+ */
1013
+ export function decodeQueueEvents(
1014
+ cfg: PredictConfig,
1015
+ result: DecodableTransactionResult,
1016
+ ): QueueEvent[] {
1017
+ const pkg = predictOrdersOrigin(cfg);
1018
+ const lotSize = BigInt(cfg.units.positionLotSize);
1019
+ const out: QueueEvent[] = [];
1020
+ for (const e of result.events ?? []) {
1021
+ for (const d of QUEUE_EVENT_DECODERS) {
1022
+ if (!matches(e, pkg, 'queue_events', d.name)) continue;
1023
+ out.push(d.map(d.layout.parse(eventPayload(e, 'queue_events', d.name)) as never, lotSize));
1024
+ break;
1025
+ }
1026
+ }
1027
+ return out;
1028
+ }
1029
+
1030
+ function ofType<T extends QueueEvent['type']>(
1031
+ cfg: PredictConfig,
1032
+ result: DecodableTransactionResult,
1033
+ ...types: T[]
1034
+ ): Extract<QueueEvent, { type: T }>[] {
1035
+ return decodeQueueEvents(cfg, result).filter((e): e is Extract<QueueEvent, { type: T }> =>
1036
+ (types as string[]).includes(e.type),
1037
+ );
1038
+ }
1039
+
1040
+ export const decodeEnqueues = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1041
+ ofType(cfg, r, 'enqueued');
1042
+ export const decodeCohortCommits = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1043
+ ofType(cfg, r, 'cohort-committed');
1044
+ export const decodeQueuedFills = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1045
+ ofType(cfg, r, 'filled');
1046
+ export const decodeQueuedRefunds = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1047
+ ofType(cfg, r, 'refunded');
1048
+ export const decodeOpenRecordPayouts = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1049
+ ofType(cfg, r, 'open-record-settled', 'open-record-payout-skipped');
1050
+ export const decodeMarketPayoutsCompleted = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1051
+ ofType(cfg, r, 'market-payouts-completed');
1052
+ export const decodeRecordFunds = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1053
+ ofType(cfg, r, 'record-funds-parked', 'record-funds-claimed');
1054
+ export const decodeQueueOps = (cfg: PredictConfig, r: DecodableTransactionResult) =>
1055
+ ofType(cfg, r, 'queued-orders-cleaned');
1056
+
1057
+ /**
1058
+ * The delayed-execution admin events, in event order: the companion desk's
1059
+ * `DelayedExecutionPolicyUpdated` (matched against the companion's original ID) and Predict's
1060
+ * `FlushOperatorUpdated` and `OrderFlowUpdated` (matched against `predictDelayedExecution`).
1061
+ * Throws while the config records neither package.
1062
+ */
1063
+ export function decodePolicyUpdates(
1064
+ cfg: PredictConfig,
1065
+ result: DecodableTransactionResult,
1066
+ ): PolicyUpdateReceipt[] {
1067
+ const orders = predictOrdersOrigin(cfg);
1068
+ const predict = delayedExecutionOrigin(cfg);
1069
+ const out: PolicyUpdateReceipt[] = [];
1070
+ for (const e of result.events ?? []) {
1071
+ if (matches(e, orders, 'queue_events', 'DelayedExecutionPolicyUpdated')) {
1072
+ const p = queueEvents.DelayedExecutionPolicyUpdated.parse(
1073
+ eventPayload(e, 'queue_events', 'DelayedExecutionPolicyUpdated'),
1074
+ );
1075
+ out.push({
1076
+ type: 'policy-updated',
1077
+ deskId: normalizeSuiAddress(p.desk_id),
1078
+ policy: policyFromBcs(p.policy),
1079
+ timestampMs: p.onchain_timestamp_ms,
1080
+ });
1081
+ } else if (matches(e, predict, 'config_events', 'FlushOperatorUpdated')) {
1082
+ const f = configEvents.FlushOperatorUpdated.parse(
1083
+ eventPayload(e, 'config_events', 'FlushOperatorUpdated'),
1084
+ );
1085
+ out.push({
1086
+ type: 'flush-operator-updated',
1087
+ operator: normalizeSuiAddress(f.operator),
1088
+ added: f.added,
1089
+ timestampMs: f.onchain_timestamp_ms,
1090
+ });
1091
+ } else if (matches(e, predict, 'config_events', 'OrderFlowUpdated')) {
1092
+ const o = configEvents.OrderFlowUpdated.parse(
1093
+ eventPayload(e, 'config_events', 'OrderFlowUpdated'),
1094
+ );
1095
+ out.push({
1096
+ type: 'order-flow-updated',
1097
+ orderFlow: o.order_flow.name,
1098
+ enabled: o.enabled,
1099
+ timestampMs: o.onchain_timestamp_ms,
1100
+ });
1101
+ }
1102
+ }
1103
+ return out;
1104
+ }
1105
+
1106
+ /**
1107
+ * `vault_events::ExpiryPnlRealized`: the change in the pool's gross realized result on one expiry
1108
+ * since that expiry's previous emission, emitted with every `ExpiryPnl`. An expiry's first
1109
+ * emission (its first settled sweep) carries the lifetime result, which can be a loss. A later
1110
+ * one carries the extra cash a later sweep returned, always a profit. Gross: before the
1111
+ * protocol/LP split, and including the sponsor fee subsidies mints moved into expiry cash.
1112
+ */
1113
+ export interface ExpiryPnlRealizedReceipt {
1114
+ vaultId: string;
1115
+ marketId: string;
1116
+ propbookUnderlyingId: number;
1117
+ expiryMs: bigint;
1118
+ /** The settlement price, 1e9-scaled. */
1119
+ settlementPriceRaw: bigint;
1120
+ /** False only for a loss, which only an expiry's first emission reports. */
1121
+ inProfit: boolean;
1122
+ /** The change's magnitude, in USDC. */
1123
+ amount: number;
1124
+ /** The change with its sign: `+amount` for a profit, `−amount` for a loss. */
1125
+ signedAmountRaw: bigint;
1126
+ raw: { amount: bigint };
1127
+ }
1128
+
1129
+ /** Every `ExpiryPnlRealized` in a result, in event order. Introduced with delayed execution. */
1130
+ export function decodeExpiryPnlRealized(
1131
+ cfg: PredictConfig,
1132
+ result: DecodableTransactionResult,
1133
+ ): ExpiryPnlRealizedReceipt[] {
1134
+ return decodeAll(
1135
+ result,
1136
+ delayedExecutionOrigin(cfg),
1137
+ 'vault_events',
1138
+ 'ExpiryPnlRealized',
1139
+ vaultEvents.ExpiryPnlRealized,
1140
+ ).map((e) => ({
1141
+ vaultId: normalizeSuiAddress(e.pool_vault_id),
1142
+ marketId: normalizeSuiAddress(e.expiry_market_id),
1143
+ propbookUnderlyingId: e.propbook_underlying_id,
1144
+ expiryMs: e.expiry,
1145
+ settlementPriceRaw: e.settlement_price,
1146
+ inProfit: e.in_profit,
1147
+ amount: fromRaw(e.amount, 6),
1148
+ signedAmountRaw: e.in_profit ? e.amount : -e.amount,
1149
+ raw: { amount: e.amount },
1150
+ }));
1151
+ }
1152
+
1153
+ /**
1154
+ * The pool's gross realized P&L in raw USDC: the signed sum of `ExpiryPnlRealized` changes. Over
1155
+ * every emission of every expiry it equals the sum of each expiry's latest `ExpiryPnl`, with no
1156
+ * per-expiry dedup. Subtract the `OrderMinted.fee_incentive_subsidy` totals to isolate the
1157
+ * trading result.
1158
+ */
1159
+ export function realizedPnlRaw(
1160
+ receipts: readonly Pick<ExpiryPnlRealizedReceipt, 'signedAmountRaw'>[],
1161
+ ): bigint {
1162
+ return receipts.reduce((sum, r) => sum + r.signedAmountRaw, 0n);
1163
+ }
1164
+
476
1165
  export { exactlyOne };