Position Health Management

Increase borrow, compound, and add collateral to manage position health.

Position Health Management

When a position's LTV drops below the pool's open LTV (e.g. price appreciation), you have excess borrowing capacity. When a position approaches liquidation, you can add collateral to improve health. These endpoints let you manage position health programmatically.

Concepts

  • LTV (Loan-to-Value): debt / collateral value. Lower = healthier.
  • Open LTV: maximum LTV the pool allows for borrowing (e.g. 78% = 7800 bps).
  • Liquidation LTV: threshold where the position gets liquidated (e.g. 90%).
  • Headroom: when current LTV is well below liquidation LTV, you can borrow more.

Step 1: Check Borrow Headroom

curl -X POST https://api.lavarage.xyz/api/v1/positions/increase-borrow-quote \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positionAddress": "YOUR_POSITION",
    "userPublicKey": "YOUR_WALLET",
    "mode": "withdraw"
  }'

Response includes:

  • maxAdditionalBorrow — max you can borrow in quote token smallest units
  • currentLTV / projectedLTV — LTV before and after borrowing max
  • hasHeadroom — true if position has meaningful borrowing capacity
  • priceScenarios — what-if table showing PnL and LTV at various price changes

Step 2a: Withdraw (Borrow More)

Borrow additional quote tokens and receive them in your wallet:

curl -X POST https://api.lavarage.xyz/api/v1/positions/increase-borrow \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positionAddress": "YOUR_POSITION",
    "userPublicKey": "YOUR_WALLET",
    "additionalBorrowAmount": "500000000",
    "mode": "withdraw"
  }'

Sign and submit the returned transaction. Your debt increases and you receive the quote tokens.

Step 2b: Compound (Re-Leverage)

Borrow more, swap to base token via Jupiter, and deposit as additional collateral — all in one transaction:

# First get a compound quote to see the swap estimate
curl -X POST https://api.lavarage.xyz/api/v1/positions/increase-borrow-quote \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positionAddress": "YOUR_POSITION",
    "userPublicKey": "YOUR_WALLET",
    "mode": "compound",
    "slippageBps": 50
  }'

# Then build the transaction
curl -X POST https://api.lavarage.xyz/api/v1/positions/increase-borrow \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positionAddress": "YOUR_POSITION",
    "userPublicKey": "YOUR_WALLET",
    "additionalBorrowAmount": "500000000",
    "mode": "compound",
    "slippageBps": 50,
    "astralaneTipLamports": 10000
  }'

Compound mode includes a Jupiter swap, so it supports MEV protection via astralaneTipLamports. Submit the signed transaction via POST /api/v1/bundle/submit with mevProtect: true.

The compound quote's jupiterQuote.outAmount tells you how many base tokens you'll receive. The projectedLTV accounts for both the increased debt and the new collateral.

Step 3: Add Collateral (Rescue from Liquidation)

If your position is approaching liquidation, add more base tokens as collateral:

# Get quote to see projected LTV improvement
curl -X POST https://api.lavarage.xyz/api/v1/positions/add-collateral-quote \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positionAddress": "YOUR_POSITION",
    "userPublicKey": "YOUR_WALLET",
    "collateralAmount": "1000000000"
  }'

# Build the transaction
curl -X POST https://api.lavarage.xyz/api/v1/positions/add-collateral \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positionAddress": "YOUR_POSITION",
    "userPublicKey": "YOUR_WALLET",
    "collateralAmount": "1000000000"
  }'

The collateral amount is in the base token's smallest units. The add-collateral quote response includes baseTokenAddress and baseDecimals so you know which token to send and at what precision.

Automation Example: Auto-Compound Bot

// Poll positions and auto-compound when headroom is available
async function autoCompound(positionAddress: string, wallet: Keypair) {
  const quote = await fetch(`${API_BASE}/api/v1/positions/increase-borrow-quote`, {
    method: 'POST',
    headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      positionAddress,
      userPublicKey: wallet.publicKey.toBase58(),
      mode: 'compound',
      slippageBps: 100,
    }),
  }).then(r => r.json());

  if (!quote.hasHeadroom || Number(quote.maxAdditionalBorrow) <= 0) return;

  const { transaction } = await fetch(`${API_BASE}/api/v1/positions/increase-borrow`, {
    method: 'POST',
    headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      positionAddress,
      userPublicKey: wallet.publicKey.toBase58(),
      additionalBorrowAmount: quote.maxAdditionalBorrow,
      mode: 'compound',
      slippageBps: 100,
    }),
  }).then(r => r.json());

  const tx = VersionedTransaction.deserialize(bs58.decode(transaction));
  tx.sign([wallet]);
  const sig = await connection.sendRawTransaction(tx.serialize());
  console.log('Compounded:', sig);
}