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 deposit | 1.000 |
| Exchange rate after 30 days | ~1.008 |
| YT deposited | 1,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
| Stage | Action | SDK Method | Holdings After |
|---|
| Start | — | — | 1,000 USDC |
| Initialize | Create yield position (one-time) | vault.ixInitializeYieldPosition() | 1,000 USDC |
| Strip | Base to PT + YT (auto-deposits YT) | vault.ixStripFromBase() | 1,000 PT + 1,000 YT (deposited) |
| Collect | Claim accrued interest | ytPosition.ixStageYield() + ixCollectInterest() | 1,000 PT + 1,000 YT + ~8.1 SY |
| Withdraw | Prepare to merge | ytPosition.ixWithdrawYt() | 1,000 PT + 1,000 YT + ~8.1 SY |
| Merge | PT + YT to base asset | vault.ixMergeToBase() | ~1,008 USDC |
Result: ~0.8% return over 90 days (~3.3% annualized), matching the underlying lending rate.
Next Steps