@stbr/solana-vault
v2.0.0
Published
Core TypeScript SDK for SVS Solana Vault Standards
Readme
@stbr/solana-vault
TypeScript SDK and CLI for the Solana Vault Standard (SVS). Build yield-bearing vaults with deposit/withdraw operations, share accounting, preview functions, and modular extensions.
Features
- Core Vault Operations - Deposit, mint, withdraw, redeem with slippage protection
- Preview Functions - Off-chain calculation of expected shares/assets
- Inflation Attack Protection - Virtual offset mechanism prevents donation attacks
- Vault-Favoring Rounding - All operations round to protect vault solvency
- Multi-Vault Support - Multiple vaults per asset via
vault_id - CLI Tool - Full-featured command-line interface for vault management
- Modular Extensions - Fees, caps, access control, timelocks, strategies
Installation
npm install @stbr/solana-vaultQuick Start
SDK Usage
import { SolanaVault, ManagedVault } from "@stbr/solana-vault";
import { BN } from "@coral-xyz/anchor";
// Load an SVS-1 vault (live balance)
const vault = await SolanaVault.load(program, assetMint, 1);
// Preview deposit to calculate expected shares
const expectedShares = await vault.previewDeposit(new BN(1_000_000));
// Deposit with 5% slippage protection
await vault.deposit(user, {
assets: new BN(1_000_000),
minSharesOut: expectedShares.mul(new BN(95)).div(new BN(100)),
});
// Preview and redeem shares
const expectedAssets = await vault.previewRedeem(shares);
await vault.redeem(user, {
shares,
minAssetsOut: expectedAssets.mul(new BN(95)).div(new BN(100)),
});
// SVS-2 vaults: use ManagedVault for sync() support
const managed = await ManagedVault.load(program, assetMint, 1);
await managed.sync(authority); // Sync stored balance with actualCLI Usage
# Install globally
npm install -g @stbr/solana-vault
# Initialize configuration
solana-vault config init
# Add a vault alias
solana-vault config add-vault my-vault <ADDRESS> --variant svs-1
# Common operations
solana-vault info my-vault # View vault state
solana-vault balance my-vault # Check your balance
solana-vault preview my-vault deposit 1000000 # Preview deposit
solana-vault deposit my-vault -a 1000000 # Deposit assets
solana-vault redeem my-vault --all # Redeem all shares
solana-vault dashboard my-vault # Live monitoringSDK Modules
// Core vault operations
export { SolanaVault } from "./vault";
export { ManagedVault } from "./managed-vault";
// Share/asset conversion math
export { convertToShares, convertToAssets, Rounding } from "./math";
// PDA derivation utilities
export { getVaultAddress, getSharesMintAddress } from "./pda";
// Extension modules
export * from "./fees"; // Management, performance, entry/exit fees
export * from "./cap"; // Global and per-user deposit caps
export * from "./emergency"; // Emergency withdrawal with penalty
export * from "./access-control"; // Whitelist/blacklist + merkle proofs
export * from "./multi-asset"; // Multi-vault portfolio allocation
export * from "./timelock"; // Governance proposal lifecycle
export * from "./strategy"; // DeFi strategy deploymentCore Operations
| Operation | User Action | Slippage Param | Rounding |
|-----------|-------------|----------------|----------|
| deposit | Pay exact assets → receive shares | minSharesOut | Floor (fewer shares) |
| mint | Receive exact shares → pay assets | maxAssetsIn | Ceiling (pay more) |
| withdraw | Receive exact assets → burn shares | maxSharesIn | Ceiling (burn more) |
| redeem | Burn exact shares → receive assets | minAssetsOut | Floor (receive less) |
CLI Commands
Inspect
info <vault>- Display vault statebalance <vault>- Check user balancepreview <vault> <op> <amount>- Preview operationslist- List configured vaultshistory <vault>- Transaction history
Operate
deposit <vault> -a <amount>- Deposit assetsmint <vault> --shares <amount>- Mint exact shareswithdraw <vault> -a <amount>- Withdraw exact assetsredeem <vault> --shares <amount>- Redeem shares
Admin
pause <vault>- Emergency pauseunpause <vault>- Resume operationssync <vault>- Sync balance (SVS-2/4)transfer-authority <vault>- Transfer ownership
Extensions
fees show|configure|collect- Fee managementcap show|configure|check- Deposit capsaccess show|set-mode|add|remove- Access controlemergency show|configure|withdraw- Emergency withdrawaltimelock show|propose|execute|cancel- Timelocked governancestrategy show|add|deploy|recall- DeFi strategiesportfolio show|deposit|redeem|rebalance- Multi-vault portfoliosct configure|apply-pending|status- Confidential transfers (SVS-3/4)
Monitoring
dashboard <vault>- Real-time monitoringhealth <vault>- Comprehensive health check
Global flags: --dry-run, --yes, --output json|table|csv, --keypair <path>, --url <rpc>
View Functions
All view functions work off-chain (no transactions required):
// Get vault state
const state = await vault.getState();
// Total assets and shares
const totalAssets = await vault.totalAssets();
const totalShares = await vault.totalShares();
// Convert between assets and shares
const shares = await vault.convertToShares(assets);
const assets = await vault.convertToAssets(shares);
// Preview operations
const sharesOut = await vault.previewDeposit(assets);
const assetsIn = await vault.previewMint(shares);
const sharesIn = await vault.previewWithdraw(assets);
const assetsOut = await vault.previewRedeem(shares);
// Admin functions
const isPaused = await vault.isPaused();
const authority = await vault.getAuthority();PDA Derivation
import { getVaultAddress, getSharesMintAddress } from "@stbr/solana-vault";
// Vault PDA: ["vault", asset_mint, vault_id.to_le_bytes()]
const [vaultPda, bump] = getVaultAddress(programId, assetMint, vaultId);
// Shares Mint PDA: ["shares", vault_pubkey]
const [sharesMint, mintBump] = getSharesMintAddress(programId, vaultPda);Error Handling
import { parseVaultError, isSlippageError, VaultErrorCode } from "@stbr/solana-vault";
try {
await vault.deposit(user, params);
} catch (error) {
const parsed = parseVaultError(error);
if (parsed) {
switch (parsed.code) {
case VaultErrorCode.SlippageExceeded:
console.error("Slippage tolerance exceeded");
break;
case VaultErrorCode.VaultPaused:
console.error("Vault is paused");
break;
case VaultErrorCode.InsufficientShares:
console.error("Not enough shares");
break;
}
}
}Slippage Protection
Always use slippage protection to guard against MEV:
// Helper function
function applySlippage(amount: BN, bps: number, isReceiving: boolean): BN {
const basis = new BN(10000);
const slippage = new BN(bps);
return isReceiving
? amount.mul(basis.sub(slippage)).div(basis) // Accept less
: amount.mul(basis.add(slippage)).div(basis); // Pay more
}
// Usage (50 bps = 0.5% slippage)
const minShares = applySlippage(expectedShares, 50, true);
const maxAssets = applySlippage(requiredAssets, 50, false);SVS Variants
| Variant | Balance Model | Privacy | Use Case | |---------|---------------|---------|----------| | SVS-1 | Live (reads actual balance) | Public | Simple vaults, lending | | SVS-2 | Stored (cached, needs sync) | Public | Yield aggregators, managed funds | | SVS-3 | Live | Confidential | Private savings | | SVS-4 | Stored | Confidential | Private managed funds |
Note: SVS-3/SVS-4 require the @stbr/svs-privacy-sdk package and a proof backend.
Configuration
The CLI stores config in ~/.solana-vault/config.yaml:
defaults:
cluster: devnet
keypair: ~/.config/solana/id.json
output: table
vaults:
my-vault:
address: "7xKYqBvpmmN..."
variant: svs-1
assetMint: "EPjFWdd5Aufq..."Requirements
- Node.js 20+
- Solana CLI (for keypair management)
- SVS program deployed (devnet IDs in main README)
Documentation
License
Apache 2.0
