Skip to main content
Set up the Exponent SDK and walk through the complete Core lifecycle, from stripping yield assets into PT and YT, to collecting yield, and merging back.

Installation

yarn add @exponent-labs/exponent-sdk

Setup

import { Vault, YtPosition, 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 vaultAddress = new PublicKey("...");

const vault = await Vault.load(LOCAL_ENV, connection, vaultAddress);

1. Initialize a Yield Position

Before stripping, you need to create a YieldTokenPosition account for your wallet. This is a one-time setup per vault.
YT is just an SPL token — the protocol can’t track yield for tokens sitting in your wallet. The YieldTokenPosition account escrows your YT and records the SY exchange rate at entry, which is needed to compute your earned yield. ixStripFromBase automatically deposits YT into this position, so it must exist before you strip.
const initIx = vault.ixInitializeYieldPosition({
  owner: wallet.publicKey,
});

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

2. Strip Base Tokens into PT and YT

Use ixStripFromBase to convert a base asset (e.g., USDC) directly into PT and YT. This wraps the base into SY, strips it into PT and YT, and deposits the YT into your yield position — all in a single atomic instruction. Your position begins accruing interest and emissions immediately.
const ix = await vault.ixStripFromBase({
  owner: wallet.publicKey,
  amountBase: 1_000_000n, // e.g., 1 USDC (6 decimals)
});

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

const ytPosition = await YtPosition.loadByOwner(
  LOCAL_ENV,
  connection,
  wallet.publicKey,
  vault,
);
If you already hold SY tokens, use vault.ixStrip() instead — it skips the base-to-SY wrapping step but does not auto-deposit YT. You would then need to call ytPosition.ixDepositYt() separately.

3. Stage Yield

Before collecting, you need to stage yield. This computes your earned interest and emissions based on the current SY exchange rate.
const stageIx = ytPosition.ixStageYield({
  payer: wallet.publicKey,
});

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

4. Collect Interest

After staging, collect your earned interest (paid in SY tokens).
const collectIx = ytPosition.ixCollectInterest({
  signer: wallet.publicKey,
});

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

5. Withdraw YT

Before merging, withdraw your YT from the yield position back to your wallet. The merge instruction burns YT directly from your token account.
const withdrawIx = ytPosition.ixWithdrawYt({
  amount: 1_000_000n, // amount of YT to withdraw
});

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

6. Merge PT and YT Back to Base

When you’re ready to exit, merge your PT and YT back into the base asset.
const { ixs, setupIxs } = await vault.ixMergeToBase({
  owner: wallet.publicKey,
  amountPy: 1_000_000n, // amount of PT & YT to merge
});

const tx = new Transaction().add(...setupIxs, ...ixs);
await sendAndConfirmTransaction(connection, tx, [wallet]);

Reading State

Query vault and position state without sending transactions:
// Current SY exchange rate
const rate = vault.currentSyExchangeRate;

// Vault expiration
const expiresAt = vault.expirationDate;

// Claimable interest (in base token units)
const claimable = ytPosition.getClaimableInterest(rate);

// Claimable emissions
const emissions = ytPosition.getClaimableEmissions();

Next Steps