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:
An initialized vault in the Voltr Protocol
Manager authority for the vault
The Voltr SDK installed:
Copy npm install @voltr/sdk
Setup
First, import the required dependencies:
Copy import { Connection , Keypair , PublicKey , TransactionInstruction } from "@solana/web3.js" ;
import { VoltrClient } from "@voltr/sdk" ;
import { BN } from "@coral-xyz/anchor" ;
Initialize the client:
Copy 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:
Copy 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
Copy 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
Copy 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
Copy 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
Copy 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
Copy 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
Copy 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
Copy 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
Consider breaking up large operations
Account for remaining accounts
2. Fee Management
Copy 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
Time transactions during lower gas periods
Optimize remaining accounts
4. Security Checklist
Before operations:
After operations:
Function Reference
Key Functions
Copy // 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 .