Skip to main content
This page follows 1,000 USDC through every stage of the core Exponent flow: stripping into PT and YT, collecting yield, and merging back to the base asset. Every code block uses the real SDK — for isolated copy-paste snippets, see the SDK Quickstart.

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(/* ... */);

const vault = await Vault.load(LOCAL_ENV, connection, new PublicKey("..."));

// Scenario starting point
const rate = vault.currentSyExchangeRate; // 1.00
const maturity = vault.expirationDate;    // 90 days from now

Initialize a Yield Position

YT does not earn yield sitting in your wallet — it is just an SPL token. To start accruing interest and emissions, it must be deposited into a YieldTokenPosition. This is a one-time setup per vault, and must be done before calling ixStripFromBase (which auto-deposits YT).
// One-time: create a yield position for this vault
const initIx = vault.ixInitializeYieldPosition({
  owner: wallet.publicKey,
});

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

Strip

Stripping converts a base asset into PT and YT in one atomic instruction. The vault wraps the base into SY under the hood, then mints equal amounts of PT and YT based on the current exchange rate. YT is automatically deposited into your yield position and begins accruing immediately. At a rate of 1.00, depositing 1,000 USDC produces 1,000 PT + 1,000 YT.
const stripIx = await vault.ixStripFromBase({
  owner: wallet.publicKey,
  amountBase: 1_000_000_000n, // 1,000 USDC (6 decimals)
});

const tx = new Transaction().add(stripIx);
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({ syIn, depositor }) to skip the base-to-SY wrapping step. Note that ixStrip does not auto-deposit YT — you would need to call ytPosition.ixDepositYt() separately.
Holdings: 1,000 PT + 1,000 YT (deposited)

Collect Yield

Yield accrues over time

As the underlying protocol (e.g., Marginfi) earns interest, the SY exchange rate grows. The deposited YT position tracks this growth.
Value
Exchange rate at deposit1.000
Exchange rate after 30 days~1.008
YT deposited1,000
Accrued interest~8.1 SY

Stage and collect

Before collecting, the yield must be staged — this snapshots the current exchange rate and computes what is owed.
// Reload to get latest state
const ytPosition = await YtPosition.loadByOwner(
  LOCAL_ENV, connection, wallet.publicKey, vault
);

// Check how much can be claimed
const claimable = ytPosition.getClaimableInterest(vault.currentSyExchangeRate);

const stageIx = ytPosition.ixStageYield({
  payer: wallet.publicKey,
});

const collectIx = ytPosition.ixCollectInterest({
  signer: wallet.publicKey,
});

const tx = new Transaction().add(stageIx, collectIx);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Holdings: 1,000 PT + 1,000 YT (deposited) + ~8.1 SY (collected)

Redeem at Maturity

At maturity, the exchange rate freezes. PT becomes redeemable for its full SY backing, and YT stops accruing. To exit, withdraw YT from the yield position, then merge PT + YT back into the base asset.
// Withdraw YT from yield position
const withdrawIx = ytPosition.ixWithdrawYt({
  amount: 1_000_000_000n, // 1,000 YT
});

// Merge PT + YT back to base asset in one instruction
const { ixs, setupIxs } = await vault.ixMergeToBase({
  owner: wallet.publicKey,
  amountPy: 1_000_000_000n, // 1,000 PT+YT
});

const tx = new Transaction().add(withdrawIx, ...setupIxs, ...ixs);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Use vault.ixMerge({ pyIn, depositor }) to receive SY back instead of the base asset.

Summary

StageActionSDK MethodHoldings After
Start1,000 USDC
InitializeCreate yield position (one-time)vault.ixInitializeYieldPosition()1,000 USDC
StripBase to PT + YT (auto-deposits YT)vault.ixStripFromBase()1,000 PT + 1,000 YT (deposited)
CollectClaim accrued interestytPosition.ixStageYield() + ixCollectInterest()1,000 PT + 1,000 YT + ~8.1 SY
WithdrawPrepare to mergeytPosition.ixWithdrawYt()1,000 PT + 1,000 YT + ~8.1 SY
MergePT + YT to base assetvault.ixMergeToBase()~1,008 USDC
Result: ~0.8% return over 90 days (~3.3% annualized), matching the underlying lending rate.

Next Steps