@mysten/deepbook-v3 2.1.3 → 2.3.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 +45 -0
- package/PREDICT.md +17 -5
- package/dist/account.d.mts.map +1 -1
- package/dist/account.mjs +3 -1
- package/dist/account.mjs.map +1 -1
- package/dist/contracts/account/account.d.mts +23 -23
- package/dist/contracts/account/account.d.mts.map +1 -1
- package/dist/contracts/account/account_events.d.mts +20 -20
- package/dist/contracts/account/account_registry.d.mts +19 -19
- package/dist/contracts/account/account_registry.d.mts.map +1 -1
- 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/deps/sui/vec_map.mjs +37 -0
- package/dist/contracts/deepbook_predict/deps/sui/vec_map.mjs.map +1 -0
- package/dist/contracts/deepbook_predict/expiry_cash.mjs +1 -1
- package/dist/contracts/deepbook_predict/expiry_cash.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/expiry_market.mjs +15 -6
- package/dist/contracts/deepbook_predict/expiry_market.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/market_manager.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/order_events.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/plp.mjs +53 -31
- package/dist/contracts/deepbook_predict/plp.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pool_accounting.mjs +7 -7
- package/dist/contracts/deepbook_predict/pool_accounting.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/predict_account.mjs +1 -1
- package/dist/contracts/deepbook_predict/predict_account.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/pricing.mjs +13 -1
- package/dist/contracts/deepbook_predict/pricing.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/registry.mjs +2 -1
- package/dist/contracts/deepbook_predict/registry.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/strike_exposure.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/strike_payout_tree.mjs +13 -1
- package/dist/contracts/deepbook_predict/strike_payout_tree.mjs.map +1 -1
- package/dist/contracts/deepbook_predict/vault_events.mjs +19 -7
- package/dist/contracts/deepbook_predict/vault_events.mjs.map +1 -1
- package/dist/contracts/deepbook_sessions/session_config.d.mts +8 -8
- package/dist/contracts/deepbook_sessions/session_config.d.mts.map +1 -1
- package/dist/contracts/deepbook_sessions/sessions.d.mts +22 -22
- package/dist/contracts/deepbook_sessions/sessions.d.mts.map +1 -1
- package/dist/deployments/index.d.mts +3 -2
- package/dist/deployments/index.d.mts.map +1 -1
- package/dist/deployments/index.mjs +4 -1
- package/dist/deployments/index.mjs.map +1 -1
- package/dist/deployments/mainnet.d.mts +14 -0
- package/dist/deployments/mainnet.d.mts.map +1 -0
- package/dist/deployments/mainnet.mjs +73 -0
- package/dist/deployments/mainnet.mjs.map +1 -0
- package/dist/deployments/testnet.mjs +23 -23
- package/dist/deployments/testnet.mjs.map +1 -1
- package/dist/deployments/types.d.mts +1 -1
- package/dist/predict/client.d.mts +25 -4
- package/dist/predict/client.d.mts.map +1 -1
- package/dist/predict/client.mjs +4 -4
- package/dist/predict/client.mjs.map +1 -1
- package/dist/predict/config/index.d.mts +2 -0
- package/dist/predict/config/index.d.mts.map +1 -1
- package/dist/predict/config/index.mjs +4 -1
- package/dist/predict/config/index.mjs.map +1 -1
- package/dist/predict/config/mainnet.d.mts +17 -0
- package/dist/predict/config/mainnet.d.mts.map +1 -0
- package/dist/predict/config/mainnet.mjs +26 -0
- package/dist/predict/config/mainnet.mjs.map +1 -0
- package/dist/predict/config/types.d.mts +6 -0
- package/dist/predict/config/types.d.mts.map +1 -1
- package/dist/predict/index.d.mts +4 -2
- package/dist/predict/index.mjs +3 -1
- package/dist/predict/pricing.d.mts +6 -6
- package/dist/predict/pricing.d.mts.map +1 -1
- package/dist/predict/pricing.mjs +6 -6
- package/dist/predict/pricing.mjs.map +1 -1
- package/dist/predict/reads/balances.mjs.map +1 -1
- package/dist/predict/reads/markets.mjs +1 -1
- package/dist/predict/reads/markets.mjs.map +1 -1
- package/dist/predict/reads/pricing.d.mts +2 -1
- package/dist/predict/reads/pricing.d.mts.map +1 -1
- package/dist/predict/reads/pricing.mjs.map +1 -1
- package/dist/sessions.d.mts.map +1 -1
- package/dist/sessions.mjs +3 -1
- 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/deepbookAdmin.d.mts +4 -4
- package/dist/transactions/marginAdmin.d.mts +7 -7
- package/dist/transactions/marginMaintainer.d.mts +5 -5
- package/dist/transactions/marginManager.d.mts +32 -32
- package/dist/transactions/marginPool.d.mts +18 -18
- package/dist/transactions/marginPool.d.mts.map +1 -1
- 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 +3 -3
- package/src/account.ts +3 -1
- package/src/contracts/deepbook_predict/builder_code.ts +3 -3
- package/src/contracts/deepbook_predict/config_events.ts +9 -2
- package/src/contracts/deepbook_predict/deps/sui/vec_map.ts +33 -0
- package/src/contracts/deepbook_predict/expiry_cash.ts +1 -1
- package/src/contracts/deepbook_predict/expiry_market.ts +70 -11
- package/src/contracts/deepbook_predict/market_lifecycle_cap.ts +3 -10
- package/src/contracts/deepbook_predict/market_manager.ts +2 -2
- package/src/contracts/deepbook_predict/order_events.ts +6 -6
- package/src/contracts/deepbook_predict/plp.ts +263 -81
- package/src/contracts/deepbook_predict/pool_accounting.ts +14 -14
- package/src/contracts/deepbook_predict/pool_valuation_cap.ts +69 -0
- package/src/contracts/deepbook_predict/predict_account.ts +1 -1
- package/src/contracts/deepbook_predict/pricing.ts +16 -4
- package/src/contracts/deepbook_predict/protocol_config.ts +202 -7
- package/src/contracts/deepbook_predict/registry.ts +91 -17
- package/src/contracts/deepbook_predict/strike_exposure.ts +1 -1
- package/src/contracts/deepbook_predict/strike_payout_tree.ts +27 -0
- package/src/contracts/deepbook_predict/vault_events.ts +45 -14
- package/src/contracts/propbook/block_scholes_store.ts +8 -42
- package/src/deployments/index.ts +13 -3
- package/src/deployments/mainnet.ts +107 -0
- package/src/deployments/testnet.ts +25 -25
- package/src/deployments/types.ts +1 -1
- package/src/predict/client.ts +45 -15
- package/src/predict/config/index.ts +7 -2
- package/src/predict/config/mainnet.ts +27 -0
- package/src/predict/config/types.ts +7 -1
- package/src/predict/index.ts +5 -0
- package/src/predict/pricing.ts +11 -9
- package/src/predict/reads/balances.ts +1 -1
- package/src/predict/reads/markets.ts +1 -1
- package/src/predict/reads/pricing.ts +2 -1
- package/src/sessions.ts +4 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":["#config","opts","#buildMint","#feeds","#resolveMarket","#strikeTicks","#buildRedeem","#client","#referencePriceOf","#positionsCache","#strikeRawFor","#underlying","#marketCache","resolved","#assertAdmittedTick","#gridTick","#assertLot"],"sources":["../../src/predict/client.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport type { ClientWithCoreApi, SuiClientRegistration } from '@mysten/sui/client';\nimport { Transaction, coinWithBalance, type TransactionResult } from '@mysten/sui/transactions';\nimport { isValidSuiObjectId } from '@mysten/sui/utils';\nimport { TESTNET_PREDICT } from '../deployments/testnet.js';\nimport { getConfig, type PredictConfig, type UnderlyingConfig } from './config/index.js';\nimport { toGeneratedConfig, type GeneratedConfig } from './config/generated.js';\nimport {\n\tdecodeAccountsCreated,\n\tdecodeBuilderCodeSets,\n\tdecodeClaims,\n\tdecodeDeposits,\n\tdecodeMints,\n\tdecodePlpCancels,\n\tdecodePlpRequests,\n\tdecodeRedeems,\n\tdecodeWithdrawals,\n\texactlyOne,\n\ttype DecodableTransactionResult,\n} from './decode.js';\nimport { PredictInputError } from './errors.js';\nimport { simulateWithEvents } from './reads/inspect.js';\nimport {\n\tpositionsFromTable,\n\tresolvePositionsTable,\n\ttype OpenPosition,\n\ttype PositionsHandle,\n} from './reads/positions.js';\nimport { accountBalance, hasPosition } from './reads/balances.js';\nimport {\n\tactiveMarketIds,\n\tcurrentNav,\n\texpiryMarketId,\n\tmarketState,\n\tmarketStates,\n\trangePrices,\n\treferenceTick,\n\ttype MarketState,\n} from './reads/markets.js';\nimport { poolStats } from './reads/pool.js';\nimport { readPricerSnapshot, type PricerSnapshot } from './reads/pricing.js';\nimport { boardPricer, type BoardPricer } from './pricing.js';\nimport { POS_INF_TICK, binaryRangeTicks, type Side } from './ticks.js';\nimport {\n\tcancelSupplyRequest,\n\tcancelWithdrawRequest,\n\tdepositFunds,\n\trequestSupply,\n\trequestWithdraw,\n\tsetBuilderCode,\n\tunsetBuilderCode,\n\twithdrawFunds,\n} from './tx/authed.js';\n\nimport { accountContract, deriveAccountWrapperIdFrom } from './tx/common.js';\nimport type { MarketFeeds } from './tx/trade.js';\nimport { mintExactAmount, mintExactQuantity, redeemLive, redeemSettled } from './tx/trade.js';\nimport {\n\tpriceToRaw,\n\tprobabilityToRaw,\n\trawToProbability,\n\trawToUsdc,\n\tusdcToRaw,\n\tfromRaw,\n} from './units.js';\n\n// `position_lot_size` — a position quantity must be a whole multiple of this many\n// raw payout units ($0.01 lots). See packages/predict/sources/constants.move.\n/**\n * Testnet's `position_lot_size`, read from the deployment record. Validation uses the lot\n * size of the config actually in play; this is the convenience constant for testnet callers.\n */\nexport const POSITION_LOT_SIZE = BigInt(TESTNET_PREDICT.units.positionLotSize);\n\n// Most `tx.*` builders are one builder's worth of commands in a fresh PTB.\nfunction txOf(command: (tx: Transaction) => TransactionResult | void): Transaction {\n\tconst tx = new Transaction();\n\ttx.add(command);\n\treturn tx;\n}\n\n/** A live/settled market addressed by its human coordinates: a binary position\n * (single strike + side) or a two-strike range position. */\nexport type MarketDescriptor = {\n\tunderlying: string;\n\texpiryMs: number | bigint;\n\t/**\n\t * Pin resolution to this exact `ExpiryMarket` object, skipping the\n\t * underlying+expiry lookup — a caller that reviewed a specific market object\n\t * mints against exactly that object, not whatever resolves at submit time.\n\t */\n\tmarketId?: string;\n} & (\n\t| {\n\t\t\tside: Side;\n\t\t\t/**\n\t\t\t * Strike in USD, or \"reference\" to trade at the market's on-chain reference\n\t\t\t * price (the Polymarket-style anchor: derived from the exact previous-window\n\t\t\t * oracle observation, so consecutive windows chain settlement → next strike).\n\t\t\t */\n\t\t\tstrike: number | 'reference';\n\t }\n\t| {\n\t\t\t/** A range position: pays out when settlement lands inside `(lower, upper]`\n\t\t\t * (left-open, right-closed — same convention as the on-chain range key). */\n\t\t\tside: 'range';\n\t\t\t/** Lower strike bound in USD — finite, on the tick grid. */\n\t\t\tlower: number;\n\t\t\t/** Upper strike bound in USD — finite, on the tick grid, above `lower`. */\n\t\t\tupper: number;\n\t }\n);\n\n/** Options for the friendly `mint` (exact payout quantity). */\nexport interface MintOptions {\n\tquantity: number;\n\tmaxCost?: number;\n\tmaxProbability?: number;\n}\n\n/** Options for `mintAmount` (spend up to a premium budget, floor the quantity received). */\nexport interface MintAmountOptions {\n\t/** Premium budget in quote units — the max premium paid (chain also caps it at the account balance). */\n\tspend: number;\n\tminQuantity: number;\n\t/** All-in cost ceiling in quote units (premium + fees). Omitted → uncapped. */\n\tmaxCost?: number;\n}\n\n/** Options for `redeem`: which order and how much to close. `claimSettled` takes only\n * `orderId` — a settled claim closes the order in full. */\nexport interface CloseOptions {\n\torderId: bigint;\n\tquantity: number;\n}\n\n/** One tradeable market as returned by read.markets(). */\nexport interface ActiveMarket {\n\tid: string;\n\texpiryMs: bigint;\n\t/** Strike granularity in USD (e.g. 0.01). */\n\ttickSize: number;\n\t/**\n\t * Coarser step new mint strikes must align to. A numeric strike must be a whole\n\t * multiple of this (the market's `referencePrice` is the one exception the chain\n\t * admits off-grid); otherwise the mint aborts `EInvalidAdmissionTick`.\n\t */\n\tadmissionTickSize: number;\n\tmintPaused: boolean;\n\t/** The window's anchor strike in USD, or null until the keeper seeds it. */\n\treferencePrice: number | null;\n}\n\n/** A resolved live market: its on-chain state summary for the caller. */\nexport interface MarketSummary {\n\tid: string;\n\texpiryMs: bigint;\n\ttickSize: number;\n\t/**\n\t * Coarser step new mint strikes must align to. A numeric strike must be a whole\n\t * multiple of this (the market's `referencePrice` is the one exception the chain\n\t * admits off-grid); otherwise the mint aborts `EInvalidAdmissionTick`.\n\t */\n\tadmissionTickSize: number;\n\tmintPaused: boolean;\n\tnav: number;\n\t/** The window's anchor strike in USD, or null until the keeper seeds it. */\n\treferencePrice: number | null;\n}\n\n/** Aggregate pool figures. Balances in human units (shares raw); the pending fields\n * are request COUNTS, not amounts — the on-chain getters expose queue lengths, and\n * the escrowed DUSDC/PLP behind them is tracked separately. */\nexport interface PoolSummary {\n\tplpTotalSupply: bigint;\n\tidleUsdc: number;\n\t/** Number of LP supply requests queued for the next flush. */\n\tsupplyRequestsPending: number;\n\t/** Number of LP withdraw requests queued for the next flush. */\n\twithdrawRequestsPending: number;\n}\n\n/** Exact pre-trade quote: the dry-run receipt of the mint you are about to send. */\nexport interface MintQuote {\n\t/** Fill price, 0..1 per $1 payout. */\n\tentryProbability: number;\n\t/** Premium paid into LP backing (quote units). */\n\tpremium: number;\n\t/**\n\t * Fee breakdown. `referral` is a PORTION of the trader-paid trading fee and\n\t * congestion surcharge routed to the referrer — it is already inside those\n\t * numbers and is NOT an extra debit. `inventoryImpact` is a separate charge and\n\t * IS part of `cost`.\n\t */\n\tfees: {\n\t\ttrading: number;\n\t\tsubsidy: number;\n\t\tbuilder: number;\n\t\tpenalty: number;\n\t\treferral: number;\n\t\tinventoryImpact: number;\n\t};\n\t/**\n\t * All-in account debit: premium + (trading − subsidy) + builder + penalty +\n\t * inventoryImpact — exactly what the chain withdraws (the deployed\n\t * `compute_mint_quote`'s `all_in_cost`); pass this (plus your buffer) as maxCost.\n\t */\n\tcost: number;\n\tquantity: number;\n\traw: { premium: bigint; cost: bigint; quantity: bigint; entryProbability: bigint };\n\t/** True: computed by the real mint code path against real account state. */\n\tfeesExact: true;\n}\n\n/** Exact pre-close quote: the dry-run receipt of the redeem you are about to send. */\nexport interface RedeemQuote {\n\t/** NET quote credited to the account. */\n\tproceeds: number;\n\t/** Gross close value before fees. */\n\tgross: number;\n\t/** `inventoryImpactRebate` is credited back on the close, so `proceeds` is\n\t * gross + rebate − trading − builder − penalty. */\n\tfees: { trading: number; builder: number; penalty: number; inventoryImpactRebate: number };\n\tquantityClosed: number;\n\tremaining: number;\n\traw: { proceeds: bigint; gross: bigint; quantityClosed: bigint };\n\tfeesExact: true;\n}\n\ninterface ResolvedMarket {\n\tid: string;\n\tstate: MarketState;\n}\n\n// The strike-bearing (binary) arm of MarketDescriptor, for read.price and its\n// seam — anonymous board pricing has no range semantics.\ntype BinaryMarketCoordinates = Pick<MarketDescriptor, 'underlying' | 'expiryMs' | 'marketId'> & {\n\tstrike: number | 'reference';\n};\n\n/** The Sui client surface PredictClient reads through: any `ClientWithCoreApi`\n * (gRPC or JSON-RPC) provides both the `simulateTransaction` the reads/quotes\n * sit on and the `core` object methods position enumeration needs. */\nexport interface PredictCompatibleClient extends ClientWithCoreApi {}\n\n/**\n * Register PredictClient as a `client.predict` extension, mirroring\n * `@mysten/deepbook-v3`'s `deepbook(...)`: `client.$extend(predict({ network }))`.\n */\nexport function predict<Name extends string = 'predict'>({\n\tname = 'predict' as Name,\n\tnetwork,\n\tconfig,\n}: {\n\tname?: Name;\n\tnetwork: 'testnet' | 'mainnet';\n\tconfig?: PredictConfig;\n}): SuiClientRegistration<PredictCompatibleClient, Name, PredictClient> {\n\treturn {\n\t\tname,\n\t\tregister: (client) => new PredictClient({ client, network, config }),\n\t};\n}\n\n/**\n * The one object an app constructs. Wraps the config, a client for reads, and\n * a derived-account model so callers pass owner addresses, decimal amounts, and\n * human market coordinates — the facade converts to raw units, resolves markets\n * (cached), and delegates to the internal tx primitives / reads. Callers who need\n * to compose their own PTBs can use the generated bindings under `contracts/`.\n */\nexport class PredictClient {\n\treadonly cfg: PredictConfig;\n\t// The flat slice every generated call resolves `options.config` against.\n\tget #config(): GeneratedConfig {\n\t\treturn toGeneratedConfig(this.cfg);\n\t}\n\t#client: PredictCompatibleClient;\n\t// underlying:expiryMs → resolved market. The id and tickSizeRaw — the only\n\t// state tx building depends on — are immutable per (underlying, expiry), so\n\t// one resolution per market per client suffices. (mintPaused IS mutable; the\n\t// cached copy is never consulted for a tx decision — the chain enforces it.)\n\t#marketCache = new Map<string, ResolvedMarket>();\n\t// owner → resolved position-store ids. accountUid and the table id are\n\t// immutable once created, so cache-forever; a missing table (no Predict\n\t// data yet) is NOT cached — it appears after the owner's first trade.\n\t#positionsCache = new Map<string, PositionsHandle>();\n\n\tconstructor(opts: {\n\t\tnetwork: 'testnet' | 'mainnet';\n\t\tclient: PredictCompatibleClient;\n\t\tconfig?: PredictConfig;\n\t}) {\n\t\tthis.cfg = opts.config ?? getConfig(opts.network);\n\t\tthis.#client = opts.client;\n\t}\n\n\t/** The deterministic id of an owner's canonical account wrapper — no chain read. */\n\twrapperIdFor(owner: string): string {\n\t\treturn deriveAccountWrapperIdFrom(this.#config, owner);\n\t}\n\n\t// The deployment's wiring for a symbol; throws a typed error on an unknown symbol.\n\t// Per-underlying ids are the one thing the flat config slice does not carry.\n\t#underlying(underlying: string): UnderlyingConfig {\n\t\tconst u = this.cfg.underlyings[underlying];\n\t\tif (!u) throw new PredictInputError(`unknown underlying: ${underlying}`);\n\t\treturn u;\n\t}\n\n\t// The oracle feed ids for a symbol; throws a typed error on an unknown symbol.\n\t#feeds(underlying: string): MarketFeeds {\n\t\tconst u = this.#underlying(underlying);\n\t\treturn {\n\t\t\tpythFeed: u.pythFeed,\n\t\t\tblockScholesValueStore: u.blockScholesValueStore,\n\t\t\tblockScholesSviStore: u.blockScholesSviStore,\n\t\t};\n\t}\n\n\t// Resolve (and cache) a market's id + state from its human coordinates. An\n\t// explicit `marketId` pin skips the underlying+expiry lookup but still reads\n\t// that market's state — tx building depends on tickSizeRaw.\n\tasync #resolveMarket(\n\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs' | 'marketId'>,\n\t): Promise<ResolvedMarket> {\n\t\tif (m.marketId != null) {\n\t\t\tif (!isValidSuiObjectId(m.marketId)) {\n\t\t\t\tthrow new PredictInputError(`invalid marketId: ${JSON.stringify(m.marketId)}`);\n\t\t\t}\n\t\t\tconst resolved: ResolvedMarket = this.#marketCache.get(m.marketId) ?? {\n\t\t\t\tid: m.marketId,\n\t\t\t\tstate: await marketState(this.#client, this.#config, m.marketId),\n\t\t\t};\n\t\t\t// The pin must agree with the descriptor's coordinates: catching a stale or\n\t\t\t// wrong-market id here beats minting against mismatched oracle feeds. (The\n\t\t\t// underlying cannot be cross-checked — market state does not carry it.)\n\t\t\tif (resolved.state.expiryMs !== BigInt(m.expiryMs)) {\n\t\t\t\tthrow new PredictInputError(\n\t\t\t\t\t`pinned market ${m.marketId} expires at ${resolved.state.expiryMs}, descriptor says ${BigInt(m.expiryMs)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.#marketCache.set(m.marketId, resolved);\n\t\t\treturn resolved;\n\t\t}\n\t\tconst expiryMs = BigInt(m.expiryMs);\n\t\tconst key = `${m.underlying}:${expiryMs}`;\n\t\tconst hit = this.#marketCache.get(key);\n\t\tif (hit) return hit;\n\t\tconst u = this.#underlying(m.underlying);\n\t\tconst id = await expiryMarketId(this.#client, this.#config, u, expiryMs);\n\t\tif (!id) throw new PredictInputError(`no market for ${m.underlying} at expiry ${expiryMs}`);\n\t\tconst state = await marketState(this.#client, this.#config, id);\n\t\tconst resolved: ResolvedMarket = { id, state };\n\t\tthis.#marketCache.set(key, resolved);\n\t\treturn resolved;\n\t}\n\n\t// Reference PRICE in USD from a state (tick index × tick size), or null.\n\tstatic #referencePriceOf(state: MarketState): number | null {\n\t\treturn state.referenceTickRaw == null\n\t\t\t? null\n\t\t\t: fromRaw(state.referenceTickRaw * state.tickSizeRaw, 9);\n\t}\n\n\t// A finite tick from a USD strike, validated exactly like binaryRangeTicks:\n\t// whole-tick multiple, inside the finite domain (1..POS_INF_TICK-1).\n\t#gridTick(strike: number, tickSizeRaw: bigint): bigint {\n\t\tconst raw = priceToRaw(strike);\n\t\tconst tick = raw / tickSizeRaw;\n\t\tif (tick * tickSizeRaw !== raw) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`strike ${strike} is not on the ${fromRaw(tickSizeRaw, 9)} tick grid`,\n\t\t\t);\n\t\t}\n\t\tif (tick <= 0n || tick >= POS_INF_TICK) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`strike tick ${tick} outside the finite tick domain (1..POS_INF_TICK-1)`,\n\t\t\t);\n\t\t}\n\t\treturn tick;\n\t}\n\n\t// New finite MINT boundaries must land on the market's coarser ADMISSION grid,\n\t// not merely the fine tick grid — the chain asserts exactly this\n\t// (`assert_admitted_mint_ticks`, `EInvalidAdmissionTick`). The ±inf sentinels are\n\t// exempt, and the market's reference tick is the one finite boundary allowed to\n\t// bypass the grid, so an off-grid tick is only rejected after confirming it is not\n\t// the reference (one extra read, and only on the failing path).\n\tasync #assertAdmittedTick(tick: bigint, marketId: string, state: MarketState): Promise<void> {\n\t\tif (tick === 0n || tick === POS_INF_TICK) return;\n\t\tconst multiple = state.admissionTickSizeRaw / state.tickSizeRaw;\n\t\tif (multiple > 0n && tick % multiple === 0n) return;\n\t\tconst reference = await referenceTick(this.#client, this.#config, marketId);\n\t\tif (reference != null && reference === tick) return;\n\t\tconst admission = fromRaw(state.admissionTickSizeRaw, 9);\n\t\tthrow new PredictInputError(\n\t\t\t`strike ${fromRaw(tick * state.tickSizeRaw, 9)} is not on the ${admission} admission grid ` +\n\t\t\t\t`(mint boundaries must be a multiple of ${admission}, or the market's reference strike)`,\n\t\t);\n\t}\n\n\t// Resolve a descriptor's strike(s) to the (lower, higher) tick pair. A binary\n\t// numeric strike converts and validates against the tick grid; \"reference\"\n\t// reads the market's reference tick FRESH (never cached — it is unset early in\n\t// a window) and uses it directly: it is on the tick grid by construction. A\n\t// range descriptor converts both bounds to finite grid ticks (\"reference\" is\n\t// binary-only: a range has no single reference strike).\n\tasync #strikeTicks(\n\t\tm: MarketDescriptor,\n\t\tmarketId: string,\n\t\tstate: MarketState,\n\t): Promise<{ lowerTick: bigint; higherTick: bigint }> {\n\t\tif (m.side === 'range') {\n\t\t\tif (!(m.lower < m.upper)) {\n\t\t\t\tthrow new PredictInputError(`range lower ${m.lower} must be below upper ${m.upper}`);\n\t\t\t}\n\t\t\tconst lowerTick = this.#gridTick(m.lower, state.tickSizeRaw);\n\t\t\tconst higherTick = this.#gridTick(m.upper, state.tickSizeRaw);\n\t\t\tawait this.#assertAdmittedTick(lowerTick, marketId, state);\n\t\t\tawait this.#assertAdmittedTick(higherTick, marketId, state);\n\t\t\treturn { lowerTick, higherTick };\n\t\t}\n\t\tif (m.strike !== 'reference') {\n\t\t\tconst ticks = binaryRangeTicks(priceToRaw(m.strike), m.side, state.tickSizeRaw);\n\t\t\tawait this.#assertAdmittedTick(ticks.lowerTick, marketId, state);\n\t\t\tawait this.#assertAdmittedTick(ticks.higherTick, marketId, state);\n\t\t\treturn ticks;\n\t\t}\n\t\tconst tick = await referenceTick(this.#client, this.#config, marketId);\n\t\tif (tick == null) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`reference price not set yet for ${m.underlying} @ ${m.expiryMs} — retry shortly or pass a numeric strike`,\n\t\t\t);\n\t\t}\n\t\treturn m.side === 'up'\n\t\t\t? { lowerTick: tick, higherTick: POS_INF_TICK }\n\t\t\t: { lowerTick: 0n, higherTick: tick };\n\t}\n\n\t// Raw payout quantity must land on a lot boundary — the chain rejects otherwise.\n\t#assertLot(quantityRaw: bigint): void {\n\t\t// From the config in play, not the exported testnet constant — a deployment with a\n\t\t// different `position_lot_size` must not be validated against testnet's.\n\t\tconst lot = BigInt(this.cfg.units.positionLotSize);\n\t\tif (quantityRaw % lot !== 0n) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`quantity ${quantityRaw} raw is not a whole ${lot}-unit lot (position_lot_size)`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Shared construction for tx.mint and read.quoteMint. The quote dry-runs the\n\t// same mint the trade sends; quoteMint omits the caller's cost/probability caps\n\t// (they only gate via abort and don't change the receipt numbers).\n\tasync #buildMint(owner: string, m: MarketDescriptor, opts: MintOptions): Promise<Transaction> {\n\t\tconst feeds = this.#feeds(m.underlying);\n\t\tconst { id, state } = await this.#resolveMarket(m);\n\t\tconst quantityRaw = usdcToRaw(opts.quantity);\n\t\tthis.#assertLot(quantityRaw);\n\t\tconst { lowerTick, higherTick } = await this.#strikeTicks(m, id, state);\n\t\treturn txOf(\n\t\t\tmintExactQuantity(this.#config, {\n\t\t\t\texpiryMarketId: id,\n\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\tlowerTick,\n\t\t\t\thigherTick,\n\t\t\t\tquantityRaw,\n\t\t\t\tmaxCostRaw: opts.maxCost != null ? usdcToRaw(opts.maxCost) : undefined,\n\t\t\t\tmaxProbabilityRaw:\n\t\t\t\t\topts.maxProbability != null ? probabilityToRaw(opts.maxProbability) : undefined,\n\t\t\t\t...feeds,\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Shared construction for tx.redeem and read.quoteRedeem.\n\tasync #buildRedeem(owner: string, m: MarketDescriptor, opts: CloseOptions): Promise<Transaction> {\n\t\tconst feeds = this.#feeds(m.underlying);\n\t\tconst { id } = await this.#resolveMarket(m);\n\t\tconst closeQuantityRaw = usdcToRaw(opts.quantity);\n\t\tthis.#assertLot(closeQuantityRaw);\n\t\treturn txOf(\n\t\t\tredeemLive(this.#config, {\n\t\t\t\texpiryMarketId: id,\n\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\torderId: opts.orderId,\n\t\t\t\tcloseQuantityRaw,\n\t\t\t\t...feeds,\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Raw strike for anonymous pricing: numeric strikes validate against the tick\n\t// grid; \"reference\" reads the market's reference tick fresh (unset → typed error).\n\tasync #strikeRawFor(\n\t\tm: BinaryMarketCoordinates,\n\t\tmarketId: string,\n\t\tstate: MarketState,\n\t): Promise<bigint> {\n\t\tif (m.strike !== 'reference') {\n\t\t\t// Same validation as the mint path: on the grid AND inside the finite tick\n\t\t\t// domain (0 / POS_INF are the ±inf sentinels, not quotable strikes).\n\t\t\treturn this.#gridTick(m.strike, state.tickSizeRaw) * state.tickSizeRaw;\n\t\t}\n\t\tconst tick = await referenceTick(this.#client, this.#config, marketId);\n\t\tif (tick == null) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`reference price not set yet for ${m.underlying} @ ${m.expiryMs} — retry shortly or pass a numeric strike`,\n\t\t\t);\n\t\t}\n\t\treturn tick * state.tickSizeRaw;\n\t}\n\n\t// === tx builders ===\n\t// Each returns a ready-to-sign Transaction. Market-resolving builders are async.\n\treadonly tx = {\n\t\tcreateManager: (): Transaction => txOf(accountContract(this.cfg).createAccount()),\n\n\t\t// `create: true` composes first-time funding into ONE PTB: create the account\n\t\t// wrapper, deposit into it through the fresh handle, and `share` it LAST (once\n\t\t// shared, by-value use of the handle is over). The wrapper is derived from the\n\t\t// transaction SENDER (`account_registry::new` takes no owner), so `owner` MUST\n\t\t// be the address that signs this transaction — a sponsored/backend signer would\n\t\t// silently fund its own fresh account instead. The caller also asserts the\n\t\t// account does not exist yet: `new` ABORTS at the deterministic address if it\n\t\t// already exists — no chain read is done here. Gate on your own existence check\n\t\t// (`wrapperIdFor(owner)` + a getObject), or retry without the flag on that abort.\n\t\t//\n\t\t// Without `create`, the sourced coin goes into the existing account's stored\n\t\t// balance via the PTB-callable `deposit_funds` (folds settle → authorize → load →\n\t\t// deposit; clock auto-injected). Command order is auth → deposit (auth is a hot\n\t\t// potato consumed by the deposit). See\n\t\t// `packages/account/sources/account.move` (`deposit_funds`).\n\t\tdeposit: (\n\t\t\towner: string,\n\t\t\tamountUsdc: number | string,\n\t\t\topts?: { create?: boolean },\n\t\t): Transaction => {\n\t\t\tconst tx = new Transaction();\n\t\t\tconst coin = tx.add(\n\t\t\t\tcoinWithBalance({\n\t\t\t\t\ttype: this.cfg.quoteCoinType,\n\t\t\t\t\tbalance: usdcToRaw(amountUsdc),\n\t\t\t\t\tuseGasCoin: false,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (opts?.create) {\n\t\t\t\ttx.add(\n\t\t\t\t\taccountContract(this.cfg).createAccountAndDeposit({\n\t\t\t\t\t\tcoin,\n\t\t\t\t\t\tcoinType: this.cfg.quoteCoinType,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\ttx.add(\n\t\t\t\t\tdepositFunds({\n\t\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), coin },\n\t\t\t\t\t\ttypeArguments: [this.cfg.quoteCoinType],\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn tx;\n\t\t},\n\n\t\t// Withdraw `amountUsdc` from the account back to `owner`. By default the funds land\n\t\t// in the owner's DUSDC *address balance* (the versionless accumulator) via\n\t\t// `0x2::coin::send_funds` — no coin-object churn, and they merge into the same\n\t\t// balance `deposit` draws from, closing the loop. Pass `{ toCoinObject: true }` to\n\t\t// instead receive a discrete `Coin<T>` object (for wallets/explorers that only\n\t\t// render coin objects, or to compose the coin further in your own PTB). Either way\n\t\t// the underlying `withdraw_funds` returns the raw `Coin<T>` — the PTB-callable form\n\t\t// that folds settle → authorize → load → withdraw (clock auto-injected, `ctx`\n\t\t// implicit); command order is auth → withdraw. See\n\t\t// `packages/account/sources/account.move` (`withdraw_funds`).\n\t\twithdraw: (\n\t\t\towner: string,\n\t\t\tamountUsdc: number | string,\n\t\t\topts?: { toCoinObject?: boolean },\n\t\t): Transaction => {\n\t\t\tconst tx = new Transaction();\n\t\t\tconst coin = tx.add(\n\t\t\t\twithdrawFunds({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), amount: usdcToRaw(amountUsdc) },\n\t\t\t\t\ttypeArguments: [this.cfg.quoteCoinType],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (opts?.toCoinObject) {\n\t\t\t\ttx.transferObjects([coin], owner);\n\t\t\t} else {\n\t\t\t\ttx.moveCall({\n\t\t\t\t\ttarget: '0x2::coin::send_funds',\n\t\t\t\t\ttypeArguments: [this.cfg.quoteCoinType],\n\t\t\t\t\targuments: [coin, tx.pure.address(owner)],\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn tx;\n\t\t},\n\n\t\tmint: (owner: string, m: MarketDescriptor, opts: MintOptions): Promise<Transaction> =>\n\t\t\tthis.#buildMint(owner, m, opts),\n\n\t\tmintAmount: async (\n\t\t\towner: string,\n\t\t\tm: MarketDescriptor,\n\t\t\topts: MintAmountOptions,\n\t\t): Promise<Transaction> => {\n\t\t\tconst feeds = this.#feeds(m.underlying);\n\t\t\t// The chain requires a positive all-in cost cap (EMintCostCapRequired);\n\t\t\t// reject a zero cap pre-flight rather than surface a cryptic Move abort.\n\t\t\tif (opts.maxCost != null && opts.maxCost <= 0) {\n\t\t\t\tthrow new PredictInputError('maxCost must be > 0');\n\t\t\t}\n\t\t\tconst { id, state } = await this.#resolveMarket(m);\n\t\t\t// No lot check: min_quantity is a floor the chain compares against an\n\t\t\t// already-lot-floored minted quantity, so any floor value is legal.\n\t\t\tconst minQuantityRaw = usdcToRaw(opts.minQuantity);\n\t\t\tconst { lowerTick, higherTick } = await this.#strikeTicks(m, id, state);\n\t\t\treturn txOf(\n\t\t\t\tmintExactAmount(this.#config, {\n\t\t\t\t\texpiryMarketId: id,\n\t\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\t\tlowerTick,\n\t\t\t\t\thigherTick,\n\t\t\t\t\tmaxPremiumRaw: usdcToRaw(opts.spend),\n\t\t\t\t\tminQuantityRaw,\n\t\t\t\t\tmaxCostRaw: opts.maxCost != null ? usdcToRaw(opts.maxCost) : undefined,\n\t\t\t\t\t...feeds,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\n\t\tredeem: (owner: string, m: MarketDescriptor, opts: CloseOptions): Promise<Transaction> =>\n\t\t\tthis.#buildRedeem(owner, m, opts),\n\n\t\tclaimSettled: async (\n\t\t\towner: string,\n\t\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs' | 'marketId'>,\n\t\t\topts: Pick<CloseOptions, 'orderId'>,\n\t\t): Promise<Transaction> => {\n\t\t\tconst { id } = await this.#resolveMarket(m);\n\t\t\treturn txOf(\n\t\t\t\tredeemSettled(this.#config, {\n\t\t\t\t\texpiryMarketId: id,\n\t\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\t\torderId: opts.orderId,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\n\t\t// Queue a supply request pulling `amountUsdc` from the account's existing custody\n\t\t// balance. `request_supply` auto-settles DUSDC then `account.withdraw`s the payment\n\t\t// into queue escrow; the PLP fill is delivered at the next flush, not returned here.\n\t\t// Command order is auth → request (auth is a hot potato consumed by this call). The\n\t\t// `minPlpOut` slot is the per-request floor on PLP minted at flush — pinned to 0\n\t\t// (no floor) here; after three flushes miss the floor the request is cancelled and\n\t\t// refunded.\n\t\tsupplyPlp: (owner: string, amountUsdc: number | string): Transaction =>\n\t\t\ttxOf(\n\t\t\t\trequestSupply({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: {\n\t\t\t\t\t\twrapper: this.wrapperIdFor(owner),\n\t\t\t\t\t\tamount: usdcToRaw(amountUsdc),\n\t\t\t\t\t\tminPlpOut: 0n,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Queue a withdraw request pulling `shares` (raw PLP u64) from account custody into\n\t\t// queue escrow — the Move parameter is named `amount`, but on `request_withdraw` it\n\t\t// counts PLP SHARES, not DUSDC. Auto-settles flush-delivered PLP first; the DUSDC\n\t\t// fill lands on the account at the next flush (no `withdraw_settled` entrypoint).\n\t\t// Command order is auth → request. The `minDusdcOut` slot is the per-request floor\n\t\t// on DUSDC paid at flush — pinned to 0 (no floor) here; after three flushes miss the\n\t\t// floor the request is cancelled and refunded.\n\t\twithdrawPlp: (owner: string, shares: bigint): Transaction =>\n\t\t\ttxOf(\n\t\t\t\trequestWithdraw({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: {\n\t\t\t\t\t\twrapper: this.wrapperIdFor(owner),\n\t\t\t\t\t\tamount: shares,\n\t\t\t\t\t\tminDusdcOut: 0n,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Cancel a still-pending supply request by queue `index`, refunding its escrowed\n\t\t// DUSDC straight back into the requesting account. Command order is auth → cancel.\n\t\tcancelSupplyPlp: (owner: string, index: bigint): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tcancelSupplyRequest({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), index },\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Cancel a still-pending withdraw request by queue `index`, refunding its escrowed\n\t\t// PLP straight back into the requesting account. Command order is auth → cancel.\n\t\tcancelWithdrawPlp: (owner: string, index: bigint): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tcancelWithdrawRequest({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), index },\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Set the account's sticky builder-code attribution to `builderCodeId`, an existing\n\t\t// `BuilderCode` object borrowed as `&BuilderCode`. Command order is auth → set (auth\n\t\t// is a hot potato consumed by this call). Lives in the PREDICT package's\n\t\t// `predict_account` module, NOT the account package. Deployed sig\n\t\t// `packages/predict/sources/predict_account.move:134` — 3 moveCall args\n\t\t// (wrapper, auth, code; ctx implicit).\n\t\tsetBuilderCode: (owner: string, builderCodeId: string): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tsetBuilderCode({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), code: builderCodeId },\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Clear the account's sticky builder-code attribution. Command order is auth → unset.\n\t\t// Deployed sig `.../predict_account.move:151` — 2 moveCall args (wrapper, auth; ctx\n\t\t// implicit).\n\t\tunsetBuilderCode: (owner: string): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tunsetBuilderCode({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner) },\n\t\t\t\t}),\n\t\t\t),\n\t};\n\n\t// === reads ===\n\treadonly read = {\n\t\t// All tradeable (active) markets with the state a frontend needs to render\n\t\t// and mint: one chain read for ids + one batched PTB for the states.\n\t\tmarkets: async (): Promise<ActiveMarket[]> => {\n\t\t\tconst ids = await activeMarketIds(this.#client, this.#config);\n\t\t\tconst states = await marketStates(this.#client, this.#config, ids);\n\t\t\treturn ids.map((id, i) => ({\n\t\t\t\tid,\n\t\t\t\texpiryMs: states[i].expiryMs,\n\t\t\t\ttickSize: fromRaw(states[i].tickSizeRaw, 9),\n\t\t\t\tadmissionTickSize: fromRaw(states[i].admissionTickSizeRaw, 9),\n\t\t\t\tmintPaused: states[i].mintPaused,\n\t\t\t\treferencePrice: PredictClient.#referencePriceOf(states[i]),\n\t\t\t}));\n\t\t},\n\n\t\t// Validate an app-stored order id against the chain (stale after full\n\t\t// close or partial-close replacement — see RedeemReceipt.replacementOrderId).\n\t\thasPosition: (owner: string, marketId: string, orderId: bigint): Promise<boolean> =>\n\t\t\thasPosition(this.#client, this.#config, owner, marketId, orderId),\n\n\t\t// All open positions for an owner, enumerated from the chain (the\n\t\t// account's positions Table): 1 call per page warm, +2 resolution calls\n\t\t// once per owner. Returns [] for owners with no Predict account.\n\t\tpositions: async (owner: string): Promise<OpenPosition[]> => {\n\t\t\tlet handle = this.#positionsCache.get(owner);\n\t\t\tif (!handle?.positionsTableId) {\n\t\t\t\tconst resolved = await resolvePositionsTable(this.#client, this.#config, owner);\n\t\t\t\tif (!resolved) return []; // never onboarded — do not cache\n\t\t\t\tif (resolved.positionsTableId) this.#positionsCache.set(owner, resolved);\n\t\t\t\thandle = resolved;\n\t\t\t}\n\t\t\tif (!handle.positionsTableId) return [];\n\t\t\treturn positionsFromTable(this.#client, handle.positionsTableId);\n\t\t},\n\n\t\t// Anonymous board pricing: the chain's probability for both sides of a\n\t\t// strike, from one fresh pricer (no account needed). This is the ↑/↓\n\t\t// button price before a user has onboarded.\n\t\tprice: async (m: BinaryMarketCoordinates): Promise<{ up: number; down: number }> => {\n\t\t\tconst feeds = this.#feeds(m.underlying);\n\t\t\tconst { id, state } = await this.#resolveMarket(m);\n\t\t\tconst strikeRaw = await this.#strikeRawFor(m, id, state);\n\t\t\tconst { upRaw, downRaw } = await rangePrices(\n\t\t\t\tthis.#client,\n\t\t\t\tthis.#config,\n\t\t\t\tid,\n\t\t\t\tfeeds,\n\t\t\t\tstrikeRaw,\n\t\t\t\tstate.tickSizeRaw,\n\t\t\t);\n\t\t\treturn { up: rawToProbability(upRaw), down: rawToProbability(downRaw) };\n\t\t},\n\n\t\t// A client-side board pricer for one market: ONE simulate reads the chain's\n\t\t// resolved pricer (already forward-selected + rolled to now), then prices every\n\t\t// strike LOCALLY with no further chain calls — `pricer.up(strike)`,\n\t\t// `.down(strike)`, `.range(lo,hi)`, `.strikeAtProbability(p)`. Use this to paint a\n\t\t// whole board instantly; `read.price` / `read.quoteMint` stay the authoritative\n\t\t// per-strike quote at trade time. Throws the same typed stale-oracle/expired\n\t\t// PredictMoveError `read.price` would when the chain itself cannot quote.\n\t\tpricer: async (\n\t\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs'>,\n\t\t): Promise<BoardPricer & { asOf: PricerSnapshot['sources'] }> => {\n\t\t\tconst feeds = this.#feeds(m.underlying);\n\t\t\tconst { id } = await this.#resolveMarket(m);\n\t\t\tconst snap = await readPricerSnapshot(this.#client, this.#config, id, feeds);\n\t\t\treturn { ...boardPricer(snap), asOf: snap.sources };\n\t\t},\n\n\t\t// Exact pre-trade quote: dry-runs the caller's own mint (same tx as\n\t\t// tx.mint) and decodes the receipt. Requires a funded account; throws\n\t\t// the same typed errors the real trade would — quote doubles as preflight.\n\t\tquoteMint: async (\n\t\t\towner: string,\n\t\t\tm: MarketDescriptor,\n\t\t\topts: Pick<MintOptions, 'quantity'>,\n\t\t): Promise<MintQuote> => {\n\t\t\tconst tx = await this.#buildMint(owner, m, opts);\n\t\t\tconst events = await simulateWithEvents(this.#client, tx, owner);\n\t\t\tconst r = exactlyOne(decodeMints(this.cfg, { events }), 'OrderMinted');\n\t\t\t// Mirrors the deployed `compute_mint_quote`'s all_in_cost exactly:\n\t\t\t// premium + (trading − subsidy) + builder + penalty + inventory-impact.\n\t\t\t// `referral_fee` is deliberately NOT added — it is a portion OF the\n\t\t\t// trader-paid trading fee and congestion surcharge, not an extra debit.\n\t\t\tconst costRaw =\n\t\t\t\tr.raw.premium +\n\t\t\t\t(r.raw.tradingFee - r.raw.feeIncentiveSubsidy) +\n\t\t\t\tr.raw.builderFee +\n\t\t\t\tr.raw.penaltyFee +\n\t\t\t\tr.raw.inventoryImpactCharge;\n\t\t\treturn {\n\t\t\t\tentryProbability: r.entryProbability,\n\t\t\t\tpremium: r.premium,\n\t\t\t\tfees: r.fees,\n\t\t\t\tcost: rawToUsdc(costRaw),\n\t\t\t\tquantity: r.quantity,\n\t\t\t\traw: {\n\t\t\t\t\tpremium: r.raw.premium,\n\t\t\t\t\tcost: costRaw,\n\t\t\t\t\tquantity: r.raw.quantity,\n\t\t\t\t\tentryProbability: r.raw.entryProbability,\n\t\t\t\t},\n\t\t\t\tfeesExact: true,\n\t\t\t};\n\t\t},\n\n\t\t// Exact pre-close quote: dry-runs the caller's own redeem and decodes\n\t\t// the receipt — the informed close against the floor-less deployed redeem.\n\t\tquoteRedeem: async (\n\t\t\towner: string,\n\t\t\tm: MarketDescriptor,\n\t\t\topts: CloseOptions,\n\t\t): Promise<RedeemQuote> => {\n\t\t\tconst tx = await this.#buildRedeem(owner, m, opts);\n\t\t\tconst events = await simulateWithEvents(this.#client, tx, owner);\n\t\t\tconst r = exactlyOne(decodeRedeems(this.cfg, { events }), 'order-redeemed');\n\t\t\treturn {\n\t\t\t\tproceeds: r.proceeds,\n\t\t\t\tgross: r.gross,\n\t\t\t\tfees: r.fees,\n\t\t\t\tquantityClosed: r.quantityClosed,\n\t\t\t\tremaining: r.remaining,\n\t\t\t\traw: {\n\t\t\t\t\tproceeds: r.raw.proceeds,\n\t\t\t\t\tgross: r.raw.gross,\n\t\t\t\t\tquantityClosed: r.raw.quantityClosed,\n\t\t\t\t},\n\t\t\t\tfeesExact: true,\n\t\t\t};\n\t\t},\n\n\t\tmarket: async (\n\t\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs'>,\n\t\t): Promise<MarketSummary | null> => {\n\t\t\tconst expiryMs = BigInt(m.expiryMs);\n\t\t\t// Deliberately re-queries and overwrites the cache instead of reading\n\t\t\t// through it: this read must return live state (nav, mintPaused), and\n\t\t\t// refreshing the cache on the way keeps later tx builds consistent.\n\t\t\tconst u = this.#underlying(m.underlying);\n\t\t\tconst id = await expiryMarketId(this.#client, this.#config, u, expiryMs);\n\t\t\tif (!id) return null;\n\t\t\tconst state = await marketState(this.#client, this.#config, id);\n\t\t\tthis.#marketCache.set(`${m.underlying}:${expiryMs}`, { id, state });\n\t\t\tconst navRaw = await currentNav(this.#client, this.#config, id, u);\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\texpiryMs: state.expiryMs,\n\t\t\t\ttickSize: fromRaw(state.tickSizeRaw, 9), // strike/price scale\n\t\t\t\tadmissionTickSize: fromRaw(state.admissionTickSizeRaw, 9),\n\t\t\t\tmintPaused: state.mintPaused,\n\t\t\t\tnav: rawToUsdc(navRaw),\n\t\t\t\treferencePrice: PredictClient.#referencePriceOf(state),\n\t\t\t};\n\t\t},\n\n\t\tbalance: async (owner: string): Promise<number> =>\n\t\t\trawToUsdc(await accountBalance(this.#client, this.#config, owner, this.cfg.quoteCoinType)),\n\n\t\t// PLP shares held in the owner's account custody (raw u64, 6-decimal PLP coin).\n\t\tplpBalance: (owner: string): Promise<bigint> =>\n\t\t\taccountBalance(this.#client, this.#config, owner, this.cfg.coinTypes.plp),\n\n\t\tpool: async (): Promise<PoolSummary> => {\n\t\t\tconst s = await poolStats(this.#client, this.#config);\n\t\t\treturn {\n\t\t\t\tplpTotalSupply: s.plpTotalSupply, // shares raw (6-decimal)\n\t\t\t\tidleUsdc: rawToUsdc(s.idleBalance),\n\t\t\t\t// These are queue LENGTHS (counts of pending requests), not token amounts.\n\t\t\t\tsupplyRequestsPending: Number(s.supplyRequestsPending),\n\t\t\t\twithdrawRequestsPending: Number(s.withdrawRequestsPending),\n\t\t\t};\n\t\t},\n\t};\n\n\t// === execution-result decoders ===\n\t// Pure event parsing (no network): pass the executed/simulated transaction\n\t// result (with events included) and get a typed receipt back. Singular forms\n\t// throw unless exactly one matching event exists; plural forms return all\n\t// (an integrator batching N actions in one PTB gets N receipts).\n\treadonly decode = {\n\t\tmint: (r: DecodableTransactionResult) => exactlyOne(decodeMints(this.cfg, r), 'OrderMinted'),\n\t\tmints: (r: DecodableTransactionResult) => decodeMints(this.cfg, r),\n\t\tredeem: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeRedeems(this.cfg, r), 'order-redeemed'),\n\t\tredeems: (r: DecodableTransactionResult) => decodeRedeems(this.cfg, r),\n\t\tclaim: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeClaims(this.cfg, r), 'SettledOrderRedeemed'),\n\t\tclaims: (r: DecodableTransactionResult) => decodeClaims(this.cfg, r),\n\t\tcreateManager: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeAccountsCreated(this.cfg, r), 'AccountCreated'),\n\t\tdeposit: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeDeposits(this.cfg, r), 'Deposited'),\n\t\twithdraw: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeWithdrawals(this.cfg, r), 'Withdrawn'),\n\t\tplpRequest: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodePlpRequests(this.cfg, r), 'supply/withdraw-requested'),\n\t\tplpCancel: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodePlpCancels(this.cfg, r), 'RequestCancelled'),\n\t\tbuilderCode: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeBuilderCodeSets(this.cfg, r), 'BuilderCodeSet'),\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.mjs","names":["#config","opts","#buildMint","#feeds","#resolveMarket","#strikeTicks","#buildRedeem","#client","#referencePriceOf","#positionsCache","#strikeRawFor","#underlying","#marketCache","resolved","#assertAdmittedTick","#gridTick","#assertLot"],"sources":["../../src/predict/client.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport type { ClientWithCoreApi, SuiClientRegistration } from '@mysten/sui/client';\nimport { Transaction, coinWithBalance, type TransactionResult } from '@mysten/sui/transactions';\nimport { isValidSuiObjectId } from '@mysten/sui/utils';\nimport { TESTNET_PREDICT } from '../deployments/testnet.js';\nimport { getConfig, type PredictConfig, type UnderlyingConfig } from './config/index.js';\nimport { toGeneratedConfig, type GeneratedConfig } from './config/generated.js';\nimport {\n\tdecodeAccountsCreated,\n\tdecodeBuilderCodeSets,\n\tdecodeClaims,\n\tdecodeDeposits,\n\tdecodeMints,\n\tdecodePlpCancels,\n\tdecodePlpRequests,\n\tdecodeRedeems,\n\tdecodeWithdrawals,\n\texactlyOne,\n\ttype DecodableTransactionResult,\n} from './decode.js';\nimport { PredictInputError } from './errors.js';\nimport { simulateWithEvents } from './reads/inspect.js';\nimport {\n\tpositionsFromTable,\n\tresolvePositionsTable,\n\ttype OpenPosition,\n\ttype PositionsHandle,\n} from './reads/positions.js';\nimport { accountBalance, hasPosition } from './reads/balances.js';\nimport {\n\tactiveMarketIds,\n\tcurrentNav,\n\texpiryMarketId,\n\tmarketState,\n\tmarketStates,\n\trangePrices,\n\treferenceTick,\n\ttype MarketState,\n} from './reads/markets.js';\nimport { poolStats } from './reads/pool.js';\nimport { readPricerSnapshot, type PricerSnapshot } from './reads/pricing.js';\nimport { boardPricer, type BoardPricer } from './pricing.js';\nimport { POS_INF_TICK, binaryRangeTicks, type Side } from './ticks.js';\nimport {\n\tcancelSupplyRequest,\n\tcancelWithdrawRequest,\n\tdepositFunds,\n\trequestSupply,\n\trequestWithdraw,\n\tsetBuilderCode,\n\tunsetBuilderCode,\n\twithdrawFunds,\n} from './tx/authed.js';\n\nimport { accountContract, deriveAccountWrapperIdFrom } from './tx/common.js';\nimport type { MarketFeeds } from './tx/trade.js';\nimport { mintExactAmount, mintExactQuantity, redeemLive, redeemSettled } from './tx/trade.js';\nimport {\n\tpriceToRaw,\n\tprobabilityToRaw,\n\trawToProbability,\n\trawToUsdc,\n\tusdcToRaw,\n\tfromRaw,\n} from './units.js';\n\n// `position_lot_size` — a position quantity must be a whole multiple of this many\n// raw payout units ($0.01 lots). See packages/predict/sources/constants.move.\n/**\n * Testnet's `position_lot_size`, read from the deployment record. Validation uses the lot\n * size of the config actually in play; this is the convenience constant for testnet callers.\n */\nexport const POSITION_LOT_SIZE = BigInt(TESTNET_PREDICT.units.positionLotSize);\n\n// Most `tx.*` builders are one builder's worth of commands in a fresh PTB.\nfunction txOf(command: (tx: Transaction) => TransactionResult | void): Transaction {\n\tconst tx = new Transaction();\n\ttx.add(command);\n\treturn tx;\n}\n\n/** A live/settled market addressed by its human coordinates: a binary position\n * (single strike + side) or a two-strike range position. */\nexport type MarketDescriptor = {\n\tunderlying: string;\n\texpiryMs: number | bigint;\n\t/**\n\t * Pin resolution to this exact `ExpiryMarket` object, skipping the\n\t * underlying+expiry lookup — a caller that reviewed a specific market object\n\t * mints against exactly that object, not whatever resolves at submit time.\n\t */\n\tmarketId?: string;\n} & (\n\t| {\n\t\t\tside: Side;\n\t\t\t/**\n\t\t\t * Strike in USD, or \"reference\" to trade at the market's on-chain reference\n\t\t\t * price (the Polymarket-style anchor: derived from the exact previous-window\n\t\t\t * oracle observation, so consecutive windows chain settlement → next strike).\n\t\t\t */\n\t\t\tstrike: number | 'reference';\n\t }\n\t| {\n\t\t\t/** A range position: pays out when settlement lands inside `(lower, upper]`\n\t\t\t * (left-open, right-closed — same convention as the on-chain range key). */\n\t\t\tside: 'range';\n\t\t\t/** Lower strike bound in USD — finite, on the tick grid. */\n\t\t\tlower: number;\n\t\t\t/** Upper strike bound in USD — finite, on the tick grid, above `lower`. */\n\t\t\tupper: number;\n\t }\n);\n\n/** Options for the friendly `mint` (exact payout quantity). */\nexport interface MintOptions {\n\tquantity: number;\n\tmaxCost?: number;\n\tmaxProbability?: number;\n}\n\n/** Options for `mintAmount` (spend up to a premium budget, floor the quantity received). */\nexport interface MintAmountOptions {\n\t/** Premium budget in quote units — the max premium paid (chain also caps it at the account balance). */\n\tspend: number;\n\tminQuantity: number;\n\t/** All-in cost ceiling in quote units (premium + fees). Omitted → uncapped. */\n\tmaxCost?: number;\n}\n\n/** Options for `redeem`: which order and how much to close. `claimSettled` takes only\n * `orderId` — a settled claim closes the order in full. */\nexport interface CloseOptions {\n\torderId: bigint;\n\tquantity: number;\n}\n\n/** Options for `supplyPlp`. */\nexport interface PlpSupplyOptions {\n\t/**\n\t * Floor on the PLP minted for the whole request, as raw `bigint` shares — PLP is raw\n\t * everywhere in this SDK. It is a floor on the MARK, not a share count: a flush quoting\n\t * less does not fill smaller, it declines. Omitted → `0n`, no floor.\n\t *\n\t * How a miss is handled is the deployment's `lp_request_limit_flush_attempts`: at the\n\t * shipped count of one the first flush below the floor cancels and refunds the request.\n\t */\n\tminPlpOut?: bigint;\n}\n\n/** Options for `withdrawPlp`. */\nexport interface PlpWithdrawOptions {\n\t/**\n\t * Floor on the USDC paid for the whole request, in USD decimals like every other amount\n\t * here. A floor on the MARK, not an amount: a flush quoting less declines rather than\n\t * paying out smaller. Omitted → no floor. Measured after the protocol's withdraw fee.\n\t */\n\tminUsdcOut?: number | string;\n}\n\n/** One tradeable market as returned by read.markets(). */\nexport interface ActiveMarket {\n\tid: string;\n\texpiryMs: bigint;\n\t/** Strike granularity in USD (e.g. 0.01). */\n\ttickSize: number;\n\t/**\n\t * Coarser step new mint strikes must align to. A numeric strike must be a whole\n\t * multiple of this (the market's `referencePrice` is the one exception the chain\n\t * admits off-grid); otherwise the mint aborts `EInvalidAdmissionTick`.\n\t */\n\tadmissionTickSize: number;\n\tmintPaused: boolean;\n\t/** The window's anchor strike in USD, or null until the keeper seeds it. */\n\treferencePrice: number | null;\n}\n\n/** A resolved live market: its on-chain state summary for the caller. */\nexport interface MarketSummary {\n\tid: string;\n\texpiryMs: bigint;\n\ttickSize: number;\n\t/**\n\t * Coarser step new mint strikes must align to. A numeric strike must be a whole\n\t * multiple of this (the market's `referencePrice` is the one exception the chain\n\t * admits off-grid); otherwise the mint aborts `EInvalidAdmissionTick`.\n\t */\n\tadmissionTickSize: number;\n\tmintPaused: boolean;\n\tnav: number;\n\t/** The window's anchor strike in USD, or null until the keeper seeds it. */\n\treferencePrice: number | null;\n}\n\n/** Aggregate pool figures. Balances in human units (shares raw); the pending fields\n * are request COUNTS, not amounts — the on-chain getters expose queue lengths, and\n * the escrowed USDC/PLP behind them is tracked separately. */\nexport interface PoolSummary {\n\tplpTotalSupply: bigint;\n\tidleUsdc: number;\n\t/** Number of LP supply requests queued for the next flush. */\n\tsupplyRequestsPending: number;\n\t/** Number of LP withdraw requests queued for the next flush. */\n\twithdrawRequestsPending: number;\n}\n\n/** Exact pre-trade quote: the dry-run receipt of the mint you are about to send. */\nexport interface MintQuote {\n\t/** Fill price, 0..1 per $1 payout. */\n\tentryProbability: number;\n\t/** Premium paid into LP backing (quote units). */\n\tpremium: number;\n\t/**\n\t * Fee breakdown. `referral` is a PORTION of the trader-paid trading fee and\n\t * congestion surcharge routed to the referrer — it is already inside those\n\t * numbers and is NOT an extra debit. `inventoryImpact` is a separate charge and\n\t * IS part of `cost`.\n\t */\n\tfees: {\n\t\ttrading: number;\n\t\tsubsidy: number;\n\t\tbuilder: number;\n\t\tpenalty: number;\n\t\treferral: number;\n\t\tinventoryImpact: number;\n\t};\n\t/**\n\t * All-in account debit: premium + (trading − subsidy) + builder + penalty +\n\t * inventoryImpact — exactly what the chain withdraws (the deployed\n\t * `compute_mint_quote`'s `all_in_cost`); pass this (plus your buffer) as maxCost.\n\t */\n\tcost: number;\n\tquantity: number;\n\traw: { premium: bigint; cost: bigint; quantity: bigint; entryProbability: bigint };\n\t/** True: computed by the real mint code path against real account state. */\n\tfeesExact: true;\n}\n\n/** Exact pre-close quote: the dry-run receipt of the redeem you are about to send. */\nexport interface RedeemQuote {\n\t/** NET quote credited to the account. */\n\tproceeds: number;\n\t/** Gross close value before fees. */\n\tgross: number;\n\t/** `inventoryImpactRebate` is credited back on the close, so `proceeds` is\n\t * gross + rebate − trading − builder − penalty. */\n\tfees: { trading: number; builder: number; penalty: number; inventoryImpactRebate: number };\n\tquantityClosed: number;\n\tremaining: number;\n\traw: { proceeds: bigint; gross: bigint; quantityClosed: bigint };\n\tfeesExact: true;\n}\n\ninterface ResolvedMarket {\n\tid: string;\n\tstate: MarketState;\n}\n\n// The strike-bearing (binary) arm of MarketDescriptor, for read.price and its\n// seam — anonymous board pricing has no range semantics.\ntype BinaryMarketCoordinates = Pick<MarketDescriptor, 'underlying' | 'expiryMs' | 'marketId'> & {\n\tstrike: number | 'reference';\n};\n\n/** The Sui client surface PredictClient reads through: any `ClientWithCoreApi`\n * (gRPC or JSON-RPC) provides both the `simulateTransaction` the reads/quotes\n * sit on and the `core` object methods position enumeration needs. */\nexport interface PredictCompatibleClient extends ClientWithCoreApi {}\n\n/**\n * Register PredictClient as a `client.predict` extension, mirroring\n * `@mysten/deepbook-v3`'s `deepbook(...)`: `client.$extend(predict({ network }))`.\n */\nexport function predict<Name extends string = 'predict'>({\n\tname = 'predict' as Name,\n\tnetwork,\n\tconfig,\n}: {\n\tname?: Name;\n\tnetwork: 'testnet' | 'mainnet';\n\tconfig?: PredictConfig;\n}): SuiClientRegistration<PredictCompatibleClient, Name, PredictClient> {\n\treturn {\n\t\tname,\n\t\tregister: (client) => new PredictClient({ client, network, config }),\n\t};\n}\n\n/**\n * The one object an app constructs. Wraps the config, a client for reads, and\n * a derived-account model so callers pass owner addresses, decimal amounts, and\n * human market coordinates — the facade converts to raw units, resolves markets\n * (cached), and delegates to the internal tx primitives / reads. Callers who need\n * to compose their own PTBs can use the generated bindings under `contracts/`.\n */\nexport class PredictClient {\n\treadonly cfg: PredictConfig;\n\t// The flat slice every generated call resolves `options.config` against.\n\tget #config(): GeneratedConfig {\n\t\treturn toGeneratedConfig(this.cfg);\n\t}\n\t#client: PredictCompatibleClient;\n\t// underlying:expiryMs → resolved market. The id and tickSizeRaw — the only\n\t// state tx building depends on — are immutable per (underlying, expiry), so\n\t// one resolution per market per client suffices. (mintPaused IS mutable; the\n\t// cached copy is never consulted for a tx decision — the chain enforces it.)\n\t#marketCache = new Map<string, ResolvedMarket>();\n\t// owner → resolved position-store ids. accountUid and the table id are\n\t// immutable once created, so cache-forever; a missing table (no Predict\n\t// data yet) is NOT cached — it appears after the owner's first trade.\n\t#positionsCache = new Map<string, PositionsHandle>();\n\n\tconstructor(opts: {\n\t\tnetwork: 'testnet' | 'mainnet';\n\t\tclient: PredictCompatibleClient;\n\t\tconfig?: PredictConfig;\n\t}) {\n\t\tthis.cfg = opts.config ?? getConfig(opts.network);\n\t\tthis.#client = opts.client;\n\t}\n\n\t/** The deterministic id of an owner's canonical account wrapper — no chain read. */\n\twrapperIdFor(owner: string): string {\n\t\treturn deriveAccountWrapperIdFrom(this.#config, owner);\n\t}\n\n\t// The deployment's wiring for a symbol; throws a typed error on an unknown symbol.\n\t// Per-underlying ids are the one thing the flat config slice does not carry.\n\t#underlying(underlying: string): UnderlyingConfig {\n\t\tconst u = this.cfg.underlyings[underlying];\n\t\tif (!u) throw new PredictInputError(`unknown underlying: ${underlying}`);\n\t\treturn u;\n\t}\n\n\t// The oracle feed ids for a symbol; throws a typed error on an unknown symbol.\n\t#feeds(underlying: string): MarketFeeds {\n\t\tconst u = this.#underlying(underlying);\n\t\treturn {\n\t\t\tpythFeed: u.pythFeed,\n\t\t\tblockScholesValueStore: u.blockScholesValueStore,\n\t\t\tblockScholesSviStore: u.blockScholesSviStore,\n\t\t};\n\t}\n\n\t// Resolve (and cache) a market's id + state from its human coordinates. An\n\t// explicit `marketId` pin skips the underlying+expiry lookup but still reads\n\t// that market's state — tx building depends on tickSizeRaw.\n\tasync #resolveMarket(\n\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs' | 'marketId'>,\n\t): Promise<ResolvedMarket> {\n\t\tif (m.marketId != null) {\n\t\t\tif (!isValidSuiObjectId(m.marketId)) {\n\t\t\t\tthrow new PredictInputError(`invalid marketId: ${JSON.stringify(m.marketId)}`);\n\t\t\t}\n\t\t\tconst resolved: ResolvedMarket = this.#marketCache.get(m.marketId) ?? {\n\t\t\t\tid: m.marketId,\n\t\t\t\tstate: await marketState(this.#client, this.#config, m.marketId),\n\t\t\t};\n\t\t\t// The pin must agree with the descriptor's coordinates: catching a stale or\n\t\t\t// wrong-market id here beats minting against mismatched oracle feeds. (The\n\t\t\t// underlying cannot be cross-checked — market state does not carry it.)\n\t\t\tif (resolved.state.expiryMs !== BigInt(m.expiryMs)) {\n\t\t\t\tthrow new PredictInputError(\n\t\t\t\t\t`pinned market ${m.marketId} expires at ${resolved.state.expiryMs}, descriptor says ${BigInt(m.expiryMs)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.#marketCache.set(m.marketId, resolved);\n\t\t\treturn resolved;\n\t\t}\n\t\tconst expiryMs = BigInt(m.expiryMs);\n\t\tconst key = `${m.underlying}:${expiryMs}`;\n\t\tconst hit = this.#marketCache.get(key);\n\t\tif (hit) return hit;\n\t\tconst u = this.#underlying(m.underlying);\n\t\tconst id = await expiryMarketId(this.#client, this.#config, u, expiryMs);\n\t\tif (!id) throw new PredictInputError(`no market for ${m.underlying} at expiry ${expiryMs}`);\n\t\tconst state = await marketState(this.#client, this.#config, id);\n\t\tconst resolved: ResolvedMarket = { id, state };\n\t\tthis.#marketCache.set(key, resolved);\n\t\treturn resolved;\n\t}\n\n\t// Reference PRICE in USD from a state (tick index × tick size), or null.\n\tstatic #referencePriceOf(state: MarketState): number | null {\n\t\treturn state.referenceTickRaw == null\n\t\t\t? null\n\t\t\t: fromRaw(state.referenceTickRaw * state.tickSizeRaw, 9);\n\t}\n\n\t// A finite tick from a USD strike, validated exactly like binaryRangeTicks:\n\t// whole-tick multiple, inside the finite domain (1..POS_INF_TICK-1).\n\t#gridTick(strike: number, tickSizeRaw: bigint): bigint {\n\t\tconst raw = priceToRaw(strike);\n\t\tconst tick = raw / tickSizeRaw;\n\t\tif (tick * tickSizeRaw !== raw) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`strike ${strike} is not on the ${fromRaw(tickSizeRaw, 9)} tick grid`,\n\t\t\t);\n\t\t}\n\t\tif (tick <= 0n || tick >= POS_INF_TICK) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`strike tick ${tick} outside the finite tick domain (1..POS_INF_TICK-1)`,\n\t\t\t);\n\t\t}\n\t\treturn tick;\n\t}\n\n\t// New finite MINT boundaries must land on the market's coarser ADMISSION grid,\n\t// not merely the fine tick grid — the chain asserts exactly this\n\t// (`assert_admitted_mint_ticks`, `EInvalidAdmissionTick`). The ±inf sentinels are\n\t// exempt, and the market's reference tick is the one finite boundary allowed to\n\t// bypass the grid, so an off-grid tick is only rejected after confirming it is not\n\t// the reference (one extra read, and only on the failing path).\n\tasync #assertAdmittedTick(tick: bigint, marketId: string, state: MarketState): Promise<void> {\n\t\tif (tick === 0n || tick === POS_INF_TICK) return;\n\t\tconst multiple = state.admissionTickSizeRaw / state.tickSizeRaw;\n\t\tif (multiple > 0n && tick % multiple === 0n) return;\n\t\tconst reference = await referenceTick(this.#client, this.#config, marketId);\n\t\tif (reference != null && reference === tick) return;\n\t\tconst admission = fromRaw(state.admissionTickSizeRaw, 9);\n\t\tthrow new PredictInputError(\n\t\t\t`strike ${fromRaw(tick * state.tickSizeRaw, 9)} is not on the ${admission} admission grid ` +\n\t\t\t\t`(mint boundaries must be a multiple of ${admission}, or the market's reference strike)`,\n\t\t);\n\t}\n\n\t// Resolve a descriptor's strike(s) to the (lower, higher) tick pair. A binary\n\t// numeric strike converts and validates against the tick grid; \"reference\"\n\t// reads the market's reference tick FRESH (never cached — it is unset early in\n\t// a window) and uses it directly: it is on the tick grid by construction. A\n\t// range descriptor converts both bounds to finite grid ticks (\"reference\" is\n\t// binary-only: a range has no single reference strike).\n\tasync #strikeTicks(\n\t\tm: MarketDescriptor,\n\t\tmarketId: string,\n\t\tstate: MarketState,\n\t): Promise<{ lowerTick: bigint; higherTick: bigint }> {\n\t\tif (m.side === 'range') {\n\t\t\tif (!(m.lower < m.upper)) {\n\t\t\t\tthrow new PredictInputError(`range lower ${m.lower} must be below upper ${m.upper}`);\n\t\t\t}\n\t\t\tconst lowerTick = this.#gridTick(m.lower, state.tickSizeRaw);\n\t\t\tconst higherTick = this.#gridTick(m.upper, state.tickSizeRaw);\n\t\t\tawait this.#assertAdmittedTick(lowerTick, marketId, state);\n\t\t\tawait this.#assertAdmittedTick(higherTick, marketId, state);\n\t\t\treturn { lowerTick, higherTick };\n\t\t}\n\t\tif (m.strike !== 'reference') {\n\t\t\tconst ticks = binaryRangeTicks(priceToRaw(m.strike), m.side, state.tickSizeRaw);\n\t\t\tawait this.#assertAdmittedTick(ticks.lowerTick, marketId, state);\n\t\t\tawait this.#assertAdmittedTick(ticks.higherTick, marketId, state);\n\t\t\treturn ticks;\n\t\t}\n\t\tconst tick = await referenceTick(this.#client, this.#config, marketId);\n\t\tif (tick == null) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`reference price not set yet for ${m.underlying} @ ${m.expiryMs} — retry shortly or pass a numeric strike`,\n\t\t\t);\n\t\t}\n\t\treturn m.side === 'up'\n\t\t\t? { lowerTick: tick, higherTick: POS_INF_TICK }\n\t\t\t: { lowerTick: 0n, higherTick: tick };\n\t}\n\n\t// Raw payout quantity must land on a lot boundary — the chain rejects otherwise.\n\t#assertLot(quantityRaw: bigint): void {\n\t\t// From the config in play, not the exported testnet constant — a deployment with a\n\t\t// different `position_lot_size` must not be validated against testnet's.\n\t\tconst lot = BigInt(this.cfg.units.positionLotSize);\n\t\tif (quantityRaw % lot !== 0n) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`quantity ${quantityRaw} raw is not a whole ${lot}-unit lot (position_lot_size)`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Shared construction for tx.mint and read.quoteMint. The quote dry-runs the\n\t// same mint the trade sends; quoteMint omits the caller's cost/probability caps\n\t// (they only gate via abort and don't change the receipt numbers).\n\tasync #buildMint(owner: string, m: MarketDescriptor, opts: MintOptions): Promise<Transaction> {\n\t\tconst feeds = this.#feeds(m.underlying);\n\t\tconst { id, state } = await this.#resolveMarket(m);\n\t\tconst quantityRaw = usdcToRaw(opts.quantity);\n\t\tthis.#assertLot(quantityRaw);\n\t\tconst { lowerTick, higherTick } = await this.#strikeTicks(m, id, state);\n\t\treturn txOf(\n\t\t\tmintExactQuantity(this.#config, {\n\t\t\t\texpiryMarketId: id,\n\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\tlowerTick,\n\t\t\t\thigherTick,\n\t\t\t\tquantityRaw,\n\t\t\t\tmaxCostRaw: opts.maxCost != null ? usdcToRaw(opts.maxCost) : undefined,\n\t\t\t\tmaxProbabilityRaw:\n\t\t\t\t\topts.maxProbability != null ? probabilityToRaw(opts.maxProbability) : undefined,\n\t\t\t\t...feeds,\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Shared construction for tx.redeem and read.quoteRedeem.\n\tasync #buildRedeem(owner: string, m: MarketDescriptor, opts: CloseOptions): Promise<Transaction> {\n\t\tconst feeds = this.#feeds(m.underlying);\n\t\tconst { id } = await this.#resolveMarket(m);\n\t\tconst closeQuantityRaw = usdcToRaw(opts.quantity);\n\t\tthis.#assertLot(closeQuantityRaw);\n\t\treturn txOf(\n\t\t\tredeemLive(this.#config, {\n\t\t\t\texpiryMarketId: id,\n\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\torderId: opts.orderId,\n\t\t\t\tcloseQuantityRaw,\n\t\t\t\t...feeds,\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Raw strike for anonymous pricing: numeric strikes validate against the tick\n\t// grid; \"reference\" reads the market's reference tick fresh (unset → typed error).\n\tasync #strikeRawFor(\n\t\tm: BinaryMarketCoordinates,\n\t\tmarketId: string,\n\t\tstate: MarketState,\n\t): Promise<bigint> {\n\t\tif (m.strike !== 'reference') {\n\t\t\t// Same validation as the mint path: on the grid AND inside the finite tick\n\t\t\t// domain (0 / POS_INF are the ±inf sentinels, not quotable strikes).\n\t\t\treturn this.#gridTick(m.strike, state.tickSizeRaw) * state.tickSizeRaw;\n\t\t}\n\t\tconst tick = await referenceTick(this.#client, this.#config, marketId);\n\t\tif (tick == null) {\n\t\t\tthrow new PredictInputError(\n\t\t\t\t`reference price not set yet for ${m.underlying} @ ${m.expiryMs} — retry shortly or pass a numeric strike`,\n\t\t\t);\n\t\t}\n\t\treturn tick * state.tickSizeRaw;\n\t}\n\n\t// === tx builders ===\n\t// Each returns a ready-to-sign Transaction. Market-resolving builders are async.\n\treadonly tx = {\n\t\tcreateManager: (): Transaction => txOf(accountContract(this.cfg).createAccount()),\n\n\t\t// `create: true` composes first-time funding into ONE PTB: create the account\n\t\t// wrapper, deposit into it through the fresh handle, and `share` it LAST (once\n\t\t// shared, by-value use of the handle is over). The wrapper is derived from the\n\t\t// transaction SENDER (`account_registry::new` takes no owner), so `owner` MUST\n\t\t// be the address that signs this transaction — a sponsored/backend signer would\n\t\t// silently fund its own fresh account instead. The caller also asserts the\n\t\t// account does not exist yet: `new` ABORTS at the deterministic address if it\n\t\t// already exists — no chain read is done here. Gate on your own existence check\n\t\t// (`wrapperIdFor(owner)` + a getObject), or retry without the flag on that abort.\n\t\t//\n\t\t// Without `create`, the sourced coin goes into the existing account's stored\n\t\t// balance via the PTB-callable `deposit_funds` (folds settle → authorize → load →\n\t\t// deposit; clock auto-injected). Command order is auth → deposit (auth is a hot\n\t\t// potato consumed by the deposit). See\n\t\t// `packages/account/sources/account.move` (`deposit_funds`).\n\t\tdeposit: (\n\t\t\towner: string,\n\t\t\tamountUsdc: number | string,\n\t\t\topts?: { create?: boolean },\n\t\t): Transaction => {\n\t\t\tconst tx = new Transaction();\n\t\t\tconst coin = tx.add(\n\t\t\t\tcoinWithBalance({\n\t\t\t\t\ttype: this.cfg.quoteCoinType,\n\t\t\t\t\tbalance: usdcToRaw(amountUsdc),\n\t\t\t\t\tuseGasCoin: false,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (opts?.create) {\n\t\t\t\ttx.add(\n\t\t\t\t\taccountContract(this.cfg).createAccountAndDeposit({\n\t\t\t\t\t\tcoin,\n\t\t\t\t\t\tcoinType: this.cfg.quoteCoinType,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\ttx.add(\n\t\t\t\t\tdepositFunds({\n\t\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), coin },\n\t\t\t\t\t\ttypeArguments: [this.cfg.quoteCoinType],\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn tx;\n\t\t},\n\n\t\t// Withdraw `amountUsdc` from the account back to `owner`. By default the funds land\n\t\t// in the owner's USDC *address balance* (the versionless accumulator) via\n\t\t// `0x2::coin::send_funds` — no coin-object churn, and they merge into the same\n\t\t// balance `deposit` draws from, closing the loop. Pass `{ toCoinObject: true }` to\n\t\t// instead receive a discrete `Coin<T>` object (for wallets/explorers that only\n\t\t// render coin objects, or to compose the coin further in your own PTB). Either way\n\t\t// the underlying `withdraw_funds` returns the raw `Coin<T>` — the PTB-callable form\n\t\t// that folds settle → authorize → load → withdraw (clock auto-injected, `ctx`\n\t\t// implicit); command order is auth → withdraw. See\n\t\t// `packages/account/sources/account.move` (`withdraw_funds`).\n\t\twithdraw: (\n\t\t\towner: string,\n\t\t\tamountUsdc: number | string,\n\t\t\topts?: { toCoinObject?: boolean },\n\t\t): Transaction => {\n\t\t\tconst tx = new Transaction();\n\t\t\tconst coin = tx.add(\n\t\t\t\twithdrawFunds({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), amount: usdcToRaw(amountUsdc) },\n\t\t\t\t\ttypeArguments: [this.cfg.quoteCoinType],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (opts?.toCoinObject) {\n\t\t\t\ttx.transferObjects([coin], owner);\n\t\t\t} else {\n\t\t\t\ttx.moveCall({\n\t\t\t\t\ttarget: '0x2::coin::send_funds',\n\t\t\t\t\ttypeArguments: [this.cfg.quoteCoinType],\n\t\t\t\t\targuments: [coin, tx.pure.address(owner)],\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn tx;\n\t\t},\n\n\t\tmint: (owner: string, m: MarketDescriptor, opts: MintOptions): Promise<Transaction> =>\n\t\t\tthis.#buildMint(owner, m, opts),\n\n\t\tmintAmount: async (\n\t\t\towner: string,\n\t\t\tm: MarketDescriptor,\n\t\t\topts: MintAmountOptions,\n\t\t): Promise<Transaction> => {\n\t\t\tconst feeds = this.#feeds(m.underlying);\n\t\t\t// The chain requires a positive all-in cost cap (EMintCostCapRequired);\n\t\t\t// reject a zero cap pre-flight rather than surface a cryptic Move abort.\n\t\t\tif (opts.maxCost != null && opts.maxCost <= 0) {\n\t\t\t\tthrow new PredictInputError('maxCost must be > 0');\n\t\t\t}\n\t\t\tconst { id, state } = await this.#resolveMarket(m);\n\t\t\t// No lot check: min_quantity is a floor the chain compares against an\n\t\t\t// already-lot-floored minted quantity, so any floor value is legal.\n\t\t\tconst minQuantityRaw = usdcToRaw(opts.minQuantity);\n\t\t\tconst { lowerTick, higherTick } = await this.#strikeTicks(m, id, state);\n\t\t\treturn txOf(\n\t\t\t\tmintExactAmount(this.#config, {\n\t\t\t\t\texpiryMarketId: id,\n\t\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\t\tlowerTick,\n\t\t\t\t\thigherTick,\n\t\t\t\t\tmaxPremiumRaw: usdcToRaw(opts.spend),\n\t\t\t\t\tminQuantityRaw,\n\t\t\t\t\tmaxCostRaw: opts.maxCost != null ? usdcToRaw(opts.maxCost) : undefined,\n\t\t\t\t\t...feeds,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\n\t\tredeem: (owner: string, m: MarketDescriptor, opts: CloseOptions): Promise<Transaction> =>\n\t\t\tthis.#buildRedeem(owner, m, opts),\n\n\t\tclaimSettled: async (\n\t\t\towner: string,\n\t\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs' | 'marketId'>,\n\t\t\topts: Pick<CloseOptions, 'orderId'>,\n\t\t): Promise<Transaction> => {\n\t\t\tconst { id } = await this.#resolveMarket(m);\n\t\t\treturn txOf(\n\t\t\t\tredeemSettled(this.#config, {\n\t\t\t\t\texpiryMarketId: id,\n\t\t\t\t\twrapperId: this.wrapperIdFor(owner),\n\t\t\t\t\torderId: opts.orderId,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\n\t\t// Queue a supply request pulling `amountUsdc` from the account's existing custody\n\t\t// balance. `request_supply` auto-settles USDC then `account.withdraw`s the payment\n\t\t// into queue escrow; the PLP fill is delivered at the next flush, not returned here.\n\t\t// Command order is auth → request (auth is a hot potato consumed by this call). The\n\t\t// `minPlpOut` slot is the per-request floor on PLP minted at flush — `options.minPlpOut`\n\t\t// when given, otherwise 0 (no floor). At the shipped attempt count of one, the first\n\t\t// flush whose mark quotes less cancels and refunds the request; three is the\n\t\t// configurable maximum, not the default.\n\t\tsupplyPlp: (\n\t\t\towner: string,\n\t\t\tamountUsdc: number | string,\n\t\t\toptions: PlpSupplyOptions = {},\n\t\t): Transaction =>\n\t\t\ttxOf(\n\t\t\t\trequestSupply({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: {\n\t\t\t\t\t\twrapper: this.wrapperIdFor(owner),\n\t\t\t\t\t\tamount: usdcToRaw(amountUsdc),\n\t\t\t\t\t\tminPlpOut: options.minPlpOut ?? 0n,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Queue a withdraw request pulling `shares` (raw PLP u64) from account custody into\n\t\t// queue escrow — the Move parameter is named `amount`, but on `request_withdraw` it\n\t\t// counts PLP SHARES, not USDC. Auto-settles flush-delivered PLP first; the USDC\n\t\t// fill lands on the account at the next flush (no `withdraw_settled` entrypoint).\n\t\t// Command order is auth → request. The `minUsdcOut` slot is the per-request floor\n\t\t// on USDC paid at flush — `options.minUsdcOut` when given, otherwise 0 (no floor).\n\t\t// At the shipped attempt count of one, the first flush whose mark quotes less\n\t\t// cancels and refunds the request; three is the configurable maximum, not the\n\t\t// default.\n\t\twithdrawPlp: (owner: string, shares: bigint, options: PlpWithdrawOptions = {}): Transaction =>\n\t\t\ttxOf(\n\t\t\t\trequestWithdraw({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: {\n\t\t\t\t\t\twrapper: this.wrapperIdFor(owner),\n\t\t\t\t\t\tamount: shares,\n\t\t\t\t\t\tminUsdcOut: options.minUsdcOut === undefined ? 0n : usdcToRaw(options.minUsdcOut),\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Cancel a still-pending supply request by queue `index`, refunding its escrowed\n\t\t// USDC straight back into the requesting account. Command order is auth → cancel.\n\t\tcancelSupplyPlp: (owner: string, index: bigint): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tcancelSupplyRequest({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), index },\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Cancel a still-pending withdraw request by queue `index`, refunding its escrowed\n\t\t// PLP straight back into the requesting account. Command order is auth → cancel.\n\t\tcancelWithdrawPlp: (owner: string, index: bigint): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tcancelWithdrawRequest({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), index },\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Set the account's sticky builder-code attribution to `builderCodeId`, an existing\n\t\t// `BuilderCode` object borrowed as `&BuilderCode`. Command order is auth → set (auth\n\t\t// is a hot potato consumed by this call). Lives in the PREDICT package's\n\t\t// `predict_account` module, NOT the account package. Deployed sig\n\t\t// `packages/predict/sources/predict_account.move:134` — 3 moveCall args\n\t\t// (wrapper, auth, code; ctx implicit).\n\t\tsetBuilderCode: (owner: string, builderCodeId: string): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tsetBuilderCode({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner), code: builderCodeId },\n\t\t\t\t}),\n\t\t\t),\n\n\t\t// Clear the account's sticky builder-code attribution. Command order is auth → unset.\n\t\t// Deployed sig `.../predict_account.move:151` — 2 moveCall args (wrapper, auth; ctx\n\t\t// implicit).\n\t\tunsetBuilderCode: (owner: string): Transaction =>\n\t\t\ttxOf(\n\t\t\t\tunsetBuilderCode({\n\t\t\t\t\tconfig: this.#config,\n\t\t\t\t\targuments: { wrapper: this.wrapperIdFor(owner) },\n\t\t\t\t}),\n\t\t\t),\n\t};\n\n\t// === reads ===\n\treadonly read = {\n\t\t// All tradeable (active) markets with the state a frontend needs to render\n\t\t// and mint: one chain read for ids + one batched PTB for the states.\n\t\tmarkets: async (): Promise<ActiveMarket[]> => {\n\t\t\tconst ids = await activeMarketIds(this.#client, this.#config);\n\t\t\tconst states = await marketStates(this.#client, this.#config, ids);\n\t\t\treturn ids.map((id, i) => ({\n\t\t\t\tid,\n\t\t\t\texpiryMs: states[i].expiryMs,\n\t\t\t\ttickSize: fromRaw(states[i].tickSizeRaw, 9),\n\t\t\t\tadmissionTickSize: fromRaw(states[i].admissionTickSizeRaw, 9),\n\t\t\t\tmintPaused: states[i].mintPaused,\n\t\t\t\treferencePrice: PredictClient.#referencePriceOf(states[i]),\n\t\t\t}));\n\t\t},\n\n\t\t// Validate an app-stored order id against the chain (stale after full\n\t\t// close or partial-close replacement — see RedeemReceipt.replacementOrderId).\n\t\thasPosition: (owner: string, marketId: string, orderId: bigint): Promise<boolean> =>\n\t\t\thasPosition(this.#client, this.#config, owner, marketId, orderId),\n\n\t\t// All open positions for an owner, enumerated from the chain (the\n\t\t// account's positions Table): 1 call per page warm, +2 resolution calls\n\t\t// once per owner. Returns [] for owners with no Predict account.\n\t\tpositions: async (owner: string): Promise<OpenPosition[]> => {\n\t\t\tlet handle = this.#positionsCache.get(owner);\n\t\t\tif (!handle?.positionsTableId) {\n\t\t\t\tconst resolved = await resolvePositionsTable(this.#client, this.#config, owner);\n\t\t\t\tif (!resolved) return []; // never onboarded — do not cache\n\t\t\t\tif (resolved.positionsTableId) this.#positionsCache.set(owner, resolved);\n\t\t\t\thandle = resolved;\n\t\t\t}\n\t\t\tif (!handle.positionsTableId) return [];\n\t\t\treturn positionsFromTable(this.#client, handle.positionsTableId);\n\t\t},\n\n\t\t// Anonymous board pricing: the chain's probability for both sides of a\n\t\t// strike, from one fresh pricer (no account needed). This is the ↑/↓\n\t\t// button price before a user has onboarded.\n\t\tprice: async (m: BinaryMarketCoordinates): Promise<{ up: number; down: number }> => {\n\t\t\tconst feeds = this.#feeds(m.underlying);\n\t\t\tconst { id, state } = await this.#resolveMarket(m);\n\t\t\tconst strikeRaw = await this.#strikeRawFor(m, id, state);\n\t\t\tconst { upRaw, downRaw } = await rangePrices(\n\t\t\t\tthis.#client,\n\t\t\t\tthis.#config,\n\t\t\t\tid,\n\t\t\t\tfeeds,\n\t\t\t\tstrikeRaw,\n\t\t\t\tstate.tickSizeRaw,\n\t\t\t);\n\t\t\treturn { up: rawToProbability(upRaw), down: rawToProbability(downRaw) };\n\t\t},\n\n\t\t// A client-side board pricer for one market: ONE simulate reads the chain's\n\t\t// resolved pricer (already forward-selected + rolled to now), then prices every\n\t\t// strike LOCALLY with no further chain calls — `pricer.up(strike)`,\n\t\t// `.down(strike)`, `.range(lo,hi)`, `.strikeAtProbability(p)`. Use this to paint a\n\t\t// whole board instantly; `read.price` / `read.quoteMint` stay the authoritative\n\t\t// per-strike quote at trade time. Throws the same typed stale-oracle/expired\n\t\t// PredictMoveError `read.price` would when the chain itself cannot quote.\n\t\tpricer: async (\n\t\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs'>,\n\t\t): Promise<BoardPricer & { asOf: PricerSnapshot['sources'] }> => {\n\t\t\tconst feeds = this.#feeds(m.underlying);\n\t\t\tconst { id } = await this.#resolveMarket(m);\n\t\t\tconst snap = await readPricerSnapshot(this.#client, this.#config, id, feeds);\n\t\t\treturn { ...boardPricer(snap), asOf: snap.sources };\n\t\t},\n\n\t\t// Exact pre-trade quote: dry-runs the caller's own mint (same tx as\n\t\t// tx.mint) and decodes the receipt. Requires a funded account; throws\n\t\t// the same typed errors the real trade would — quote doubles as preflight.\n\t\tquoteMint: async (\n\t\t\towner: string,\n\t\t\tm: MarketDescriptor,\n\t\t\topts: Pick<MintOptions, 'quantity'>,\n\t\t): Promise<MintQuote> => {\n\t\t\tconst tx = await this.#buildMint(owner, m, opts);\n\t\t\tconst events = await simulateWithEvents(this.#client, tx, owner);\n\t\t\tconst r = exactlyOne(decodeMints(this.cfg, { events }), 'OrderMinted');\n\t\t\t// Mirrors the deployed `compute_mint_quote`'s all_in_cost exactly:\n\t\t\t// premium + (trading − subsidy) + builder + penalty + inventory-impact.\n\t\t\t// `referral_fee` is deliberately NOT added — it is a portion OF the\n\t\t\t// trader-paid trading fee and congestion surcharge, not an extra debit.\n\t\t\tconst costRaw =\n\t\t\t\tr.raw.premium +\n\t\t\t\t(r.raw.tradingFee - r.raw.feeIncentiveSubsidy) +\n\t\t\t\tr.raw.builderFee +\n\t\t\t\tr.raw.penaltyFee +\n\t\t\t\tr.raw.inventoryImpactCharge;\n\t\t\treturn {\n\t\t\t\tentryProbability: r.entryProbability,\n\t\t\t\tpremium: r.premium,\n\t\t\t\tfees: r.fees,\n\t\t\t\tcost: rawToUsdc(costRaw),\n\t\t\t\tquantity: r.quantity,\n\t\t\t\traw: {\n\t\t\t\t\tpremium: r.raw.premium,\n\t\t\t\t\tcost: costRaw,\n\t\t\t\t\tquantity: r.raw.quantity,\n\t\t\t\t\tentryProbability: r.raw.entryProbability,\n\t\t\t\t},\n\t\t\t\tfeesExact: true,\n\t\t\t};\n\t\t},\n\n\t\t// Exact pre-close quote: dry-runs the caller's own redeem and decodes\n\t\t// the receipt — the informed close against the floor-less deployed redeem.\n\t\tquoteRedeem: async (\n\t\t\towner: string,\n\t\t\tm: MarketDescriptor,\n\t\t\topts: CloseOptions,\n\t\t): Promise<RedeemQuote> => {\n\t\t\tconst tx = await this.#buildRedeem(owner, m, opts);\n\t\t\tconst events = await simulateWithEvents(this.#client, tx, owner);\n\t\t\tconst r = exactlyOne(decodeRedeems(this.cfg, { events }), 'order-redeemed');\n\t\t\treturn {\n\t\t\t\tproceeds: r.proceeds,\n\t\t\t\tgross: r.gross,\n\t\t\t\tfees: r.fees,\n\t\t\t\tquantityClosed: r.quantityClosed,\n\t\t\t\tremaining: r.remaining,\n\t\t\t\traw: {\n\t\t\t\t\tproceeds: r.raw.proceeds,\n\t\t\t\t\tgross: r.raw.gross,\n\t\t\t\t\tquantityClosed: r.raw.quantityClosed,\n\t\t\t\t},\n\t\t\t\tfeesExact: true,\n\t\t\t};\n\t\t},\n\n\t\tmarket: async (\n\t\t\tm: Pick<MarketDescriptor, 'underlying' | 'expiryMs'>,\n\t\t): Promise<MarketSummary | null> => {\n\t\t\tconst expiryMs = BigInt(m.expiryMs);\n\t\t\t// Deliberately re-queries and overwrites the cache instead of reading\n\t\t\t// through it: this read must return live state (nav, mintPaused), and\n\t\t\t// refreshing the cache on the way keeps later tx builds consistent.\n\t\t\tconst u = this.#underlying(m.underlying);\n\t\t\tconst id = await expiryMarketId(this.#client, this.#config, u, expiryMs);\n\t\t\tif (!id) return null;\n\t\t\tconst state = await marketState(this.#client, this.#config, id);\n\t\t\tthis.#marketCache.set(`${m.underlying}:${expiryMs}`, { id, state });\n\t\t\tconst navRaw = await currentNav(this.#client, this.#config, id, u);\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\texpiryMs: state.expiryMs,\n\t\t\t\ttickSize: fromRaw(state.tickSizeRaw, 9), // strike/price scale\n\t\t\t\tadmissionTickSize: fromRaw(state.admissionTickSizeRaw, 9),\n\t\t\t\tmintPaused: state.mintPaused,\n\t\t\t\tnav: rawToUsdc(navRaw),\n\t\t\t\treferencePrice: PredictClient.#referencePriceOf(state),\n\t\t\t};\n\t\t},\n\n\t\tbalance: async (owner: string): Promise<number> =>\n\t\t\trawToUsdc(await accountBalance(this.#client, this.#config, owner, this.cfg.quoteCoinType)),\n\n\t\t// PLP shares held in the owner's account custody (raw u64, 6-decimal PLP coin).\n\t\tplpBalance: (owner: string): Promise<bigint> =>\n\t\t\taccountBalance(this.#client, this.#config, owner, this.cfg.coinTypes.plp),\n\n\t\tpool: async (): Promise<PoolSummary> => {\n\t\t\tconst s = await poolStats(this.#client, this.#config);\n\t\t\treturn {\n\t\t\t\tplpTotalSupply: s.plpTotalSupply, // shares raw (6-decimal)\n\t\t\t\tidleUsdc: rawToUsdc(s.idleBalance),\n\t\t\t\t// These are queue LENGTHS (counts of pending requests), not token amounts.\n\t\t\t\tsupplyRequestsPending: Number(s.supplyRequestsPending),\n\t\t\t\twithdrawRequestsPending: Number(s.withdrawRequestsPending),\n\t\t\t};\n\t\t},\n\t};\n\n\t// === execution-result decoders ===\n\t// Pure event parsing (no network): pass the executed/simulated transaction\n\t// result (with events included) and get a typed receipt back. Singular forms\n\t// throw unless exactly one matching event exists; plural forms return all\n\t// (an integrator batching N actions in one PTB gets N receipts).\n\treadonly decode = {\n\t\tmint: (r: DecodableTransactionResult) => exactlyOne(decodeMints(this.cfg, r), 'OrderMinted'),\n\t\tmints: (r: DecodableTransactionResult) => decodeMints(this.cfg, r),\n\t\tredeem: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeRedeems(this.cfg, r), 'order-redeemed'),\n\t\tredeems: (r: DecodableTransactionResult) => decodeRedeems(this.cfg, r),\n\t\tclaim: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeClaims(this.cfg, r), 'SettledOrderRedeemed'),\n\t\tclaims: (r: DecodableTransactionResult) => decodeClaims(this.cfg, r),\n\t\tcreateManager: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeAccountsCreated(this.cfg, r), 'AccountCreated'),\n\t\tdeposit: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeDeposits(this.cfg, r), 'Deposited'),\n\t\twithdraw: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeWithdrawals(this.cfg, r), 'Withdrawn'),\n\t\tplpRequest: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodePlpRequests(this.cfg, r), 'supply/withdraw-requested'),\n\t\tplpCancel: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodePlpCancels(this.cfg, r), 'RequestCancelled'),\n\t\tbuilderCode: (r: DecodableTransactionResult) =>\n\t\t\texactlyOne(decodeBuilderCodeSets(this.cfg, r), 'BuilderCodeSet'),\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { MAINNET_DEPLOYMENT, MAINNET_UNITS } from "../../deployments/mainnet.mjs";
|
|
1
2
|
import { TESTNET_DEPLOYMENT, TESTNET_UNITS } from "../../deployments/testnet.mjs";
|
|
2
3
|
import { NetworkArg, getDeployment, getUnits } from "../../deployments/index.mjs";
|
|
3
4
|
import { PredictConfig, PredictPackages, UnderlyingConfig } from "./types.mjs";
|
|
5
|
+
import { MAINNET_CONFIG } from "./mainnet.mjs";
|
|
4
6
|
import { TESTNET_CONFIG } from "./testnet.mjs";
|
|
5
7
|
|
|
6
8
|
//#region src/predict/config/index.d.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/predict/config/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/predict/config/index.ts"],"mappings":";;;;;;;;iBAUgB,SAAA,CAAU,OAAA,EAAS,UAAA,GAAa,aAAA"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { MAINNET_DEPLOYMENT, MAINNET_UNITS } from "../../deployments/mainnet.mjs";
|
|
1
2
|
import { TESTNET_DEPLOYMENT, TESTNET_UNITS } from "../../deployments/testnet.mjs";
|
|
2
3
|
import { getDeployment, getUnits } from "../../deployments/index.mjs";
|
|
4
|
+
import { MAINNET_CONFIG } from "./mainnet.mjs";
|
|
3
5
|
import { TESTNET_CONFIG } from "./testnet.mjs";
|
|
4
6
|
|
|
5
7
|
//#region src/predict/config/index.ts
|
|
6
8
|
function getConfig(network) {
|
|
7
9
|
if (network === "testnet") return TESTNET_CONFIG;
|
|
8
|
-
|
|
10
|
+
if (network === "mainnet") return MAINNET_CONFIG;
|
|
11
|
+
throw new Error(`@mysten/deepbook-v3/predict: no Predict deployment recorded for network '${network}'. Predict is recorded for testnet and mainnet; for your own deployment pass \`config\` to PredictClient or \`predict({ config })\`.`);
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/predict/config/index.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { TESTNET_CONFIG } from './testnet.js';\nimport type { PredictConfig } from './types.js';\nimport type { NetworkArg } from '../../deployments/index.js';\n\nexport { TESTNET_CONFIG };\nexport type { PredictConfig, PredictPackages, UnderlyingConfig } from './types.js';\n\nexport function getConfig(network: NetworkArg): PredictConfig {\n\tif (network === 'testnet') return TESTNET_CONFIG;\n\tthrow new Error(\n\t\t`@mysten/deepbook-v3/predict: no Predict deployment recorded for network '${network}'. ` +\n\t\t\t'Predict is testnet
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/predict/config/index.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { MAINNET_CONFIG } from './mainnet.js';\nimport { TESTNET_CONFIG } from './testnet.js';\nimport type { PredictConfig } from './types.js';\nimport type { NetworkArg } from '../../deployments/index.js';\n\nexport { TESTNET_CONFIG, MAINNET_CONFIG };\nexport type { PredictConfig, PredictPackages, UnderlyingConfig } from './types.js';\n\nexport function getConfig(network: NetworkArg): PredictConfig {\n\tif (network === 'testnet') return TESTNET_CONFIG;\n\tif (network === 'mainnet') return MAINNET_CONFIG;\n\tthrow new Error(\n\t\t`@mysten/deepbook-v3/predict: no Predict deployment recorded for network '${network}'. ` +\n\t\t\t'Predict is recorded for testnet and mainnet; for your own deployment pass `config` to ' +\n\t\t\t'PredictClient ' +\n\t\t\t'or `predict({ config })`.',\n\t);\n}\n\n// Provenance: which on-chain deployment these ids came from.\nexport {\n\tgetDeployment,\n\tgetUnits,\n\tMAINNET_DEPLOYMENT,\n\tMAINNET_UNITS,\n\tTESTNET_DEPLOYMENT,\n\tTESTNET_UNITS,\n} from '../../deployments/index.js';\n"],"mappings":";;;;;;;AAUA,SAAgB,UAAU,SAAoC;AAC7D,KAAI,YAAY,UAAW,QAAO;AAClC,KAAI,YAAY,UAAW,QAAO;AAClC,OAAM,IAAI,MACT,4EAA4E,QAAQ,sIAIpF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PredictConfig } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/predict/config/mainnet.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Mainnet deployment constants, read from the shared generated record in
|
|
6
|
+
* `src/deployments/` rather than transcribed here. `/account` and `/sessions` read slices of
|
|
7
|
+
* that same record, so a redeploy (`pnpm sync-deployment`) moves every subpath together and
|
|
8
|
+
* they cannot end up addressing different deployments.
|
|
9
|
+
*
|
|
10
|
+
* The record is generated from the deploy tooling's `deployment.mainnet.json`; see
|
|
11
|
+
* `scripts/sync-deployment.ts`. `getDeployment('mainnet')` names the deployment and the
|
|
12
|
+
* deepbookv3 commit these ids came from.
|
|
13
|
+
*/
|
|
14
|
+
declare const MAINNET_CONFIG: PredictConfig;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { MAINNET_CONFIG };
|
|
17
|
+
//# sourceMappingURL=mainnet.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mainnet.d.mts","names":[],"sources":["../../../src/predict/config/mainnet.ts"],"mappings":";;;;;AAgBA;;;;;;;;cAAa,cAAA,EAAgB,aAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MAINNET_PREDICT } from "../../deployments/mainnet.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/predict/config/mainnet.ts
|
|
4
|
+
/**
|
|
5
|
+
* Mainnet deployment constants, read from the shared generated record in
|
|
6
|
+
* `src/deployments/` rather than transcribed here. `/account` and `/sessions` read slices of
|
|
7
|
+
* that same record, so a redeploy (`pnpm sync-deployment`) moves every subpath together and
|
|
8
|
+
* they cannot end up addressing different deployments.
|
|
9
|
+
*
|
|
10
|
+
* The record is generated from the deploy tooling's `deployment.mainnet.json`; see
|
|
11
|
+
* `scripts/sync-deployment.ts`. `getDeployment('mainnet')` names the deployment and the
|
|
12
|
+
* deepbookv3 commit these ids came from.
|
|
13
|
+
*/
|
|
14
|
+
const MAINNET_CONFIG = Object.freeze({
|
|
15
|
+
network: "mainnet",
|
|
16
|
+
packages: MAINNET_PREDICT.packages,
|
|
17
|
+
objects: MAINNET_PREDICT.objects,
|
|
18
|
+
quoteCoinType: MAINNET_PREDICT.quoteCoinType,
|
|
19
|
+
coinTypes: MAINNET_PREDICT.coinTypes,
|
|
20
|
+
units: MAINNET_PREDICT.units,
|
|
21
|
+
underlyings: MAINNET_PREDICT.underlyings
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { MAINNET_CONFIG };
|
|
26
|
+
//# sourceMappingURL=mainnet.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mainnet.mjs","names":[],"sources":["../../../src/predict/config/mainnet.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { MAINNET_PREDICT } from '../../deployments/mainnet.js';\nimport type { PredictConfig } from './types.js';\n\n/**\n * Mainnet deployment constants, read from the shared generated record in\n * `src/deployments/` rather than transcribed here. `/account` and `/sessions` read slices of\n * that same record, so a redeploy (`pnpm sync-deployment`) moves every subpath together and\n * they cannot end up addressing different deployments.\n *\n * The record is generated from the deploy tooling's `deployment.mainnet.json`; see\n * `scripts/sync-deployment.ts`. `getDeployment('mainnet')` names the deployment and the\n * deepbookv3 commit these ids came from.\n */\nexport const MAINNET_CONFIG: PredictConfig = Object.freeze({\n\t// The record widens `network` to `string` so the published types don't pin a literal;\n\t// this file is the mainnet config by construction.\n\tnetwork: 'mainnet',\n\tpackages: MAINNET_PREDICT.packages,\n\tobjects: MAINNET_PREDICT.objects,\n\tquoteCoinType: MAINNET_PREDICT.quoteCoinType,\n\tcoinTypes: MAINNET_PREDICT.coinTypes,\n\tunits: MAINNET_PREDICT.units,\n\tunderlyings: MAINNET_PREDICT.underlyings,\n});\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAa,iBAAgC,OAAO,OAAO;CAG1D,SAAS;CACT,UAAU,gBAAgB;CAC1B,SAAS,gBAAgB;CACzB,eAAe,gBAAgB;CAC/B,WAAW,gBAAgB;CAC3B,OAAO,gBAAgB;CACvB,aAAa,gBAAgB;CAC7B,CAAC"}
|
|
@@ -31,6 +31,12 @@ interface PredictConfig {
|
|
|
31
31
|
oracleRegistry: string;
|
|
32
32
|
accountRegistry: string;
|
|
33
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* The deployment's settlement coin type. Always read this rather than assuming a type:
|
|
36
|
+
* the contracts renamed the collateral to `usdc::usdc::USDC`, but a deployment published
|
|
37
|
+
* before that rename still serves its original coin type, and this field is what the
|
|
38
|
+
* deployment record actually carries.
|
|
39
|
+
*/
|
|
34
40
|
quoteCoinType: string;
|
|
35
41
|
/**
|
|
36
42
|
* Coin types the deployment owns. `plp` is NOT derivable from `packages.predict`: a Move
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/predict/config/types.ts"],"mappings":";;UAGiB,eAAA;EAChB,OAAA;EACA,OAAA;EACA,QAAA;AAAA;;;;;AAQD;UAAiB,gBAAA;EAChB,MAAA;EACA,oBAAA;EADA;EAGA,QAAA;EAAA;EAEA,sBAAA;EAEA;EAAA,oBAAA;AAAA;AAID;AAAA,UAAiB,aAAA;EAChB,OAAA;EACA,QAAA,EAAU,eAAA;EACV,OAAA;IACC,QAAA;IACA,cAAA;IACA,SAAA;IACA,cAAA;IACA,eAAA;EAAA;
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/predict/config/types.ts"],"mappings":";;UAGiB,eAAA;EAChB,OAAA;EACA,OAAA;EACA,QAAA;AAAA;;;;;AAQD;UAAiB,gBAAA;EAChB,MAAA;EACA,oBAAA;EADA;EAGA,QAAA;EAAA;EAEA,sBAAA;EAEA;EAAA,oBAAA;AAAA;AAID;AAAA,UAAiB,aAAA;EAChB,OAAA;EACA,QAAA,EAAU,eAAA;EACV,OAAA;IACC,QAAA;IACA,cAAA;IACA,SAAA;IACA,cAAA;IACA,eAAA;EAAA;EALD;;;;;;EAaA,aAAA;EAMA;;;;;EAAA,SAAA;IAAa,GAAA;IAAa,IAAA;EAAA;EAQb;EANb,KAAA;IACC,eAAA;IACA,eAAA;IACA,iBAAA;IACA,wBAAA;EAAA;EAED,WAAA,EAAa,MAAA,SAAe,gBAAA;AAAA"}
|
package/dist/predict/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { MAINNET_DEPLOYMENT, MAINNET_UNITS } from "../deployments/mainnet.mjs";
|
|
1
2
|
import { TESTNET_DEPLOYMENT, TESTNET_UNITS } from "../deployments/testnet.mjs";
|
|
2
3
|
import { getDeployment, getUnits } from "../deployments/index.mjs";
|
|
3
4
|
import { PredictConfig, PredictPackages, UnderlyingConfig } from "./config/types.mjs";
|
|
5
|
+
import { MAINNET_CONFIG } from "./config/mainnet.mjs";
|
|
4
6
|
import { TESTNET_CONFIG } from "./config/testnet.mjs";
|
|
5
7
|
import { getConfig } from "./config/index.mjs";
|
|
6
8
|
import { BalanceChangeReceipt, BuilderCodeReceipt, ClaimReceipt, CreateManagerReceipt, DecodableEvent, DecodableTransactionResult, MintReceipt, PlpCancelReceipt, PlpRequestReceipt, RedeemReceipt } from "./decode.mjs";
|
|
@@ -11,8 +13,8 @@ import { MarketFeeds, loadLivePricer } from "./tx/trade.mjs";
|
|
|
11
13
|
import { ReadClient } from "./reads/inspect.mjs";
|
|
12
14
|
import { PricerSnapshot } from "./reads/pricing.mjs";
|
|
13
15
|
import { POS_INF_TICK, Side, binaryRangeTicks } from "./ticks.mjs";
|
|
14
|
-
import { ActiveMarket, CloseOptions, MarketDescriptor, MarketSummary, MintAmountOptions, MintOptions, MintQuote, POSITION_LOT_SIZE, PoolSummary, PredictClient, PredictCompatibleClient, RedeemQuote, predict } from "./client.mjs";
|
|
16
|
+
import { ActiveMarket, CloseOptions, MarketDescriptor, MarketSummary, MintAmountOptions, MintOptions, MintQuote, POSITION_LOT_SIZE, PlpSupplyOptions, PlpWithdrawOptions, PoolSummary, PredictClient, PredictCompatibleClient, RedeemQuote, predict } from "./client.mjs";
|
|
15
17
|
import { deriveAccountWrapperId, generateAuth } from "./tx/common.mjs";
|
|
16
18
|
import { U64_MAX, priceToRaw, probabilityToRaw, rawToPrice, rawToProbability, rawToUsdc, usdcToRaw } from "./units.mjs";
|
|
17
19
|
import { MoveAbortError, PredictInputError, PredictMoveError, decodeMoveAbort } from "./errors.mjs";
|
|
18
|
-
export { type ActiveMarket, type BalanceChangeReceipt, type BuilderCodeReceipt, type ClaimReceipt, type CloseOptions, type CreateManagerReceipt, type DecodableEvent, type DecodableTransactionResult, type GeneratedConfig, type MarketDescriptor, type MarketFeeds, type MarketSummary, type MintAmountOptions, type MintOptions, type MintQuote, type MintReceipt, type MoveAbortError, type OpenPosition, POSITION_LOT_SIZE, POS_INF_TICK, type PlpCancelReceipt, type PlpRequestReceipt, type PoolSummary, PredictClient, type PredictCompatibleClient, type PredictConfig, PredictInputError, PredictMoveError, type PredictPackages, type PricerSnapshot, type ReadClient, type RedeemQuote, type RedeemReceipt, type Side, TESTNET_CONFIG, TESTNET_DEPLOYMENT, TESTNET_UNITS, U64_MAX, type UnderlyingConfig, binaryRangeTicks, decodeMoveAbort, deriveAccountWrapperId, generateAuth, getConfig, getDeployment, getUnits, loadLivePricer, predict, priceToRaw, pricing_d_exports as pricing, probabilityToRaw, rawToPrice, rawToProbability, rawToUsdc, toGeneratedConfig, usdcToRaw };
|
|
20
|
+
export { type ActiveMarket, type BalanceChangeReceipt, type BuilderCodeReceipt, type ClaimReceipt, type CloseOptions, type CreateManagerReceipt, type DecodableEvent, type DecodableTransactionResult, type GeneratedConfig, MAINNET_CONFIG, MAINNET_DEPLOYMENT, MAINNET_UNITS, type MarketDescriptor, type MarketFeeds, type MarketSummary, type MintAmountOptions, type MintOptions, type MintQuote, type MintReceipt, type MoveAbortError, type OpenPosition, POSITION_LOT_SIZE, POS_INF_TICK, type PlpCancelReceipt, type PlpRequestReceipt, type PlpSupplyOptions, type PlpWithdrawOptions, type PoolSummary, PredictClient, type PredictCompatibleClient, type PredictConfig, PredictInputError, PredictMoveError, type PredictPackages, type PricerSnapshot, type ReadClient, type RedeemQuote, type RedeemReceipt, type Side, TESTNET_CONFIG, TESTNET_DEPLOYMENT, TESTNET_UNITS, U64_MAX, type UnderlyingConfig, binaryRangeTicks, decodeMoveAbort, deriveAccountWrapperId, generateAuth, getConfig, getDeployment, getUnits, loadLivePricer, predict, priceToRaw, pricing_d_exports as pricing, probabilityToRaw, rawToPrice, rawToProbability, rawToUsdc, toGeneratedConfig, usdcToRaw };
|
package/dist/predict/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { MAINNET_DEPLOYMENT, MAINNET_UNITS } from "../deployments/mainnet.mjs";
|
|
1
2
|
import { TESTNET_DEPLOYMENT, TESTNET_UNITS } from "../deployments/testnet.mjs";
|
|
2
3
|
import { getDeployment, getUnits } from "../deployments/index.mjs";
|
|
4
|
+
import { MAINNET_CONFIG } from "./config/mainnet.mjs";
|
|
3
5
|
import { TESTNET_CONFIG } from "./config/testnet.mjs";
|
|
4
6
|
import { getConfig } from "./config/index.mjs";
|
|
5
7
|
import { toGeneratedConfig } from "./config/generated.mjs";
|
|
@@ -11,4 +13,4 @@ import { loadLivePricer } from "./tx/trade.mjs";
|
|
|
11
13
|
import { pricing_exports } from "./pricing.mjs";
|
|
12
14
|
import { POSITION_LOT_SIZE, PredictClient, predict } from "./client.mjs";
|
|
13
15
|
|
|
14
|
-
export { POSITION_LOT_SIZE, POS_INF_TICK, PredictClient, PredictInputError, PredictMoveError, TESTNET_CONFIG, TESTNET_DEPLOYMENT, TESTNET_UNITS, U64_MAX, binaryRangeTicks, decodeMoveAbort, deriveAccountWrapperId, generateAuth, getConfig, getDeployment, getUnits, loadLivePricer, predict, priceToRaw, pricing_exports as pricing, probabilityToRaw, rawToPrice, rawToProbability, rawToUsdc, toGeneratedConfig, usdcToRaw };
|
|
16
|
+
export { MAINNET_CONFIG, MAINNET_DEPLOYMENT, MAINNET_UNITS, POSITION_LOT_SIZE, POS_INF_TICK, PredictClient, PredictInputError, PredictMoveError, TESTNET_CONFIG, TESTNET_DEPLOYMENT, TESTNET_UNITS, U64_MAX, binaryRangeTicks, decodeMoveAbort, deriveAccountWrapperId, generateAuth, getConfig, getDeployment, getUnits, loadLivePricer, predict, priceToRaw, pricing_exports as pricing, probabilityToRaw, rawToPrice, rawToProbability, rawToUsdc, toGeneratedConfig, usdcToRaw };
|
|
@@ -36,12 +36,12 @@ declare function probability(inputs: PricerInputs, strike: number, side: 'up' |
|
|
|
36
36
|
declare function strikeAtProbability(inputs: PricerInputs, p: number): number | null;
|
|
37
37
|
/** Roll `a` and `b` down by the fraction of anchored time remaining, matching the chain's
|
|
38
38
|
* `roll_down_svi` (variance decays toward expiry). `remainingMs` = expiry − now;
|
|
39
|
-
* `anchorTteMs` = expiry − the SVI observation's **
|
|
40
|
-
* freshness gate
|
|
41
|
-
* (
|
|
42
|
-
* fraction. `read.pricer` avoids the question entirely (the chain
|
|
43
|
-
* `rho`, `m`, `sigma` are unchanged. Feed an UNrolled provider surface;
|
|
44
|
-
* expects. */
|
|
39
|
+
* `anchorTteMs` = expiry − the SVI observation's **provider `svi_timestamp`** (its per-update
|
|
40
|
+
* source timestamp) — the same clock the freshness gate accepts, and what the chain anchors on
|
|
41
|
+
* (`pricing.move`: "One clock serves every job"). Anchoring on the batch's ingestion time
|
|
42
|
+
* instead rolls by the wrong fraction. `read.pricer` avoids the question entirely (the chain
|
|
43
|
+
* has already rolled). `rho`, `m`, `sigma` are unchanged. Feed an UNrolled provider surface;
|
|
44
|
+
* the result is what {@link upProbability} expects. */
|
|
45
45
|
declare function rollDown(svi: Svi, remainingMs: number, anchorTteMs: number): Svi;
|
|
46
46
|
/** The forward the contract prices against: Pyth spot re-anchored by the Block-Scholes
|
|
47
47
|
* basis (`spot · forward/bsSpot`), falling back to the Block-Scholes forward when Pyth is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.d.mts","names":[],"sources":["../../src/predict/pricing.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"pricing.d.mts","names":[],"sources":["../../src/predict/pricing.ts"],"mappings":";;;;;;UA+BiB,GAAA;EAChB,CAAA;EACA,CAAA;EACA,GAAA;EACA,CAAA;EACA,KAAA;AAAA;;;;UAMgB,YAAA;;EAEhB,OAAA;EACA,GAAA,EAAK,GAAA;AAAA;;;;iBAiCU,aAAA,CAAc,MAAA,EAAQ,YAAA,EAAc,MAAA;;;iBAwBpC,eAAA,CAAgB,MAAA,EAAQ,YAAA,EAAc,MAAA;;;iBAMtC,gBAAA,CAAiB,MAAA,EAAQ,YAAA,EAAc,KAAA,UAAe,MAAA;;iBAStD,WAAA,CAAY,MAAA,EAAQ,YAAA,EAAc,MAAA,UAAgB,IAAA;;;iBAOlD,mBAAA,CAAoB,MAAA,EAAQ,YAAA,EAAc,CAAA;;;;AA9C1D;;;;;iBA8EgB,QAAA,CAAS,GAAA,EAAK,GAAA,EAAK,WAAA,UAAqB,WAAA,WAAsB,GAAA;;;;AAtD9E;;;;iBAkEgB,OAAA,CAAQ,QAAA,UAAkB,MAAA,UAAgB,SAAA;;;;UAQzC,WAAA,SAAoB,YAAA;EApErB;EAsEf,EAAA,CAAG,MAAA;;EAEH,IAAA,CAAK,MAAA;EAxEmC;EA0ExC,WAAA,CAAY,MAAA,UAAgB,IAAA;EA1E0B;EA4EtD,KAAA,CAAM,KAAA,UAAe,MAAA;EA5E8D;EA8EnF,mBAAA,CAAoB,CAAA;AAAA;;iBAIL,WAAA,CAAY,MAAA,EAAQ,YAAA,GAAe,WAAA"}
|
package/dist/predict/pricing.mjs
CHANGED
|
@@ -86,12 +86,12 @@ function strikeAtProbability(inputs, p) {
|
|
|
86
86
|
}
|
|
87
87
|
/** Roll `a` and `b` down by the fraction of anchored time remaining, matching the chain's
|
|
88
88
|
* `roll_down_svi` (variance decays toward expiry). `remainingMs` = expiry − now;
|
|
89
|
-
* `anchorTteMs` = expiry − the SVI observation's **
|
|
90
|
-
* freshness gate
|
|
91
|
-
* (
|
|
92
|
-
* fraction. `read.pricer` avoids the question entirely (the chain
|
|
93
|
-
* `rho`, `m`, `sigma` are unchanged. Feed an UNrolled provider surface;
|
|
94
|
-
* expects. */
|
|
89
|
+
* `anchorTteMs` = expiry − the SVI observation's **provider `svi_timestamp`** (its per-update
|
|
90
|
+
* source timestamp) — the same clock the freshness gate accepts, and what the chain anchors on
|
|
91
|
+
* (`pricing.move`: "One clock serves every job"). Anchoring on the batch's ingestion time
|
|
92
|
+
* instead rolls by the wrong fraction. `read.pricer` avoids the question entirely (the chain
|
|
93
|
+
* has already rolled). `rho`, `m`, `sigma` are unchanged. Feed an UNrolled provider surface;
|
|
94
|
+
* the result is what {@link upProbability} expects. */
|
|
95
95
|
function rollDown(svi, remainingMs, anchorTteMs) {
|
|
96
96
|
const frac = anchorTteMs > 0 ? remainingMs / anchorTteMs : 0;
|
|
97
97
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.mjs","names":["forward"],"sources":["../../src/predict/pricing.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n// Faithful float port of the deployed `deepbook_predict::pricing::compute_nd2`\n// (testnet `predict-testnet-8-21`, sourceCommit 1f79fe87) — the SVI-adjusted digital\n// probability, WITH the skew-correction term. It operates on the pricer's\n// ALREADY-RESOLVED forward and ALREADY-ROLLED-DOWN SVI, exactly as `load_live_pricer`\n// returns them (decoded by `reads/pricing.ts`). So the two on-chain steps that pick the\n// forward (Pyth-spot vs Block-Scholes, admin flag + freshness) and roll `a`/`b` down by\n// remaining/anchored time already happened on-chain — this module never re-derives them,\n// which is what keeps it faithful.\n//\n// This is the fast client-side board pricer: read one `Pricer` snapshot, then price every\n// strike locally with no further chain calls. `read.price` / `read.quoteMint` (a chain\n// dry-run) stay the authoritative quote at trade time. Divergence vs the chain is up to\n// ~1e-4 in probability, dominated by the chain's fixed-point truncation near ATM when sigma\n// sits at its floor (float64 here is the more precise side, not the less); negligible for\n// display. `tests/testnet/pricing.test.ts` bounds it live against the deployment.\n//\n// The on-chain formula (pricing.move `compute_nd2`, 1f79fe87):\n// k = ln(strike / forward)\n// x = k - m\n// w = a + b·(ρ·x + √(x² + σ²)) // a, b already rolled down\n// d2 = −(k + w/2) / √w // clamped to ±8\n// w′ = b·(ρ + x/√(x² + σ²)) // SVI slope\n// price = N(d2) − φ(d2)·w′ / (2·√w) // the skew correction, clamped [0,1]\n\n/** Rolled-down SVI parameters for one expiry, in decimal (NOT the chain's 1e9/1e18 integer\n * scaling) — the surface AFTER Predict's remaining-time roll-down, as carried by the\n * on-chain `Pricer`. `a`, `rho`, `m` are signed; `b`, `sigma` are non-negative. */\nexport interface Svi {\n\ta: number;\n\tb: number;\n\trho: number;\n\tm: number;\n\tsigma: number;\n}\n\n/** A resolved pricer snapshot: the forward the contract prices against and its rolled SVI\n * surface, both in decimal. Produced by `read.pricer(market)`; consume via {@link boardPricer}\n * or the pure functions below. */\nexport interface PricerInputs {\n\t/** Forward price the digital settles against, in decimal (same units as `strike`). */\n\tforward: number;\n\tsvi: Svi;\n}\n\n/** Standard normal CDF via erf (Abramowitz–Stegun 7.1.26, |err| < 1.5e-7). */\nfunction normalCdf(x: number): number {\n\treturn 0.5 * (1 + erf(x / Math.SQRT2));\n}\n\n/** Standard normal PDF. */\nfunction normalPdf(x: number): number {\n\treturn Math.exp(-0.5 * x * x) / Math.sqrt(2 * Math.PI);\n}\n\nfunction erf(x: number): number {\n\tconst sign = x >= 0 ? 1 : -1;\n\tconst ax = Math.abs(x);\n\tconst t = 1 / (1 + 0.3275911 * ax);\n\tconst y =\n\t\t1 -\n\t\t((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t + 0.254829592) *\n\t\t\tt *\n\t\t\tMath.exp(-ax * ax);\n\treturn sign * y;\n}\n\n// Clamp |d2| at 8, matching the chain (`normal_cdf`/`normal_pdf` saturate beyond that).\nfunction clampD2(d2: number): number {\n\treturn d2 > 8 ? 8 : d2 < -8 ? -8 : d2;\n}\n\n/** P(settle > strike) — the UP digital, with the SVI skew correction. `inputs.svi` is the\n * already-rolled surface (no roll-down applied here). `forward` and `strike` share units.\n * Returns a probability in [0, 1]. */\nexport function upProbability(inputs: PricerInputs, strike: number): number {\n\tconst { forward, svi } = inputs;\n\tif (!(forward > 0)) return 0;\n\tif (strike <= 0) return 1; // neg-inf limit\n\tconst { a, b, rho, m, sigma } = svi;\n\tconst k = Math.log(strike / forward);\n\tconst km = k - m;\n\tconst root = Math.sqrt(km * km + sigma * sigma);\n\tconst inner = rho * km + root; // >= 0 for |rho| <= 1\n\tconst w = a + b * inner; // total variance\n\t// The chain guarantees w > 0 at every strike (assert_min_total_variance_positive at\n\t// load time), so this branch is unreachable in practice; return the variance→0 tail\n\t// limit rather than throw, so a UI never crashes on a degenerate snapshot.\n\tif (w <= 0) return k < 0 ? 1 : 0;\n\tconst sq = Math.sqrt(w);\n\tconst d2 = clampD2(-((k + w / 2) / sq));\n\tconst nd2 = normalCdf(d2);\n\tconst wPrime = b * (rho + km / root); // SVI slope × b\n\tconst price = nd2 - (normalPdf(d2) * wPrime) / (2 * sq); // skew correction\n\treturn price < 0 ? 0 : price > 1 ? 1 : price;\n}\n\n/** P(settle < strike) — the DOWN digital. Exactly `1 − up`, matching the chain's\n * `range_price(-inf, strike] = up(-inf) − up(strike) = 1 − up(strike)`. */\nexport function downProbability(inputs: PricerInputs, strike: number): number {\n\treturn 1 - upProbability(inputs, strike);\n}\n\n/** Probability mass in `(lower, higher]`, floored at 0 (matches `compute_range_price`'s\n * saturating subtraction). Use `lower <= 0` for the −∞ bound and `higher = Infinity` for +∞. */\nexport function rangeProbability(inputs: PricerInputs, lower: number, higher: number): number {\n\t// up(lower) − up(higher), where up(+inf) = 0 and up(<= 0) = 1.\n\tconst upLower = lower <= 0 ? 1 : upProbability(inputs, lower);\n\tconst upHigher = higher === Infinity ? 0 : upProbability(inputs, higher);\n\tconst d = upLower - upHigher;\n\treturn d < 0 ? 0 : d;\n}\n\n/** Binary probability at `strike` for the given side (`up` = P(>strike), `down` = 1 − up). */\nexport function probability(inputs: PricerInputs, strike: number, side: 'up' | 'down'): number {\n\tconst up = upProbability(inputs, strike);\n\treturn side === 'up' ? up : 1 - up;\n}\n\n/** Strike where P(settle > strike) = `p`, by bisection (UP is monotone-decreasing in\n * strike). Null when no crossing exists within ±64% of forward. */\nexport function strikeAtProbability(inputs: PricerInputs, p: number): number | null {\n\tconst { forward } = inputs;\n\tif (!(forward > 0) || !(p > 0 && p < 1)) return null;\n\tconst up = (strike: number) => upProbability(inputs, strike);\n\tlet r = 0.01;\n\twhile (up(forward * (1 - r)) < p || up(forward * (1 + r)) > p) {\n\t\tr *= 2;\n\t\tif (r > 0.64) return null;\n\t}\n\tlet lo = forward * (1 - r);\n\tlet hi = forward * (1 + r);\n\tfor (let i = 0; i < 64; i++) {\n\t\tconst mid = (lo + hi) / 2;\n\t\tif (up(mid) > p) lo = mid;\n\t\telse hi = mid;\n\t}\n\treturn (lo + hi) / 2;\n}\n\n// --- Resolving raw feed data client-side (for consumers that hold their own live oracle\n// feed and want to price with NO chain call, e.g. deepbook-app). The turnkey path is\n// `read.pricer(market)`, which reads these already resolved from the chain's `Pricer`;\n// these two helpers reproduce the on-chain resolution when you'd rather not read the chain.\n\n/** Roll `a` and `b` down by the fraction of anchored time remaining, matching the chain's\n * `roll_down_svi` (variance decays toward expiry). `remainingMs` = expiry − now;\n * `anchorTteMs` = expiry − the SVI observation's **batch envelope time** — the same clock the\n * freshness gate uses, and what the chain anchors on. It is NOT the provider's calibration\n * (model) time, which stays on the stored observation: using that rolls by the wrong\n * fraction. `read.pricer` avoids the question entirely (the chain has already rolled).\n * `rho`, `m`, `sigma` are unchanged. Feed an UNrolled provider surface; the result is what {@link upProbability}\n * expects. */\nexport function rollDown(svi: Svi, remainingMs: number, anchorTteMs: number): Svi {\n\tconst frac = anchorTteMs > 0 ? remainingMs / anchorTteMs : 0;\n\treturn { ...svi, a: svi.a * frac, b: svi.b * frac };\n}\n\n/** The forward the contract prices against: Pyth spot re-anchored by the Block-Scholes\n * basis (`spot · forward/bsSpot`), falling back to the Block-Scholes forward when Pyth is\n * absent. Pass `pythSpot <= 0` to force the fallback. NOTE: on-chain this branch is also\n * gated by the admin flag `use_pyth_spot_for_forward` (default on) and a Pyth freshness\n * window — when the flag is off or the Pyth spot is stale, the chain uses `bsForward`. If\n * you track that config/freshness, apply it before calling (or use `read.pricer`, which\n * gets the resolved forward from the chain). */\nexport function forward(pythSpot: number, bsSpot: number, bsForward: number): number {\n\tif (pythSpot > 0 && bsSpot > 0) return pythSpot * (bsForward / bsSpot);\n\treturn bsForward;\n}\n\n/** A pricer bound to one resolved snapshot: price a whole board of strikes locally, no\n * chain calls. Returned by `read.pricer(market)`; also constructable directly from inputs\n * you already hold (e.g. from a `Pricer` snapshot decoded elsewhere). */\nexport interface BoardPricer extends PricerInputs {\n\t/** P(settle > strike). */\n\tup(strike: number): number;\n\t/** P(settle < strike) = 1 − up. */\n\tdown(strike: number): number;\n\t/** P(side wins at strike). */\n\tprobability(strike: number, side: 'up' | 'down'): number;\n\t/** Probability mass in `(lower, higher]` (use `lower<=0`/`higher=Infinity` for the tails). */\n\trange(lower: number, higher: number): number;\n\t/** Strike where P(> strike) = `p`, or null if outside ±64% of forward. */\n\tstrikeAtProbability(p: number): number | null;\n}\n\n/** Build a {@link BoardPricer} from a resolved snapshot (decimal forward + rolled SVI). Pure. */\nexport function boardPricer(inputs: PricerInputs): BoardPricer {\n\treturn {\n\t\tforward: inputs.forward,\n\t\tsvi: inputs.svi,\n\t\tup: (strike) => upProbability(inputs, strike),\n\t\tdown: (strike) => downProbability(inputs, strike),\n\t\tprobability: (strike, side) => probability(inputs, strike, side),\n\t\trange: (lower, higher) => rangeProbability(inputs, lower, higher),\n\t\tstrikeAtProbability: (p) => strikeAtProbability(inputs, p),\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pricing.mjs","names":["forward"],"sources":["../../src/predict/pricing.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n// Faithful float port of `deepbook_predict::pricing::compute_nd2` as of the anchor the\n// generated bindings are pinned to (`sui-codegen.config.ts`: the `deepbook-predict-testnet`\n// deployment). `pricing.move` is untouched across the anchors this SDK has used, so the\n// formula is unchanged from earlier deployments — the SVI-adjusted digital\n// probability, WITH the skew-correction term. It operates on the pricer's\n// ALREADY-RESOLVED forward and ALREADY-ROLLED-DOWN SVI, exactly as `load_live_pricer`\n// returns them (decoded by `reads/pricing.ts`). So the two on-chain steps that pick the\n// forward (Pyth-spot vs Block-Scholes, admin flag + freshness) and roll `a`/`b` down by\n// remaining/anchored time already happened on-chain — this module never re-derives them,\n// which is what keeps it faithful.\n//\n// This is the fast client-side board pricer: read one `Pricer` snapshot, then price every\n// strike locally with no further chain calls. `read.price` / `read.quoteMint` (a chain\n// dry-run) stay the authoritative quote at trade time. Divergence vs the chain is up to\n// ~1e-4 in probability, dominated by the chain's fixed-point truncation near ATM when sigma\n// sits at its floor (float64 here is the more precise side, not the less); negligible for\n// display. `tests/testnet/pricing.test.ts` bounds it live against the deployment.\n//\n// The on-chain formula (pricing/pricing.move `compute_nd2`):\n// k = ln(strike / forward)\n// x = k - m\n// w = a + b·(ρ·x + √(x² + σ²)) // a, b already rolled down\n// d2 = −(k + w/2) / √w // clamped to ±8\n// w′ = b·(ρ + x/√(x² + σ²)) // SVI slope\n// price = N(d2) − φ(d2)·w′ / (2·√w) // the skew correction, clamped [0,1]\n\n/** Rolled-down SVI parameters for one expiry, in decimal (NOT the chain's 1e9/1e18 integer\n * scaling) — the surface AFTER Predict's remaining-time roll-down, as carried by the\n * on-chain `Pricer`. `a`, `rho`, `m` are signed; `b`, `sigma` are non-negative. */\nexport interface Svi {\n\ta: number;\n\tb: number;\n\trho: number;\n\tm: number;\n\tsigma: number;\n}\n\n/** A resolved pricer snapshot: the forward the contract prices against and its rolled SVI\n * surface, both in decimal. Produced by `read.pricer(market)`; consume via {@link boardPricer}\n * or the pure functions below. */\nexport interface PricerInputs {\n\t/** Forward price the digital settles against, in decimal (same units as `strike`). */\n\tforward: number;\n\tsvi: Svi;\n}\n\n/** Standard normal CDF via erf (Abramowitz–Stegun 7.1.26, |err| < 1.5e-7). */\nfunction normalCdf(x: number): number {\n\treturn 0.5 * (1 + erf(x / Math.SQRT2));\n}\n\n/** Standard normal PDF. */\nfunction normalPdf(x: number): number {\n\treturn Math.exp(-0.5 * x * x) / Math.sqrt(2 * Math.PI);\n}\n\nfunction erf(x: number): number {\n\tconst sign = x >= 0 ? 1 : -1;\n\tconst ax = Math.abs(x);\n\tconst t = 1 / (1 + 0.3275911 * ax);\n\tconst y =\n\t\t1 -\n\t\t((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t + 0.254829592) *\n\t\t\tt *\n\t\t\tMath.exp(-ax * ax);\n\treturn sign * y;\n}\n\n// Clamp |d2| at 8, matching the chain (`normal_cdf`/`normal_pdf` saturate beyond that).\nfunction clampD2(d2: number): number {\n\treturn d2 > 8 ? 8 : d2 < -8 ? -8 : d2;\n}\n\n/** P(settle > strike) — the UP digital, with the SVI skew correction. `inputs.svi` is the\n * already-rolled surface (no roll-down applied here). `forward` and `strike` share units.\n * Returns a probability in [0, 1]. */\nexport function upProbability(inputs: PricerInputs, strike: number): number {\n\tconst { forward, svi } = inputs;\n\tif (!(forward > 0)) return 0;\n\tif (strike <= 0) return 1; // neg-inf limit\n\tconst { a, b, rho, m, sigma } = svi;\n\tconst k = Math.log(strike / forward);\n\tconst km = k - m;\n\tconst root = Math.sqrt(km * km + sigma * sigma);\n\tconst inner = rho * km + root; // >= 0 for |rho| <= 1\n\tconst w = a + b * inner; // total variance\n\t// The chain guarantees w > 0 at every strike (assert_min_total_variance_positive at\n\t// load time), so this branch is unreachable in practice; return the variance→0 tail\n\t// limit rather than throw, so a UI never crashes on a degenerate snapshot.\n\tif (w <= 0) return k < 0 ? 1 : 0;\n\tconst sq = Math.sqrt(w);\n\tconst d2 = clampD2(-((k + w / 2) / sq));\n\tconst nd2 = normalCdf(d2);\n\tconst wPrime = b * (rho + km / root); // SVI slope × b\n\tconst price = nd2 - (normalPdf(d2) * wPrime) / (2 * sq); // skew correction\n\treturn price < 0 ? 0 : price > 1 ? 1 : price;\n}\n\n/** P(settle < strike) — the DOWN digital. Exactly `1 − up`, matching the chain's\n * `range_price(-inf, strike] = up(-inf) − up(strike) = 1 − up(strike)`. */\nexport function downProbability(inputs: PricerInputs, strike: number): number {\n\treturn 1 - upProbability(inputs, strike);\n}\n\n/** Probability mass in `(lower, higher]`, floored at 0 (matches `compute_range_price`'s\n * saturating subtraction). Use `lower <= 0` for the −∞ bound and `higher = Infinity` for +∞. */\nexport function rangeProbability(inputs: PricerInputs, lower: number, higher: number): number {\n\t// up(lower) − up(higher), where up(+inf) = 0 and up(<= 0) = 1.\n\tconst upLower = lower <= 0 ? 1 : upProbability(inputs, lower);\n\tconst upHigher = higher === Infinity ? 0 : upProbability(inputs, higher);\n\tconst d = upLower - upHigher;\n\treturn d < 0 ? 0 : d;\n}\n\n/** Binary probability at `strike` for the given side (`up` = P(>strike), `down` = 1 − up). */\nexport function probability(inputs: PricerInputs, strike: number, side: 'up' | 'down'): number {\n\tconst up = upProbability(inputs, strike);\n\treturn side === 'up' ? up : 1 - up;\n}\n\n/** Strike where P(settle > strike) = `p`, by bisection (UP is monotone-decreasing in\n * strike). Null when no crossing exists within ±64% of forward. */\nexport function strikeAtProbability(inputs: PricerInputs, p: number): number | null {\n\tconst { forward } = inputs;\n\tif (!(forward > 0) || !(p > 0 && p < 1)) return null;\n\tconst up = (strike: number) => upProbability(inputs, strike);\n\tlet r = 0.01;\n\twhile (up(forward * (1 - r)) < p || up(forward * (1 + r)) > p) {\n\t\tr *= 2;\n\t\tif (r > 0.64) return null;\n\t}\n\tlet lo = forward * (1 - r);\n\tlet hi = forward * (1 + r);\n\tfor (let i = 0; i < 64; i++) {\n\t\tconst mid = (lo + hi) / 2;\n\t\tif (up(mid) > p) lo = mid;\n\t\telse hi = mid;\n\t}\n\treturn (lo + hi) / 2;\n}\n\n// --- Resolving raw feed data client-side (for consumers that hold their own live oracle\n// feed and want to price with NO chain call, e.g. deepbook-app). The turnkey path is\n// `read.pricer(market)`, which reads these already resolved from the chain's `Pricer`;\n// these two helpers reproduce the on-chain resolution when you'd rather not read the chain.\n\n/** Roll `a` and `b` down by the fraction of anchored time remaining, matching the chain's\n * `roll_down_svi` (variance decays toward expiry). `remainingMs` = expiry − now;\n * `anchorTteMs` = expiry − the SVI observation's **provider `svi_timestamp`** (its per-update\n * source timestamp) — the same clock the freshness gate accepts, and what the chain anchors on\n * (`pricing.move`: \"One clock serves every job\"). Anchoring on the batch's ingestion time\n * instead rolls by the wrong fraction. `read.pricer` avoids the question entirely (the chain\n * has already rolled). `rho`, `m`, `sigma` are unchanged. Feed an UNrolled provider surface;\n * the result is what {@link upProbability} expects. */\nexport function rollDown(svi: Svi, remainingMs: number, anchorTteMs: number): Svi {\n\tconst frac = anchorTteMs > 0 ? remainingMs / anchorTteMs : 0;\n\treturn { ...svi, a: svi.a * frac, b: svi.b * frac };\n}\n\n/** The forward the contract prices against: Pyth spot re-anchored by the Block-Scholes\n * basis (`spot · forward/bsSpot`), falling back to the Block-Scholes forward when Pyth is\n * absent. Pass `pythSpot <= 0` to force the fallback. NOTE: on-chain this branch is also\n * gated by the admin flag `use_pyth_spot_for_forward` (default on) and a Pyth freshness\n * window — when the flag is off or the Pyth spot is stale, the chain uses `bsForward`. If\n * you track that config/freshness, apply it before calling (or use `read.pricer`, which\n * gets the resolved forward from the chain). */\nexport function forward(pythSpot: number, bsSpot: number, bsForward: number): number {\n\tif (pythSpot > 0 && bsSpot > 0) return pythSpot * (bsForward / bsSpot);\n\treturn bsForward;\n}\n\n/** A pricer bound to one resolved snapshot: price a whole board of strikes locally, no\n * chain calls. Returned by `read.pricer(market)`; also constructable directly from inputs\n * you already hold (e.g. from a `Pricer` snapshot decoded elsewhere). */\nexport interface BoardPricer extends PricerInputs {\n\t/** P(settle > strike). */\n\tup(strike: number): number;\n\t/** P(settle < strike) = 1 − up. */\n\tdown(strike: number): number;\n\t/** P(side wins at strike). */\n\tprobability(strike: number, side: 'up' | 'down'): number;\n\t/** Probability mass in `(lower, higher]` (use `lower<=0`/`higher=Infinity` for the tails). */\n\trange(lower: number, higher: number): number;\n\t/** Strike where P(> strike) = `p`, or null if outside ±64% of forward. */\n\tstrikeAtProbability(p: number): number | null;\n}\n\n/** Build a {@link BoardPricer} from a resolved snapshot (decimal forward + rolled SVI). Pure. */\nexport function boardPricer(inputs: PricerInputs): BoardPricer {\n\treturn {\n\t\tforward: inputs.forward,\n\t\tsvi: inputs.svi,\n\t\tup: (strike) => upProbability(inputs, strike),\n\t\tdown: (strike) => downProbability(inputs, strike),\n\t\tprobability: (strike, side) => probability(inputs, strike, side),\n\t\trange: (lower, higher) => rangeProbability(inputs, lower, higher),\n\t\tstrikeAtProbability: (p) => strikeAtProbability(inputs, p),\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balances.mjs","names":["account.loadAccount","account.balance","predictAccount.hasPosition"],"sources":["../../../src/predict/reads/balances.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 { deriveAccountWrapperIdFrom } from '../tx/common.js';\nimport { accountMoveCalls as account } from '../../account.js';\nimport * as predictAccount from '../../contracts/deepbook_predict/predict_account.js';\nimport { inspectReturns, type ReadClient } from './inspect.js';\nimport { parseU64LE } from './parse.js';\n\n// An owner's stored account balance for `coinType` (the deployment's quote coin,\n//
|
|
1
|
+
{"version":3,"file":"balances.mjs","names":["account.loadAccount","account.balance","predictAccount.hasPosition"],"sources":["../../../src/predict/reads/balances.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 { deriveAccountWrapperIdFrom } from '../tx/common.js';\nimport { accountMoveCalls as account } from '../../account.js';\nimport * as predictAccount from '../../contracts/deepbook_predict/predict_account.js';\nimport { inspectReturns, type ReadClient } from './inspect.js';\nimport { parseU64LE } from './parse.js';\n\n// An owner's stored account balance for `coinType` (the deployment's quote coin,\n// USDC on testnet, unless the caller asks for another). Chains `account::load_account(wrapper)` →\n// `account::balance<T>(account, root, clock)`; the u64 is command 1's return —\n// see packages/account/sources/account.move:{80,86}. The clock is auto-injected by\n// the generated `balance` wrapper; the wrapper id is derived off-chain (no read).\nexport async function accountBalance(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\towner: string,\n\tcoinType: string,\n): Promise<bigint> {\n\tconst tx = new Transaction();\n\tconst acct = tx.add(\n\t\taccount.loadAccount({ config, arguments: { self: deriveAccountWrapperIdFrom(config, owner) } }),\n\t);\n\ttx.add(account.balance({ config, typeArguments: [coinType], arguments: { self: acct } }));\n\tconst cmds = await inspectReturns(client, tx);\n\treturn parseU64LE(cmds[1][0]);\n}\n\n// Whether the owner's account still holds `orderId` on `marketId`. The cheap\n// on-chain validator for app-stored order ids (stale after a full close or a\n// partial-close replacement — see RedeemReceipt.replacementOrderId). Chains\n// `account::load_account(wrapper)` → `predict_account::has_position(account,\n// market_id, order_id)` — see packages/predict/sources/predict_account.move:85.\nexport async function hasPosition(\n\tclient: ReadClient,\n\tconfig: GeneratedConfig,\n\towner: string,\n\tmarketId: string,\n\torderId: bigint,\n): Promise<boolean> {\n\tconst tx = new Transaction();\n\tconst acct = tx.add(\n\t\taccount.loadAccount({ config, arguments: { self: deriveAccountWrapperIdFrom(config, owner) } }),\n\t);\n\ttx.add(\n\t\tpredictAccount.hasPosition({\n\t\t\tconfig,\n\t\t\targuments: { account: acct, expiryMarketId: marketId, orderId },\n\t\t}),\n\t);\n\tconst cmds = await inspectReturns(client, tx);\n\treturn (cmds[1][0][0] ?? 0) !== 0; // BCS bool: 1 byte\n}\n"],"mappings":";;;;;;;;AAeA,eAAsB,eACrB,QACA,QACA,OACA,UACkB;CAClB,MAAM,KAAK,IAAI,aAAa;CAC5B,MAAM,OAAO,GAAG,IACfA,YAAoB;EAAE;EAAQ,WAAW,EAAE,MAAM,2BAA2B,QAAQ,MAAM,EAAE;EAAE,CAAC,CAC/F;AACD,IAAG,IAAIC,QAAgB;EAAE;EAAQ,eAAe,CAAC,SAAS;EAAE,WAAW,EAAE,MAAM,MAAM;EAAE,CAAC,CAAC;AAEzF,QAAO,YADM,MAAM,eAAe,QAAQ,GAAG,EACtB,GAAG,GAAG;;AAQ9B,eAAsB,YACrB,QACA,QACA,OACA,UACA,SACmB;CACnB,MAAM,KAAK,IAAI,aAAa;CAC5B,MAAM,OAAO,GAAG,IACfD,YAAoB;EAAE;EAAQ,WAAW,EAAE,MAAM,2BAA2B,QAAQ,MAAM,EAAE;EAAE,CAAC,CAC/F;AACD,IAAG,IACFE,cAA2B;EAC1B;EACA,WAAW;GAAE,SAAS;GAAM,gBAAgB;GAAU;GAAS;EAC/D,CAAC,CACF;AAED,UADa,MAAM,eAAe,QAAQ,GAAG,EAChC,GAAG,GAAG,MAAM,OAAO"}
|
|
@@ -3,8 +3,8 @@ import { parseOptionalId, parseOptionalU64, parseU64LE, parseVectorOfIds } from
|
|
|
3
3
|
import { POS_INF_TICK } from "../ticks.mjs";
|
|
4
4
|
import { admissionTickSize, currentNav as currentNav$1, expiry, mintPaused, referenceTick as referenceTick$1, tickSize } from "../../contracts/deepbook_predict/expiry_market.mjs";
|
|
5
5
|
import { loadLivePricer } from "../tx/trade.mjs";
|
|
6
|
-
import { activeExpiryMarkets } from "../../contracts/deepbook_predict/plp.mjs";
|
|
7
6
|
import { rangePrice } from "../../contracts/deepbook_predict/pricing.mjs";
|
|
7
|
+
import { activeExpiryMarkets } from "../../contracts/deepbook_predict/plp.mjs";
|
|
8
8
|
import { strikeFromTick } from "../../contracts/deepbook_predict/range_codec.mjs";
|
|
9
9
|
import { expiryMarketId as expiryMarketId$1 } from "../../contracts/deepbook_predict/registry.mjs";
|
|
10
10
|
import { Transaction } from "@mysten/sui/transactions";
|