Instant withdrawals let a depositor burn LP tokens and receive one reserve token immediately when the vault has enough executable reserve liquidity. Use the read helpers first, then build the reserve-withdrawal instruction.
If capacity is unavailable for the requested output mint, use the queued withdrawal flow instead.
Check vault capacity
fetchInstantWithdrawalCapacity returns the vault-level amount that can currently be withdrawn from reserves for one output mint.
import { ExponentVault } from "@exponent-labs/exponent-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const vault = await ExponentVault.load({ connection, address: vaultAddress });
const USDC_MINT = new PublicKey("...");
const capacity = await vault.fetchInstantWithdrawalCapacity({
outputMint: USDC_MINT,
});
console.log("mint:", capacity.mint.toBase58());
console.log("amount:", capacity.amount);
console.log("decimals:", capacity.decimals);
Return value
| Field | Type | Description |
|---|
mint | PublicKey | Vault underlying or selected output mint |
amount | bigint | Gross instant-withdrawal capacity in raw mint units |
decimals | number | Decimal places for the returned mint |
Check user capacity
fetchUserInstantWithdrawalCapacity applies the user’s spendable LP balance to the vault-level capacity.
const userCapacity = await vault.fetchUserInstantWithdrawalCapacity({
owner: wallet.publicKey,
outputMint: USDC_MINT,
});
Parameters
| Parameter | Type | Description |
|---|
owner | PublicKey | Depositor wallet public key |
outputMint | PublicKey | Optional. Reserve mint to receive |
tokenLpAccount | PublicKey | Optional. LP token account to read instead of the owner’s ATA |
tokenProgram | PublicKey | Optional. Token program for the LP account |
Quote an instant withdrawal
fetchInstantWithdrawalQuote quotes an executable instant withdrawal for a selected LP amount and output mint.
const quote = await vault.fetchInstantWithdrawalQuote({
lpAmountIn: 500_000_000n,
outputMint: USDC_MINT,
});
console.log("LP burned:", quote.lp.amountIn);
console.log("fee:", quote.fee.amount);
console.log("net base value:", quote.net.amount);
console.log("output:", quote.output.amount);
console.log("slot:", quote.quotedAtSlot);
Parameters
| Parameter | Type | Description |
|---|
lpAmountIn | bigint | LP token amount to burn |
outputMint | PublicKey | Reserve mint to receive |
Return value
| Field | Type | Description |
|---|
lp | InstantWithdrawalQuoteLpBreakdown | LP input, fee amount, user amount, mint, and decimals |
gross | InstantWithdrawalQuoteAmount | Gross base value consumed by reserve and window limits |
fee | InstantWithdrawalQuoteAmount | Base value retained in the vault by the LP fee split |
net | InstantWithdrawalQuoteAmount | Base value converted into the selected output token |
output | InstantWithdrawalQuoteAmount | Expected amount for the selected output mint |
quotedAtSlot | number | Slot used for the quote |
Execute from reserves
Use ixExecuteWithdrawalFromReservesWithResolvedAumAccounts after quoting. The resolved helper includes derived AUM accounts from current strategy state, including positions that require RPC-derived accounts.
import {
ExponentVault,
SQUADS_PROGRAM_ID,
} from "@exponent-labs/exponent-sdk";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
import { Connection, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const vault = await ExponentVault.load({ connection, address: vaultAddress });
const outputMint = new PublicKey("...");
const entryIdx = vault.state.tokenEntries.findIndex((entry) =>
entry.mint.equals(outputMint),
);
if (entryIdx === -1) {
throw new Error("Output mint is not a vault token entry");
}
const entry = vault.state.tokenEntries[entryIdx];
const quote = await vault.fetchInstantWithdrawalQuote({
lpAmountIn: 500_000_000n,
outputMint,
});
const ix = await vault.ixExecuteWithdrawalFromReservesWithResolvedAumAccounts({
owner: wallet.publicKey,
entryIdx,
lpAmount: quote.lp.amountIn,
tokenSrc: entry.tokenSquadsAccount,
tokenVaultSrc: entry.tokenAccountVault,
tokenDst: getAssociatedTokenAddressSync(outputMint, wallet.publicKey),
squadsProgram: SQUADS_PROGRAM_ID,
});
const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Required parameters
| Parameter | Type | Description |
|---|
owner | PublicKey | Depositor wallet public key |
entryIdx | number | Index of the vault token entry to withdraw |
lpAmount | bigint | number | LP token amount to burn |
tokenSrc | PublicKey | Squads-owned reserve token account for the selected entry |
tokenVaultSrc | PublicKey | Vault-owned reserve token account for the selected entry |
tokenDst | PublicKey | Depositor token account for the output mint |
squadsProgram | PublicKey | Squads program ID |
Optional parameters
| Parameter | Type | Description |
|---|
tokenLpSrc | PublicKey | Depositor LP token source account. Defaults to the depositor’s ATA |
tokenProgram | PublicKey | Token program for reserve transfers |
token2022Program | PublicKey | Token-2022 program when needed |
tokenLpEscrow | PublicKey | LP token escrow. Defaults to the vault’s LP escrow |
mintLp | PublicKey | LP mint. Defaults to the vault’s LP mint |
extraRemainingAccounts | AccountMeta[] | Additional AUM accounts when you are not using the resolved helper |
Quotes depend on reserve balances, AUM, LP supply, and the instant withdrawal window. Fetch a quote and submit the transaction promptly.
Queued withdrawal fallback
Instant withdrawal only uses executable reserve liquidity. If the quote is unavailable or the output amount is too low, use ixQueueWithdrawal and ixExecuteWithdrawal instead.