Predict Positions SDK
The position functions in the DeepBook Predict SDK place and follow queued orders, quote a mint, claim a position held in the account, list the positions an account holds, and decode the receipt of each trade. Predict explains the mechanics that these builders wrap.
Both networks run Predict protocol version 4, where every trade is a queued order, so use the functions under Queued orders. Mainnet needs version 2.8.0 or later, as DeepBook Predict SDK explains. read.executionMode() confirms which path a network is on.
Every function is a member of client.predict, which DeepBook Predict SDK shows how to register. Each builder and quote that targets a market takes the market as a market descriptor: an object that names the market by its underlying, expiryMs, and optional marketId, plus the strike, as a binary or range position, where the call needs one. The function then reads the chain to resolve the market object and caches it per client, so those functions are asynchronous. The SDK takes and returns amounts as decimal USDC values and converts them to 6-decimal base units; see Units.
How do queued orders work?
A mint or an early sell is a queued order. You place it with its limits and its money, it waits in its market's queue until Pyth Lazer publishes its signed price for the order's price instant, τ, about 800 ms after placement, and a keeper or any other caller then fills it at that price or refunds it.
A queued order differs from an immediate trade in 4 ways:
- Placement and fill are separate transactions. The enqueue debits the order's budget and a flat order fee into the order's escrow and returns a record ID. The fill lands about a second later in another caller's transaction. Unused budget comes back at the fill.
- The slippage is cents per contract.
slippageCentsbounds how far the all-in price per$1of payout might rise above the quote's price without the fee subsidy, soslippageCents: 10lets a contract quoted at 42 cents before the subsidy fill at up to 52 cents, fees included. It is never a percentage.'auto'sizes it from a model of the price's movement until τ. - A filled mint is an Open record. It stays in the market's queue rather than entering the account, so
read.positionsdoes not list it. Follow it by its record ID, sell it with another queued order, and let the queue's settlement walk pay it after expiry. - A refund is a normal outcome. An order that misses its limits at τ, or that the market cannot cover, gets a refund with a reason code, and a refund for the order's own limits or for admission keeps the order fee.
read.executionMode
Use read.executionMode to find out which trade path a network is on. It returns a Promise<ExecutionMode>, one of 'immediate', 'awaiting-cutover', 'delayed', 'unsupported', or 'retired'. It reads the ProtocolConfig version watermark and checks whether the configuration records delayed execution. 'retired' means a later upgrade raised a version floor above the code this SDK release calls, so upgrade the SDK.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.read.planMint
Use read.planMint to build a purchase form's state and the limits a queued mint carries. It returns a Promise<MintPlan>. It quotes the order at the current price, for a visitor without an account too, turns the slippage into the enqueue's limits, and runs the enqueue builder's preflight, so accepting is false, with a typed refusal, when the order would be refused now. The preflight covers the queue gates, the balance, and the order's limits, not every onchain check.
It takes these parameters:
owner: The address that owns the account.m: The market and strike, as a binary or range market descriptor. Snap a numeric strike onto the admission grid withsnapStrike, and prefer a strike near the money, because admission refuses an entry probability outside the market's band.opts: APlanMintOptionsobject: eitheramount, an all-in spend in USDC that includes the order fee unlessorderFeeis'exclusive', orquantity, an exact payout, plusslippageCents.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.A MintPlan carries potentialPayout, minPayout at the worst price, payoutMultiple, pricePerContract, worstPricePerContract, orderFee, budget, totalDebit, the account's balance, maxNow, the largest amount the market and the balance take now, a timing preview of τ and the deadline, and the order the plan builds. The plan sizes the limits from the price without the fee subsidy, because placement checks the order without it. planMint throws a PredictPreflightError with code entry-band for a strike outside the band, min-premium for a budget that buys less than 1 USDC of premium, and past-cutoff for a market past its expiry, where the chain has no live price to quote. Near the cutoff, the plan's refusal is past-cutoff instead, and the preview runs on the device clock, so the chain can still refuse an order placed in the last seconds.
tx.enqueuePlan
Use tx.enqueuePlan to queue the order a plan describes. It returns a Promise<QueuedOrderPlan>, the transaction and a preview of τ, the deadline, the escrow, the order fee, and whether a sell needs funding. Pass the descriptor you planned the mint with, or the coordinates a sell plan took. It reads the gates and the balance again and throws a PredictPreflightError for a refused plan or a balance that now escrows less than the plan's budget, and a PredictInputError for an order fee that rose since the plan or for another owner, market, strike, or record than the plan's target. Each enqueue it builds starts with a check that aborts the transaction if the order desk's fee rose between building and execution.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.The lower-level builders tx.enqueueMint, tx.enqueueMintAmount, tx.enqueueMintCost, and tx.enqueueSell take the limits directly, in SDK units, and run the same preflight. Every queued mint needs a finite cost cap, because the chain aborts a zero or unlimited max_cost with EMintCostCapRequired.
The preflight codes are not-live, no-queue, retired, paused, stuck, past-cutoff, queue-full, account-cap, fee, market-cash, min-premium, entry-band, cost-above-payout, below-min-sell, record-not-open, and not-record-owner. fee means the balance cannot cover the order fee, or the plan's whole debit, so prompt a deposit. Some checks run only onchain at placement, such as the market's SVI age and room in the payout tree for a new strike, and those abort the transaction rather than raising a preflight code. describePredictError turns any of these aborts into readable text.
decode.enqueue
Use decode.enqueue to read the record ID, τ, deadline, escrow, and order fee from the enqueue's OrderEnqueued event. It throws unless the result holds exactly one, and decode.enqueues returns every enqueue in a batched transaction. Persist recordId: it is the handle for everything that follows, and nothing onchain lists an account's queue records for you.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.read.waitForOutcome, read.order, and read.orders
Use read.waitForOutcome to poll a record until it is filled, refunded, or closed. It returns a Promise<QueuedOrderOutcome> whose outcome is 'filled', 'refunded', 'closed', 'gone', or 'timeout', with the record's order view. It polls every 250 ms by default for up to 30 seconds, and keeps polling a record the full node does not show yet. After expiry, 'gone' for a filled record means the queue paid it out and deleted it, not that you lost the order.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.read.order(m, recordId) and read.orders(m, recordIds) read records without waiting. Each record's view.state is 'placed', 'priced', 'refunding', 'filled', 'refunded', or 'closed'. A filled record's view.position carries the packed orderId and the held quantity, and view.sellable reports whether you can sell it now. The record ID identifies the queued order in its market's queue, and the order ID identifies the position the record holds, which cost.settledPayout takes. A keeper that commits a price and fills in one transaction moves an order from 'placed' straight to 'filled', so do not count on seeing 'priced'.
read.planSell
Use read.planSell to plan an early sell of an Open record. It returns a Promise<SellPlan> with the proceeds at the current price, net after the order fee, the minProceeds and minNet floors at the worst price the slippage allows, and the order for tx.enqueuePlan. It throws PredictPreflightError with code record-not-open for a record that is not Open. A sell pays the order fee whatever it returns, so net is negative for a sell worth less than the fee. read.quoteSell returns the same quote without the plan.
It takes these parameters:
owner: The address that owns the account and the record.m: The market'sunderlying,expiryMs, and optionalmarketId.opts: APlanSellOptionsobject with therecordId, the payoutquantityto sell, andslippageCents.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.The whole position moves into the sell's own record, so after a sell, including a partial one, the remainder lives under the sell's record ID. A sell the market cannot cover at the fill gets a refund, and the position returns to an Open record. When a sell's cash need is above the market's spare cash, tx.enqueueSell appends rebalance_expiry_cash after the enqueue by default, and its fundMarket option controls that.
tx.refund, tx.claimParked, and tx.payOpen
Keepers refund an order still unfinished 5 seconds after its τ, so these builders are recovery paths, and each is permissionless:
tx.refund(m, { maxOrders })refunds the market's orders past their deadline. Offer it only when a record'sview.canRequestRefundistrue, and never prepend it to other transactions. It needs no account and works during the emergency freeze.tx.claimParked(m, recordId)sends a finished record's parked USDC, a refund or change its receive address could not take while denied, to that address once it is clear.tx.payOpen(m, recordId)pays a settled Open record that the settlement walk skipped.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.read.settlement and cost.settledPayout
After expiry, read.market, read.price, and the quotes abort with ELivePricingExpired, and the queue's keeper settles the market, pays each Open record, and deletes it, usually within seconds. read.settlement(m) still works: it returns the settlement price as a decimal and as settlementPriceRaw, with tickSizeRaw, or settled: false until a keeper settles. Pass the stored orderId with those 2 raw values to cost.settledPayout for what the position is owed at that price, in raw USDC. That is a calculation, not proof of payment: the payout walk's OpenRecordSettled event is the payment to the account's receive address, and a record the walk skipped, because the market was short of cash or the address was denied, emits OpenRecordPayoutSkipped instead and stays Open until tx.payOpen pays it. read.pendingFunds(owner) reports refunds, sell proceeds, and payouts that reached the account but are not settled into its stored balance yet, which read.balance already counts.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.Queue decoders
decode.queueEvents returns every queue event in a result, tagged and in chain order, and queue.reduceOrderEvents folds a stream of them into the same order states the reads return, for an indexer or an event feed. The typed decoders are decode.cohortCommits, decode.queuedFills, decode.queuedRefunds, decode.openRecordPayouts, decode.marketPayoutsCompleted, decode.recordFunds, and decode.queueOps. They match the order-flow package's events against its original ID, and decode.queuedFills sits beside decode.mints and decode.redeems, which still read the Predict OrderMinted and LiveOrderRedeemed that every fill emits.
Queued-order examples
The following sample checks the execution mode, picks a strike near the money, plans an all-in budget mint, queues it, and waits for the outcome:
examples/deepbook-predict/src/queue-mint.ts. You probably need to run `pnpm prebuild` and restart the site.The following sample sells an Open record early, offers a manual refund only for an overdue order, and reads a settled result:
examples/deepbook-predict/src/queue-sell.ts. You probably need to run `pnpm prebuild` and restart the site.How to quote a mint
read.quoteMint and read.quoteMintCost quote a mint without placing it. They read Predict's protocol version 4 quote functions and preview a queued fill at the current clock: the quote has queued: true, fees.penalty is 0, and the flat order fee is in orderFee, on top of cost. The fill itself prices at its committed Pyth tick, so a quote is an estimate. For an order form, read.planMint is the fuller tool, because it adds the slippage limits and the enqueue builder's preflight. Both quotes read the owner's account, so it must exist, and both throw PredictInputError when the configuration lacks the order-flow package or its desk. Neither checks that the balance covers the order, so use a plan or the enqueue preflight for that.
read.quoteMint
Use read.quoteMint to quote an exact payout quantity. It returns a Promise<MintQuote>, priced through quote_mint_for_account, so the quote carries the account's builder fee. An exact-quantity quote is not capped by the account's balance. It takes the owner, the market descriptor m, and an object with the payout quantity, a whole lot of 0.01 USDC.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.MintQuote carries these fields:
| Field | Meaning |
|---|---|
entryProbability | Fill price between 0 and 1 per 1 USDC of payout |
premium | Premium alone, before fees |
fees | Fee breakdown by component, in the following list |
cost | All-in account debit for the fill, which the order's maxCost caps |
quantity | Payout quantity the quote priced |
raw | Exact bigint amounts for premium, cost, quantity, and entryProbability |
feesExact | Always true, because the fees come from the chain's own quote functions |
queued | true when the quote previews a queued fill |
orderFee | The flat order fee, charged once per order on top of cost, on a queued preview |
fees breaks the debit into these components:
trading: The trading fee before the sponsor subsidy, summed over the finite boundaries of the range.subsidy: The sponsor-funded part of the trading fee, which you do not pay.builder: The builder add-on, 0 when the account carries no builder code.penalty: The retired congestion surcharge, 0 on a queued preview.referral: The part of the trading fee that the protocol routes to a referrer, 0 unless the account has a referrer.inventoryImpact: The inventory-impact charge, a separate charge thatcostincludes.
cost is premium + (trading - subsidy) + builder + penalty + inventoryImpact, and referral is a part of the trading fee that the protocol routes to a referrer, not an extra debit.
read.quoteMintCost
Use read.quoteMintCost to see what an all-in budget buys. It returns a Promise<MintQuote>, priced through quote_mint_exact_cost_for_account at min(spend, available - orderFee), the budget an enqueue escrows, so this quote is capped by the account's balance. It takes the owner, the market descriptor m, and an object with spend and minQuantity. Read quantity from it to set a minQuantity floor on the queued order.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.For a preview that costs no chain call at all, Predict Cost SDK runs the same budget search locally from a pricer snapshot.
Why do the immediate builders abort?
tx.mint, tx.mintAmount, and tx.mintCost build the retired immediate mints, tx.redeem builds the retired live close, and read.quoteRedeem quotes it. Every call they build aborts with EDelayedExecutionRequired on both networks, and version 2.7.0 deprecates the 5 functions. Build every trade with tx.enqueuePlan or the enqueue* builders instead, and quote an early sell with read.planSell or read.quoteSell.
tx.claimSettled
Use tx.claimSettled to claim a position held in the account, which only an immediate mint from before the cutover created, once its market has settled. It is the SDK form of the owner-authorized redeem_settled and returns a Promise<Transaction>. A settled claim always closes the order in full, so the builder takes no quantity, and the order ID identifies the position, so it takes no side or strike. The payout is the full quantity when the settlement price lands inside the position's range and 0 otherwise. It does not pay a queued fill, which the queue's settlement walk pays instead.
Before settlement the claim aborts with EMarketNotSettled, and expiry alone does not settle a market. Settlement runs through the permissionless expiry_market::try_settle, which the SDK does not build. The SDK also builds no redeem_settled_permissionless, which only allowlisted keepers can call.
It takes these parameters:
owner: The address that owns the account and signs the transaction.m: The market'sunderlying,expiryMs, and optionalmarketId.opts: An object with the position'sorderId.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.How to read account positions
The SDK reads positions straight from the account's onchain position table, so neither read needs an indexer. The fastest path is to persist the order ID from each mint receipt and replace it after each partial close; use these reads to recover a lost ID or to validate a stored one.
read.positions
Use read.positions to list every open position an owner's account holds. A queued fill is not one of them: it is an Open record in the market's queue, which read.order reads. It returns a Promise<OpenPosition[]>, an entry for each position, each carrying the marketId and orderId that tx.redeem, tx.claimSettled, and read.hasPosition take. It returns an empty array for an owner with no Predict account or no Predict positions.
The SDK caches the account and table IDs per owner once the table exists, so later reads cost 1 request per page of positions. A transport failure throws rather than reading as an empty list, and a table that still has entries after 10 pages throws a plain Error. OpenPosition carries no underlying or expiry, so supply those yourself when you build the descriptor for a close.
It takes this parameter:
owner: The address that owns the account.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.packages/deepbook-v3/src/predict/reads/positions.ts. You probably need to run `pnpm prebuild` and restart the site.read.hasPosition
Use read.hasPosition to check whether an owner's account still holds a specific order on a specific market. It returns a Promise<boolean>. It is the cheap check for an order ID your app stored, which goes stale after a full close or after a partial close replaces it. The read loads the owner's wrapper, so call it for an account that exists.
It takes these parameters:
owner: The address that owns the account.marketId: The object ID of the market'sExpiryMarket.orderId: The order ID to check, as abigint.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.How to decode trade receipts
The receipt decoders turn an executed transaction's events into typed receipts, with no network call. Include events when you execute the transaction, and pass the result. Without events, a singular decoder throws PredictInputError because it finds no matching event, and a plural decoder returns an empty array. A decoder also throws PredictInputError when a matching event carries no Binary Canonical Serialization (BCS) payload. Each singular decoder throws PredictInputError unless the result holds exactly 1 matching event, and each plural decoder returns every matching receipt in event order, for a transaction that batches several trades. DeepBook Predict SDK covers how the decoders read events.
decode.mint and decode.mints
Use decode.mint to read the receipt of a queued mint fill, and decode.mints to read every fill in a single transaction, such as a keeper's resolve. Each decodes the OrderMinted event and returns a MintReceipt, or an array of them. Keep orderId, which cost.settledPayout takes to show the position's settled result. positionRootId stays stable across partial-close replacements, quantity is the quantity the contract actually minted, which it rounds down to a lot for tx.mintAmount, and raw carries every fee component as an exact bigint.
It takes this parameter:
r: The executed transaction result, including its events.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.packages/deepbook-v3/src/predict/decode.ts. You probably need to run `pnpm prebuild` and restart the site.decode.redeem and decode.redeems
Use decode.redeem to read the receipt of a queued sell fill, and decode.redeems to read every sell fill in a single transaction. Each decodes the LiveOrderRedeemed event and returns a RedeemReceipt, or an array of them. After a partial close, replacementOrderId carries the order ID of the remaining quantity: store it in place of the old one, or the next close targets an order that no longer exists. It is null after a full close, and proceeds is the net amount the close credits, which the SDK computes the same way as in RedeemQuote.
It takes this parameter:
r: The executed transaction result, including its events.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.packages/deepbook-v3/src/predict/decode.ts. You probably need to run `pnpm prebuild` and restart the site.decode.claim and decode.claims
Use decode.claim to read the receipt of a settled claim, and decode.claims to read every claim in a single transaction. Each decodes the SettledOrderRedeemed event and returns a ClaimReceipt, or an array of them, with the payout alongside the market, account, and order identifiers.
It takes this parameter:
r: The executed transaction result, including its events.
packages/deepbook-v3/src/predict/client.ts. You probably need to run `pnpm prebuild` and restart the site.packages/deepbook-v3/src/predict/decode.ts. You probably need to run `pnpm prebuild` and restart the site.