OrderBuilder class for more in-depth details on each function.4000ms, so every tx.wait() the SDK does internally (in setApprovals, runApprovals, cancelOrders, redeemPositions, etc.) can take up to ~4s to notice a mined transaction. On a fast chain like BNB, lower it to ~300ms so confirmations feel near-instant:BrowserProvider (e.g. MetaMask): provider.pollingInterval = 300.ConditionalTokens) and ERC-20 (USDT). This can be achieved by sending a transaction to the respective contracts (see the Contracts section) and approving both the CTF_EXCHANGE and the NEG_RISK_CTF_EXCHANGE or via the SDK utils.Constants.ts file or in the Deployed Contracts documentation.setApprovals() sets every approval for every market type in a single call. For most apps the scoped-approvals API is the better fit, and is the recommended approach whenever you build an approval UI. It returns only the approvals a given operation needs, as a list of plain, self-describing steps you can render as a checklist, pre-check, run with live progress, and gate on user confirmation.ApprovalScope (operation, plus isNegRisk / isYieldBearing, and an optional side to narrow a TRADE).ApprovalStep[] with getApprovalSteps (one operation) or getAllApprovalSteps (everything). Both are pure (no signer, no network access), so you can render the checklist before the wallet is connected.runApprovals, or drive them yourself with checkApprovals / setApproval.isNegRisk and isYieldBearing describe the market and can be fetched from the GET /markets (or GET /categories) endpoint.getApprovalSteps returns the minimal, ordered set for the operation. The labels below are the SDK's default copy (they match the Predict web app). Operations that need no approval return an empty array. |TRADE scope covers both order directions by default. Pass side: Side.BUY for just the collateral allowance, or side: Side.SELL for just the ERC-1155 approval. CONVERT is neg-risk only and throws InvalidApprovalOperationError for a standard market.ApprovalStep shapelabel/description are sensible English defaults. For custom wording or i18n, key your own copy off the stable id and ignore them.OrderBuilder you use to check and run them.getApprovalSteps and getAllApprovalSteps don't touch the chain, so you can also call them on a signer-less builder (OrderBuilder.make(ChainId.BnbMainnet)) to render the checklist before the wallet is connected. You'll need a signer for everything after (checkApprovals, setApproval, runApprovals).runApprovals(steps, opts) runs the steps in order, deduplicating by id (so you can safely pass a union of scopes or a curated subset). Options:skipSatisfied (default true): pre-check each step on-chain and skip the ones already in place.stopOnError (default true): stop after the first failed step.onProgress: a callback invoked as each step transitions, receiving { step, status, transaction? }.onProgress reports each step through this lifecycle:| Status | Meaning |
|---|---|
checking | reading on-chain whether it's already approved (only when skipSatisfied) |
skipped | already in place, nothing sent |
submitting | transaction sent, awaiting confirmation |
confirmed | the transaction succeeded |
failed | the transaction reverted or failed |
{ success, steps }, where each entry is { step, status: "skipped" | "confirmed" | "failed", transaction? } (the transaction carries the receipt for submitted steps):getApprovalSteps(scope) for getAllApprovalSteps() to approve everything the protocol could need in one pass. That is the per-step, progress-reportable equivalent of setApprovals() (and a slight superset, since it also includes the split allowances).checkApprovals batches the on-chain reads (via multicall) so you can render the initial state in one round-trip.runApprovals([...tradeSteps, ...splitSteps]) (duplicates are removed automatically).Kernel.execute when a predictAccount is configured.getApprovalSteps and getAllApprovalSteps are pure and need no signer. checkApproval / checkApprovals, setApproval, and runApprovals require one and throw MissingSignerError otherwise.setApprovals() still exists for the fire-and-forget "approve everything" case where you don't need per-step control or reporting.OrderBuilder: Instantiate the OrderBuilder class by calling OrderBuilder.make.predictAccount address, which is also known as the deposit address.getLimitOrderAmounts to calculate order amounts.buildOrder to generate a LIMIT strategy order.feeRateBps via the GET /markets endpoint on the REST APIsigner and maker to the predictAccount address, NOT the signer/privy wallet address.buildTypedData to generate typed data for the order.SignedOrder object by calling signTypedDataOrder.buildTypedDataHash.LIMIT strategy buy order:OrderBuilder: Instantiate the OrderBuilder class by calling OrderBuilder.make.getLimitOrderAmounts to calculate order amounts.buildOrder to generate a LIMIT strategy order.feeRateBps via the GET /markets endpoint on the REST APIbuildTypedData to generate typed data for the order.SignedOrder object by calling signTypedDataOrder.buildTypedDataHash.MARKET sell order:OrderBuilder: Instantiate the OrderBuilder class by calling OrderBuilder.make.getMarketOrderAmounts to calculate order amounts.buildOrder to generate a MARKET strategy order.feeRateBps via the GET /markets endpoint on the REST APIbuildTypedData to create typed data for the order.SignedOrder object by calling signTypedDataOrder.buildTypedDataHash.isMinAmountOut: true so that slippage decreases the takerAmount (minimum shares out), while makerAmount equals the expected cost (avg price × shares). This avoids inflating the USD commitment, allowing you to spend your full wallet balance.takerAmount (you're willing to receive less collateral)slippageBps and isMinAmountOut values when submitting your order to the REST API.OrderBuilder class provides the redeemPositions method to redeem your positions on the Predict protocol. The method supports all market types through the isNegRisk and isYieldBearing options.OrderBuilder: Instantiate the OrderBuilder class by calling the static make method.redeemPositions method with the appropriate options.conditionId and indexSet can be fetched from the GET /positions endpoint.OrderBuilder class provides the mergePositions method to combine both outcome tokens back into collateral (USDT). This is useful when you hold equal amounts of both YES and NO positions.OrderBuilder: Instantiate the OrderBuilder class by calling the static make method.mergePositions method with the appropriate options.conditionId can be fetched from the GET /positions endpoint.OrderBuilder class provides the convertPositions method to convert NO positions in a NegRisk market into the complementary YES positions plus collateral (USDT). Only NegRisk markets support conversions.amount converted, the selected NO positions are burned and you receive:amount of the YES position for every other market in the category.amount * (numberOfNoPositions - 1) of collateral (USDT).OrderBuilder: Instantiate the OrderBuilder class by calling the static make method.convertPositions method with the appropriate options.negRiskOnChainId matches the field of the same name returned by the GET /categories endpoint: the category's on-chain NegRisk market ID, a 32-byte hex string. Note that this is not the numeric id the API uses for markets and categories. The indexSet is a bitmask that selects which NO positions to convert: for each one, set the bit at the market's questionIndex (also returned by the GET /categories and GET /positions endpoints).CONVERT operation.balanceOf allows to easily check the current USDT balance of the connected signer.GET /orders.isNegRisk and isYieldBearing: Separate orders based on the isNegRisk and isYieldBearing properties.isNegRisk and isYieldBearing properties.