Skip to main content
This page walks through the full orderbook trading lifecycle — loading state, getting quotes, posting and filling orders, collecting interest, and withdrawing funds.

Installation

yarn add @exponent-labs/exponent-sdk

Setup

import { Orderbook, LOCAL_ENV } from "@exponent-labs/exponent-sdk";
import {
  Connection,
  PublicKey,
  Transaction,
  sendAndConfirmTransaction,
  Keypair,
} from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const wallet = Keypair.fromSecretKey(/* your keypair */);
const orderbookAddress = new PublicKey("...");
const syMintAddress = new PublicKey("...");

const orderbook = await Orderbook.load(LOCAL_ENV, connection, orderbookAddress);

1. Get a Quote

getQuote simulates a trade and returns the expected output before you send a transaction.
import { QuoteDirection } from "@exponent-labs/exponent-sdk";

const clock = await connection.getClock();
const unixNow = Number(clock.unixTimestamp);

const quote = orderbook.getQuote({
  inAmount: 1_000_000_000,
  direction: QuoteDirection.SY_TO_YT,
  unixNow,
  syExchangeRate: 1.000009210084,
});

console.log("Expected output:", quote.outAmount);
console.log("Maker fees:", quote.makerFees);
console.log("Taker fees:", quote.takerFees);
Always use connection.getClock() for the unixNow parameter — Date.now() may drift from the onchain clock and produce inaccurate quotes.

2. Post a Limit Order

ixWrapperPostOffer places a limit order on the orderbook. The wrapper handles token account creation for you.
import { OfferType, offerOptions } from "@exponent-labs/exponent-sdk";

const { ix, setupIxs } = await orderbook.ixWrapperPostOffer({
  trader: wallet.publicKey,
  price: 5.0,
  amount: 1_000_000_000n,
  offerType: OfferType.SellYt,
  offerOption: offerOptions("FillOrKill", [false]),
  virtualOffer: false,
  expirySeconds: 3600,
  mintSy: syMintAddress,
});

const tx = new Transaction().add(...setupIxs, ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);
The setupIxs array creates PT, YT, and SY token accounts if they don’t exist. Always include them before ix in your transaction.

3. Execute a Market Order

ixWrapperMarketOffer fills against existing orders immediately.
import { OfferType, offerOptions } from "@exponent-labs/exponent-sdk";

const { ix, setupIxs } = await orderbook.ixWrapperMarketOffer({
  trader: wallet.publicKey,
  maxPriceApy: 5.5,
  amount: 1_000_000_000n,
  offerType: OfferType.BuyYt,
  minAmountOut: 990_000_000n,
  virtualOffer: false,
  mintSy: syMintAddress,
});

const tx = new Transaction().add(...setupIxs, ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Set minAmountOut for slippage protection. The transaction reverts if the output falls below this threshold.

4. Check Open Orders

Query your active orders to see what’s currently on the book.
const openOrders = orderbook.getUserOpenOrders(wallet.publicKey);

for (const order of openOrders) {
  console.log("Index:", order.offerIndex);
  console.log("Type:", order.type);
  console.log("Price APY:", order.priceApy);
  console.log("Amount:", order.amount);
}

5. Remove an Order

Cancel an open order using its offerIdx from getUserOpenOrders.
const ix = await orderbook.ixWrapperRemoveOffer({
  trader: wallet.publicKey,
  offerIdx: openOrders[0].offerIndex,
  mintSy: syMintAddress,
});

const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Use getUserOpenOrders to find the offerIdx of the order you want to remove. Removing an order returns PT/YT back to your escrow balance.

6. Collect Interest

Collect yield that has accrued on YT held in your open or filled orders.
const ix = await orderbook.ixWrapperCollectInterest({
  trader: wallet.publicKey,
  mintSy: syMintAddress,
});

const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Interest accrues on YT held in open sell orders and from filled buy orders. You can collect it at any time without affecting your active orders.

7. Withdraw Funds

Withdraw PT, YT, and SY from your orderbook escrow back to your wallet.
import { amount } from "@exponent-labs/exponent-sdk";

const ix = await orderbook.ixWrapperWithdrawFunds({
  trader: wallet.publicKey,
  mintSy: syMintAddress,
  ptAmount: amount("All"),
  ytAmount: amount("All"),
  syAmount: amount("All"),
});

const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Use amount("All") to withdraw all available funds, or amount("Some", [500_000_000n]) for a specific amount. The amount helper is imported from @exponent-labs/exponent-sdk.

Reading State

Read orderbook and user state without transactions:
import { QuoteDirection } from "@exponent-labs/exponent-sdk";

// Check your escrow balances
const balances = orderbook.getUserBalances(wallet.publicKey);
console.log("PT:", balances.pt);
console.log("YT:", balances.yt);
console.log("SY:", balances.sy);
console.log("Staked YT:", balances.stakedYt);
console.log("Staged interest:", balances.staged);

// Get a quote for a potential trade
const clock = await connection.getClock();
const quote = orderbook.getQuote({
  inAmount: 1_000_000_000,
  direction: QuoteDirection.SY_TO_YT,
  unixNow: Number(clock.unixTimestamp),
  syExchangeRate: 1.0001,
});

// View open orders
const orders = orderbook.getUserOpenOrders(wallet.publicKey);

Next Steps