Code Examples

TypeScript and Python examples for common integration patterns.

TypeScript: Open a 3x Long SOL Position

Full working example using the native fetch API. No SDK required.

import { VersionedTransaction, Connection } from '@solana/web3.js'
import bs58 from 'bs58'

const API_BASE = 'https://api.lavarage.xyz'
const API_KEY = process.env.LAVARAGE_API_KEY!

interface OpenByTokenRequest {
  baseTokenMint: string
  userPublicKey: string
  collateralAmount: string
  leverage: number
  side: 'LONG' | 'SHORT'
  slippageBps?: number
  quoteTokenMint?: string
}

async function openLeveragedPosition(
  wallet: { publicKey: string; signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction> },
  params: OpenByTokenRequest,
): Promise<string> {
  // Step 1: Build the unsigned transaction
  const res = await fetch(`${API_BASE}/api/v1/positions/open-by-token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY,
    },
    body: JSON.stringify(params),
  })

  if (!res.ok) {
    const err = await res.json()
    throw new Error(`API error ${err.code}: ${err.message}`)
  }

  const { transaction } = await res.json()

  // Step 2: Deserialise, sign, submit
  const txBytes = bs58.decode(transaction)
  const tx = VersionedTransaction.deserialize(txBytes)
  const signedTx = await wallet.signTransaction(tx)

  const connection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed')
  const signature = await connection.sendRawTransaction(signedTx.serialize(), {
    skipPreflight: false,
    preflightCommitment: 'confirmed',
  })

  await connection.confirmTransaction(signature, 'confirmed')
  return signature
}

// Usage
const signature = await openLeveragedPosition(wallet, {
  baseTokenMint: 'So11111111111111111111111111111111111111112', // SOL
  userPublicKey: wallet.publicKey,
  collateralAmount: '1000000000', // 1 SOL in lamports
  leverage: 3,
  side: 'LONG',
  slippageBps: 50, // 0.5%
})

console.log('Position opened:', signature)

TypeScript: Full Position Lifecycle

// 1. Open
const openSig = await openLeveragedPosition(wallet, { ... })

// 2. Poll positions
const posRes = await fetch(
  `${API_BASE}/api/v1/positions?owner=${wallet.publicKey}&status=OPEN`,
  { headers: { 'x-api-key': API_KEY } }
)
const positions = await posRes.json()
const position = positions[0]

// 3. Get close quote
const quoteRes = await fetch(`${API_BASE}/api/v1/positions/close-quote`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
  body: JSON.stringify({
    positionAddress: position.address,
    userPublicKey: wallet.publicKey,
  }),
})
const quote = await quoteRes.json()
console.log('Close quote — repay:', quote.repayAmount, 'fee:', quote.fee)

// 4. Build close transaction
const closeRes = await fetch(`${API_BASE}/api/v1/positions/close`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
  body: JSON.stringify({
    positionAddress: position.address,
    userPublicKey: wallet.publicKey,
    slippageBps: 50,
  }),
})
const { transaction } = await closeRes.json()

// 5. Sign and submit
const closeTx = VersionedTransaction.deserialize(bs58.decode(transaction))
const signedClose = await wallet.signTransaction(closeTx)
const closeSig = await connection.sendRawTransaction(signedClose.serialize())
await connection.confirmTransaction(closeSig, 'confirmed')
console.log('Position closed:', closeSig)

Python: Basic Position Lifecycle

import requests
import base58
from solders.transaction import VersionedTransaction
from solders.keypair import Keypair

API_BASE = "https://api.lavarage.xyz"
API_KEY = "your-api-key"
HEADERS = {"Content-Type": "application/json", "x-api-key": API_KEY}

# Open a 3x long SOL position
open_res = requests.post(
    f"{API_BASE}/api/v1/positions/open-by-token",
    headers=HEADERS,
    json={
        "baseTokenMint": "So11111111111111111111111111111111111111112",
        "userPublicKey": str(keypair.pubkey()),
        "collateralAmount": "1000000000",
        "leverage": 3,
        "side": "LONG",
        "slippageBps": 50,
    }
)
open_res.raise_for_status()
transaction = open_res.json()["transaction"]

# Deserialise, sign, submit
tx_bytes = base58.b58decode(transaction)
tx = VersionedTransaction.from_bytes(tx_bytes)
tx.sign([keypair])  # sign with the user's keypair
# submit via your preferred RPC client

# List open positions
positions_res = requests.get(
    f"{API_BASE}/api/v1/positions",
    headers=HEADERS,
    params={"owner": str(keypair.pubkey()), "status": "OPEN"}
)
positions = positions_res.json()
print(f"Open positions: {len(positions)}")

Generate a TypeScript Client from the OpenAPI Spec

# Download the spec
curl https://api.lavarage.xyz/docs-json -o openapi.json

# Generate a TypeScript fetch client
npx @openapitools/openapi-generator-cli generate \
  -i openapi.json \
  -g typescript-fetch \
  -o ./lavarage-client \
  --additional-properties=typescriptThreePlus=true

# Generate a Python client
npx @openapitools/openapi-generator-cli generate \
  -i openapi.json \
  -g python \
  -o ./lavarage-python-client

The generated client includes full TypeScript types for all request/response shapes.