Predict Cost SDK
The cost namespace on @mysten/deepbook-v3/predict prices a Predict trade without touching the chain. It is an exact integer port of the deployed fee path, not an estimate: feed it the same inputs the execution sees and it returns the same raw amounts the contract charges. That makes it the right tool for an order ticket that has to re-price on every keystroke, for a board of candidate strikes, and for sizing a spend before a transaction exists.
It pairs with the pricing namespace, which supplies the probabilities. pricing answers what this range is worth, and cost answers what it debits.
import { cost, pricing } from '@mysten/deepbook-v3/predict';
A local preview is arithmetic, not a preflight. cost never reads the chain, so it cannot see your balance, your builder code, the expiry's cash backing, a paused market, or the no-trade window, and it cannot tell you whether the probabilities you handed it are fresh. Confirm every trade with read.planMint or read.planSell, which quote against real state and run the enqueue builder's preflight.
What does the arithmetic need?
Every entry point in this namespace takes the same 3 kinds of input.
The market's fee policy
FeePolicy is the market's own fee snapshot, taken at market creation. A market created before an admin changed a rate keeps the old one, so read it from that market's MarketCreated event rather than assuming it:
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.cost.SHIPPED_FEE_POLICY is the template the contracts compile in: a 10 percent Bernoulli fee, a 2.2 percent per-leg floor, a one-day ramp window that is inert at a 1.0 multiplier, a 1 to 99 percent entry band, and inventory impact disabled. Neither deployment runs it. Both charge a 20.4 percent base fee, ramp the fee to 3 times over the last 60 seconds, and admit entries in a narrow band, 15 to 85 percent, so a preview built from it comes out low. Version 2.7.0 adds read.feePolicy(market), one object read that returns the policy a market snapshotted at creation, ready to pass as fees. Use that for a live market:
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.The range's boundary probabilities
Predict charges a trading fee at each finite boundary of a range, so the namespace works in boundary probabilities rather than a single range probability. null is an infinite side: the negative infinity lower bound of a down position, and the positive infinity higher bound of an up position. Neither pays a fee leg.
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.lowerUp holds the lower boundary's probability and higherUp holds the higher boundary's probability. A down position sets lowerUp to null, an up position sets higherUp to null, and a range between 2 finite strikes sets both. cost.rangeProbability returns the range's own probability, lowerUp minus higherUp, counting a null lower side as 1 and a null higher side as 0.
Pass either shape as probabilities:
- Raw boundary probabilities you already hold, as 1e9-scaled
bigintvalues. UseprobabilityToRawon a value fromread.price. This is the exact path, and the result setsexactProbabilitiestotrue. - A local pricer snapshot plus the range's strikes in USD, as
{ pricer, lower, upper }.costprices the boundaries itself with the same float math thepricingnamespace uses, so the result is close but not bit-exact, andexactProbabilitiesisfalse.
exactProbabilities reports only how the probabilities arrived. It does not certify that they came from the chain, that they are fresh, or that any other input matches execution state. On either path, treat the result as a preview and confirm it with a chain quote before you submit.
The book, when inventory impact is on
Predict prices the inventory-impact charge against the market's payout tree, so a policy with a non-zero inventoryImpactMaxRate needs a book argument: maxPayout, totalPayout, and the payout peak inside the candidate range, plus the peak outside it for a close. Both deployments ship with impact disabled, so you do not need book until an admin turns it on. To check, read inventoryImpactMaxRate on the market's fee policy. A non-zero value means you pass book.
How do I preview a mint's cost?
The namespace has 2 mint previews: cost.mintCost for an exact payout quantity and cost.mintCostForBudget for an all-in budget.
cost.mintCost
Use cost.mintCost to price an exact payout quantity, the local twin of an exact-quantity queued mint priced at the clock. It mirrors the contract's compute_mint_quote, including the admission checks, and throws a PredictInputError naming the abort the chain would have raised: the entry-probability band on each finite leg and on the range, the 1 USDC minimum premium, the lot grid set by cost.POSITION_LOT_SIZE, and the rule that a contract must never cost more than it can pay out. Predict describes the Move abort codes.
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.MintCost decomposes the debit in human units and carries the exact integers alongside. costPerContract is the all-in price of $1 of payout, which is the number to compare across strikes, and payoutMultiple is its reciprocal, the figure an order ticket usually shows:
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.fees here has no referral member, unlike the chain quote's. A referral is a split of protocol proceeds, not a trader debit, so it never changes cost.
A full mint preview runs in this order:
- Read the market's fee policy with
read.feePolicy(market)on version 2.7.0 or later, or from the market'sMarketCreatedevent on an earlier version. - Read the range's price with
read.priceand convert each finite boundary withprobabilityToRaw. - Call
cost.mintCostwith the policy, the market'sexpiryMs, the probabilities, and the quantity. - Before submitting, confirm the trade with
read.planMint, which runs the enqueue builder's preflight.
The example passes cost.SHIPPED_FEE_POLICY only to keep it short. That template previews low, so for a live market pass the policy from read.feePolicy(market) as fees instead.
import { cost, probabilityToRaw } from '@mysten/deepbook-v3/predict';
const { up } = await client.predict.read.price(descriptor);
const preview = cost.mintCost({
fees: cost.SHIPPED_FEE_POLICY,
expiryMs: market.expiryMs,
probabilities: { lowerUp: probabilityToRaw(up), higherUp: null },
quantity: 100,
});
console.log(preview.cost, preview.payoutMultiple, preview.exactProbabilities); // true
cost.mintCostForBudget
Use cost.mintCostForBudget to size a fill inside an all-in budget. It runs the same lot search as the contract's mint_exact_cost over the same cost function, so the quantity it reports is the quantity that entrypoint would size and the cost it reports is the debit that entrypoint would take.
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.Pass accountBalance to reproduce the cap the chain applies before sizing, which also lets U64_MAX mean your whole balance. The result adds the budget figures an order preview needs:
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.The same 3 sizing limits that qualify the onchain entrypoint qualify this one, because it is the same search:
- The one-lot remainder holds only when the budget binds. Where the budget is what limits the fill,
unspentBudgetis less than the incremental all-in cost of one more lot. A fill limited by the maximum-payout bound or saturated at the 32-bit lot cap can leave much more. - The maximum-payout step-down is best effort. It preserves the contract's own fallback, rounding included, so it can miss a larger admissible fill or reject a
minQuantitythat another fill would have met. - Backing is not a sizing input. Neither this function nor the chain quote preflights the expiry's cash backing or its exposure-index capacity.
Queue the order with tx.enqueuePlan or tx.enqueueMintCost, which sizes the fill at its price instant rather than at the preview's prices. This preview itself is pure arithmetic, so it needs no deployment at all.
What does closing a live position pay out?
A live close credits proceeds, and cost.redeemLiveProceeds previews them locally.
cost.redeemLiveProceeds
Use cost.redeemLiveProceeds to price closing a live position, the mirror of cost.mintCost. It charges the same per-boundary trading fee, the same builder fee, and the same congestion surcharge, and it credits the inventory-impact term as a rebate rather than charging it. There is no sponsor subsidy on a close, because incentives subsidize mints only. It clamps each deduction at the payout remaining after the ones before it, exactly as the contract clamps them, so a close can never cost more than it releases.
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.Price it against the order's own range, which is the pair of boundaries you minted it over, because that is what redeem_live reprices. Supply positionQuantity to validate the close and get the remainder back:
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.proceeds is the figure the real call compares min_proceeds against. A preview does not guarantee execution at that amount, so take the floor a queued sell sends from read.planSell, which applies your slippage to a fresh chain quote.
Order helpers
An order ID packs the position's durable terms, and 2 helpers unpack the parts a close preview needs. Use them to turn a position from read.positions into redeemLiveProceeds inputs:
cost.decodeOrderRange(orderId, lotSize?)returns the order'slowerTick,higherTick, and mintedquantity. AlowerTickof0is negative infinity and ahigherTickofcost.POS_INF_TICKis positive infinity.cost.orderStrikes(range, tickSizeRaw)converts that tick pair to strikes in USD, withnullfor each infinite side, which is the shape the{ pricer, lower, upper }probability source takes.
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.Which fee components can I compute client-side?
The namespace exports each term of the fee path on its own, for a UI that itemizes a charge or a test that pins one. Design explains what each one is for:
| Function | Move counterpart | Returns |
|---|---|---|
cost.bernoulliFeeRate(baseFee, probability) | strike_exposure_config::raw_bernoulli_fee_rate | The rate before the floor and the ramp, zero at the certain ends |
cost.expiryFeeMultiplier(policy, timeToExpiryMs) | strike_exposure_config::expiry_fee_multiplier | 1.0 outside the ramp window, rising linearly to the maximum at expiry |
cost.tradingFee(policy, boundaries, quantity, timeToExpiryMs) | The per-leg trading fee | One leg per finite boundary, each floored and ramped on its own |
cost.builderFee(fee, quantity, hasBuilderCode) | expiry_market::builder_fee_amount | The builder's cut of the trading fee, capped as a share of quantity |
cost.feeIncentiveSubsidy(fee, feeIncentiveBalance, rate) | The sponsor's share of a mint fee | The part of the trading fee the trader does not pay. rate defaults to 20 percent |
cost.settledPayout(orderId, settlementPriceRaw, tickSizeRaw) | What an order pays at a settlement price | Mirrors strike_exposure::settled_order_payout. Pass read.settlement's raw price and tick size. It computes what is owed, and the queue's OpenRecordSettled event is the payment |
cost.congestionPenaltyRate(policy, state, gasPrice) | The gas-price congestion surcharge | A per-unit rate, not an amount, so a budget search can re-price it at every candidate |
cost.inventoryImpactPotential(policy, liability) | strike_exposure::inventory_impact_potential_for_liability | The book-level potential whose difference a trade pays |
cost.mintInventoryImpact(...) | The mint-side impact charge | The charge added to a mint's debit |
cost.closeInventoryImpact(...) | The close-side impact rebate | The rebate credited on a live close |
cost.rangeProbability(boundaries) | The range's own probability | lowerUp minus higherUp, saturating at zero |
cost.boundaryProbabilities(pricer, lower, upper) | The local pricer | Boundary probabilities from a snapshot and a pair of strikes |
The fee subsidy rate became admin-set in Predict protocol version 4, so version 2.7.0 takes it as an input: pass feeIncentiveSubsidyRate, the raw 1e9-scaled protocol_config::fee_incentive_subsidy_rate, which read.queue(market).protocol.feeIncentiveSubsidyRate returns. If you omit it, the functions assume 20 percent, which misquotes the subsidy whenever the live rate differs, unless the market's incentive balance caps the subsidy under both rates. Protocol version 4 retires the congestion surcharge, so leave penaltyRate at its default of 0. The namespace also exports the scale constants: cost.FLOAT_SCALING, cost.POSITION_LOT_SIZE, cost.MIN_PREMIUM, cost.BUILDER_FEE_MULTIPLIER, cost.MAX_BUILDER_FEE_RATE, cost.FEE_INCENTIVE_SUBSIDY_RATE, which 2.7.0 deprecates, and cost.MAX_QUANTITY_LOTS.
packages/deepbook-v3/src/predict/cost.ts. You probably need to run `pnpm prebuild` and restart the site.Related links
- Predict Positions SDK: the builders and chain quotes these previews stand in for.
- Predict Markets SDK:
read.pricer, the snapshot these functions price from, and thepricingnamespace. - Design: what each fee component charges for.
- Predict: the Move entrypoints and their abort codes.