A TypeScript SDK to help developers interface with the Predict's protocol.
- How to install the SDK
- How to set approvals
- How to set scoped approvals (per-operation)
- How to use a Predict account
- How to create a LIMIT order (recommended)
- How to create a MARKET order
- How to apply slippage
- How to redeem positions
- How to merge positions
- How to check USDT balance
- How to interface with contracts
- How to cancel orders
- License
This package has ethers v6 as a peer dependency.
yarn add @predictdotfun/sdk ethersnpm install @predictdotfun/sdk ethersSee the OrderBuilder class for more in-depth details on each function.
Tip (faster confirmations): ethers' default provider polling interval is 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:
import { JsonRpcProvider, Wallet } from "ethers";
const provider = new JsonRpcProvider(process.env.RPC_PROVIDER_URL);
provider.pollingInterval = 300; // default is 4000ms
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY, provider);The interval lives on the provider, so set it on whatever provider you pass in, including a BrowserProvider (e.g. MetaMask): provider.pollingInterval = 300.
Predict supports interacting with the protocol using either a traditional Externally Owned Account (EOA) or a Smart Wallet ("Predict Account"). If you use the web app, a Smart Wallet is automatically created for you. To interact with your Smart Wallet programmatically using the SDK, follow the example shown in How to use a Predict account.
Before trading, you need to set approvals for ERC-1155 (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.
Contracts: The current deployed contracts can be found either in the Constants.ts file or in the Deployed Contracts documentation.
The following example demonstrates how to set the necessary approvals using the SDK utils.
import { Wallet, MaxInt256 } from "ethers";
import { OrderBuilder, ChainId, Side } from "@predictdotfun/sdk";
// Create a wallet to send the approvals transactions (must be the orders' `maker`)
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
// The main function which initiates the OrderBuilder (only once per signer) and then provides it as dependency to other util functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// Call an helper function to set the approvals and provide the OrderBuilder instance.
await setApprovals(orderBuilder);
}
async function setApprovals(orderBuilder: OrderBuilder) {
// Set all the approval needed within the protocol
const result = await orderBuilder.setApprovals();
// Check if the approvals were set successfully
if (!result.success) {
throw new Error("Failed to set approvals.");
}
}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.
The mental model is simple: everything produces steps, and one runner runs steps.
- Describe what the user is about to do with an
ApprovalScope(operation, plusisNegRisk/isYieldBearing, and an optionalsideto narrow aTRADE). - Turn it into an ordered
ApprovalStep[]withgetApprovalSteps(one operation) orgetAllApprovalSteps(everything). Both are pure (no signer, no network access), so you can render the checklist before the wallet is connected. - Run the steps with
runApprovals, or drive them yourself withcheckApprovals/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. |
A 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.
Each step is plain data, safe to render and serialize:
{
id: "ERC1155_APPROVAL:CTF_EXCHANGE", // stable identifier: `${type}:${spenderKey}`
type: "ERC1155_APPROVAL", // or "ERC20_ALLOWANCE"
spender: "0x8BC0...B689", // the contract being granted permission
token: "0x22DA...d244", // the token contract (conditional tokens for ERC-1155, USDT for ERC-20)
label: "Approve Exchange", // default copy
description: "Allows you to interact with the exchange.",
}The label/description are sensible English defaults. For custom wording or i18n, key your own copy off the stable id and ignore them.
You'll typically build the steps from the same signer-backed OrderBuilder you use to check and run them.
import { OrderBuilder, ChainId, Side } from "@predictdotfun/sdk";
const builder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// For a single operation on a market:
const steps = builder.getApprovalSteps({
operation: "TRADE",
isNegRisk: true,
isYieldBearing: false,
// side: Side.BUY, // optional TRADE narrowing
});
// For onboarding, every approval across both market types (and, by default, both tracks):
const allSteps = builder.getAllApprovalSteps(); // or { isYieldBearing: false } to limit to one trackgetApprovalSteps 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(defaulttrue): pre-check each step on-chain and skip the ones already in place.stopOnError(defaulttrue): stop after the first failed step.onProgress: a callback invoked as each step transitions, receiving{ step, status, transaction? }.
const builder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
const steps = builder.getApprovalSteps({ operation: "TRADE", isNegRisk: true, isYieldBearing: false });
const report = await builder.runApprovals(steps, {
skipSatisfied: true, // default
stopOnError: true, // default
onProgress: ({ step, status }) => updateUI(step.id, status),
});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 |
The returned report is { success, steps }, where each entry is { step, status: "skipped" | "confirmed" | "failed", transaction? } (the transaction carries the receipt for submitted steps):
if (!report.success) {
const failed = report.steps.filter((s) => s.status === "failed");
throw new Error(`Approvals failed: ${failed.map((s) => s.step.id).join(", ")}`);
}This is the flow behind an in-app "Approvals" modal: render the steps, mark the ones already done, then run the rest with live updates.
const builder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// 1. Build the plan.
const steps = builder.getApprovalSteps({ operation: "TRADE", isNegRisk, isYieldBearing });
// 2. Render the checklist, marking which are already satisfied (one batched multicall read).
for (const { step, satisfied } of await builder.checkApprovals(steps)) {
addRow(step.id, step.label, step.description, satisfied ? "done" : "pending");
}
// 3. Run the remaining steps, updating each row as it progresses.
const report = await builder.runApprovals(steps, {
onProgress: ({ step, status }) => setRowStatus(step.id, status),
});For first-time onboarding, swap 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).
For full control (e.g. gating each step on a user confirmation), use the per-step primitives. checkApprovals batches the on-chain reads (via multicall) so you can render the initial state in one round-trip.
const builder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
const steps = builder.getApprovalSteps({ operation: "SPLIT", isNegRisk: false, isYieldBearing: false });
// Batched pre-check to mark which steps are already done.
const checks = await builder.checkApprovals(steps);
for (const { step, satisfied } of checks) {
if (satisfied) continue; // already approved
// setApproval is a raw send: ERC-20 defaults to MaxUint256, ERC-1155 to `approved: true`.
// Pass `{ approved: false }` to revoke, or `{ amount }` to cap an allowance.
const result = await builder.setApproval(step);
if (!result.success) break; // you decide whether to continue
}- Compose freely. Union step lists to cover several operations at once, e.g. to make a market both trade-ready and splittable:
runApprovals([...tradeSteps, ...splitSteps])(duplicates are removed automatically). - Predict accounts (smart wallets) are supported transparently: every step routes through
Kernel.executewhen apredictAccountis configured. - Signer requirements.
getApprovalStepsandgetAllApprovalStepsare pure and need no signer.checkApproval/checkApprovals,setApproval, andrunApprovalsrequire one and throwMissingSignerErrorotherwise. setApprovals()still exists for the fire-and-forget "approve everything" case where you don't need per-step control or reporting.
Here's an example of how to use a Predict account to create/cancel orders and set approvals.
- Initiate the Privy Wallet: The wallet is needed to sign orders. Can be found in the account settings.
- Ensure the Privy Wallet has funds: You will need to add some ETH to be able to set approvals and cancel orders, if needed.
- Initialize
OrderBuilder: Instantiate theOrderBuilderclass by callingOrderBuilder.make.- NOTE: Include the
predictAccountaddress, which is also known as the deposit address.
- NOTE: Include the
- Set Approvals: Ensure the necessary approvals are set (refer to Set Approvals).
- Determine Order Amounts: Use
getLimitOrderAmountsto calculate order amounts. - Build Order: Use
buildOrderto generate aLIMITstrategy order.- NOTE: Fetch the
feeRateBpsvia theGET /marketsendpoint on the REST API - NOTE: Set the
signerandmakerto thepredictAccountaddress, NOT the signer/privy wallet address.
- NOTE: Fetch the
- Generate Typed Data: Call
buildTypedDatato generate typed data for the order. - Sign Order: Obtain a
SignedOrderobject by callingsignTypedDataOrder. - Compute Order Hash: Compute the order hash using
buildTypedDataHash.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId, Side } from "@predictdotfun/sdk";
// Create a wallet to send the approvals transactions (must be the orders' `maker`)
const signer = new Wallet(process.env.PRIVY_WALLET_PRIVATE_KEY);
// The main function which initiates the OrderBuilder (only once per signer) and then provides it as dependency to other util functions
async function main() {
// Create a new instance of the OrderBuilder class with the predictAccount option
// Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer, {
predictAccount: "PREDICT_ACCOUNT_ADDRESS", // Your deposit address from account settings
});
// Call an helper function to create the order and provide the OrderBuilder instance
await createOrder(orderBuilder);
}
async function createOrder(orderBuilder: OrderBuilder) {
// Step 1. Set approvals and define the order params as usual
// Step 2. Create the order (maker and signer are automatically set to the predictAccount)
const order = orderBuilder.buildOrder("LIMIT", {
side: Side.BUY, // Equivalent to 0
tokenId: "OUTCOME_ON_CHAIN_ID", // This can be fetched via the API or on-chain
makerAmount, // 0.4 USDT * 10 shares (in wei)
takerAmount, // 10 shares (in wei)
nonce: 0n,
feeRateBps: 0, // Should be fetched via the `GET /markets` endpoint
});
// Step 3. Sign and submit the order as usual
}This will allow you to perform operations via your Predict Account (via the smart wallet).
Here's an example of how to use the OrderBuilder to create and sign a LIMIT strategy buy order:
- Create Wallet: The wallet is needed to sign orders.
- Initialize
OrderBuilder: Instantiate theOrderBuilderclass by callingOrderBuilder.make. - Set Approvals: Ensure the necessary approvals are set (refer to Set Approvals).
- Determine Order Amounts: Use
getLimitOrderAmountsto calculate order amounts. - Build Order: Use
buildOrderto generate aLIMITstrategy order.- NOTE: Fetch the
feeRateBpsvia theGET /marketsendpoint on the REST API
- NOTE: Fetch the
- Generate Typed Data: Call
buildTypedDatato generate typed data for the order. - Sign Order: Obtain a
SignedOrderobject by callingsignTypedDataOrder. - Compute Order Hash: Compute the order hash using
buildTypedDataHash.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId, Side } from "@predictdotfun/sdk";
// Create a wallet for signing orders
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
// The main function which initiates the OrderBuilder (only once per signer) and then provides it as dependency to other util functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// Call an helper function to create the order and provide the OrderBuilder instance
await createOrder(orderBuilder);
}
async function createOrder(orderBuilder: OrderBuilder) {
/**
* NOTE: You can also call `setApprovals` once per wallet.
*/
// Set all the approval needed within the protocol (if needed)
const result = await orderBuilder.setApprovals();
// Check if the approvals were set successfully
if (!result.success) {
throw new Error("Failed to set approvals.");
}
// Simple helper function to calculate the amounts for a `LIMIT` order
const { lastPrice, pricePerShare, makerAmount, takerAmount } = orderBuilder.getLimitOrderAmounts({
side: Side.BUY,
pricePerShareWei: 400000000000000000n, // 0.4 USDT (in wei)
quantityWei: 10000000000000000000n, // 10 shares (in wei)
});
// Build a limit order (if you are using a Predict account replace `signer.address` with your deposit address)
const order = orderBuilder.buildOrder("LIMIT", {
maker: signer.address,
signer: signer.address,
side: Side.BUY, // Equivalent to 0
tokenId: "OUTCOME_ON_CHAIN_ID", // This can be fetched via the API or on-chain
makerAmount, // 0.4 USDT * 10 shares (in wei)
takerAmount, // 10 shares (in wei)
nonce: 0n,
feeRateBps: 0, // Should be fetched via the `GET /markets` endpoint
});
// Build typed data for the order (isNegRisk and isYieldBearing can be fetched via the API)
const typedData = orderBuilder.buildTypedData(order, { isNegRisk: true, isYieldBearing: true });
// Sign the order by providing the typedData of the order
const signedOrder = await orderBuilder.signTypedDataOrder(typedData);
// Compute the order's hash
const hash = orderBuilder.buildTypedDataHash(typedData);
// Example structure required to create an order via Predict's API
const createOrderBody = {
data: {
order: { ...signedOrder, hash },
pricePerShare,
strategy: "LIMIT",
},
};
}Similarly to the above, here's the flow to create a MARKET sell order:
- Create Wallet: The wallet is needed to sign orders.
- Initialize
OrderBuilder: Instantiate theOrderBuilderclass by callingOrderBuilder.make. - Set Approvals: Ensure the necessary approvals are set (refer to Set Approvals).
- Fetch Orderbook: Query the Predict API for the latest orderbook for the market.
- Determine Order Amounts: Use
getMarketOrderAmountsto calculate order amounts. - Build Order: Call
buildOrderto generate aMARKETstrategy order.- NOTE: Fetch the
feeRateBpsvia theGET /marketsendpoint on the REST API
- NOTE: Fetch the
- Generate Typed Data: Use
buildTypedDatato create typed data for the order. - Sign Order: Obtain a
SignedOrderobject by callingsignTypedDataOrder. - Compute Order Hash: Compute the order hash using
buildTypedDataHash.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId, Side } from "@predictdotfun/sdk";
// Create a wallet for signing orders
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
// The main function which initiates the OrderBuilder (only once per signer) and then provides it as dependency to other util functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// Call an helper function to create the order and provide the OrderBuilder instance
await createOrder(orderBuilder);
}
async function createOrder(orderBuilder: OrderBuilder) {
// Fetch the orderbook for the specific market via `GET /markets/{marketId}/orderbook`
const book = {};
/**
* NOTE: You can also call `setApprovals` once per wallet.
*/
// Set all the approval needed within the protocol (if needed)
const result = await orderBuilder.setApprovals();
// Check if the approvals were set successfully
if (!result.success) {
throw new Error("Failed to set approvals.");
}
// Helper function to calculate the amounts for a `MARKET` order
const {
lastPrice,
pricePerShare,
makerAmount,
takerAmount,
amount, // Non-deflated share quantity (differs from takerAmount when isMinAmountOut is true)
// Only needed if you set a slippage tolerance in the input
slippageBps,
isMinAmountOut, // Whether the alternative slippage model was used
} = orderBuilder.getMarketOrderAmounts(
{
side: Side.SELL,
quantityWei: 10000000000000000000n, // 10 shares (in wei) e.g. parseEther("10")
slippageBps: 100n, // E.g. 1% slippage tolerance (100 bps)
},
book, // It's recommended to re-fetch the orderbook regularly to avoid issues
);
// Build a limit order (if you are using a Predict account replace `signer.address` with your deposit address)
const order = orderBuilder.buildOrder("MARKET", {
maker: signer.address,
signer: signer.address,
side: Side.SELL, // Equivalent to 1
tokenId: "OUTCOME_ON_CHAIN_ID", // This can be fetched via the API or on-chain
makerAmount, // 10 shares (in wei)
takerAmount, // 0.4 USDT * 10 shares (in wei)
nonce: 0n,
feeRateBps: 0, // Should be fetched via the `GET /markets` endpoint
});
// Build typed data for the order (isNegRisk and isYieldBearing can be fetched via the API)
const typedData = orderBuilder.buildTypedData(order, { isNegRisk: false, isYieldBearing: false });
// Sign the order by providing the typedData of the order
const signedOrder = await orderBuilder.signTypedDataOrder(typedData);
// Compute the order's hash
const hash = orderBuilder.buildTypedDataHash(typedData);
// Example structure required to create an order via Predict's API
const createOrderBody = {
data: {
order: { ...signedOrder, hash },
pricePerShare,
strategy: "MARKET",
slippageBps,
},
};
}By default, no additional slippage is applied to the order maker/taker amounts. You can specify a slippage tolerance in basis points (1 bps = 0.01%) to adjust the amounts:
- BUY orders: set
isMinAmountOut: trueso that slippage decreases thetakerAmount(minimum shares out), whilemakerAmountequals the expected cost (avg price × shares). This avoids inflating the USD commitment, allowing you to spend your full wallet balance. - SELL orders: slippage decreases the
takerAmount(you're willing to receive less collateral)
// Market order with 1% slippage (100 bps)
const amounts = orderBuilder.getMarketOrderAmounts(
{
side: Side.BUY,
quantityWei: 10000000000000000000n, // 10 shares (in wei)
slippageBps: 100n, // 1% slippage tolerance
isMinAmountOut: true,
},
book,
);
// makerAmount is the expected cost, takerAmount is deflated by slippage
console.log(`Maker Amount: ${amounts.makerAmount}`); // Expected cost (not inflated)
console.log(`Taker Amount: ${amounts.takerAmount}`); // Deflated by slippage
console.log(`Amount: ${amounts.amount}`); // Original share quantity
console.log(`Price Per Share: ${amounts.pricePerShare}`);
console.log(`Slippage Applied: ${amounts.slippageBps} bps`); // 100n
// Value-based market order with slippage
const valueAmounts = orderBuilder.getMarketOrderAmounts(
{
side: Side.BUY,
valueWei: 5000000000000000000n, // 5 USDT (in wei)
slippageBps: 50n, // 0.5% slippage tolerance
isMinAmountOut: true,
},
book,
);Note: Slippage will only be applied if you provide the slippageBps and isMinAmountOut values when submitting your order to the REST API.
The 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.
- Create a Wallet: Initialize a wallet that will be used to sign the redemption transaction.
- Initialize
OrderBuilder: Instantiate theOrderBuilderclass by calling the staticmakemethod. - Redeem Positions: Call the
redeemPositionsmethod with the appropriate options.
The conditionId and indexSet can be fetched from the GET /positions endpoint.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId } from "@predictdotfun/sdk";
// Initialize the wallet with your private key
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
// The main function initiates the OrderBuilder (only once per signer)
// Then provides it as dependency to other functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// Redeem positions for a standard market
await redeemStandardPositions(orderBuilder);
// Redeem positions for a NegRisk market
await redeemNegRiskPositions(orderBuilder);
}
async function redeemStandardPositions(orderBuilder: OrderBuilder) {
const conditionId = "CONDITION_ID_FROM_API"; // A hash string
const indexSet = "INDEX_SET_FROM_API"; // 1 or 2 based on the position you want to redeem
const result = await orderBuilder.redeemPositions({
conditionId,
indexSet,
isNegRisk: false,
isYieldBearing: true, // Set based on market type
});
if (result.success) {
console.log("Positions redeemed successfully:", result.receipt);
} else {
console.error("Failed to redeem positions:", result.cause);
}
}
async function redeemNegRiskPositions(orderBuilder: OrderBuilder) {
const conditionId = "CONDITION_ID_FROM_API"; // A hash string
const indexSet = "INDEX_SET_FROM_API"; // 1 or 2 based on the position you want to redeem
const amount = "POSITION_AMOUNT_FROM_API"; // The amount to redeem, usually the max
const result = await orderBuilder.redeemPositions({
conditionId,
indexSet,
amount,
isNegRisk: true,
isYieldBearing: true, // Set based on market type
});
if (result.success) {
console.log("Positions redeemed successfully:", result.receipt);
} else {
console.error("Failed to redeem positions:", result.cause);
}
}The 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.
- Create a Wallet: Initialize a wallet that will be used to sign the merge transaction.
- Initialize
OrderBuilder: Instantiate theOrderBuilderclass by calling the staticmakemethod. - Merge Positions: Call the
mergePositionsmethod with the appropriate options.
The conditionId can be fetched from the GET /positions endpoint.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId } from "@predictdotfun/sdk";
// Initialize the wallet with your private key
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
await mergePositions(orderBuilder);
}
async function mergePositions(orderBuilder: OrderBuilder) {
const conditionId = "CONDITION_ID_FROM_API";
const amount = 10000000000000000000n; // 10 tokens (in wei)
const result = await orderBuilder.mergePositions({
conditionId,
amount,
isNegRisk: false,
isYieldBearing: true, // Set based on market type
});
if (result.success) {
console.log("Positions merged successfully:", result.receipt);
} else {
console.error("Failed to merge positions:", result.cause);
}
}The method balanceOf allows to easily check the current USDT balance of the connected signer.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId } from "@predictdotfun/sdk";
// Initialize the wallet with your private key
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
// The main function initiates the OrderBuilder (only once per signer)
// Then provides it as dependency to other functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
await checkBalance(orderBuilder);
}
async function checkBalance(orderBuilder: OrderBuilder) {
// Fetch the current account/wallet balance in wei
const balanceWei = await orderBuilder.balanceOf();
// Example check
if (balanceWei >= orderAmountWei) {
console.log("Enough balance to create the order");
} else {
console.error("Not enough balance to create the order");
}
}To facilitate interactions with Predict's contracts we expose the necessary instances of each contract, including ABIs and types.
import { OrderBuilder, ChainId } from "@predictdotfun/sdk";
import { Wallet } from "ethers";
// Create a wallet to interact with on-chain contracts
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY);
// The main function initiates the OrderBuilder (only once per signer)
// Then provides it as dependency to other functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
await callContracts(orderBuilder);
}
async function callContracts(orderBuilder: OrderBuilder) {
// If the signer is not provided within `OrderBuilder.make` the contracts won't be initiated
if (!orderBuilder.contracts) {
throw new Error("The signer was not provided during the OrderBuilder init.");
}
// You can now call contract functions (the actual contract instance is within `contract`)
// The `codec` property contains the ethers Interface, useful to encode and decode data
const balance = await orderBuilder.contracts["USDT"].contract.balanceOf(signer.address);
}Some other useful utils, ABIs and types exposed by the SDK.
import {
// Supported Chains
ChainId,
// Addresses
AddressesByChainId,
// Contract Interfaces
CTFExchange,
ConditionalTokens,
YieldBearingConditionalTokens,
NegRiskAdapter,
NegRiskCtfExchange,
ERC20,
// ABIs
CTFExchangeAbi,
NegRiskCtfExchangeAbi,
NegRiskAdapterAbi,
ConditionalTokensAbi,
YieldBearingConditionalTokensAbi,
ERC20Abi,
// Order builder
OrderBuilder,
} from "@predictdotfun/sdk";Here's an example on how to cancel orders via the SDK
- Fetch Orders: Retrieve your open orders using
GET /orders. - Group by
isNegRiskandisYieldBearing: Separate orders based on theisNegRiskandisYieldBearingproperties. - Cancel Orders: Call the cancel function and provide the orders to cancel and the
isNegRiskandisYieldBearingproperties. - Check Transaction Success: Check to confirm the transaction was successful.
import { Wallet } from "ethers";
import { OrderBuilder, ChainId, Side } from "@predictdotfun/sdk";
// Create a new JsonRpcProvider instance
const provider = new JsonRpcProvider(process.env.RPC_PROVIDER_URL);
// Create a wallet to send the cancel transactions on-chain
const signer = new Wallet(process.env.WALLET_PRIVATE_KEY).connect(provider);
// The main function which initiates the OrderBuilder (only once per signer) and then provides it as dependency to other util functions
async function main() {
// Create a new instance of the OrderBuilder class. Note: This should only be done once per signer
const orderBuilder = await OrderBuilder.make(ChainId.BnbMainnet, signer);
// Call a helper function to cancel orders and provide the OrderBuilder instance
await cancelOrdersHelper(orderBuilder);
}
async function cancelOrdersHelper(orderBuilder: OrderBuilder) {
// Fetch your open orders from the `GET /orders` endpoint
const apiResponse = [
// There are more fields, but for cancellations we only care about `order`, `isNegRisk` and `isYieldBearing`
{ order: {}, isNegRisk: true, isYieldBearing: true },
{ order: {}, isNegRisk: true, isYieldBearing: false },
{ order: {}, isNegRisk: false, isYieldBearing: true },
{ order: {}, isNegRisk: false, isYieldBearing: false },
];
// Determine which orders you want to cancel
const ordersToCancel = [
{ order: {}, isNegRisk: true, isYieldBearing: true },
{ order: {}, isNegRisk: true, isYieldBearing: false },
{ order: {}, isNegRisk: false, isYieldBearing: true },
{ order: {}, isNegRisk: false, isYieldBearing: false },
];
const regularOrders: Order[] = [];
const negRiskOrders: Order[] = [];
const regularYieldBearingOrders: Order[] = [];
const negRiskYieldBearingOrders: Order[] = [];
// Group the orders by `isNegRisk` and `isYieldBearing`
for (const { order, isNegRisk, isYieldBearing } of ordersToCancel) {
if (isYieldBearing) {
if (isNegRisk) {
negRiskYieldBearingOrders.push(order);
} else {
regularYieldBearingOrders.push(order);
}
} else {
if (isNegRisk) {
negRiskOrders.push(order);
} else {
regularOrders.push(order);
}
}
}
// Call the cancel function
const regResult = await orderBuilder.cancelOrders(regularOrders, { isNegRisk: false, isYieldBearing: false });
const negRiskResult = await orderBuilder.cancelOrders(negRiskOrders, { isNegRisk: true, isYieldBearing: false });
const regYieldBearingResult = await orderBuilder.cancelOrders(regularYieldBearingOrders, {
isNegRisk: false,
isYieldBearing: true,
});
const negRiskYieldBearingResult = await orderBuilder.cancelOrders(negRiskYieldBearingOrders, {
isNegRisk: true,
isYieldBearing: true,
});
// Check for the transactions success
const success =
regResult.success && negRiskResult.success && regYieldBearingResult.success && negRiskYieldBearingResult.success;
}By contributing to this project, you agree that your contributions will be licensed under the project's MIT License.