Documentation Index
Fetch the complete documentation index at: https://docs.exponent.finance/llms.txt
Use this file to discover all available pages before exploring further.
The core instructions module enables vault managers and allocators to strip base tokens (e.g., LSTs) into PT (Principal Tokens) and YT (Yield Tokens), and merge them back. All interactions are executed as Squads sync transactions validated against onchain policies.
For background on how stripping and merging works, see Core Concepts.
Transaction Structure
Every core 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]);
| Part | What it contains | Why it’s separate |
|---|
preInstructions | Any permissionless setup instructions | Must be top-level instructions |
instruction | Squads sync transaction wrapping all vault-signed instructions | Executes with the vault’s smart account as signer |
postInstructions | Any post-operation instructions | Must be top-level instructions |
Initialize Yield Position
Before the vault can strip or merge tokens, a yield position account must exist on the Exponent Core program. coreAction.initializeYieldPosition creates this account.
Orderbook and CLMM operations automatically initialize the yield position if it doesn’t exist. You only need to call this manually if strip or merge is your first Core interaction for a given vault.
import {
coreAction,
createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
coreAction.initializeYieldPosition({
vault: new PublicKey("..."), // Exponent Core vault address
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
vault | PublicKey | The Exponent Core vault address (the yield-stripping vault, not the strategy vault) |
A matching policy must exist before executing. See Policy Builders.
Strip
coreAction.strip strips a base token (e.g., an LST like JitoSOL) into equal amounts of PT and YT through the Exponent Core program.
import {
coreAction,
createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
coreAction.strip({
vault: new PublicKey("..."), // Exponent Core vault address
amountBase: 1_000_000_000n, // 1 token in native units
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
vault | PublicKey | The Exponent Core vault address (the yield-stripping vault, not the strategy vault) |
amountBase | bigint | Amount of base token to strip, in native units |
A matching policy must exist before executing. See Policy Builders.
Merge
coreAction.merge merges equal amounts of PT and YT back into the base token.
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
coreAction.merge({
vault: new PublicKey("..."),
amountPy: 1_000_000_000n, // Must hold equal PT and YT
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
vault | PublicKey | The Exponent Core vault address |
amountPy | bigint | Amount of PT/YT to merge — must hold equal amounts of both |
The merge operation requires the vault to hold equal amounts of PT and YT. If the vault holds 100 PT and 80 YT, you can merge at most 80.
A matching policy must exist before executing. See Policy Builders.
AMM (Market Two) Swaps
The AMM (Market Two) is the legacy AMM market type on the exponent_core program. The SDK exposes its three swap operations as marketTwoAction.tradePt, marketTwoAction.buyYt, and marketTwoAction.sellYt. Each one trades against the market’s underlying SY mint.
Trade PT
marketTwoAction.tradePt is a bidirectional PT/SY swap. The sign of netTraderPt selects the direction; syConstraint is the signed slippage bound matching the on-chain handler.
import {
marketTwoAction,
createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
marketTwoAction.tradePt({
market: new PublicKey("..."),
netTraderPt: 1_000_000_000n, // positive = buy PT (spend SY), negative = sell PT (receive SY)
syConstraint: 950_000_000n, // signed slippage bound
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
market | PublicKey | The Market Two PDA being traded against |
netTraderPt | bigint | Signed PT amount. Positive = buy PT (spend SY); negative = sell PT |
syConstraint | bigint | Signed SY slippage bound matching the on-chain trade_pt handler |
A matching policy must exist before executing. See AMM Swap Policies.
Buy YT
marketTwoAction.buyYt buys YT with SY. PT is transient inside the same instruction.
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
marketTwoAction.buyYt({
market: new PublicKey("..."),
syIn: 100_000_000n, // Maximum SY to spend
ytOut: 1_000_000_000n, // Target YT to receive
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
market | PublicKey | The Market Two PDA being traded against |
syIn | bigint | Maximum SY the trader is willing to spend |
ytOut | bigint | Target YT to receive |
A matching policy must exist before executing. See AMM Swap Policies.
Sell YT
marketTwoAction.sellYt sells YT for SY. PT is transient inside the same instruction.
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
marketTwoAction.sellYt({
market: new PublicKey("..."),
ytIn: 1_000_000_000n, // YT to sell
minSyOut: 95_000_000n, // Slippage floor
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
market | PublicKey | The Market Two PDA being traded against |
ytIn | bigint | YT to sell |
minSyOut | bigint | Minimum SY to receive — slippage floor |
A matching policy must exist before executing. See AMM Swap Policies.
Full Flow Example
This example demonstrates stripping a base token into PT + YT, then merging them back.
Step 1: Strip Base Token into PT + YT
import {
coreAction,
createVaultSyncTransaction,
} 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 EXPONENT_VAULT = new PublicKey("..."); // Exponent Core vault
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
coreAction.strip({
vault: EXPONENT_VAULT,
amountBase: 2_000_000_000n, // 2 tokens
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Step 2: Merge PT + YT Back to Base Token
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
coreAction.merge({
vault: EXPONENT_VAULT,
amountPy: 2_000_000_000n,
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);