@apollosolution/vault-sdk
v0.1.1
Published
TypeScript SDK for integrating SendIt vaults into external applications
Maintainers
Readme
@apollosolution/vault-sdk
TypeScript SDK for integrating SendIt vaults into external applications.
Note: This SDK focuses on vault operations and transaction construction. For wallet management, we recommend using @solana/wallet-adapter-react or similar wallet integration libraries.
What This SDK Does
✅ Vault Discovery: Find vaults by type or deposit token
✅ Vault Information: Get detailed vault metrics, APY, TVL, and configuration
✅ User Positions: Track user deposits and earnings across vaults
✅ Transaction Construction: Create unsigned transactions for deposits/withdrawals
✅ Fee Calculations: Calculate deposit fees and estimate future earnings
✅ Analytics: Get comprehensive vault statistics and performance metrics
What This SDK Doesn't Do
❌ Wallet Management: Connect, disconnect, or manage wallet state
❌ Transaction Signing: Sign transactions with user's private keys
❌ Transaction Submission: Send transactions to the Solana network
Why this separation? Wallet management is a security-sensitive area best handled by dedicated, audited libraries like
@solana/wallet-adapter-react. This keeps our SDK focused, lightweight, and secure.
Installation
npm install @apollosolution/vault-sdk
# or
yarn add @apollosolution/vault-sdk
# or
pnpm add @apollosolution/vault-sdkQuick Start
import { VaultClient } from '@apollosolution/vault-sdk';
// Initialize the client
const client = new VaultClient({
apiUrl: 'https://backend.sendit.fun' // Optional, this is the default
});
// Get vault information
const vault = await client.singleSided.getVault('VAULT_ADDRESS');
console.log(`Vault APY: ${vault.vault.metrics.grossAPY}%`);
// Get user position
const position = await client.singleSided.getUserPosition(
'VAULT_ADDRESS',
'USER_WALLET_ADDRESS'
);
console.log(`User position: ${position.position.underlyingAmount} tokens`);Features
- 🚀 Simple, intuitive API
- 💼 Full TypeScript support
- ⚡ Transaction construction
- 📊 Position tracking and analytics
- 💰 Fee calculation utilities
Documentation
For complete documentation and examples, see the integration guide.
API Reference
VaultClient
The main client for interacting with SendIt vaults.
const client = new VaultClient({
apiUrl?: string; // API endpoint (default: https://backend.sendit.fun)
apiKey?: string; // Optional API key for authentication
timeout?: number; // Request timeout in ms (default: 30000)
});Single-Sided Vaults
Access single-sided vault functionality through client.singleSided:
Vault Discovery
// List all single-sided vaults
const vaults = await client.singleSided.listVaults();
// Get vault by deposit token (e.g., NOBODY vault)
const nobodyVault = await client.singleSided.getVaultByToken('C29ebrgYjYoJPMGPnPSGY1q3mMGk4iDSqnQeQQA7moon');
// Also accepts PublicKey objects
const vault = await client.singleSided.getVaultByToken(new PublicKey('C29ebrgYjYoJPMGPnPSGY1q3mMGk4iDSqnQeQQA7moon'));Vault Information
// Get detailed vault information
const vault = await client.singleSided.getVault(vaultId);
console.log(vault.vault.metrics.grossAPY); // Annual Percentage Yield
console.log(vault.vault.tvl.totalValueUsd); // Total Value Locked in USD
// Get vault statistics summary
const stats = await client.singleSided.getVaultStats(vaultId);
console.log(stats); // { tvl, tvlUsd, grossAPR, grossAPY, depositFeePercent, etc. }User Positions
// Get user position in a vault
const position = await client.singleSided.getUserPosition(vaultId, walletAddress);
// Also accepts PublicKey objects
const position = await client.singleSided.getUserPosition(vaultId, new PublicKey('WALLET_ADDRESS'));
console.log(position.position.underlyingAmount); // User's deposited amount
console.log(position.position.underlyingAmountUsd); // USD value
console.log(position.position.vaultTokens); // Vault tokens owned
console.log(position.position.share); // % of vault owned
console.log(position.wallet.depositToken.balance); // Available wallet balanceTransactions
// Create deposit transaction (returns unsigned transactions)
const depositTxs = await client.singleSided.deposit(vaultId, amount, walletAddress);
// Create withdrawal transaction (returns unsigned transactions)
const withdrawTxs = await client.singleSided.withdraw(vaultId, amount, walletAddress);
// Withdraw entire position (returns unsigned transactions)
const withdrawMaxTxs = await client.singleSided.withdrawMax(vaultId, walletAddress);
// All transaction methods accept string or PublicKey for wallet address
const depositTxs = await client.singleSided.deposit(vaultId, amount, new PublicKey('WALLET_ADDRESS'));Financial Calculations
// Calculate deposit fees
const fees = await client.singleSided.calculateDepositFee(vaultId, amount);
console.log(fees); // { fee, feePercentage, netDeposit }
// Estimate earnings over time
const earnings = await client.singleSided.estimateEarnings(vaultId, amount);
console.log(earnings); // { dailyEarnings, monthlyEarnings, yearlyEarnings, grossAPR, grossAPY }Examples
Wallet Integration with @solana/wallet-adapter-react
import { VaultClient } from '@apollosolution/vault-sdk';
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { useState } from 'react';
export function DepositComponent() {
const { publicKey, signAllTransactions } = useWallet();
const { connection } = useConnection();
const [amount, setAmount] = useState('');
const client = new VaultClient();
const handleDeposit = async () => {
if (!publicKey || !signAllTransactions) return;
try {
// Calculate fees before deposit
const fees = await client.singleSided.calculateDepositFee('VAULT_ADDRESS', amount);
console.log(`Deposit fee: ${fees.fee} (${fees.feePercentage}%)`);
console.log(`Net deposit: ${fees.netDeposit}`);
// Create deposit transactions (returns UNSIGNED transactions)
const transactions = await client.singleSided.deposit(
'VAULT_ADDRESS',
amount,
publicKey
);
// ⚠️ SDK returns unsigned transactions - you must sign them with your wallet
const signedTxs = await signAllTransactions(transactions);
// Send transactions using your preferred method
for (const tx of signedTxs) {
const signature = await connection.sendTransaction(tx, {
skipPreflight: false,
maxRetries: 3
});
await connection.confirmTransaction(signature, 'confirmed');
console.log(`Transaction confirmed: ${signature}`);
}
} catch (error) {
console.error('Deposit failed:', error);
}
};
return (
<div>
<input
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Amount to deposit"
/>
<button onClick={handleDeposit}>Deposit</button>
</div>
);
}Complete Vault Discovery Example
import { VaultClient, PublicKey } from '@apollosolution/vault-sdk';
const client = new VaultClient();
async function findAndAnalyzeVault() {
// Find NOBODY vault
const nobodyMint = 'C29ebrgYjYoJPMGPnPSGY1q3mMGk4iDSqnQeQQA7moon';
try {
// Get the NOBODY vault directly by token
const vault = await client.singleSided.getVaultByToken(nobodyMint);
const stats = await client.singleSided.getVaultStats(vault.vault.address);
console.log(`NOBODY Vault ${vault.vault.address}:`);
console.log(` APY: ${vault.vault.metrics.grossAPY}%`);
console.log(` TVL: $${stats.tvlUsd.toLocaleString()}`);
console.log(` Deposit Fee: ${stats.depositFeePercent}%`);
console.log(` Deposit Token: ${vault.vault.depositToken.symbol}`);
console.log(` Vault Token: ${vault.vault.vaultToken.symbol}`);
return vault;
} catch (error) {
console.log('NOBODY vault not found');
return null;
}
}Monitor User Position
import { VaultClient } from '@apollosolution/vault-sdk';
const client = new VaultClient();
async function monitorPosition(vaultId: string, wallet: string) {
try {
const position = await client.singleSided.getUserPosition(vaultId, wallet);
console.log('Current Position:', {
vaultTokens: position.position.vaultTokens,
underlyingValue: position.position.underlyingAmount,
valueUsd: position.position.underlyingAmountUsd,
shareOfVault: `${position.position.share}%`
});
console.log('Wallet Balance:', {
depositToken: position.wallet.depositToken.balance,
valueUsd: position.wallet.depositToken.balanceUsd
});
// Calculate potential earnings
const earnings = await client.singleSided.estimateEarnings(
vaultId,
position.position.underlyingAmount
);
console.log('Estimated Earnings:', {
daily: `$${Number(earnings.dailyEarnings).toFixed(2)}`,
monthly: `$${Number(earnings.monthlyEarnings).toFixed(2)}`,
yearly: `$${Number(earnings.yearlyEarnings).toFixed(2)}`
});
} catch (error) {
console.error('Failed to fetch position:', error);
}
}
// Monitor every 30 seconds
setInterval(() => {
monitorPosition('VAULT_ADDRESS', 'WALLET_ADDRESS');
}, 30000);Error Handling Best Practices
import { VaultClient, ApiError } from '@apollosolution/vault-sdk';
const client = new VaultClient();
async function safeVaultOperation() {
try {
const vault = await client.singleSided.getVault('VAULT_ADDRESS');
return vault;
} catch (error) {
if (error instanceof ApiError) {
// Handle SDK-specific errors
console.error(`API Error (${error.code}):`, error.message);
switch (error.code) {
case 'VAULT_NOT_FOUND':
console.log('This vault does not exist');
break;
case 'NETWORK_ERROR':
console.log('Please check your internet connection');
break;
default:
console.log('An unexpected error occurred');
}
} else {
// Handle other errors
console.error('Unexpected error:', error);
}
throw error;
}
}TypeScript Types
The SDK provides comprehensive TypeScript types for all responses:
import {
VaultClient,
VaultResponse,
UserPositionResponse,
VaultListResponse,
VaultType,
TokenInfo,
VaultMetrics,
PublicKey
} from '@apollosolution/vault-sdk';
// All API responses are fully typed
const client = new VaultClient();
// VaultResponse type includes all vault information
const vault: VaultResponse = await client.singleSided.getVault('VAULT_ID');
// Access nested properties with full IntelliSense support
const apy: number = vault.vault.metrics.grossAPY;
const tvl: number = vault.vault.tvl.totalValueUsd;
const depositToken: TokenInfo = vault.vault.depositToken;
// UserPositionResponse includes both position and wallet data
const position: UserPositionResponse = await client.singleSided.getUserPosition('VAULT_ID', 'WALLET');
const userBalance: string = position.wallet.depositToken.balance;
const vaultShare: number = position.position.share;Configuration
Client Configuration
const client = new VaultClient({
apiUrl: 'https://backend.sendit.fun', // Default: https://backend.sendit.fun
apiKey: 'your-api-key', // Optional: for authenticated endpoints
timeout: 30000 // Default: 30000ms (30 seconds)
});Environment Variables
You can also configure the SDK using environment variables:
# Optional: Override default API URL
VAULT_SDK_API_URL=https://backend.sendit.fun
# Optional: Set default API key
VAULT_SDK_API_KEY=your-api-key
# Optional: Set default timeout
VAULT_SDK_TIMEOUT=30000Supported Vault Types
Currently supported vault types:
- ✅ single-sided: Single-token vaults (accessible via
client.singleSided) - 🔜 sol: SOL-specific vaults (coming soon)
Rate Limits
The SDK respects the backend API rate limits. If you encounter rate limiting:
- Implement exponential backoff for retries
- Cache vault information when possible
- Use batch operations where available
Security
- ✅ No Private Keys: SDK never handles private keys or seeds
- ✅ HTTPS Only: All API calls use HTTPS
- ✅ Input Validation: All inputs are validated before API calls
- ✅ Error Handling: Comprehensive error handling with specific error codes
License
MIT
