Skip to main content
The orderbook instructions module enables vault managers and allocators to trade PT (Principal Tokens) and YT (Yield Tokens) on Exponent Orderbook. All interactions are executed as Squads sync transactions validated against onchain policies.

Transaction Structure

Every orderbook interaction goes through createVaultSyncTransaction, which returns three parts:
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions,   // Array of VaultInstruction descriptors
    owner,          // Vault PDA (the Squads smart account)
    connection,
    policyPda,      // Policy authorizing this execution
    vaultPda,       // Squads vault PDA
    signer,         // The allocator or manager wallet
    vaultAddress,   // ExponentStrategyVault PDA (auto-resolves hook accounts)
  });

// Send all three parts in order
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
PartWhat it containsWhy it’s separate
preInstructionsAny permissionless setup instructionsMust be top-level instructions
instructionSquads sync transaction wrapping all vault-signed instructionsExecutes with the vault’s smart account as signer
postInstructionsAny post-operation instructionsMust be top-level instructions

Trade Directions

The OrderbookTradeDirection enum specifies the side of the trade:
import { OrderbookTradeDirection } from "@exponent-labs/exponent-sdk";

OrderbookTradeDirection.BUY_PT   // Buy principal tokens
OrderbookTradeDirection.SELL_PT  // Sell principal tokens
OrderbookTradeDirection.BUY_YT   // Buy yield tokens
OrderbookTradeDirection.SELL_YT  // Sell yield tokens

Post Offer

orderbookAction.postOffer posts a limit order on the orderbook at a specified APY price.
import {
  orderbookAction,
  createVaultSyncTransaction,
  OrderbookTradeDirection,
} from "@exponent-labs/exponent-sdk";

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.postOffer({
        orderbook: new PublicKey("..."),
        direction: OrderbookTradeDirection.BUY_PT,
        priceApy: 0.10,             // 10% APY
        amount: 1_000_000_000n,     // 1 token in native units
        offerIdx: 0,                // Unique offer index per trader
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Parameters

ParameterTypeDescription
orderbookPublicKeyThe orderbook account address
directionOrderbookTradeDirectionTrade direction (BUY_PT, SELL_PT, BUY_YT, SELL_YT)
priceApynumberLimit price expressed as an APY (e.g., 0.10 for 10%)
amountbigintAmount in native token units
offerIdxnumberUnique offer index per trader — used for position tracking
offerOptionOrderbookOfferOptionOptional. "FillOrKill" to require full fill or cancel
virtualOfferbooleanOptional. Use virtual offers to share PT/YT liquidity
expirySecondsnumberOptional. Time-to-live in seconds before the offer auto-cancels
A matching policy must exist before executing. See Policy Builders.

Market Offer

orderbookAction.marketOffer executes a market order against existing resting offers on the orderbook.
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.marketOffer({
        orderbook: new PublicKey("..."),
        direction: OrderbookTradeDirection.BUY_PT,
        maxPriceApy: 0.15,            // Will not pay more than 15% APY
        amount: 500_000_000n,
        minAmountOut: 480_000_000n,    // Slippage protection
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Parameters

ParameterTypeDescription
orderbookPublicKeyThe orderbook account address
directionOrderbookTradeDirectionTrade direction
maxPriceApynumberMaximum acceptable APY price
amountbigintAmount to spend in native token units
minAmountOutbigintMinimum output amount — slippage protection
virtualOfferbooleanOptional. Use virtual offers
A matching policy must exist before executing. See Policy Builders.

Remove Offer

orderbookAction.removeOffer cancels an existing limit order on the orderbook.
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.removeOffer({
        orderbook: new PublicKey("..."),
        offerIdx: 0,
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Parameters

ParameterTypeDescription
orderbookPublicKeyThe orderbook account address
offerIdxnumberThe offer index to cancel (same index used when posting)
A matching policy must exist before executing. See Policy Builders.

Withdraw Funds

orderbookAction.withdrawFunds withdraws settled funds from the user escrow on the orderbook back to the vault’s token accounts.
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.withdrawFunds({
        orderbook: new PublicKey("..."),
        ptAmount: null,    // null = withdraw max
        ytAmount: null,
        syAmount: null,
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Parameters

ParameterTypeDescription
orderbookPublicKeyThe orderbook account address
ptAmount`bigintnull`Optional. PT amount to withdraw — null withdraws the maximum available
ytAmount`bigintnull`Optional. YT amount to withdraw — null withdraws the maximum available
syAmount`bigintnull`Optional. SY amount to withdraw — null withdraws the maximum available
A matching policy must exist before executing. See Policy Builders.

Full Flow Example

This example demonstrates a complete orderbook interaction: post a limit buy for PT, then cancel it and withdraw any settled funds.

Step 1: Post a Limit Buy PT Order

import {
  orderbookAction,
  createVaultSyncTransaction,
  OrderbookTradeDirection,
} from "@exponent-labs/exponent-sdk";
import { Connection, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");

const ORDERBOOK = new PublicKey("...");

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.postOffer({
        orderbook: ORDERBOOK,
        direction: OrderbookTradeDirection.BUY_PT,
        priceApy: 0.08,            // 8% APY
        amount: 2_000_000_000n,    // 2 tokens
        offerIdx: 0,
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Step 2: Cancel the Order

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.removeOffer({
        orderbook: ORDERBOOK,
        offerIdx: 0,
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Step 3: Withdraw All Settled Funds

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      orderbookAction.withdrawFunds({
        orderbook: ORDERBOOK,
        ptAmount: null,
        ytAmount: null,
        syAmount: null,
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);