Documentation Index
Fetch the complete documentation index at: https://kamino.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Withdrawing collateral from a multiply position after fully repaying debt allows you to unlock and retrieve your equity.
This operation uses buildWithdrawTxns (not getWithdrawWithLeverageIxs, which is for deleveraging by selling collateral to repay debt).
Multiply Withdraw with xStocks
Withdraw TSLAx collateral from a multiply position after all debt has been repaid.
Import Dependencies
Import the required packages for Solana RPC communication, Kamino SDK operations, and transaction building.import {
createSolanaRpc,
createSolanaRpcSubscriptions,
address,
pipe,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
getSignatureFromTransaction,
} from '@solana/kit';
import {
KaminoMarket,
KaminoAction,
MultiplyObligation,
PROGRAM_ID,
parseKeypairFile,
DEFAULT_RECENT_SLOT_DURATION_MS,
} from '@kamino-finance/klend-sdk';
import BN from 'bn.js';
Load Configuration and Initialize Market
Load the keypair and initialize the xStocks market.const KEYPAIR_FILE = '/path/to/your/keypair.json';
const signer = await parseKeypairFile(KEYPAIR_FILE);
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');
const marketPubkey = address('5wJeMrUYECGq41fxRESKALVcHnNX26TAWy4W98yULsua'); // xStocks Market
const market = await KaminoMarket.load(rpc, marketPubkey, DEFAULT_RECENT_SLOT_DURATION_MS);
Find TSLAx Reserve
Dynamically discover the TSLAx token mint by searching the market reserves by symbol.const tslaReserve = Array.from(market!.reserves.values()).find((reserve) => reserve.symbol === 'TSLAx');
if (!tslaReserve) {
console.log('TSLAx reserve not found in xStocks market');
}
const collTokenMint = tslaReserve.getLiquidityMint();
const debtTokenMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); // USDC
Set the amount of TSLAx collateral to withdraw.const withdrawAmount = new BN(1_250_000); // ~$5 worth of TSLAx (8 decimals)
const currentSlot = await rpc.getSlot().send();
buildWithdrawTxns requires all debt to be repaid before withdrawing collateral. If you have outstanding debt, repay it first or use getWithdrawWithLeverageIxs to deleverage by selling collateral.
Fetch Existing Multiply Obligation
Create the multiply obligation type and fetch the existing position from the blockchain.const obligationType = new MultiplyObligation(collTokenMint, debtTokenMint, PROGRAM_ID);
const obligation = await market!.getObligationByWallet(address(signer.address), obligationType);
if (!obligation) {
console.log('No obligation found for this wallet. You must have collateral deposited to withdraw.');
}
Build Withdrawal Transaction
Use KaminoAction.buildWithdrawTxns to generate the withdrawal instructions.const withdrawAction = await KaminoAction.buildWithdrawTxns(
market!,
withdrawAmount,
collTokenMint,
signer,
obligationType,
true, // useV2Ixs
undefined, // scopeRefreshConfig
currentSlot,
1_000_000, // extraComputeBudget
true, // includeAtaIxs
false // requestElevationGroup
);
const allInstructions = [
...(withdrawAction.setupIxs || []),
...(withdrawAction.lendingIxs || []),
...(withdrawAction.cleanupIxs || []),
];
buildWithdrawTxns is used for withdrawing collateral when debt is fully repaid. For deleveraging (selling collateral to repay outstanding debt), use getWithdrawWithLeverageIxs instead.
Send Transaction
Get a fresh blockhash, build the transaction, sign it, and send it to the network.const { value: latestBlockhash } = await rpc.getLatestBlockhash({ commitment: 'finalized' }).send();
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(signer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions(allInstructions, tx)
);
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
const signature = getSignatureFromTransaction(signedTransaction);
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction, {
commitment: 'confirmed',
skipPreflight: true,
});
console.log(`Withdraw successful! Withdrew ~$5 worth of TSLAx from multiply position.`);
console.log(`Transaction signature: ${signature}`);
The withdrawal is complete. Your TSLAx collateral has been transferred to your wallet.
Borrow and Multiply SDK Methods
| Method | Operation | When to Use |
|---|
getDepositWithLeverageIxs | Open position or add collateral | Creating or adding to a leveraged position |
buildRepayTxns | Repay with wallet funds | Reducing debt using USDC, SOL, etc. from wallet |
buildWithdrawTxns | Withdraw collateral | Withdrawing collateral after debt is repaid |
getWithdrawWithLeverageIxs | Deleverage and withdraw | Sell collateral to repay debt and receive remaining value in wallet |
getRepayWithCollIxs | Repay debt with collateral | Sell collateral to repay debt without withdrawing (value stays in position) |
Multiply operations use MultiplyObligation. Vanilla operations use VanillaObligation. The obligation type determines which PDA is derived for your position.