Skip to main content

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.
1

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';
2

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);
3

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
4

Configure Withdrawal Parameters

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();
TSLAx uses 8 decimals.
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.
5

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.');
}
6

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.
7

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

MethodOperationWhen to Use
getDepositWithLeverageIxsOpen position or add collateralCreating or adding to a leveraged position
buildRepayTxnsRepay with wallet fundsReducing debt using USDC, SOL, etc. from wallet
buildWithdrawTxnsWithdraw collateralWithdrawing collateral after debt is repaid
getWithdrawWithLeverageIxsDeleverage and withdrawSell collateral to repay debt and receive remaining value in wallet
getRepayWithCollIxsRepay debt with collateralSell 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.