Voltr SDK

Voltr Protocol - Deposit & Withdrawal Technical Guide

This technical guide explains how to use the Voltr SDK to deposit and withdraw funds from strategies. It includes complete code examples and important technical considerations.

Prerequisites

Ensure you have:

  1. An initialized vault in the Voltr Protocol

  2. Manager authority for the vault

  3. The Voltr SDK installed:

    npm install @voltr/sdk

Setup

First, import the required dependencies:

import { Connection, Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
import { VoltrClient } from "@voltr/sdk";
import { BN } from "@coral-xyz/anchor";

Initialize the client:

const connection = new Connection("https://api.mainnet-beta.solana.com");
const wallet = Keypair.fromSecretKey(/* your keypair */);
const client = new VoltrClient(connection, wallet);

Depositing Funds to Strategies

1. Pre-Deposit Checks

Before depositing, check current balances and strategy status:

async function checkBalances(
  vaultPubkey: PublicKey,
  strategyPubkey: PublicKey
) {
  // Get vault data
  const vault = await client.fetchVaultAccount(vaultPubkey);
  const idleAmount = vault.asset.totalAmount;

  // Get strategy data
  const vaultStrategy = await client.fetchVaultStrategyAccount(strategyPubkey);
  const deployedAmount = vaultStrategy.currentAmount;

  return {
    idleAmount,
    deployedAmount,
    totalAmount: idleAmount.add(deployedAmount)
  };
}

2. Create Deposit Instruction

async function createDepositInstruction(
  amount: number,
  vault: PublicKey,
  strategy: PublicKey
): Promise<TransactionInstruction> {
  // Get necessary PDAs
  const vaultData = await client.fetchVaultAccount(vault);
  const addresses = client.findStrategyAddresses(
    vault,
    client.findVaultAssetIdleAuth(vault),
    vaultData.asset.assetMint
  );

  return await client.createDepositStrategyIx(
    new BN(amount),
    {
      vault,
      vaultAssetMint: vaultData.asset.assetMint,
      strategy: addresses.strategy,
      vaultStrategy: addresses.vaultStrategy,
      counterpartyAssetTa: vaultData.asset.idleAta,
      protocolProgram: new PublicKey("..."), // Protocol-specific program ID
      remainingAccounts: [] // Protocol-specific accounts
    }
  );
}

3. Complete Deposit Function

async function depositToStrategy(
  amount: number,
  vault: PublicKey,
  strategy: PublicKey
) {
  try {
    // 1. Verify manager authority
    const vaultData = await client.fetchVaultAccount(vault);
    if (!wallet.publicKey.equals(vaultData.manager)) {
      throw new Error("Not authorized as vault manager");
    }

    // 2. Check available funds
    const { idleAmount } = await checkBalances(vault, strategy);
    if (idleAmount.lt(new BN(amount))) {
      throw new Error("Insufficient idle funds");
    }

    // 3. Create deposit instruction
    const depositIx = await createDepositInstruction(amount, vault, strategy);

    // 4. Add your transaction handling code here
    // Build and send transaction
    
    return depositIx;
  } catch (error) {
    console.error("Deposit failed:", error);
    throw error;
  }
}

Withdrawing Funds from Strategies

1. Pre-Withdrawal Checks

async function checkWithdrawalAvailability(
  vaultPubkey: PublicKey,
  strategyPubkey: PublicKey,
  amount: BN
) {
  const vaultStrategy = await client.fetchVaultStrategyAccount(strategyPubkey);
  const currentAmount = vaultStrategy.currentAmount;
  
  if (currentAmount.lt(amount)) {
    throw new Error("Insufficient funds in strategy");
  }
  
  // Add any protocol-specific checks here
  
  return true;
}

2. Create Withdrawal Instruction

async function createWithdrawalInstruction(
  amount: number,
  vault: PublicKey,
  strategy: PublicKey
): Promise<TransactionInstruction> {
  // Get necessary PDAs
  const vaultData = await client.fetchVaultAccount(vault);
  const addresses = client.findStrategyAddresses(
    vault,
    client.findVaultAssetIdleAuth(vault),
    vaultData.asset.assetMint
  );

  return await client.createWithdrawStrategyIx(
    new BN(amount),
    {
      vault,
      vaultAssetMint: vaultData.asset.assetMint,
      strategy: addresses.strategy,
      vaultStrategy: addresses.vaultStrategy,
      counterpartyAssetTa: vaultData.asset.idleAta,
      counterpartyAssetTaAuth: client.findVaultAssetIdleAuth(vault),
      protocolProgram: new PublicKey("..."), // Protocol-specific program ID
      remainingAccounts: [] // Protocol-specific accounts
    }
  );
}

3. Complete Withdrawal Function

async function withdrawFromStrategy(
  amount: number,
  vault: PublicKey,
  strategy: PublicKey
) {
  try {
    // 1. Verify manager authority
    const vaultData = await client.fetchVaultAccount(vault);
    if (!wallet.publicKey.equals(vaultData.manager)) {
      throw new Error("Not authorized as vault manager");
    }

    // 2. Check strategy balance
    await checkWithdrawalAvailability(vault, strategy, new BN(amount));

    // 3. Create withdrawal instruction
    const withdrawIx = await createWithdrawalInstruction(
      amount,
      vault,
      strategy
    );

    // 4. Add your transaction handling code here
    // Build and send transaction
    
    return withdrawIx;
  } catch (error) {
    console.error("Withdrawal failed:", error);
    throw error;
  }
}

Error Handling

interface ErrorResponse {
  success: boolean;
  error?: string;
  data?: any;
}

function handleOperationError(error: any): ErrorResponse {
  if (error.message?.includes("0x1")) {
    return {
      success: false,
      error: "Invalid amount provided"
    };
  } else if (error.message?.includes("0x2")) {
    return {
      success: false,
      error: "Invalid account owner"
    };
  }
  // Add other error mappings
  
  return {
    success: false,
    error: "Unknown error occurred"
  };
}

Complete Usage Example

async function manageStrategyFunds() {
  const vault = new PublicKey("...");
  const strategy = new PublicKey("...");
  const amount = 1000000; // Amount in base units

  try {
    // Deposit example
    const depositIx = await depositToStrategy(amount, vault, strategy);
    // Handle deposit transaction
    
    // Wait for confirmation and verify
    await checkBalances(vault, strategy);
    
    // Later... Withdraw example
    const withdrawIx = await withdrawFromStrategy(amount, vault, strategy);
    // Handle withdraw transaction
    
  } catch (error) {
    const response = handleOperationError(error);
    console.error("Operation failed:", response.error);
  }
}

Important Considerations

1. Transaction Size Limits

  • Monitor instruction size

  • Consider breaking up large operations

  • Account for remaining accounts

2. Fee Management

async function estimatePerformanceFees(
  strategyPubkey: PublicKey,
  currentBalance: BN,
  previousBalance: BN
): Promise<BN> {
  const profit = currentBalance.sub(previousBalance);
  if (profit.lten(0)) return new BN(0);
  
  const vault = await client.fetchVaultAccount(vaultPubkey);
  const feeRate = vault.configuration.performanceFee;
  
  return profit.mul(new BN(feeRate)).div(new BN(10000));
}

3. Gas Optimization

  • Batch related operations

  • Time transactions during lower gas periods

  • Optimize remaining accounts

4. Security Checklist

Before operations:

After operations:

Function Reference

Key Functions

// Deposit operations
client.createDepositStrategyIx()
client.findStrategyAddresses()
client.findVaultAssetIdleAuth()

// Withdrawal operations
client.createWithdrawStrategyIx()
client.fetchVaultAccount()
client.fetchVaultStrategyAccount()

// Account lookup
client.findStrategy()
client.findAdaptorStrategy()
client.findVaultStrategy()

For detailed API documentation and examples, refer to the Voltr SDK documentation.

Last updated