Skip to main content

Deleveraging takes value out of a multiply position in a single atomic transaction: it sells TSLAx collateral through KSwap, repays part of the USDC debt with a flash loan, and sends the rest to the wallet, with no external funds needed. The position shrinks but keeps its LTV, so its leverage stays the same. To lower leverage, repay debt with Repay or Repay with Collateral.

Multiply positions use MultiplyObligation which derives a unique PDA (Program Derived Address) based on your wallet, market, collateral token (TSLAx), and debt token (USDC). Each collateral/debt pair creates a separate obligation address, allowing you to have multiple multiply positions simultaneously.

Deleverage Multiply Position with xStocks

Reduce leverage on a TSLAx multiply position by selling collateral to repay USDC debt.
1

Import Dependencies

Use @kamino-finance/kswap-sdk 2.9.0. It’s the last version on @solana/kit 2, which @kamino-finance/klend-sdk 13 uses; 3.x moved to kit 8.
2

Load Configuration and Initialize SDKs

3

Load the Multiply Obligation

A Multiply position is its own obligation, addressed by the collateral and debt mints.
4

Read the Position

deposited and borrowed are the position’s current amounts in token units.
5

Get Scope Price Refresh Instructions

6

Define the Swap Helpers

The SDK asks for swaps through two callbacks: a quoter that prices the swap and a swapper that returns its instructions. Both use every KSwap route, sorted by output.
priceAInB must be the mid price (amountOut / amountIn, each in token units), before slippage. The SDK applies slippagePct itself, so a guaranteed or minimum-out price counts slippage twice and sizes the position wrong. getBestRoute currently returns no routes, so use getAllRoutes, which in kswap-sdk 2.9.0 takes the router context as a second argument.
7

Build the Withdraw Routes

The SDK builds one candidate transaction per swap route: flash borrow, repay part of the debt, withdraw TSLAx, swap it to USDC, repay the flash loan, and send the rest to the wallet.
withdrawAmount is in the selected token (USDC here). To close the whole position, set isClosingPosition to true.
8

Fetch Lookup Tables

Fetch Kamino’s lookup tables for each candidate transaction, one request per candidate.
/luts/find-minimal takes one transaction’s worth of addresses (between 64 and 128), so a single request for all candidates is rejected.
9

Pick the Route That Fits

Compress each candidate with its route’s lookup tables and Kamino’s, then take the best-output one that fits in a transaction.
The best-output route often has too many accounts to fit, even compressed: in testing only one or two of five to ten routes did. The slippage setting covers the gap between the best route’s quote and the one sent.
10

Sign and Send

The position is smaller and the USDC is in the wallet. The position keeps its LTV, so its leverage is unchanged.

Borrow and Multiply SDK Methods

Multiply operations use MultiplyObligation. Vanilla operations use VanillaObligation. The obligation type determines which PDA is derived for your position.