@mysten/deepbook-v3 2.6.4 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +153 -0
- package/PREDICT.md +389 -61
- package/dist/contracts/account/account.d.mts +23 -23
- package/dist/contracts/account/account.d.mts.map +1 -1
- package/dist/contracts/account/account_registry.d.mts +13 -13
- package/dist/contracts/deepbook/account.d.mts +18 -18
- package/dist/contracts/deepbook/balances.d.mts +4 -4
- package/dist/contracts/deepbook/deep_price.d.mts +3 -3
- package/dist/contracts/deepbook/order.d.mts +12 -12
- package/dist/contracts/deepbook_predict/admin.d.mts +4 -4
- package/dist/contracts/deepbook_predict/builder_code.d.mts +11 -11
- package/dist/contracts/deepbook_predict/builder_code_events.d.mts +10 -10
- package/dist/contracts/deepbook_predict/config_events.d.mts +93 -68
- package/dist/contracts/deepbook_predict/config_events.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/config_events.mjs +45 -1
- package/dist/contracts/deepbook_predict/config_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/deps/std/type_name.mjs +17 -0
- package/dist/contracts/deepbook_predict/deps/std/type_name.mjs.map +1 -0
- package/dist/contracts/deepbook_predict/expiry_market.d.mts +652 -235
- package/dist/contracts/deepbook_predict/expiry_market.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/expiry_market.mjs +652 -186
- package/dist/contracts/deepbook_predict/expiry_market.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/lp_book.mjs +1 -1
- package/dist/contracts/deepbook_predict/market_lifecycle_cap.d.mts +5 -5
- package/dist/contracts/deepbook_predict/market_manager.d.mts +27 -27
- package/dist/contracts/deepbook_predict/order_events.d.mts +50 -50
- package/dist/contracts/deepbook_predict/order_events.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/order_events.mjs +3 -1
- package/dist/contracts/deepbook_predict/order_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pause_cap.d.mts +5 -5
- package/dist/contracts/deepbook_predict/plp.d.mts +184 -82
- package/dist/contracts/deepbook_predict/plp.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/plp.mjs +126 -7
- package/dist/contracts/deepbook_predict/plp.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pool_accounting.mjs +1 -1
- package/dist/contracts/deepbook_predict/pool_valuation_cap.d.mts +5 -5
- package/dist/contracts/deepbook_predict/predict_account.d.mts +14 -14
- package/dist/contracts/deepbook_predict/pricing.d.mts +91 -58
- package/dist/contracts/deepbook_predict/pricing.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/pricing.mjs +30 -3
- package/dist/contracts/deepbook_predict/pricing.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pricing_config.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/protocol_config.d.mts +400 -92
- package/dist/contracts/deepbook_predict/protocol_config.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/protocol_config.mjs +451 -61
- package/dist/contracts/deepbook_predict/protocol_config.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/range_codec.d.mts +2 -2
- package/dist/contracts/deepbook_predict/registry.d.mts +28 -28
- package/dist/contracts/deepbook_predict/strike_exposure.mjs +1 -1
- package/dist/contracts/deepbook_predict/strike_payout_tree.mjs +17 -12
- package/dist/contracts/deepbook_predict/strike_payout_tree.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/vault_events.d.mts +154 -106
- package/dist/contracts/deepbook_predict/vault_events.d.mts.map +1 -1
- package/dist/contracts/deepbook_predict/vault_events.mjs +57 -1
- package/dist/contracts/deepbook_predict/vault_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict_math/config-arguments.d.mts +10 -0
- package/dist/contracts/deepbook_predict_math/config-arguments.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.d.mts +106 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.mjs +125 -0
- package/dist/contracts/deepbook_predict_math/lazer_price.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_math/math.d.mts +284 -0
- package/dist/contracts/deepbook_predict_math/math.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_math/math.mjs +364 -0
- package/dist/contracts/deepbook_predict_math/math.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/config-arguments.d.mts +13 -0
- package/dist/contracts/deepbook_predict_orders/config-arguments.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.d.mts +215 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.mjs +215 -0
- package/dist/contracts/deepbook_predict_orders/delayed_execution_config.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.mjs +87 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.mjs +52 -0
- package/dist/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/fixed_math/i64.mjs +25 -0
- package/dist/contracts/deepbook_predict_orders/deps/fixed_math/i64.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/balance.mjs +21 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/balance.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/table.mjs +39 -0
- package/dist/contracts/deepbook_predict_orders/deps/sui/table.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/desk.d.mts +187 -0
- package/dist/contracts/deepbook_predict_orders/desk.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/desk.mjs +261 -0
- package/dist/contracts/deepbook_predict_orders/desk.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.d.mts +1042 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.mjs +849 -0
- package/dist/contracts/deepbook_predict_orders/order_queue.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue.d.mts +683 -0
- package/dist/contracts/deepbook_predict_orders/queue.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue.mjs +912 -0
- package/dist/contracts/deepbook_predict_orders/queue.mjs.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.d.mts +195 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.d.mts.map +1 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.mjs +187 -0
- package/dist/contracts/deepbook_predict_orders/queue_events.mjs.map +1 -0
- package/dist/contracts/deepbook_sessions/session_config.d.mts +8 -8
- package/dist/contracts/deepbook_sessions/sessions.d.mts +163 -28
- package/dist/contracts/deepbook_sessions/sessions.d.mts.map +1 -1
- package/dist/contracts/deepbook_sessions/sessions.mjs +234 -5
- package/dist/contracts/deepbook_sessions/sessions.mjs.map +1 -1
- package/dist/deployments/mainnet.mjs +7 -4
- package/dist/deployments/mainnet.mjs.map +1 -1
- package/dist/deployments/testnet.mjs +7 -4
- package/dist/deployments/testnet.mjs.map +1 -1
- package/dist/predict/bindings/expiry-market.d.mts +77 -0
- package/dist/predict/bindings/expiry-market.d.mts.map +1 -0
- package/dist/predict/bindings/expiry-market.mjs +139 -0
- package/dist/predict/bindings/expiry-market.mjs.map +1 -0
- package/dist/predict/bindings/protocol-config.d.mts +39 -0
- package/dist/predict/bindings/protocol-config.d.mts.map +1 -0
- package/dist/predict/bindings/protocol-config.mjs +90 -0
- package/dist/predict/bindings/protocol-config.mjs.map +1 -0
- package/dist/predict/bindings/rename.mjs +9 -0
- package/dist/predict/bindings/rename.mjs.map +1 -0
- package/dist/predict/client.d.mts +595 -16
- package/dist/predict/client.d.mts.map +1 -1
- package/dist/predict/client.mjs +986 -10
- package/dist/predict/client.mjs.map +1 -1
- package/dist/predict/config/generated.d.mts +22 -1
- package/dist/predict/config/generated.d.mts.map +1 -1
- package/dist/predict/config/generated.mjs +30 -1
- package/dist/predict/config/generated.mjs.map +1 -1
- package/dist/predict/config/mainnet.mjs +11 -3
- package/dist/predict/config/mainnet.mjs.map +1 -1
- package/dist/predict/config/testnet.mjs +11 -3
- package/dist/predict/config/testnet.mjs.map +1 -1
- package/dist/predict/config/types.d.mts +50 -1
- package/dist/predict/config/types.d.mts.map +1 -1
- package/dist/predict/cost.d.mts +38 -11
- package/dist/predict/cost.d.mts.map +1 -1
- package/dist/predict/cost.mjs +37 -11
- package/dist/predict/cost.mjs.map +1 -1
- package/dist/predict/decode.d.mts +251 -1
- package/dist/predict/decode.d.mts.map +1 -1
- package/dist/predict/decode.mjs +342 -4
- package/dist/predict/decode.mjs.map +1 -1
- package/dist/predict/errors.d.mts +69 -6
- package/dist/predict/errors.d.mts.map +1 -1
- package/dist/predict/errors.mjs +277 -4
- package/dist/predict/errors.mjs.map +1 -1
- package/dist/predict/index.d.mts +21 -10
- package/dist/predict/index.mjs +24 -12
- package/dist/predict/queue-id.d.mts +13 -0
- package/dist/predict/queue-id.d.mts.map +1 -0
- package/dist/predict/queue-id.mjs +19 -0
- package/dist/predict/queue-id.mjs.map +1 -0
- package/dist/predict/queue.d.mts +505 -0
- package/dist/predict/queue.d.mts.map +1 -0
- package/dist/predict/queue.mjs +774 -0
- package/dist/predict/queue.mjs.map +1 -0
- package/dist/predict/reads/balances.mjs +1 -1
- package/dist/predict/reads/markets.mjs +46 -5
- package/dist/predict/reads/markets.mjs.map +1 -1
- package/dist/predict/reads/pool.mjs +1 -1
- package/dist/predict/reads/pricing.d.mts +1 -1
- package/dist/predict/reads/queue.d.mts +105 -0
- package/dist/predict/reads/queue.d.mts.map +1 -0
- package/dist/predict/reads/queue.mjs +445 -0
- package/dist/predict/reads/queue.mjs.map +1 -0
- package/dist/predict/ticks.d.mts +9 -1
- package/dist/predict/ticks.d.mts.map +1 -1
- package/dist/predict/ticks.mjs +18 -1
- package/dist/predict/ticks.mjs.map +1 -1
- package/dist/predict/tx/authed.mjs +1 -1
- package/dist/predict/tx/common.d.mts.map +1 -1
- package/dist/predict/tx/common.mjs +12 -1
- package/dist/predict/tx/common.mjs.map +1 -1
- package/dist/predict/tx/queue.d.mts +220 -0
- package/dist/predict/tx/queue.d.mts.map +1 -0
- package/dist/predict/tx/queue.mjs +399 -0
- package/dist/predict/tx/queue.mjs.map +1 -0
- package/dist/predict/tx/trade.d.mts.map +1 -1
- package/dist/predict/tx/trade.mjs +61 -43
- package/dist/predict/tx/trade.mjs.map +1 -1
- package/dist/sessions.d.mts +90 -2
- package/dist/sessions.d.mts.map +1 -1
- package/dist/sessions.mjs +107 -2
- package/dist/sessions.mjs.map +1 -1
- package/dist/transactions/balanceManager.d.mts +12 -12
- package/dist/transactions/balanceManager.d.mts.map +1 -1
- package/dist/transactions/deepbook.d.mts +20 -20
- package/dist/transactions/deepbook.d.mts.map +1 -1
- package/dist/transactions/deepbookAdmin.d.mts +4 -4
- package/dist/transactions/deepbookAdmin.d.mts.map +1 -1
- package/dist/transactions/marginAdmin.d.mts +7 -7
- package/dist/transactions/marginAdmin.d.mts.map +1 -1
- package/dist/transactions/marginLiquidations.d.mts +3 -3
- package/dist/transactions/marginMaintainer.d.mts +5 -5
- package/dist/transactions/marginMaintainer.d.mts.map +1 -1
- package/dist/transactions/marginManager.d.mts +32 -32
- package/dist/transactions/marginManager.d.mts.map +1 -1
- package/dist/transactions/marginPool.d.mts +18 -18
- package/dist/transactions/marginRegistry.d.mts +16 -16
- package/dist/transactions/marginTPSL.d.mts +10 -10
- package/dist/transactions/marginTPSL.d.mts.map +1 -1
- package/dist/transactions/poolProxy.d.mts +8 -8
- package/dist/transactions/poolProxy.d.mts.map +1 -1
- package/package.json +4 -4
- package/src/contracts/deepbook_predict/config_events.ts +39 -0
- package/src/contracts/deepbook_predict/deps/std/type_name.ts +24 -0
- package/src/contracts/deepbook_predict/expiry_market.ts +960 -169
- package/src/contracts/deepbook_predict/order_events.ts +3 -1
- package/src/contracts/deepbook_predict/plp.ts +150 -9
- package/src/contracts/deepbook_predict/pricing.ts +46 -7
- package/src/contracts/deepbook_predict/pricing_config.ts +3 -1
- package/src/contracts/deepbook_predict/protocol_config.ts +648 -33
- package/src/contracts/deepbook_predict/strike_payout_tree.ts +25 -21
- package/src/contracts/deepbook_predict/vault_events.ts +65 -0
- package/src/contracts/deepbook_predict_math/config-arguments.ts +6 -0
- package/src/contracts/deepbook_predict_math/lazer_price.ts +196 -0
- package/src/contracts/deepbook_predict_math/math.ts +553 -0
- package/src/contracts/deepbook_predict_orders/config-arguments.ts +11 -0
- package/src/contracts/deepbook_predict_orders/delayed_execution_config.ts +430 -0
- package/src/contracts/deepbook_predict_orders/deps/deepbook_predict/expiry_market.ts +108 -0
- package/src/contracts/deepbook_predict_orders/deps/deepbook_predict/pricing.ts +58 -0
- package/src/contracts/deepbook_predict_orders/deps/fixed_math/i64.ts +21 -0
- package/src/contracts/deepbook_predict_orders/deps/sui/balance.ts +19 -0
- package/src/contracts/deepbook_predict_orders/deps/sui/table.ts +37 -0
- package/src/contracts/deepbook_predict_orders/desk.ts +419 -0
- package/src/contracts/deepbook_predict_orders/order_flow.ts +19 -0
- package/src/contracts/deepbook_predict_orders/order_queue.ts +1670 -0
- package/src/contracts/deepbook_predict_orders/queue.ts +1394 -0
- package/src/contracts/deepbook_predict_orders/queue_events.ts +189 -0
- package/src/contracts/deepbook_sessions/sessions.ts +355 -4
- package/src/deployments/mainnet.ts +7 -2
- package/src/deployments/testnet.ts +7 -2
- package/src/deployments/types.ts +14 -1
- package/src/predict/bindings/expiry-market.ts +127 -0
- package/src/predict/bindings/protocol-config.ts +59 -0
- package/src/predict/bindings/rename.ts +14 -0
- package/src/predict/client.ts +2076 -13
- package/src/predict/config/generated.ts +50 -0
- package/src/predict/config/mainnet.ts +16 -2
- package/src/predict/config/testnet.ts +16 -2
- package/src/predict/config/types.ts +51 -1
- package/src/predict/cost.ts +62 -14
- package/src/predict/decode.ts +691 -2
- package/src/predict/errors.ts +391 -14
- package/src/predict/index.ts +87 -6
- package/src/predict/queue-id.ts +22 -0
- package/src/predict/queue.ts +1231 -0
- package/src/predict/reads/markets.ts +30 -0
- package/src/predict/reads/queue.ts +606 -0
- package/src/predict/ticks.ts +35 -0
- package/src/predict/tx/common.ts +25 -1
- package/src/predict/tx/queue.ts +525 -0
- package/src/predict/tx/trade.ts +80 -49
- package/src/sessions.ts +206 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.mjs","names":["max","q"],"sources":["../../src/predict/queue.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n// Delayed execution (DBU-885): the codes, cash-need math, timing previews and order-state views\n// for queued orders. Pure functions over raw bigints, no network. Exported as the `queue`\n// namespace, like `cost` and `pricing`.\n//\n// A queued order is placed now and priced later at Pyth's signed price for its τ, a channel\n// tick shortly after placement. A keeper (or anyone, see `fill` in `tx/queue.ts`) commits the\n// price and resolves the order: a fill, or a refund with a reason code. A filled mint stays in\n// its market's queue as an Open record until `enqueue_redeem_open` sells it or the queue's\n// settlement walk (`settle_step`) pays it.\n//\n// The queue lives in the order-flow companion, `deepbook_predict_orders`. The code values mirror\n// its `order_queue` getters, and the cash-need formulas are 1:1 ports (rounding included) of\n// `deepbook_predict_math::math::need_*`, which Predict's admission charges. Probabilities and λ\n// are 1e9-scaled.\n\nimport type { DelayedExecutionPolicy as DelayedExecutionPolicyBcs } from '../contracts/deepbook_predict_orders/delayed_execution_config.js';\nimport type { OrderView as OrderViewBcs } from '../contracts/deepbook_predict_orders/order_queue.js';\nimport { FLOAT_SCALING, MAX_QUANTITY_LOTS, POSITION_LOT_SIZE, decodeOrderRange } from './cost.js';\nimport type { QueueEvent } from './decode.js';\nimport { PredictInputError } from './errors.js';\nimport { U64_MAX } from './units.js';\n\n// === Codes ===\n\n/**\n * Predict's `constants::current_version` from the upgrade that added delayed execution. Enqueue\n * works once `ProtocolConfig.version_watermark` reaches it (Predict's admission aborts\n * `ECutoverNotReached` until then). The retired immediate trades (`mint_exact_*`, `redeem_live`)\n * always abort in that package, and the older packages they still run in are retired by the same\n * bump. The same on both networks: it is the code's version constant, not the on-chain package\n * version (Mainnet v4, Testnet v5).\n */\nexport const DELAYED_EXECUTION_VERSION = 4n;\n\n/**\n * Predict's `constants::current_version` of the package these bindings were generated from. Every\n * version-gated Predict call checks `chk_version`, which aborts `EPackageVersionDisabled` once\n * `ProtocolConfig.version_watermark` is above it, so a higher watermark retires the Predict code\n * this SDK calls. Bump it with Predict when regenerating.\n */\nexport const PREDICT_PACKAGE_VERSION = 4n;\n\n/**\n * `desk::current_version` of the order-flow package these bindings were generated from. The desk's\n * version floor retires older companion code, so a floor above it means the package this SDK calls\n * aborts `EPackageVersionDisabled`. Bump it with the companion when regenerating.\n */\nexport const ORDER_FLOW_PACKAGE_VERSION = 1n;\n\n/** `queue::phase_*`: what `settle_step` returns, the phase the next call runs. */\nexport const SETTLE_PHASE = Object.freeze({\n\t/** Refunding the waiting orders (reason 5). */\n\tDRAIN: 0,\n\t/** Paying the Open records, once Predict has settled the market. */\n\tPAY: 1,\n\t/**\n\t * The payout walk reached the last record and `MarketPayoutsCompleted` was emitted. A record\n\t * the market couldn't pay (`OpenRecordPayoutSkipped`) stays Open and unpaid.\n\t */\n\tDONE: 2,\n} as const);\n\n/** `order_queue::status_*`. Never renumbered on chain; unknown codes still decode. */\nexport const ORDER_STATUS = Object.freeze({\n\tPENDING: 0,\n\tCOMMITTED: 1,\n\tOPEN: 2,\n\tREFUNDED: 3,\n\tCLOSED: 4,\n\t/** Reserved: nothing sets it at launch. Counts as unfinished. */\n\tREFUND_DUE: 5,\n} as const);\n\n/** `order_queue::kind_*`. `REDEEM_LIVE` is reserved and never used by v4. */\nexport const ORDER_KIND = Object.freeze({\n\tEXACT_QUANTITY: 0,\n\tEXACT_AMOUNT: 1,\n\tEXACT_COST: 2,\n\tREDEEM_LIVE: 3,\n\tREDEEM_OPEN: 4,\n} as const);\n\n/** `order_queue::reason_*`. `0` in a record's result means filled. */\nexport const REFUND_REASON = Object.freeze({\n\tLIMITS: 1,\n\tADMISSION: 2,\n\tNO_PRICE: 3,\n\tMISSING_NODE: 4,\n\tDEADLINE: 5,\n\tFREEZE: 6,\n\tADMIN: 7,\n\tNO_CASH: 8,\n\tRECIPIENT_DENIED: 9,\n} as const);\n\n/** The Pyth Lazer channels the queue prices on (`delayed_execution_config`). */\nexport const PYTH_CHANNEL = Object.freeze({\n\tFIXED_RATE_50MS: 2,\n\tFIXED_RATE_200MS: 3,\n} as const);\n\n/** Predict's `constants::deadline_expiry_margin_ms`: every deadline is at least this long before expiry. */\nexport const DEADLINE_EXPIRY_MARGIN_MS = 5_000n;\n\n/**\n * How long after an order's deadline the app waits before offering \"Refund my order\". Keepers\n * refund overdue orders on their own, so the button only matters when they are all down.\n */\nexport const REFUND_REQUEST_GRACE_MS = 5_000n;\n\nexport type OrderStatusName =\n\t'pending' | 'committed' | 'open' | 'refunded' | 'closed' | 'refund-due' | 'unknown';\n\nexport type OrderKindName =\n\t'exact-quantity' | 'exact-amount' | 'exact-cost' | 'redeem-live' | 'redeem-open' | 'unknown';\n\nconst STATUS_NAMES: readonly OrderStatusName[] = [\n\t'pending',\n\t'committed',\n\t'open',\n\t'refunded',\n\t'closed',\n\t'refund-due',\n];\nconst KIND_NAMES: readonly OrderKindName[] = [\n\t'exact-quantity',\n\t'exact-amount',\n\t'exact-cost',\n\t'redeem-live',\n\t'redeem-open',\n];\n\n/** A status code's name, or `'unknown'` for a code this SDK version predates. */\nexport function orderStatusName(code: number): OrderStatusName {\n\treturn STATUS_NAMES[code] ?? 'unknown';\n}\n\n/** A kind code's name, or `'unknown'` for a code this SDK version predates. */\nexport function orderKindName(code: number): OrderKindName {\n\treturn KIND_NAMES[code] ?? 'unknown';\n}\n\n/** Whether a kind code is a queued mint (exact quantity, exact amount or exact cost). */\nexport function isMintKind(kind: number): boolean {\n\treturn (\n\t\tkind === ORDER_KIND.EXACT_QUANTITY ||\n\t\tkind === ORDER_KIND.EXACT_AMOUNT ||\n\t\tkind === ORDER_KIND.EXACT_COST\n\t);\n}\n\n/** Whether a kind code is a queued sell. */\nexport function isSellKind(kind: number): boolean {\n\treturn kind === ORDER_KIND.REDEEM_OPEN || kind === ORDER_KIND.REDEEM_LIVE;\n}\n\n/** What a refund reason means for the trader. */\nexport interface RefundReasonInfo {\n\tcode: number;\n\tkey:\n\t\t| 'limits'\n\t\t| 'admission'\n\t\t| 'no-price'\n\t\t| 'missing-node'\n\t\t| 'deadline'\n\t\t| 'freeze'\n\t\t| 'admin'\n\t\t| 'no-cash'\n\t\t| 'recipient-denied'\n\t\t| 'unknown';\n\t/** Display text for the refund. */\n\ttext: string;\n\t/** Whether the order fee was kept (reasons 1 and 2). `null` for an unknown code. */\n\tfeeKept: boolean | null;\n\t/** False for codes v4 reserves but never sets (3 and 6), and for unknown codes. */\n\tlive: boolean;\n}\n\n/** Every reason code v4 defines, with its text and fee treatment. */\nexport const REFUND_REASONS: Readonly<Record<number, RefundReasonInfo>> = Object.freeze({\n\t1: {\n\t\tcode: 1,\n\t\tkey: 'limits',\n\t\ttext: \"Your price limits weren't met at the fill price. Refunded, the order fee is kept.\",\n\t\tfeeKept: true,\n\t\tlive: true,\n\t},\n\t2: {\n\t\tcode: 2,\n\t\tkey: 'admission',\n\t\ttext: \"The market couldn't accept the order at the fill price. Refunded, the order fee is kept.\",\n\t\tfeeKept: true,\n\t\tlive: true,\n\t},\n\t3: {\n\t\tcode: 3,\n\t\tkey: 'no-price',\n\t\ttext: 'No price arrived for the order. Refunded in full.',\n\t\tfeeKept: false,\n\t\tlive: false,\n\t},\n\t4: {\n\t\tcode: 4,\n\t\tkey: 'missing-node',\n\t\ttext: \"The market couldn't place the order. Refunded in full.\",\n\t\tfeeKept: false,\n\t\tlive: true,\n\t},\n\t5: {\n\t\tcode: 5,\n\t\tkey: 'deadline',\n\t\ttext: \"The order wasn't priced before its deadline. Refunded in full.\",\n\t\tfeeKept: false,\n\t\tlive: true,\n\t},\n\t6: {\n\t\tcode: 6,\n\t\tkey: 'freeze',\n\t\ttext: 'The protocol was frozen. Refunded in full.',\n\t\tfeeKept: false,\n\t\tlive: false,\n\t},\n\t7: { code: 7, key: 'admin', text: 'Refunded in full by an admin.', feeKept: false, live: true },\n\t8: {\n\t\tcode: 8,\n\t\tkey: 'no-cash',\n\t\ttext: \"The market couldn't pay right now. Refunded in full.\",\n\t\tfeeKept: false,\n\t\tlive: true,\n\t},\n\t9: {\n\t\tcode: 9,\n\t\tkey: 'recipient-denied',\n\t\ttext: \"The account's receive address can't take USDC right now (it is on USDC's deny list, or USDC is paused). Refunded in full, and the refund waits in the order until it can be claimed.\",\n\t\tfeeKept: false,\n\t\tlive: true,\n\t},\n});\n\n/** A reason code's meaning. Unknown codes map to `key: 'unknown'` rather than throwing. */\nexport function refundReason(code: number): RefundReasonInfo {\n\treturn (\n\t\tREFUND_REASONS[code] ?? {\n\t\t\tcode,\n\t\t\tkey: 'unknown',\n\t\t\ttext: `Refunded (code ${code}).`,\n\t\t\tfeeKept: null,\n\t\t\tlive: false,\n\t\t}\n\t);\n}\n\n// === Policy ===\n\n/**\n * `delayed_execution_config::DelayedExecutionPolicy` with camelCase keys, as the companion's\n * `OrderDesk` holds it (`desk::policy`). Times in ms, USDC raw.\n */\nexport interface DelayedExecutionPolicy {\n\tdelayMs: bigint;\n\tstallTimeoutMs: bigint;\n\tstuckThresholdMs: bigint;\n\tgapWaitMs: bigint;\n\tpythPriceBufferMs: bigint;\n\t/** {@link PYTH_CHANNEL}: `2` is 50 ms, `3` is 200 ms. */\n\tpythChannel: number;\n\tsviMaxAgeMs: bigint;\n\tmintCapacity: bigint;\n\tsellCapacity: bigint;\n\tperAccountCap: bigint;\n\t/** Flat USDC fee charged at enqueue, raw. */\n\torderFee: bigint;\n\tminSellQuantity: bigint;\n\tsettleRefundBatch: bigint;\n\tsettlePayoutBatch: bigint;\n}\n\n/** Map the generated policy layout to {@link DelayedExecutionPolicy}. */\nexport function policyFromBcs(\n\tp: (typeof DelayedExecutionPolicyBcs)['$inferType'],\n): DelayedExecutionPolicy {\n\treturn {\n\t\tdelayMs: p.delay_ms,\n\t\tstallTimeoutMs: p.stall_timeout_ms,\n\t\tstuckThresholdMs: p.stuck_threshold_ms,\n\t\tgapWaitMs: p.gap_wait_ms,\n\t\tpythPriceBufferMs: p.pyth_price_buffer_ms,\n\t\tpythChannel: p.pyth_channel,\n\t\tsviMaxAgeMs: p.svi_max_age_ms,\n\t\tmintCapacity: p.mint_capacity,\n\t\tsellCapacity: p.sell_capacity,\n\t\tperAccountCap: p.per_account_cap,\n\t\torderFee: p.order_fee,\n\t\tminSellQuantity: p.min_sell_quantity,\n\t\tsettleRefundBatch: p.settle_refund_batch,\n\t\tsettlePayoutBatch: p.settle_payout_batch,\n\t};\n}\n\n/** `delayed_execution_config::channel_tick_ms`: 50 ms for channel 2, 200 ms for channel 3. */\nexport function channelTickMs(channel: number): bigint {\n\tif (channel === PYTH_CHANNEL.FIXED_RATE_50MS) return 50n;\n\tif (channel === PYTH_CHANNEL.FIXED_RATE_200MS) return 200n;\n\tthrow new PredictInputError(`unsupported Pyth Lazer channel ${channel}`);\n}\n\n// === Cash need (`deepbook_predict_math::math::need_*`) ===\n\nfunction assertUint(value: bigint, name: string, max: bigint = U64_MAX): void {\n\tif (typeof value !== 'bigint' || value < 0n || value > max) {\n\t\tthrow new PredictInputError(`${name} must be a bigint in [0, ${max}], got ${String(value)}`);\n\t}\n}\n\n// `math::mul_div_up`, including its abort on a zero denominator and a u64 overflow.\nfunction mulDivUp(x: bigint, y: bigint, denominator: bigint): bigint {\n\tif (denominator === 0n) throw new PredictInputError('division by zero (EInputZero)');\n\treturn (x * y + denominator - 1n) / denominator;\n}\n\nfunction plusOne(need: bigint): bigint {\n\tif (need >= U64_MAX) throw new PredictInputError('cash need overflows u64');\n\treturn need + 1n;\n}\n\n/** Exact-quantity mint cash need: `⌈quantity · (1 − p_min)⌉ + 1`. */\nexport function cashNeedExactQuantity(quantity: bigint, minEntryProbability: bigint): bigint {\n\tassertUint(quantity, 'quantity');\n\tassertUint(minEntryProbability, 'minEntryProbability', FLOAT_SCALING);\n\treturn plusOne(mulDivUp(quantity, FLOAT_SCALING - minEntryProbability, FLOAT_SCALING));\n}\n\n/**\n * Budget mint cash need: `⌈(budget + 1) · (1 / p_min − 1)⌉ + 1`, rounded as Move rounds it (one\n * `mul_div_up` of `(budget + 1) · (1e9 − p_min) / p_min`). Exact-amount mints pass\n * `min(max_premium, budget)`. `p_min = 0` throws, as the Move division aborts.\n */\nexport function cashNeedBudget(budget: bigint, minEntryProbability: bigint): bigint {\n\tassertUint(budget, 'budget', U64_MAX - 1n);\n\tassertUint(minEntryProbability, 'minEntryProbability', FLOAT_SCALING);\n\treturn plusOne(mulDivUp(budget + 1n, FLOAT_SCALING - minEntryProbability, minEntryProbability));\n}\n\n/** Sell cash need: `⌈close_quantity · (1 − λ)⌉ + 1`. */\nexport function cashNeedSell(closeQuantity: bigint, backingBufferLambda: bigint): bigint {\n\tassertUint(closeQuantity, 'closeQuantity');\n\tassertUint(backingBufferLambda, 'backingBufferLambda', FLOAT_SCALING);\n\treturn plusOne(mulDivUp(closeQuantity, FLOAT_SCALING - backingBufferLambda, FLOAT_SCALING));\n}\n\n/**\n * Whether the account can pay the order fee: a mint needs `available > fee` (it escrows a budget\n * on top), a sell needs `available ≥ fee` (it escrows only the fee). `available` is\n * `account::balance<USDC>`, unsettled accumulator funds included.\n */\nexport function feeCovered(\n\tside: 'mint' | 'sell',\n\tavailableRaw: bigint,\n\torderFeeRaw: bigint,\n): boolean {\n\treturn side === 'mint' ? availableRaw > orderFeeRaw : availableRaw >= orderFeeRaw;\n}\n\n/** Inputs for {@link mintBudget}. */\nexport interface MintBudgetInputs {\n\t/** {@link ORDER_KIND}: a mint kind. */\n\tkind: number;\n\tmaxCostRaw: bigint;\n\tavailableRaw: bigint;\n\torderFeeRaw: bigint;\n\t/** Required for exact quantity: a fill never costs more than its quantity. */\n\tquantityRaw?: bigint;\n}\n\n/**\n * The budget a queued mint escrows: `min(max_cost, available − fee)`, and for exact quantity also\n * at most the quantity. `null` when the balance doesn't cover the fee. Enqueue debits the budget\n * plus the order fee, and the unspent budget comes back at the fill.\n */\nexport function mintBudget(inputs: MintBudgetInputs): bigint | null {\n\tif (!feeCovered('mint', inputs.availableRaw, inputs.orderFeeRaw)) return null;\n\tconst budget = min(inputs.maxCostRaw, inputs.availableRaw - inputs.orderFeeRaw);\n\tif (inputs.kind !== ORDER_KIND.EXACT_QUANTITY) return budget;\n\tif (inputs.quantityRaw == null) {\n\t\tthrow new PredictInputError('quantityRaw is required for an exact-quantity budget');\n\t}\n\treturn min(budget, inputs.quantityRaw);\n}\n\n/** Inputs for {@link mintCashNeed}. */\nexport interface MintCashNeedInputs {\n\tkind: number;\n\t/** The escrowed budget, from {@link mintBudget}. */\n\tbudgetRaw: bigint;\n\tminEntryProbability: bigint;\n\t/** Exact quantity: the quantity ordered. */\n\tquantityRaw?: bigint;\n\t/** Exact amount: the premium cap. */\n\tmaxPremiumRaw?: bigint;\n}\n\n/** A queued mint's cash need, picking the formula the contract picks for its kind. */\nexport function mintCashNeed(inputs: MintCashNeedInputs): bigint {\n\tconst p = inputs.minEntryProbability;\n\tswitch (inputs.kind) {\n\t\tcase ORDER_KIND.EXACT_QUANTITY:\n\t\t\tif (inputs.quantityRaw == null) throw new PredictInputError('quantityRaw is required');\n\t\t\treturn cashNeedExactQuantity(inputs.quantityRaw, p);\n\t\tcase ORDER_KIND.EXACT_AMOUNT:\n\t\t\tif (inputs.maxPremiumRaw == null) throw new PredictInputError('maxPremiumRaw is required');\n\t\t\treturn cashNeedBudget(min(inputs.maxPremiumRaw, inputs.budgetRaw), p);\n\t\tcase ORDER_KIND.EXACT_COST:\n\t\t\treturn cashNeedBudget(inputs.budgetRaw, p);\n\t\tdefault:\n\t\t\tthrow new PredictInputError(`kind ${inputs.kind} is not a mint`);\n\t}\n}\n\n/**\n * A sell's cash need against the market's spare cash. Sells are never refused for market cash at\n * placement: the keeper funds the market before τ, and a sell the market still can't cover at the\n * fill is refunded in full (reason 8). `short` flags that risk, and the sell builder can add\n * `rebalance_expiry_cash` after the enqueue to fund the market at once.\n */\nexport function sellCashCheck(\n\tcloseQuantityRaw: bigint,\n\tspareCashRaw: bigint,\n\tbackingBufferLambda: bigint,\n): { needRaw: bigint; short: boolean } {\n\tconst needRaw = cashNeedSell(closeQuantityRaw, backingBufferLambda);\n\treturn { needRaw, short: needRaw > spareCashRaw };\n}\n\n// === Largest mint the market takes now ===\n\n/** Inputs for {@link maxMintNow}. */\nexport interface MaxMintInputs {\n\t/** `'exact-quantity'` sizes a quantity; `'budget'` sizes an exact-cost or exact-amount spend. */\n\tshape: 'exact-quantity' | 'budget';\n\t/** Market cash above required cash (`MarketQueueState.spareCash`). */\n\tspareCashRaw: bigint;\n\t/** The minimum entry probability from `expiry_market::order_flow_state`, 1e9-scaled. */\n\tminEntryProbability: bigint;\n\t/** `account::balance<USDC>`. Bounds a budget spend at `available − fee`. */\n\tavailableRaw?: bigint;\n\torderFeeRaw?: bigint;\n\t/** The deployment's `position_lot_size`. Defaults to `10_000n`. */\n\tlotSize?: bigint;\n\t/** Margin left below spare cash, in basis points. Default 100 (1%). */\n\theadroomBps?: bigint;\n\t/** When the reads were taken, echoed back as `asOfMs`. */\n\tasOfMs?: bigint;\n}\n\n/** The largest mint a market takes right now, and what binds it. A snapshot: see {@link maxMintNow}. */\nexport interface MaxMintNow {\n\t/**\n\t * The cash-limited maximum: a quantity for `'exact-quantity'`, a spend for `'budget'`. `null`\n\t * when cash doesn't bind (`p_min ≥ 1`).\n\t */\n\tcashLimitRaw: bigint | null;\n\t/** `available − fee` for `'budget'`, when a balance was given. `null` otherwise. */\n\tbalanceLimitRaw: bigint | null;\n\t/** The smaller of the two limits, or `null` when neither binds. */\n\tmaxRaw: bigint | null;\n\tlimitedBy: 'cash' | 'balance' | 'none';\n\tasOfMs: bigint | null;\n}\n\n/**\n * The largest queued mint a market's spare cash admits now (\"Max right now\"). Predict's admission\n * refuses a mint whose cash need is above spare cash (`EInsufficientMarketCash`). For exact quantity this\n * is the largest lot multiple `q` with `cashNeedExactQuantity(q) ≤ S`; for a budget it is the\n * largest `b` with `cashNeedBudget(b) ≤ S`, where `S` is spare cash less the headroom.\n *\n * It is a snapshot: fills lower spare cash, and the keeper's rebalance after each enqueue raises\n * it. Other waiting orders don't count against a mint. For exact quantity this caps only the\n * cash side: size the balance side with `cost.mintCostForBudget` at `available − fee`. A budget\n * mint with `p_min = 0` can't be placed at all (the cash need divides by `p_min`), so it reads 0.\n */\nexport function maxMintNow(inputs: MaxMintInputs): MaxMintNow {\n\tconst p = inputs.minEntryProbability;\n\tassertUint(p, 'minEntryProbability', FLOAT_SCALING);\n\tassertUint(inputs.spareCashRaw, 'spareCashRaw');\n\tconst headroom = inputs.headroomBps ?? 100n;\n\tif (headroom < 0n || headroom > 10_000n) {\n\t\tthrow new PredictInputError(`headroomBps must be in [0, 10000], got ${headroom}`);\n\t}\n\tconst spare = inputs.spareCashRaw - (inputs.spareCashRaw * headroom) / 10_000n;\n\tconst asOfMs = inputs.asOfMs ?? null;\n\n\tlet cashLimitRaw: bigint | null;\n\tlet balanceLimitRaw: bigint | null = null;\n\tif (inputs.shape === 'exact-quantity') {\n\t\tconst lot = inputs.lotSize ?? POSITION_LOT_SIZE;\n\t\tif (p >= FLOAT_SCALING) {\n\t\t\tcashLimitRaw = null;\n\t\t} else if (spare < 2n) {\n\t\t\tcashLimitRaw = 0n;\n\t\t} else {\n\t\t\tconst cap = MAX_QUANTITY_LOTS * lot;\n\t\t\tlet q = min(((spare - 1n) * FLOAT_SCALING) / (FLOAT_SCALING - p), cap);\n\t\t\tq -= q % lot;\n\t\t\twhile (q > 0n && cashNeedExactQuantity(q, p) > spare) q -= lot;\n\t\t\tcashLimitRaw = q;\n\t\t}\n\t} else {\n\t\tif (p === 0n) {\n\t\t\tcashLimitRaw = 0n;\n\t\t} else if (p >= FLOAT_SCALING) {\n\t\t\tcashLimitRaw = null;\n\t\t} else if (spare < 2n) {\n\t\t\tcashLimitRaw = 0n;\n\t\t} else {\n\t\t\tlet b = ((spare - 1n) * p) / (FLOAT_SCALING - p) - 1n;\n\t\t\twhile (b > 0n && cashNeedBudget(b, p) > spare) b -= 1n;\n\t\t\tcashLimitRaw = b > 0n ? b : 0n;\n\t\t}\n\t\tif (inputs.availableRaw != null) {\n\t\t\tconst fee = inputs.orderFeeRaw ?? 0n;\n\t\t\tbalanceLimitRaw = inputs.availableRaw > fee ? inputs.availableRaw - fee : 0n;\n\t\t}\n\t}\n\n\tif (cashLimitRaw == null && balanceLimitRaw == null) {\n\t\treturn { cashLimitRaw, balanceLimitRaw, maxRaw: null, limitedBy: 'none', asOfMs };\n\t}\n\tif (balanceLimitRaw == null || (cashLimitRaw != null && cashLimitRaw <= balanceLimitRaw)) {\n\t\treturn { cashLimitRaw, balanceLimitRaw, maxRaw: cashLimitRaw, limitedBy: 'cash', asOfMs };\n\t}\n\treturn { cashLimitRaw, balanceLimitRaw, maxRaw: balanceLimitRaw, limitedBy: 'balance', asOfMs };\n}\n\n// === Timing ===\n\n/** `(resolve_head, next_id, last_tau_ms, last_committed_tau_ms)` from `queue::queue_heads`. */\nexport interface QueueHeads {\n\tresolveHead: bigint;\n\tnextId: bigint;\n\tlastTauMs: bigint;\n\tlastCommittedTauMs: bigint;\n}\n\n/**\n * `expiry − max(no_trade_window_ms, stall_timeout_ms + 5_000)`, saturating at 0: enqueue requires\n * the order's τ below it.\n */\nexport function orderCutoffMs(\n\texpiryMs: bigint,\n\tpolicy: Pick<DelayedExecutionPolicy, 'stallTimeoutMs'>,\n\tnoTradeWindowMs: bigint,\n): bigint {\n\tconst margin = max(noTradeWindowMs, policy.stallTimeoutMs + DEADLINE_EXPIRY_MARGIN_MS);\n\treturn expiryMs > margin ? expiryMs - margin : 0n;\n}\n\n/** Inputs for {@link previewTiming}. */\nexport interface TimingPreviewInputs {\n\tnowMs: bigint;\n\tpolicy: Pick<DelayedExecutionPolicy, 'delayMs' | 'stallTimeoutMs' | 'pythChannel'>;\n\theads: QueueHeads;\n\texpiryMs: bigint;\n\tnoTradeWindowMs: bigint;\n\t/**\n\t * The newest order's channel, when known. A channel change pushes τ past the last τ, so one\n\t * cohort never mixes channels. The public reads don't expose it, so it is optional.\n\t */\n\tlastChannel?: number;\n}\n\n/** A display preview of the τ, deadline and cutoff an order placed now would get. */\nexport interface TimingPreview {\n\ttauMs: bigint;\n\t/** `min(τ + stall, expiry)`. The chain also keeps deadlines non-decreasing. */\n\tdeadlineMs: bigint;\n\tcutoffMs: bigint;\n\ttickMs: bigint;\n\t/** Whether τ is before the cutoff, so enqueue would accept the timing. */\n\tbeforeCutoff: boolean;\n}\n\n/**\n * Preview `order_queue::plan_timing`: τ is the policy channel's last tick at or before\n * `now + delay`, never below the last τ, and pushed past the last committed τ. Display only:\n * the contract uses the consensus timestamp, which can differ from the local clock.\n */\nexport function previewTiming(inputs: TimingPreviewInputs): TimingPreview {\n\tconst { policy, heads } = inputs;\n\tconst tickMs = channelTickMs(policy.pythChannel);\n\tconst rounded = ((inputs.nowMs + policy.delayMs) / tickMs) * tickMs;\n\tlet tauMs = max(rounded, heads.lastTauMs);\n\tif (\n\t\tinputs.lastChannel != null &&\n\t\theads.nextId > 0n &&\n\t\tinputs.lastChannel !== policy.pythChannel\n\t) {\n\t\ttauMs = max(rounded, nextTickAfter(heads.lastTauMs, tickMs));\n\t}\n\tif (tauMs <= heads.lastCommittedTauMs) tauMs = nextTickAfter(heads.lastCommittedTauMs, tickMs);\n\tconst deadlineMs = min(tauMs + policy.stallTimeoutMs, inputs.expiryMs);\n\tconst cutoffMs = orderCutoffMs(inputs.expiryMs, policy, inputs.noTradeWindowMs);\n\treturn { tauMs, deadlineMs, cutoffMs, tickMs, beforeCutoff: tauMs < cutoffMs };\n}\n\nfunction nextTickAfter(timeMs: bigint, tickMs: bigint): bigint {\n\treturn (timeMs / tickMs + 1n) * tickMs;\n}\n\n// === Slippage ===\n\n/** Inputs for {@link slippageBand}. All times in ms. */\nexport interface SlippageBandInputs {\n\t/** The quoted probability, in (0, 1). */\n\tprobability: number;\n\ttimeToExpiryMs: number;\n\t/** The policy's delay. */\n\tdelayMs: number;\n\t/** The channel tick: 50 or 200. */\n\ttickMs: number;\n\t/** Time between the quote and the enqueue landing. Default 500. */\n\tsigningMs?: number;\n\t/** Time between τ and the fill. Default 500. */\n\tresolveMs?: number;\n\t/** Standard deviations of movement to allow. Default 2. */\n\tk?: number;\n}\n\n/**\n * A heuristic band for a queued order's price limits: `Δp ≈ k · φ(Φ⁻¹(p)) · √(h / T)`, the\n * probability move of a digital under Brownian motion over the horizon `h` (delay + tick +\n * resolve + signing), scaled by the time `T` left. Use `maxProbability = p + Δp` on exact-quantity\n * mints and `minProbability = p − Δp` on sells, and size cost caps at the shifted probability.\n * A sizing aid pending product sign-off, not a contract rule.\n */\nexport function slippageBand(inputs: SlippageBandInputs): {\n\thorizonMs: number;\n\tdeltaProbability: number;\n\tmaxProbability: number;\n\tminProbability: number;\n} {\n\tconst p = inputs.probability;\n\tif (!(p > 0 && p < 1)) {\n\t\tthrow new PredictInputError(`probability must be in (0, 1), got ${p}`);\n\t}\n\tconst horizonMs =\n\t\tinputs.delayMs + inputs.tickMs + (inputs.resolveMs ?? 500) + (inputs.signingMs ?? 500);\n\tconst k = inputs.k ?? 2;\n\tconst delta =\n\t\tinputs.timeToExpiryMs <= horizonMs\n\t\t\t? 1\n\t\t\t: Math.min(\n\t\t\t\t\t1,\n\t\t\t\t\tk * normalPdf(inverseNormalCdf(p)) * Math.sqrt(horizonMs / inputs.timeToExpiryMs),\n\t\t\t\t);\n\treturn {\n\t\thorizonMs,\n\t\tdeltaProbability: delta,\n\t\tmaxProbability: Math.min(1, p + delta),\n\t\tminProbability: Math.max(0, p - delta),\n\t};\n}\n\n// === Order limits from a quote ===\n//\n// A queued order prices at its τ, after the quote. Its limits bound how far the price may move\n// against it in the meantime. `slippageRaw` is that move in price per contract, an absolute amount\n// and never a percentage: a contract pays $1, so 10¢ is `100_000_000n` (1e9-scaled). Each helper\n// turns a quote at the current price into the limits the enqueue takes.\n\n/** The quote a set of mint limits is sized from: the chain quote at the current price. */\nexport interface MintLimitsInputs {\n\t/** The quote's all-in cost after its fee subsidy, order fee excluded. */\n\tquoteCostRaw: bigint;\n\t/** The quote's payout quantity. */\n\tquoteQuantityRaw: bigint;\n\t/** The quote's entry probability, 1e9-scaled. */\n\tentryProbabilityRaw: bigint;\n\t/** The price move to allow per contract, 1e9-scaled: 10¢ is `100_000_000n`. */\n\tslippageRaw: bigint;\n\t/**\n\t * The quote's fee subsidy (`fee_incentive_subsidy`). Defaults to `0n`. Enqueue admission checks\n\t * the order's limits without the subsidy, and the subsidy can run out before the fill, so the\n\t * limits add it back: they are sized from the unsubsidized cost.\n\t */\n\tfeeIncentiveSubsidyRaw?: bigint;\n\t/** The deployment's `position_lot_size`. Defaults to `10_000n`. */\n\tlotSize?: bigint;\n}\n\n// Raw USDC a budget floor leaves for the per-component rounding of the fill's cost: the premium,\n// the trading, builder and referral fees and the inventory impact each round on their own.\nconst COST_ROUNDING_SLACK = 10n;\n\n/** All-in price per $1 of payout, 1e9-scaled and rounded up. */\nexport interface PricePerContract {\n\t/** The quote's price, after its fee subsidy. */\n\tnowRaw: bigint;\n\t/** The worst price the limits admit: the price without the fee subsidy, plus the slippage. */\n\tworstRaw: bigint;\n}\n\nfunction pricePerContract(inputs: MintLimitsInputs): PricePerContract {\n\tconst subsidy = inputs.feeIncentiveSubsidyRaw ?? 0n;\n\tassertUint(inputs.quoteCostRaw, 'quoteCostRaw');\n\tassertUint(inputs.quoteQuantityRaw, 'quoteQuantityRaw');\n\tassertUint(inputs.slippageRaw, 'slippageRaw', FLOAT_SCALING);\n\tassertUint(subsidy, 'feeIncentiveSubsidyRaw');\n\tif (inputs.quoteQuantityRaw === 0n) {\n\t\tthrow new PredictInputError('the quote buys no payout, so it sizes no limits');\n\t}\n\tconst nowRaw = mulDivUp(inputs.quoteCostRaw, FLOAT_SCALING, inputs.quoteQuantityRaw);\n\tconst unsubsidizedRaw = mulDivUp(\n\t\tinputs.quoteCostRaw + subsidy,\n\t\tFLOAT_SCALING,\n\t\tinputs.quoteQuantityRaw,\n\t);\n\treturn { nowRaw, worstRaw: unsubsidizedRaw + inputs.slippageRaw };\n}\n\n/**\n * Limits for a queued all-in budget mint (`enqueueMintCost`): the payout floor at the worst price.\n * The fill buys what `budgetRaw` buys at τ and refunds the order when that is below\n * `minQuantityRaw`, so the order fills while the all-in price per $1 of payout stays within\n * `slippageRaw` of the quote.\n */\nexport function budgetMintLimits(inputs: MintLimitsInputs & { budgetRaw: bigint }): {\n\tminQuantityRaw: bigint;\n\tpricePerContract: PricePerContract;\n} {\n\tassertUint(inputs.budgetRaw, 'budgetRaw');\n\tconst price = pricePerContract(inputs);\n\tconst lot = inputs.lotSize ?? POSITION_LOT_SIZE;\n\t// The fill rounds the premium and each fee on its own, so a quantity's cost can sit above\n\t// `quantity × price`. The floor leaves a few raw units of the budget for that. Inventory impact\n\t// can round by more, so `read.planMint` also checks the floor with exact quotes.\n\tconst spendable =\n\t\tinputs.budgetRaw > COST_ROUNDING_SLACK ? inputs.budgetRaw - COST_ROUNDING_SLACK : 0n;\n\tconst quantity = (spendable * FLOAT_SCALING) / price.worstRaw;\n\treturn { minQuantityRaw: (quantity / lot) * lot, pricePerContract: price };\n}\n\n/**\n * Limits for a queued exact-quantity mint (`enqueueMint`): the entry-probability cap and the\n * all-in cost cap at the worst price. The cost cap never exceeds the quantity, since a contract\n * never costs more than it pays.\n */\nexport function exactMintLimits(inputs: MintLimitsInputs): {\n\tmaxCostRaw: bigint;\n\tmaxProbabilityRaw: bigint;\n\tpricePerContract: PricePerContract;\n} {\n\tassertUint(inputs.entryProbabilityRaw, 'entryProbabilityRaw', FLOAT_SCALING);\n\tconst price = pricePerContract(inputs);\n\tconst maxCostRaw = mulDivUp(inputs.quoteQuantityRaw, price.worstRaw, FLOAT_SCALING);\n\tconst maxProbabilityRaw = inputs.entryProbabilityRaw + inputs.slippageRaw;\n\treturn {\n\t\tmaxCostRaw: min(maxCostRaw, inputs.quoteQuantityRaw),\n\t\tmaxProbabilityRaw: min(maxProbabilityRaw, FLOAT_SCALING),\n\t\tpricePerContract: price,\n\t};\n}\n\n/**\n * Limits for a queued early sell (`enqueueSell`): the close-probability floor and the proceeds\n * floor at the worst price. `proceedsRaw` is the quote's proceeds before the order fee, as\n * `minProceeds` is.\n */\nexport function sellLimits(inputs: {\n\tproceedsRaw: bigint;\n\tcloseQuantityRaw: bigint;\n\tprobabilityRaw: bigint;\n\tslippageRaw: bigint;\n}): { minProceedsRaw: bigint; minProbabilityRaw: bigint } {\n\tassertUint(inputs.proceedsRaw, 'proceedsRaw');\n\tassertUint(inputs.closeQuantityRaw, 'closeQuantityRaw');\n\tassertUint(inputs.probabilityRaw, 'probabilityRaw', FLOAT_SCALING);\n\tassertUint(inputs.slippageRaw, 'slippageRaw', FLOAT_SCALING);\n\tconst give = mulDivUp(inputs.closeQuantityRaw, inputs.slippageRaw, FLOAT_SCALING);\n\treturn {\n\t\tminProceedsRaw: inputs.proceedsRaw > give ? inputs.proceedsRaw - give : 0n,\n\t\tminProbabilityRaw:\n\t\t\tinputs.probabilityRaw > inputs.slippageRaw ? inputs.probabilityRaw - inputs.slippageRaw : 0n,\n\t};\n}\n\nfunction normalPdf(x: number): number {\n\treturn Math.exp(-0.5 * x * x) / Math.sqrt(2 * Math.PI);\n}\n\n// Acklam's rational approximation of Φ⁻¹, relative error below 1.15e-9.\nfunction inverseNormalCdf(p: number): number {\n\tconst a = [\n\t\t-3.969683028665376e1, 2.209460984245205e2, -2.759285104469687e2, 1.38357751867269e2,\n\t\t-3.066479806614716e1, 2.506628277459239,\n\t];\n\tconst b = [\n\t\t-5.447609879822406e1, 1.615858368580409e2, -1.556989798598866e2, 6.680131188771972e1,\n\t\t-1.328068155288572e1,\n\t];\n\tconst c = [\n\t\t-7.784894002430293e-3, -3.223964580411365e-1, -2.400758277161838, -2.549732539343734,\n\t\t4.374664141464968, 2.938163982698783,\n\t];\n\tconst d = [7.784695709041462e-3, 3.224671290700398e-1, 2.445134137142996, 3.754408661907416];\n\tconst low = 0.02425;\n\tif (p < low) {\n\t\tconst q = Math.sqrt(-2 * Math.log(p));\n\t\treturn (\n\t\t\t(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) /\n\t\t\t((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1)\n\t\t);\n\t}\n\tif (p > 1 - low) {\n\t\tconst q = Math.sqrt(-2 * Math.log(1 - p));\n\t\treturn -(\n\t\t\t(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) /\n\t\t\t((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1)\n\t\t);\n\t}\n\tconst q = p - 0.5;\n\tconst r = q * q;\n\treturn (\n\t\t((((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q) /\n\t\t(((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1)\n\t);\n}\n\n// === Order state ===\n\n/**\n * A queue record as `queue::order` returns it: the generated `order_queue::OrderView` layout, a\n * copy of the record without Predict's receipt and the escrow balance (`funds` is its value).\n */\nexport type QueuedOrder = (typeof OrderViewBcs)['$inferType'];\n\n/** The position a record holds: a filled mint's, a sell's, or a partial sell's remainder. */\nexport interface HeldPosition {\n\torderId: bigint;\n\trootId: bigint;\n\topenedAtMs: bigint;\n\t/**\n\t * The position's payout quantity, decoded from `orderId` at the Move lot size: a filled\n\t * mint's quantity, or what a partial sell left Open.\n\t */\n\tquantityRaw: bigint;\n}\n\ninterface OrderViewBase {\n\tstatus: number;\n\tkind: number;\n\tkindName: OrderKindName;\n\tside: 'mint' | 'sell' | 'unknown';\n}\n\n/**\n * What the app shows for one queued order. `placed` → `priced` → one of `filled` / `refunded`.\n * Report `filled` only from the record or the fill event, never from a resolve simulation.\n */\nexport type OrderView = OrderViewBase &\n\t(\n\t\t| {\n\t\t\t\tstate: 'placed';\n\t\t\t\ttauMs: bigint;\n\t\t\t\tdeadlineMs: bigint;\n\t\t\t\t/** τ has passed and the price hasn't been committed yet. */\n\t\t\t\tawaitingPrice: boolean;\n\t\t\t\t/** Keepers refund an unfinished order at its deadline. */\n\t\t\t\tautoRefundByMs: bigint;\n\t\t\t\t/** Offer \"Refund my order\": unfinished and {@link REFUND_REQUEST_GRACE_MS} past the deadline. */\n\t\t\t\tcanRequestRefund: boolean;\n\t\t }\n\t\t| {\n\t\t\t\tstate: 'priced';\n\t\t\t\ttauMs: bigint;\n\t\t\t\t/** The committed update's tick: τ, or a backup tick. */\n\t\t\t\ttickMs: bigint;\n\t\t\t\t/** The committed Pyth price, 1e9-scaled. */\n\t\t\t\tpriceRaw: bigint;\n\t\t\t\tdeadlineMs: bigint;\n\t\t\t\tmsToDeadline: bigint;\n\t\t\t\tautoRefundByMs: bigint;\n\t\t\t\tcanRequestRefund: boolean;\n\t\t }\n\t\t| {\n\t\t\t\tstate: 'refunding';\n\t\t\t\treason: RefundReasonInfo;\n\t\t\t\tdeadlineMs: bigint;\n\t\t\t\tcanRequestRefund: boolean;\n\t\t }\n\t\t| {\n\t\t\t\tstate: 'filled';\n\t\t\t\t/**\n\t\t\t\t * Filled quantity (mint) or closed quantity (sell). A partial sell's remainder is\n\t\t\t\t * `position.quantityRaw`.\n\t\t\t\t */\n\t\t\t\tquantityRaw: bigint;\n\t\t\t\t/** Cost paid (mint) or proceeds before the order fee (sell). */\n\t\t\t\tamountRaw: bigint;\n\t\t\t\tfinishedAtMs: bigint;\n\t\t\t\t/** The Open record's position: a filled mint, or a partial sell's remainder. */\n\t\t\t\tposition: HeldPosition | null;\n\t\t\t\t/** Whether `enqueue_redeem_open` can sell this record now. */\n\t\t\t\tsellable: boolean;\n\t\t\t\t/** See {@link ParkedFunds}. */\n\t\t\t\tparkedRaw: bigint;\n\t\t }\n\t\t| {\n\t\t\t\tstate: 'refunded';\n\t\t\t\treason: RefundReasonInfo;\n\t\t\t\tfinishedAtMs: bigint;\n\t\t\t\t/** A refunded sell keeps its position as an Open record, sellable again. */\n\t\t\t\tpositionBackAsOpenRecord: boolean;\n\t\t\t\tposition: HeldPosition | null;\n\t\t\t\tsellable: boolean;\n\t\t\t\t/** See {@link ParkedFunds}. */\n\t\t\t\tparkedRaw: bigint;\n\t\t }\n\t\t| {\n\t\t\t\t/** A filled mint's record whose position was later sold or settled. */\n\t\t\t\tstate: 'closed';\n\t\t\t\tquantityRaw: bigint;\n\t\t\t\tamountRaw: bigint;\n\t\t\t\tfinishedAtMs: bigint;\n\t\t\t\t/** See {@link ParkedFunds}. */\n\t\t\t\tparkedRaw: bigint;\n\t\t }\n\t\t| { state: 'unknown' }\n\t);\n\n/**\n * `parkedRaw` on a finished record: USDC the record kept because its receive address couldn't take\n * it (on USDC's deny list, or USDC paused) when its change or refund was sent. It is the\n * record's `funds`, which holds only parked USDC once the order finishes. Anyone can send it with\n * `claim_parked` once the address is clear. `0n` when nothing is parked.\n */\nexport type ParkedFunds = bigint;\n\nfunction heldPosition(p: QueuedOrder['position'], lotSize?: bigint): HeldPosition | null {\n\treturn p.order_id === 0n\n\t\t? null\n\t\t: {\n\t\t\t\torderId: p.order_id,\n\t\t\t\trootId: p.root_id,\n\t\t\t\topenedAtMs: p.opened_at_ms,\n\t\t\t\tquantityRaw: decodeOrderRange(p.order_id, lotSize).quantity,\n\t\t\t};\n}\n\n/**\n * Map a queue record to its display state. `nowMs` drives the refund flags. A record is sellable\n * while it is Open, holds a position, and `nowMs` is before the cutoff (`opts.cutoffMs`, or the\n * record's own placement cutoff when omitted). Unknown status or kind codes map to `unknown`.\n * `opts.lotSize` is the config's position lot (default 10,000, Predict's), which decodes a held\n * position's quantity.\n */\nexport function orderView(\n\trecord: QueuedOrder,\n\tnowMs: bigint,\n\topts: { cutoffMs?: bigint; lotSize?: bigint } = {},\n): OrderView {\n\tconst kind = record.kind;\n\tconst base: OrderViewBase = {\n\t\tstatus: record.status,\n\t\tkind,\n\t\tkindName: orderKindName(kind),\n\t\tside: isMintKind(kind) ? 'mint' : isSellKind(kind) ? 'sell' : 'unknown',\n\t};\n\tif (base.side === 'unknown') return { ...base, state: 'unknown' };\n\tconst { tau_ms: tauMs, deadline_ms: deadlineMs } = record.timing;\n\tconst canRequestRefund = nowMs >= deadlineMs + REFUND_REQUEST_GRACE_MS;\n\tconst position = heldPosition(record.position, opts.lotSize);\n\tconst cutoffMs = opts.cutoffMs ?? record.timing.cutoff_ms;\n\tconst sellable = position != null && nowMs < cutoffMs;\n\tconst result = record.result;\n\t// Only read on the finished statuses below, where `funds` holds parked USDC, not escrow.\n\tconst parkedRaw = record.funds;\n\tswitch (record.status) {\n\t\tcase ORDER_STATUS.PENDING:\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tstate: 'placed',\n\t\t\t\ttauMs,\n\t\t\t\tdeadlineMs,\n\t\t\t\tawaitingPrice: nowMs >= tauMs,\n\t\t\t\tautoRefundByMs: deadlineMs,\n\t\t\t\tcanRequestRefund,\n\t\t\t};\n\t\tcase ORDER_STATUS.COMMITTED:\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tstate: 'priced',\n\t\t\t\ttauMs,\n\t\t\t\ttickMs: record.price.tick_ms,\n\t\t\t\tpriceRaw: record.price.spot,\n\t\t\t\tdeadlineMs,\n\t\t\t\tmsToDeadline: deadlineMs > nowMs ? deadlineMs - nowMs : 0n,\n\t\t\t\tautoRefundByMs: deadlineMs,\n\t\t\t\tcanRequestRefund,\n\t\t\t};\n\t\tcase ORDER_STATUS.REFUND_DUE:\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tstate: 'refunding',\n\t\t\t\treason: refundReason(result.reason),\n\t\t\t\tdeadlineMs,\n\t\t\t\tcanRequestRefund,\n\t\t\t};\n\t\tcase ORDER_STATUS.OPEN:\n\t\t\tif (base.side === 'sell' && result.reason > 0) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tstate: 'refunded',\n\t\t\t\t\treason: refundReason(result.reason),\n\t\t\t\t\tfinishedAtMs: result.finished_at_ms,\n\t\t\t\t\tpositionBackAsOpenRecord: true,\n\t\t\t\t\tposition,\n\t\t\t\t\tsellable,\n\t\t\t\t\tparkedRaw,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tstate: 'filled',\n\t\t\t\tquantityRaw: result.quantity,\n\t\t\t\tamountRaw: result.amount,\n\t\t\t\tfinishedAtMs: result.finished_at_ms,\n\t\t\t\tposition,\n\t\t\t\tsellable,\n\t\t\t\tparkedRaw,\n\t\t\t};\n\t\tcase ORDER_STATUS.REFUNDED:\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tstate: 'refunded',\n\t\t\t\treason: refundReason(result.reason),\n\t\t\t\tfinishedAtMs: result.finished_at_ms,\n\t\t\t\tpositionBackAsOpenRecord: false,\n\t\t\t\tposition: null,\n\t\t\t\tsellable: false,\n\t\t\t\tparkedRaw,\n\t\t\t};\n\t\tcase ORDER_STATUS.CLOSED:\n\t\t\t// A sell record that filled stays `filled` after its remainder moves on; a mint record\n\t\t\t// (or a refunded sell sold again) is `closed` once its position left.\n\t\t\tif (base.side === 'sell' && result.reason === 0 && result.quantity > 0n) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tstate: 'filled',\n\t\t\t\t\tquantityRaw: result.quantity,\n\t\t\t\t\tamountRaw: result.amount,\n\t\t\t\t\tfinishedAtMs: result.finished_at_ms,\n\t\t\t\t\tposition: null,\n\t\t\t\t\tsellable: false,\n\t\t\t\t\tparkedRaw,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tstate: 'closed',\n\t\t\t\tquantityRaw: result.quantity,\n\t\t\t\tamountRaw: result.amount,\n\t\t\t\tfinishedAtMs: result.finished_at_ms,\n\t\t\t\tparkedRaw,\n\t\t\t};\n\t\tdefault:\n\t\t\treturn { ...base, state: 'unknown' };\n\t}\n}\n\n/** One record's state rebuilt from events, for the app's event path (indexer or own effects). */\nexport interface OrderEventState {\n\tmarketId: string;\n\trecordId: bigint;\n\t/**\n\t * `closed`: the record's position moved into a later sell's record (`enqueue_redeem_open` closes\n\t * the source record), so this record holds nothing any more.\n\t */\n\tstate: 'placed' | 'priced' | 'filled' | 'refunded' | 'settled' | 'closed';\n\tkind: number | null;\n\ttauMs: bigint | null;\n\tdeadlineMs: bigint | null;\n\t/** Set once priced: the committed Pyth price as a float (`spot / 1e9`) and its tick. */\n\tprice: number | null;\n\ttickMs: bigint | null;\n\t/**\n\t * Set on a refund. The settlement drain (`settle_step`) refunds the orders still waiting at\n\t * expiry with reason 5 (deadline), like a keeper's deadline refund.\n\t */\n\treason: RefundReasonInfo | null;\n\t/**\n\t * The position the record holds now, or null. A sell's record takes its source's position at\n\t * enqueue and keeps it through a refund, a fill leaves a mint's new position or a partial\n\t * sell's remainder, and a later sell, a full close or settlement clears it.\n\t */\n\tposition: HeldPosition | null;\n\t/** For a sell: the record its position came from. */\n\tsourceRecordId: bigint | null;\n\t/** Set when `settle_step` or `pay_open` paid the record (0 for a loser). */\n\tpayoutRaw: bigint | null;\n\t/** True after `OpenRecordPayoutSkipped`: the record stays Open, unpaid for now. */\n\tpayoutSkipped: boolean;\n\t/**\n\t * USDC the record holds parked (`RecordFundsParked`, summed) until `RecordFundsClaimed`. See\n\t * {@link ParkedFunds}.\n\t */\n\tparkedRaw: bigint;\n}\n\n/**\n * Fold decoded queue events (in chain order) into per-record states, keyed `marketId:recordId`.\n * The app shows Placed from the enqueue's own effects, Priced at the cohort commit, and switches to\n * Filled or Refunded on `QueuedOrderFilled` / `QueuedOrderRefunded`. Events for records that never\n * appeared enqueued still create an entry, so a partial event window works.\n */\nexport function reduceOrderEvents(\n\tevents: readonly QueueEvent[],\n\tinto: Map<string, OrderEventState> = new Map(),\n): Map<string, OrderEventState> {\n\tconst entry = (marketId: string, recordId: bigint): OrderEventState => {\n\t\tconst key = `${marketId}:${recordId}`;\n\t\tlet s = into.get(key);\n\t\tif (!s) {\n\t\t\ts = {\n\t\t\t\tmarketId,\n\t\t\t\trecordId,\n\t\t\t\tstate: 'placed',\n\t\t\t\tkind: null,\n\t\t\t\ttauMs: null,\n\t\t\t\tdeadlineMs: null,\n\t\t\t\tprice: null,\n\t\t\t\ttickMs: null,\n\t\t\t\treason: null,\n\t\t\t\tposition: null,\n\t\t\t\tsourceRecordId: null,\n\t\t\t\tpayoutRaw: null,\n\t\t\t\tpayoutSkipped: false,\n\t\t\t\tparkedRaw: 0n,\n\t\t\t};\n\t\t\tinto.set(key, s);\n\t\t}\n\t\treturn s;\n\t};\n\tfor (const e of events) {\n\t\tswitch (e.type) {\n\t\t\tcase 'enqueued': {\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.kind = e.kind;\n\t\t\t\ts.tauMs = e.timing.tauMs;\n\t\t\t\ts.deadlineMs = e.timing.deadlineMs;\n\t\t\t\t// A sell moves the whole position out of its source record, which the chain marks\n\t\t\t\t// Closed, and into the new record, which holds it until the sell fills or refunds.\n\t\t\t\ts.position = e.position;\n\t\t\t\ts.sourceRecordId = e.sourceRecordId;\n\t\t\t\tif (e.sourceRecordId != null) {\n\t\t\t\t\tconst source = entry(e.marketId, e.sourceRecordId);\n\t\t\t\t\tsource.state = 'closed';\n\t\t\t\t\tsource.position = null;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'cohort-committed':\n\t\t\t\tfor (const s of into.values()) {\n\t\t\t\t\tif (\n\t\t\t\t\t\ts.marketId === e.marketId &&\n\t\t\t\t\t\ts.state === 'placed' &&\n\t\t\t\t\t\ts.recordId >= e.firstRecordId &&\n\t\t\t\t\t\ts.recordId <= e.lastRecordId\n\t\t\t\t\t) {\n\t\t\t\t\t\ts.state = 'priced';\n\t\t\t\t\t\ts.price = e.price;\n\t\t\t\t\t\ts.tickMs = e.tickMs;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'filled': {\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.state = 'filled';\n\t\t\t\ts.kind = e.kind;\n\t\t\t\ts.tickMs = e.tickMs;\n\t\t\t\ts.position = e.position;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'refunded': {\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.state = 'refunded';\n\t\t\t\ts.kind = e.kind;\n\t\t\t\ts.reason = e.reason;\n\t\t\t\t// A refunded sell keeps its position, Open and sellable again from this record.\n\t\t\t\tif (!e.positionReturned) s.position = null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'open-record-settled': {\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.state = 'settled';\n\t\t\t\ts.payoutRaw = e.raw.payout;\n\t\t\t\ts.payoutSkipped = false;\n\t\t\t\ts.position = null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'open-record-payout-skipped': {\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.payoutSkipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'record-funds-parked': {\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.parkedRaw += e.raw.amount;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'record-funds-claimed': {\n\t\t\t\t// `claim_parked` sends everything the record had parked.\n\t\t\t\tconst s = entry(e.marketId, e.recordId);\n\t\t\t\ts.parkedRaw = 0n;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn into;\n}\n\nfunction min(a: bigint, b: bigint): bigint {\n\treturn a < b ? a : b;\n}\n\nfunction max(a: bigint, b: bigint): bigint {\n\treturn a > b ? a : b;\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { balance, loadAccount } from "../../contracts/account/account.mjs";
|
|
2
2
|
import { inspectReturns } from "./inspect.mjs";
|
|
3
3
|
import { deriveAccountWrapperIdFrom } from "../tx/common.mjs";
|
|
4
|
-
import { hasPosition as hasPosition$1 } from "../../contracts/deepbook_predict/predict_account.mjs";
|
|
5
4
|
import { parseU64LE } from "./parse.mjs";
|
|
5
|
+
import { hasPosition as hasPosition$1 } from "../../contracts/deepbook_predict/predict_account.mjs";
|
|
6
6
|
import { Transaction } from "@mysten/sui/transactions";
|
|
7
7
|
|
|
8
8
|
//#region src/predict/reads/balances.ts
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { parseOptionalId, parseOptionalU64, parseU64LE, parseVectorOfIds } from "./parse.mjs";
|
|
1
|
+
import { PredictMoveError } from "../errors.mjs";
|
|
3
2
|
import { POS_INF_TICK } from "../ticks.mjs";
|
|
3
|
+
import { inspectReturns } from "./inspect.mjs";
|
|
4
4
|
import { probability, rangePrice } from "../../contracts/deepbook_predict/pricing.mjs";
|
|
5
|
-
import { admissionTickSize, currentNav as currentNav$1, expiry, mintPaused, referenceTick as referenceTick$1, tickSize } from "../../contracts/deepbook_predict/expiry_market.mjs";
|
|
6
|
-
import { loadLivePricer } from "../tx/trade.mjs";
|
|
7
5
|
import { activeExpiryMarkets } from "../../contracts/deepbook_predict/plp.mjs";
|
|
6
|
+
import { ExpiryMarket, admissionTickSize, currentNav as currentNav$1, expiry, mintPaused, referenceTick as referenceTick$1, settlementPrice as settlementPrice$1, tickSize } from "../../contracts/deepbook_predict/expiry_market.mjs";
|
|
7
|
+
import { loadLivePricer } from "../tx/trade.mjs";
|
|
8
|
+
import { parseOptionalId, parseOptionalU64, parseU64LE, parseVectorOfIds } from "./parse.mjs";
|
|
8
9
|
import { strikeFromTick } from "../../contracts/deepbook_predict/range_codec.mjs";
|
|
9
10
|
import { expiryMarketId as expiryMarketId$1 } from "../../contracts/deepbook_predict/registry.mjs";
|
|
10
11
|
import { Transaction } from "@mysten/sui/transactions";
|
|
@@ -114,6 +115,20 @@ async function referenceTick(client, config, marketId) {
|
|
|
114
115
|
const [cmd0] = await inspectReturns(client, tx);
|
|
115
116
|
return parseOptionalU64(cmd0[0]);
|
|
116
117
|
}
|
|
118
|
+
async function settlementPrice(client, config, marketId) {
|
|
119
|
+
const tx = new Transaction();
|
|
120
|
+
tx.add(settlementPrice$1({
|
|
121
|
+
config,
|
|
122
|
+
arguments: { market: marketId }
|
|
123
|
+
}));
|
|
124
|
+
try {
|
|
125
|
+
const [cmd0] = await inspectReturns(client, tx);
|
|
126
|
+
return parseU64LE(cmd0[0]);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
if (e instanceof PredictMoveError && (e.module === "option" || e.module === "expiry_market" && e.abortName === "EMarketNotSettled")) return null;
|
|
129
|
+
throw e;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
117
132
|
async function currentNav(client, config, marketId, underlying) {
|
|
118
133
|
const tx = new Transaction();
|
|
119
134
|
const pricer = tx.add(loadLivePricer(config, {
|
|
@@ -132,7 +147,33 @@ async function currentNav(client, config, marketId, underlying) {
|
|
|
132
147
|
const cmds = await inspectReturns(client, tx);
|
|
133
148
|
return parseU64LE(cmds[cmds.length - 1][0]);
|
|
134
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* The fee and exposure policy a market snapshotted at creation, from its `ExpiryMarket` object:
|
|
152
|
+
* `strike_exposure.config` and `strike_exposure.inventory_impact_scale`. It is the policy the
|
|
153
|
+
* market charges for its whole life, whatever the protocol template says now, and the `cost`
|
|
154
|
+
* functions take it as `fees`. One object read, no simulate. The struct layout is fixed across
|
|
155
|
+
* package upgrades, so the v1 binding decodes every version's markets.
|
|
156
|
+
*/
|
|
157
|
+
async function marketFeePolicy(client, marketId) {
|
|
158
|
+
const { object } = await client.core.getObject({
|
|
159
|
+
objectId: marketId,
|
|
160
|
+
include: { content: true }
|
|
161
|
+
});
|
|
162
|
+
if (!object.content) throw new Error(`ExpiryMarket ${marketId} returned no content`);
|
|
163
|
+
const { config, inventory_impact_scale } = ExpiryMarket.parse(object.content).strike_exposure;
|
|
164
|
+
return {
|
|
165
|
+
baseFee: BigInt(config.base_fee),
|
|
166
|
+
minFee: BigInt(config.min_fee),
|
|
167
|
+
expiryFeeWindowMs: BigInt(config.expiry_fee_window_ms),
|
|
168
|
+
expiryFeeMaxMultiplier: BigInt(config.expiry_fee_max_multiplier),
|
|
169
|
+
minEntryProbability: BigInt(config.min_entry_probability),
|
|
170
|
+
maxEntryProbability: BigInt(config.max_entry_probability),
|
|
171
|
+
inventoryImpactMaxRate: BigInt(config.inventory_impact_max_rate),
|
|
172
|
+
inventoryImpactScale: BigInt(inventory_impact_scale),
|
|
173
|
+
backingBufferLambda: BigInt(config.backing_buffer_lambda)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
135
176
|
|
|
136
177
|
//#endregion
|
|
137
|
-
export { activeMarketIds, currentNav, expiryMarketId, marketState, marketStates, rangePrices, referenceTick };
|
|
178
|
+
export { activeMarketIds, currentNav, expiryMarketId, marketFeePolicy, marketState, marketStates, rangePrices, referenceTick, settlementPrice };
|
|
138
179
|
//# sourceMappingURL=markets.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markets.mjs","names":["plp.activeExpiryMarkets","registry.expiryMarketId","expiryMarket.expiry","expiryMarket.tickSize","expiryMarket.admissionTickSize","expiryMarket.mintPaused","expiryMarket.referenceTick","rangeCodec.strikeFromTick","pricing.rangePrice","pricing.probability","expiryMarket.currentNav"],"sources":["../../../src/predict/reads/markets.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { Transaction } from '@mysten/sui/transactions';\nimport { type GeneratedConfig } from '../config/generated.js';\nimport { type UnderlyingConfig } from '../config/index.js';\nimport { PredictMoveError } from '../errors.js';\nimport { POS_INF_TICK } from '../ticks.js';\nimport { loadLivePricer, type MarketFeeds } from '../tx/trade.js';\nimport * as expiryMarket from '../../contracts/deepbook_predict/expiry_market.js';\nimport * as plp from '../../contracts/deepbook_predict/plp.js';\nimport * as pricing from '../../contracts/deepbook_predict/pricing.js';\nimport * as rangeCodec from '../../contracts/deepbook_predict/range_codec.js';\nimport * as registry from '../../contracts/deepbook_predict/registry.js';\nimport { inspectReturns, type ReadClient } from './inspect.js';\nimport { parseOptionalId, parseOptionalU64, parseU64LE, parseVectorOfIds } from './parse.js';\n\n// On-chain ids of the pool's active (live, not-yet-settled) expiry markets.\n// `plp::active_expiry_markets(vault)` — see packages/predict/sources/plp/plp.move:179.\nexport async function activeMarketIds(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n): Promise<string[]> {\n\tconst tx = new Transaction();\n\ttx.add(plp.activeExpiryMarkets({ config }));\n\tconst [cmd0] = await inspectReturns(client, tx);\n\treturn parseVectorOfIds(cmd0[0]);\n}\n\n// The expiry market id for one underlying at one expiry, or null if none exists.\n// `registry::expiry_market_id(registry, propbook_underlying_id: u32, expiry: u64):\n// Option<ID>` — see packages/predict/sources/registry/registry.move:58.\nexport async function expiryMarketId(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tunderlying: UnderlyingConfig,\n\texpiryMs: bigint,\n): Promise<string | null> {\n\tconst tx = new Transaction();\n\ttx.add(\n\t\tregistry.expiryMarketId({\n\t\t\tconfig,\n\t\t\targuments: { propbookUnderlyingId: underlying.propbookUnderlyingId, expiry: expiryMs },\n\t\t}),\n\t);\n\tconst [cmd0] = await inspectReturns(client, tx);\n\treturn parseOptionalId(cmd0[0]);\n}\n\nexport interface MarketState {\n\texpiryMs: bigint;\n\ttickSizeRaw: bigint;\n\t/**\n\t * The COARSER raw-price step new finite mint boundaries must align to\n\t * (`expiry_market::admission_tick_size`). A numeric strike must be a whole\n\t * multiple of this — the fine `tickSizeRaw` grid alone is not sufficient — or\n\t * the chain aborts `EInvalidAdmissionTick`. The market's reference tick is the\n\t * one finite boundary allowed to bypass it.\n\t */\n\tadmissionTickSizeRaw: bigint;\n\tmintPaused: boolean;\n\t/**\n\t * The reference fine-grid tick (Polymarket-style anchor strike: derived\n\t * on-chain from the exact previous-window oracle observation), or null while\n\t * the keeper has not seeded it. Reference PRICE raw = tick * tickSizeRaw.\n\t */\n\treferenceTickRaw: bigint | null;\n}\n\n// The per-market state getters, in fixed order. `expiry_market::{expiry,\n// tick_size, mint_paused, reference_tick}` — see\n// packages/predict/sources/expiry_market.move:{101,177,259,187}. reference_tick\n// returns Option (no abort risk). settlement is read separately via\n// `settlementPrice` (its own non-batched getter below).\nconst STATE_FNS = [\n\texpiryMarket.expiry,\n\texpiryMarket.tickSize,\n\texpiryMarket.admissionTickSize,\n\texpiryMarket.mintPaused,\n\texpiryMarket.referenceTick,\n] as const;\n\nfunction parseStateAt(cmds: Uint8Array[][], base: number): MarketState {\n\treturn {\n\t\texpiryMs: parseU64LE(cmds[base][0]),\n\t\ttickSizeRaw: parseU64LE(cmds[base + 1][0]),\n\t\tadmissionTickSizeRaw: parseU64LE(cmds[base + 2][0]),\n\t\tmintPaused: (cmds[base + 3][0][0] ?? 0) !== 0, // BCS bool: 1 byte\n\t\treferenceTickRaw: parseOptionalU64(cmds[base + 4][0]),\n\t};\n}\n\nexport async function marketState(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n): Promise<MarketState> {\n\tconst [state] = await marketStates(client, config, [marketId]);\n\treturn state;\n}\n\n// Batched marketState for N markets in ONE PTB (STATE_FNS.length commands per\n// market, same order). Returns states aligned with `marketIds`.\nexport async function marketStates(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketIds: readonly string[],\n): Promise<MarketState[]> {\n\tif (marketIds.length === 0) return [];\n\tconst tx = new Transaction();\n\tfor (const id of marketIds) {\n\t\tfor (const fn of STATE_FNS) {\n\t\t\ttx.add(fn({ config, arguments: { market: id } }));\n\t\t}\n\t}\n\tconst cmds = await inspectReturns(client, tx);\n\treturn marketIds.map((_, i) => parseStateAt(cmds, STATE_FNS.length * i));\n}\n\n// Anonymous both-sides pricing for one strike: the chain's own probability for\n// (strike, +inf] and (-inf, strike]. Deployed `pricing::range_price` takes typed\n// `range_codec::Strike`s (NOT raw u64) — each boundary is built via\n// `range_codec::strike_from_tick(tick, tick_size)`, which maps tick 0 → -inf,\n// POS_INF_TICK → +inf, and any finite tick → tick*tick_size. `range_price` is a\n// public fun on the deployed package. Both sides read the SAME pricer in one PTB, so\n// `down` is the chain's number, not 1 − up.\n//\n// `range_price` now returns a `RangePrice` carrying both boundary probabilities so the\n// fee can charge each leg separately; `probability()` is the combined range number this\n// function has always returned (`lower_up.saturating_sub(higher_up)`, unchanged). The\n// extra call per side is what keeps the u64 parse below reading a u64 rather than the\n// struct's BCS.\nexport async function rangePrices(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n\tfeeds: MarketFeeds,\n\tstrikeRaw: bigint,\n\ttickSizeRaw: bigint,\n): Promise<{ upRaw: bigint; downRaw: bigint }> {\n\tconst tx = new Transaction();\n\tconst pricer = tx.add(loadLivePricer(config, { expiryMarketId: marketId, ...feeds }));\n\t// strikeRaw is a whole tick multiple (the caller validates divisibility), so the\n\t// finite boundary is `strike_from_tick(strikeRaw / tickSize, tickSize)`.\n\tconst strikeTick = strikeRaw / tickSizeRaw;\n\tconst mkStrike = (tick: bigint) =>\n\t\ttx.add(rangeCodec.strikeFromTick({ config, arguments: { tick, tickSize: tickSizeRaw } }));\n\tconst strike = mkStrike(strikeTick);\n\tconst posInf = mkStrike(POS_INF_TICK);\n\tconst negInf = mkStrike(0n);\n\t// UP: (strike, +inf], then DOWN: (-inf, strike]. The two `probability` reductions are\n\t// the last two commands, which is what the tail-relative parse below indexes.\n\tconst up = tx.add(\n\t\tpricing.rangePrice({ config, arguments: { pricer, lower: strike, higher: posInf } }),\n\t);\n\tconst down = tx.add(\n\t\tpricing.rangePrice({ config, arguments: { pricer, lower: negInf, higher: strike } }),\n\t);\n\ttx.add(pricing.probability({ config, arguments: { price: up } }));\n\ttx.add(pricing.probability({ config, arguments: { price: down } }));\n\tconst cmds = await inspectReturns(client, tx);\n\treturn {\n\t\tupRaw: parseU64LE(cmds[cmds.length - 2][0]),\n\t\tdownRaw: parseU64LE(cmds[cmds.length - 1][0]),\n\t};\n}\n\n// Fresh single read of the reference tick — used by mint-at-reference, which\n// must not trust a cached state (the reference is unset early in a window\n// until the keeper seeds it).\nexport async function referenceTick(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n): Promise<bigint | null> {\n\tconst tx = new Transaction();\n\ttx.add(expiryMarket.referenceTick({ config, arguments: { market: marketId } }));\n\tconst [cmd0] = await inspectReturns(client, tx);\n\treturn parseOptionalU64(cmd0[0]);\n}\n\n// The recorded settlement price, or null while the market is unsettled.\n//\n// On the deployed package `expiry_market::settlement_price` is public and\n// `destroy_some`s the stored Option — callable here only because simulate runs with\n// checksEnabled:false, and it aborts in std::option (EOPTION_NOT_SET) when the\n// market has not settled; we map exactly that abort (and the public\n// EMarketNotSettled variant, should a future package guard it directly) to null.\n// (A non-aborting `try_settlement_price` also exists on-chain if this ever wants to\n// drop the abort-catch.)\nexport async function settlementPrice(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n): Promise<bigint | null> {\n\tconst tx = new Transaction();\n\ttx.add(expiryMarket.settlementPrice({ config, arguments: { market: marketId } }));\n\ttry {\n\t\tconst [cmd0] = await inspectReturns(client, tx);\n\t\treturn parseU64LE(cmd0[0]);\n\t} catch (e) {\n\t\tif (\n\t\t\te instanceof PredictMoveError &&\n\t\t\t(e.module === 'option' ||\n\t\t\t\t(e.module === 'expiry_market' && e.abortName === 'EMarketNotSettled'))\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow e;\n\t}\n}\n\n// A market's current NAV mark (the per-expiry recoverable value the flush prices\n// against). Loads a fresh live pricer, then reads `current_nav(market, &pricer)` —\n// see packages/predict/sources/expiry_market.move:236. `Pricer` has copy+drop, so\n// the unconsumed borrow is fine in a read-only inspect.\nexport async function currentNav(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n\tunderlying: UnderlyingConfig,\n): Promise<bigint> {\n\tconst tx = new Transaction();\n\tconst pricer = tx.add(\n\t\tloadLivePricer(config, {\n\t\t\texpiryMarketId: marketId,\n\t\t\tpythFeed: underlying.pythFeed,\n\t\t\tblockScholesValueStore: underlying.blockScholesValueStore,\n\t\t\tblockScholesSviStore: underlying.blockScholesSviStore,\n\t\t}),\n\t);\n\ttx.add(expiryMarket.currentNav({ config, arguments: { market: marketId, pricer } }));\n\tconst cmds = await inspectReturns(client, tx);\n\t// current_nav is the last command; load_live_pricer precedes it.\n\treturn parseU64LE(cmds[cmds.length - 1][0]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"markets.mjs","names":["plp.activeExpiryMarkets","registry.expiryMarketId","expiryMarket.expiry","expiryMarket.tickSize","expiryMarket.admissionTickSize","expiryMarket.mintPaused","expiryMarket.referenceTick","rangeCodec.strikeFromTick","pricing.rangePrice","pricing.probability","expiryMarket.settlementPrice","expiryMarket.currentNav"],"sources":["../../../src/predict/reads/markets.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { Transaction } from '@mysten/sui/transactions';\nimport { type GeneratedConfig } from '../config/generated.js';\nimport { type UnderlyingConfig } from '../config/index.js';\nimport { type FeePolicy } from '../cost.js';\nimport { PredictMoveError } from '../errors.js';\nimport { POS_INF_TICK } from '../ticks.js';\nimport { loadLivePricer, type MarketFeeds } from '../tx/trade.js';\nimport * as expiryMarket from '../../contracts/deepbook_predict/expiry_market.js';\nimport * as plp from '../../contracts/deepbook_predict/plp.js';\nimport * as pricing from '../../contracts/deepbook_predict/pricing.js';\nimport * as rangeCodec from '../../contracts/deepbook_predict/range_codec.js';\nimport * as registry from '../../contracts/deepbook_predict/registry.js';\nimport { inspectReturns, type ReadClient } from './inspect.js';\nimport { parseOptionalId, parseOptionalU64, parseU64LE, parseVectorOfIds } from './parse.js';\n\n// On-chain ids of the pool's active (live, not-yet-settled) expiry markets.\n// `plp::active_expiry_markets(vault)` — see packages/predict/sources/plp/plp.move:179.\nexport async function activeMarketIds(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n): Promise<string[]> {\n\tconst tx = new Transaction();\n\ttx.add(plp.activeExpiryMarkets({ config }));\n\tconst [cmd0] = await inspectReturns(client, tx);\n\treturn parseVectorOfIds(cmd0[0]);\n}\n\n// The expiry market id for one underlying at one expiry, or null if none exists.\n// `registry::expiry_market_id(registry, propbook_underlying_id: u32, expiry: u64):\n// Option<ID>` — see packages/predict/sources/registry/registry.move:58.\nexport async function expiryMarketId(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tunderlying: UnderlyingConfig,\n\texpiryMs: bigint,\n): Promise<string | null> {\n\tconst tx = new Transaction();\n\ttx.add(\n\t\tregistry.expiryMarketId({\n\t\t\tconfig,\n\t\t\targuments: { propbookUnderlyingId: underlying.propbookUnderlyingId, expiry: expiryMs },\n\t\t}),\n\t);\n\tconst [cmd0] = await inspectReturns(client, tx);\n\treturn parseOptionalId(cmd0[0]);\n}\n\nexport interface MarketState {\n\texpiryMs: bigint;\n\ttickSizeRaw: bigint;\n\t/**\n\t * The COARSER raw-price step new finite mint boundaries must align to\n\t * (`expiry_market::admission_tick_size`). A numeric strike must be a whole\n\t * multiple of this — the fine `tickSizeRaw` grid alone is not sufficient — or\n\t * the chain aborts `EInvalidAdmissionTick`. The market's reference tick is the\n\t * one finite boundary allowed to bypass it.\n\t */\n\tadmissionTickSizeRaw: bigint;\n\tmintPaused: boolean;\n\t/**\n\t * The reference fine-grid tick (Polymarket-style anchor strike: derived\n\t * on-chain from the exact previous-window oracle observation), or null while\n\t * the keeper has not seeded it. Reference PRICE raw = tick * tickSizeRaw.\n\t */\n\treferenceTickRaw: bigint | null;\n}\n\n// The per-market state getters, in fixed order. `expiry_market::{expiry,\n// tick_size, mint_paused, reference_tick}` — see\n// packages/predict/sources/expiry_market.move:{101,177,259,187}. reference_tick\n// returns Option (no abort risk). settlement is read separately via\n// `settlementPrice` (its own non-batched getter below).\nconst STATE_FNS = [\n\texpiryMarket.expiry,\n\texpiryMarket.tickSize,\n\texpiryMarket.admissionTickSize,\n\texpiryMarket.mintPaused,\n\texpiryMarket.referenceTick,\n] as const;\n\nfunction parseStateAt(cmds: Uint8Array[][], base: number): MarketState {\n\treturn {\n\t\texpiryMs: parseU64LE(cmds[base][0]),\n\t\ttickSizeRaw: parseU64LE(cmds[base + 1][0]),\n\t\tadmissionTickSizeRaw: parseU64LE(cmds[base + 2][0]),\n\t\tmintPaused: (cmds[base + 3][0][0] ?? 0) !== 0, // BCS bool: 1 byte\n\t\treferenceTickRaw: parseOptionalU64(cmds[base + 4][0]),\n\t};\n}\n\nexport async function marketState(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n): Promise<MarketState> {\n\tconst [state] = await marketStates(client, config, [marketId]);\n\treturn state;\n}\n\n// Batched marketState for N markets in ONE PTB (STATE_FNS.length commands per\n// market, same order). Returns states aligned with `marketIds`.\nexport async function marketStates(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketIds: readonly string[],\n): Promise<MarketState[]> {\n\tif (marketIds.length === 0) return [];\n\tconst tx = new Transaction();\n\tfor (const id of marketIds) {\n\t\tfor (const fn of STATE_FNS) {\n\t\t\ttx.add(fn({ config, arguments: { market: id } }));\n\t\t}\n\t}\n\tconst cmds = await inspectReturns(client, tx);\n\treturn marketIds.map((_, i) => parseStateAt(cmds, STATE_FNS.length * i));\n}\n\n// Anonymous both-sides pricing for one strike: the chain's own probability for\n// (strike, +inf] and (-inf, strike]. Deployed `pricing::range_price` takes typed\n// `range_codec::Strike`s (NOT raw u64) — each boundary is built via\n// `range_codec::strike_from_tick(tick, tick_size)`, which maps tick 0 → -inf,\n// POS_INF_TICK → +inf, and any finite tick → tick*tick_size. `range_price` is a\n// public fun on the deployed package. Both sides read the SAME pricer in one PTB, so\n// `down` is the chain's number, not 1 − up.\n//\n// `range_price` now returns a `RangePrice` carrying both boundary probabilities so the\n// fee can charge each leg separately; `probability()` is the combined range number this\n// function has always returned (`lower_up.saturating_sub(higher_up)`, unchanged). The\n// extra call per side is what keeps the u64 parse below reading a u64 rather than the\n// struct's BCS.\nexport async function rangePrices(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n\tfeeds: MarketFeeds,\n\tstrikeRaw: bigint,\n\ttickSizeRaw: bigint,\n): Promise<{ upRaw: bigint; downRaw: bigint }> {\n\tconst tx = new Transaction();\n\tconst pricer = tx.add(loadLivePricer(config, { expiryMarketId: marketId, ...feeds }));\n\t// strikeRaw is a whole tick multiple (the caller validates divisibility), so the\n\t// finite boundary is `strike_from_tick(strikeRaw / tickSize, tickSize)`.\n\tconst strikeTick = strikeRaw / tickSizeRaw;\n\tconst mkStrike = (tick: bigint) =>\n\t\ttx.add(rangeCodec.strikeFromTick({ config, arguments: { tick, tickSize: tickSizeRaw } }));\n\tconst strike = mkStrike(strikeTick);\n\tconst posInf = mkStrike(POS_INF_TICK);\n\tconst negInf = mkStrike(0n);\n\t// UP: (strike, +inf], then DOWN: (-inf, strike]. The two `probability` reductions are\n\t// the last two commands, which is what the tail-relative parse below indexes.\n\tconst up = tx.add(\n\t\tpricing.rangePrice({ config, arguments: { pricer, lower: strike, higher: posInf } }),\n\t);\n\tconst down = tx.add(\n\t\tpricing.rangePrice({ config, arguments: { pricer, lower: negInf, higher: strike } }),\n\t);\n\ttx.add(pricing.probability({ config, arguments: { price: up } }));\n\ttx.add(pricing.probability({ config, arguments: { price: down } }));\n\tconst cmds = await inspectReturns(client, tx);\n\treturn {\n\t\tupRaw: parseU64LE(cmds[cmds.length - 2][0]),\n\t\tdownRaw: parseU64LE(cmds[cmds.length - 1][0]),\n\t};\n}\n\n// Fresh single read of the reference tick — used by mint-at-reference, which\n// must not trust a cached state (the reference is unset early in a window\n// until the keeper seeds it).\nexport async function referenceTick(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n): Promise<bigint | null> {\n\tconst tx = new Transaction();\n\ttx.add(expiryMarket.referenceTick({ config, arguments: { market: marketId } }));\n\tconst [cmd0] = await inspectReturns(client, tx);\n\treturn parseOptionalU64(cmd0[0]);\n}\n\n// The recorded settlement price, or null while the market is unsettled.\n//\n// On the deployed package `expiry_market::settlement_price` is public and\n// `destroy_some`s the stored Option — callable here only because simulate runs with\n// checksEnabled:false, and it aborts in std::option (EOPTION_NOT_SET) when the\n// market has not settled; we map exactly that abort (and the public\n// EMarketNotSettled variant, should a future package guard it directly) to null.\n// (A non-aborting `try_settlement_price` also exists on-chain if this ever wants to\n// drop the abort-catch.)\nexport async function settlementPrice(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n): Promise<bigint | null> {\n\tconst tx = new Transaction();\n\ttx.add(expiryMarket.settlementPrice({ config, arguments: { market: marketId } }));\n\ttry {\n\t\tconst [cmd0] = await inspectReturns(client, tx);\n\t\treturn parseU64LE(cmd0[0]);\n\t} catch (e) {\n\t\tif (\n\t\t\te instanceof PredictMoveError &&\n\t\t\t(e.module === 'option' ||\n\t\t\t\t(e.module === 'expiry_market' && e.abortName === 'EMarketNotSettled'))\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow e;\n\t}\n}\n\n// A market's current NAV mark (the per-expiry recoverable value the flush prices\n// against). Loads a fresh live pricer, then reads `current_nav(market, &pricer)` —\n// see packages/predict/sources/expiry_market.move:236. `Pricer` has copy+drop, so\n// the unconsumed borrow is fine in a read-only inspect.\nexport async function currentNav(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\tmarketId: string,\n\tunderlying: UnderlyingConfig,\n): Promise<bigint> {\n\tconst tx = new Transaction();\n\tconst pricer = tx.add(\n\t\tloadLivePricer(config, {\n\t\t\texpiryMarketId: marketId,\n\t\t\tpythFeed: underlying.pythFeed,\n\t\t\tblockScholesValueStore: underlying.blockScholesValueStore,\n\t\t\tblockScholesSviStore: underlying.blockScholesSviStore,\n\t\t}),\n\t);\n\ttx.add(expiryMarket.currentNav({ config, arguments: { market: marketId, pricer } }));\n\tconst cmds = await inspectReturns(client, tx);\n\t// current_nav is the last command; load_live_pricer precedes it.\n\treturn parseU64LE(cmds[cmds.length - 1][0]);\n}\n\n/**\n * The fee and exposure policy a market snapshotted at creation, from its `ExpiryMarket` object:\n * `strike_exposure.config` and `strike_exposure.inventory_impact_scale`. It is the policy the\n * market charges for its whole life, whatever the protocol template says now, and the `cost`\n * functions take it as `fees`. One object read, no simulate. The struct layout is fixed across\n * package upgrades, so the v1 binding decodes every version's markets.\n */\nexport async function marketFeePolicy(client: ReadClient, marketId: string): Promise<FeePolicy> {\n\tconst { object } = await client.core.getObject({\n\t\tobjectId: marketId,\n\t\tinclude: { content: true },\n\t});\n\tif (!object.content) throw new Error(`ExpiryMarket ${marketId} returned no content`);\n\tconst { config, inventory_impact_scale } = expiryMarket.ExpiryMarket.parse(\n\t\tobject.content,\n\t).strike_exposure;\n\treturn {\n\t\tbaseFee: BigInt(config.base_fee),\n\t\tminFee: BigInt(config.min_fee),\n\t\texpiryFeeWindowMs: BigInt(config.expiry_fee_window_ms),\n\t\texpiryFeeMaxMultiplier: BigInt(config.expiry_fee_max_multiplier),\n\t\tminEntryProbability: BigInt(config.min_entry_probability),\n\t\tmaxEntryProbability: BigInt(config.max_entry_probability),\n\t\tinventoryImpactMaxRate: BigInt(config.inventory_impact_max_rate),\n\t\tinventoryImpactScale: BigInt(inventory_impact_scale),\n\t\tbackingBufferLambda: BigInt(config.backing_buffer_lambda),\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { inspectReturns } from "./inspect.mjs";
|
|
2
|
-
import { parseU64LE } from "./parse.mjs";
|
|
3
2
|
import { idleBalance, plpTotalSupply, supplyRequestsPending, withdrawRequestsPending } from "../../contracts/deepbook_predict/plp.mjs";
|
|
3
|
+
import { parseU64LE } from "./parse.mjs";
|
|
4
4
|
import { Transaction } from "@mysten/sui/transactions";
|
|
5
5
|
|
|
6
6
|
//#region src/predict/reads/pool.ts
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { DelayedExecutionPolicy, QueueHeads, QueuedOrder } from "../queue.mjs";
|
|
2
|
+
import { OrdersGeneratedConfig } from "../config/generated.mjs";
|
|
3
|
+
import "../tx/trade.mjs";
|
|
4
|
+
import "../tx/queue.mjs";
|
|
5
|
+
import { ClientWithCoreApi } from "@mysten/sui/client";
|
|
6
|
+
|
|
7
|
+
//#region src/predict/reads/queue.d.ts
|
|
8
|
+
/** The companion's `order_flow::OrderFlow` witness type, which Predict's allowlist names. */
|
|
9
|
+
declare function orderFlowWitnessType(config: Pick<OrdersGeneratedConfig, 'predictOrdersPackageIdV1'>): string;
|
|
10
|
+
/** Everything the queued-order preflight and the app's queue view read, from one simulate. */
|
|
11
|
+
interface MarketQueueState {
|
|
12
|
+
marketId: string;
|
|
13
|
+
/** The market's `MarketQueue`. */
|
|
14
|
+
queueId: string;
|
|
15
|
+
expiryMs: bigint;
|
|
16
|
+
mintPaused: boolean;
|
|
17
|
+
cashBalance: bigint;
|
|
18
|
+
requiredCash: bigint;
|
|
19
|
+
/**
|
|
20
|
+
* Cash above required cash, 0 when below: the largest cash need a new queued mint may have
|
|
21
|
+
* now (Predict's admission refuses a larger one).
|
|
22
|
+
*/
|
|
23
|
+
spareCash: bigint;
|
|
24
|
+
/** Summed cash need of the admitted orders; `rebalance_expiry_cash` funds it. */
|
|
25
|
+
waitingCashNeed: bigint;
|
|
26
|
+
/** 1e9-scaled. The mint cash-need formulas take it. */
|
|
27
|
+
minEntryProbability: bigint;
|
|
28
|
+
/** 1e9-scaled λ. The sell cash-need formula takes it. */
|
|
29
|
+
backingBufferLambda: bigint;
|
|
30
|
+
/** Sizes a filler's resolve batch. */
|
|
31
|
+
payoutTreeNodeCount: bigint;
|
|
32
|
+
/** `queue_stuck`: enqueue would refuse as stuck right now ("pricing delayed"). */
|
|
33
|
+
stuck: boolean;
|
|
34
|
+
cohorts: {
|
|
35
|
+
count: bigint;
|
|
36
|
+
oldestUncommittedTauMs: bigint | null; /** The cohort the stuck gate's first rule watches. */
|
|
37
|
+
oldestUncommittedTauAboveCommittedMs: bigint | null;
|
|
38
|
+
};
|
|
39
|
+
heads: QueueHeads;
|
|
40
|
+
/** Unfinished mints and sells, against the policy capacities. */
|
|
41
|
+
pending: {
|
|
42
|
+
mints: bigint;
|
|
43
|
+
sells: bigint;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* The settlement payout walk (`settle_step`): it resumes at `cursor`, and `completed` is set
|
|
47
|
+
* by the call that emits `MarketPayoutsCompleted`.
|
|
48
|
+
*/
|
|
49
|
+
payout: {
|
|
50
|
+
cursor: bigint;
|
|
51
|
+
nextId: bigint;
|
|
52
|
+
completed: boolean;
|
|
53
|
+
};
|
|
54
|
+
/** The companion's `OrderDesk`: the policy every queue runs under, and its version floor. */
|
|
55
|
+
desk: {
|
|
56
|
+
id: string;
|
|
57
|
+
policy: DelayedExecutionPolicy;
|
|
58
|
+
versionWatermark: bigint;
|
|
59
|
+
};
|
|
60
|
+
protocol: {
|
|
61
|
+
noTradeWindowMs: bigint; /** The admin-set mint fee subsidy rate, 1e9-scaled (20% when unset). */
|
|
62
|
+
feeIncentiveSubsidyRate: bigint;
|
|
63
|
+
tradingPaused: boolean;
|
|
64
|
+
frozen: boolean; /** Predict's version floor. Enqueue needs it at `DELAYED_EXECUTION_VERSION`. */
|
|
65
|
+
versionWatermark: bigint;
|
|
66
|
+
/**
|
|
67
|
+
* Whether Predict allowlists this companion's `OrderFlow` witness
|
|
68
|
+
* (`protocol_config::set_order_flow`). Predict's admission, commit and fill refuse it until
|
|
69
|
+
* then (`EOrderFlowNotAllowed`).
|
|
70
|
+
*/
|
|
71
|
+
orderFlowEnabled: boolean;
|
|
72
|
+
};
|
|
73
|
+
/** Present when an owner was given. */
|
|
74
|
+
account: {
|
|
75
|
+
accountId: string;
|
|
76
|
+
/**
|
|
77
|
+
* Unfinished orders the account holds in this market, against `per_account_cap`. Stale
|
|
78
|
+
* after expiry: the settlement drain refunds without lowering it.
|
|
79
|
+
*/
|
|
80
|
+
waitingOrders: bigint; /** `account::balance<USDC>`, unsettled accumulator funds included. */
|
|
81
|
+
availableRaw: bigint;
|
|
82
|
+
} | null;
|
|
83
|
+
/** One entry per requested record ID: the record, or `null` when missing or deleted. */
|
|
84
|
+
records: (QueuedOrder | null)[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Which trade path a network is on:
|
|
88
|
+
* - `'immediate'`: the watermark isn't raised and this SDK has no delayed-execution record, so
|
|
89
|
+
* its call target is a pre-v4 Predict package. Use the immediate `mint*` / `redeem` builders.
|
|
90
|
+
* - `'awaiting-cutover'`: the config records delayed execution but the watermark isn't raised.
|
|
91
|
+
* Nothing trades: enqueue aborts `ECutoverNotReached`, and the immediate builders abort in the
|
|
92
|
+
* v4 package the config calls (`EDelayedExecutionRequired`). Trading stays paused through the
|
|
93
|
+
* cutover.
|
|
94
|
+
* - `'delayed'`: the watermark is raised. Use the `enqueue*` builders; the immediate ones abort
|
|
95
|
+
* `EDelayedExecutionRequired`.
|
|
96
|
+
* - `'unsupported'`: the watermark is raised but this SDK's config has no delayed-execution
|
|
97
|
+
* record for the network. Upgrade the SDK, or pass a config that records it.
|
|
98
|
+
* - `'retired'`: the watermark is above the Predict code version this SDK calls
|
|
99
|
+
* (`PREDICT_PACKAGE_VERSION`), so every version-gated call aborts `EPackageVersionDisabled`.
|
|
100
|
+
* Upgrade the SDK.
|
|
101
|
+
*/
|
|
102
|
+
type ExecutionMode = 'immediate' | 'awaiting-cutover' | 'delayed' | 'unsupported' | 'retired';
|
|
103
|
+
//#endregion
|
|
104
|
+
export { ExecutionMode, MarketQueueState, orderFlowWitnessType };
|
|
105
|
+
//# sourceMappingURL=queue.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.mts","names":[],"sources":["../../../src/predict/reads/queue.ts"],"mappings":";;;;;;;;iBAsCgB,oBAAA,CACf,MAAA,EAAQ,IAAA,CAAK,qBAAA;;UAMG,gBAAA;EAChB,QAAA;EAPQ;EASR,OAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,YAAA;EAPgC;;;;EAYhC,SAAA;EA0DqB;EAxDrB,eAAA;EAbA;EAeA,mBAAA;EAZA;EAcA,mBAAA;EAZA;EAcA,mBAAA;EARA;EAUA,KAAA;EACA,OAAA;IACC,KAAA;IACA,sBAAA,iBAHD;IAKC,oCAAA;EAAA;EAED,KAAA,EAAO,UAAA;EAFN;EAID,OAAA;IAAW,KAAA;IAAe,KAAA;EAAA;EAAA;;;;EAK1B,MAAA;IAAU,MAAA;IAAgB,MAAA;IAAgB,SAAA;EAAA;EAKzC;EAHD,IAAA;IACC,EAAA;IACA,MAAA,EAAQ,sBAAA;IACR,gBAAA;EAAA;EAED,QAAA;IACC,eAAA,UAeD;IAbC,uBAAA;IACA,aAAA;IACA,MAAA,WAsBD;IApBC,gBAAA;IAoBoB;;AAyLtB;;;IAvME,gBAAA;EAAA;;EAGD,OAAA;IACC,SAAA;;;;;IAKA,aAAA;IAEA,YAAA;EAAA;;EAGD,OAAA,GAAU,WAAA;AAAA;;;;;;;;;;;;;;;;;KAyLC,aAAA"}
|