nemo-vaults-sdk
v1.0.69
Published
A TypeScript SDK for interacting with Nemo Vaults on the Sui blockchain. This SDK provides comprehensive functionality for managing liquidity vaults, including deposits, withdrawals, rebalancing, and administrative operations.
Readme
Nemo Vaults SDK
A TypeScript SDK for interacting with Nemo Vaults on the Sui blockchain. This SDK provides comprehensive functionality for managing liquidity vaults, including deposits, withdrawals, rebalancing, and administrative operations.
Features
- Vault Management: Create, configure, and manage different types of vaults (Stable, Uncorrelated, Drift)
- Liquidity Operations: Deposit and withdraw liquidity with automatic optimization
- Automated Bots: Built-in reward collection and rebalancing bots
- Administrative Functions: Complete admin interface for vault configuration
- Multi-Protocol Support: Integration with various staking protocols (Haedal, Volo, Aftermath)
- Docker Support: Ready-to-use Docker containers for production deployment
Installation
npm install nemo-vaults-sdk
# or
yarn add nemo-vaults-sdk
# or
pnpm add nemo-vaults-sdkQuick Start
import { Vaults, Admin } from 'nemo-vaults-sdk';
import { SuiClient } from '@mysten/sui/client';
// Initialize the SDK
const suiClient = new SuiClient({ url: 'https://sui-mainnet.blockvision.org' });
const vaults = Vaults.createSDK({
client: suiClient,
senderAddress: 'your-wallet-address'
});
// Get all vaults
const vaultList = await vaults.getVaultList();
// Get a specific vault
const vault = await vaults.getVault('vault-id');
// Get user's vault balances
const balances = await vaults.getOwnerVaultsBalance('user-address');Core Concepts
Vault Types
- Stable Vaults: Optimized for stable asset pairs with minimal price volatility
- Uncorrelated Vaults: Designed for assets with low correlation, includes rebalancing triggers
- Drift Vaults: Specialized for trending markets with directional price movements
Liquidity Management
- Both-sided deposits: Provide both tokens in optimal ratio
- One-sided deposits: Provide single token with automatic swapping
- Flexible withdrawals: Withdraw as LP tokens or individual assets
- Slippage protection: Configurable slippage tolerance for all operations
Examples
Basic Vault Operations
import { Vaults, Admin, InputType } from 'nemo-vaults-sdk';
import { SuiClient } from '@mysten/sui/client';
import { Transaction } from '@mysten/sui/transactions';
// Initialize the SDK
const suiClient = new SuiClient({ url: 'https://sui-mainnet.blockvision.org' });
const vaults = Vaults.createSDK({
client: suiClient,
senderAddress: 'your-wallet-address'
});
async function basicVaultOperations() {
try {
// 1. Get all available vaults
console.log('Fetching all vaults...');
const allVaults = await vaults.getVaultList();
console.log(`Found ${allVaults.length} vaults`);
// 2. Get detailed information about a specific vault
const vaultId = allVaults[0].id;
const vault = await vaults.getVault(vaultId);
if (!vault) {
console.error('Vault not found');
return;
}
console.log('Vault details:', {
id: vault.id,
coinTypeA: vault.coin_type_a,
coinTypeB: vault.coin_type_b,
totalSupply: vault.total_supply,
depositEnabled: vault.is_deposit_enabled
});
// 3. Check user's vault balances
const userAddress = 'user-wallet-address';
const userBalances = await vaults.getOwnerVaultsBalance(userAddress);
console.log(`User has positions in ${userBalances.length} vaults`);
// 4. Calculate deposit amount for one-sided deposit
console.log('Calculating deposit amount...');
const depositCalc = await vaults.calculateDepositAmount({
vault_id: vaultId,
is_amount_a: true,
input_amount: '1000000', // 1 token (assuming 6 decimals)
slippage: 0.01, // 1% slippage
side: InputType.OneSide
});
console.log('Deposit calculation result:', {
amountA: depositCalc.amount_a,
amountB: depositCalc.amount_b,
lpTokens: depositCalc.ft_amount,
swapRequired: !!depositCalc.swap_result
});
// 5. Execute deposit transaction
const tx = new Transaction();
const lpToken = await vaults.deposit({
vault_id: vaultId,
slippage: 0.01,
deposit_result: depositCalc,
return_coin: true
}, tx);
console.log('Deposit transaction prepared');
// Note: You would sign and execute the transaction here
} catch (error) {
console.error('Error in vault operations:', error);
}
}Deposit and Withdrawal Operations
async function depositWithdrawExample() {
// Initialize SDK
const suiClient = new SuiClient({ url: 'https://sui-mainnet.blockvision.org' });
const vaults = Vaults.createSDK({
client: suiClient,
senderAddress: 'your-wallet-address'
});
const vaultId = 'your-vault-id';
const slippage = 0.01; // 1% slippage tolerance
try {
// === DEPOSIT OPERATIONS ===
// 1. One-sided deposit (provide only token A)
console.log('Calculating one-sided deposit...');
const oneSidedDeposit = await vaults.calculateDepositAmount({
vault_id: vaultId,
is_amount_a: true,
input_amount: '1000000', // 1 token A (assuming 6 decimals)
slippage,
side: InputType.OneSide
});
console.log('One-sided deposit calculation:', {
inputAmount: oneSidedDeposit.original_input_amount,
amountA: oneSidedDeposit.amount_a,
amountB: oneSidedDeposit.amount_b,
lpTokens: oneSidedDeposit.ft_amount,
swapRequired: !!oneSidedDeposit.swap_result
});
// Execute one-sided deposit
const depositTx = new Transaction();
await vaults.deposit({
vault_id: vaultId,
slippage,
deposit_result: oneSidedDeposit,
return_coin: false // Transfer LP tokens to user
}, depositTx);
console.log('One-sided deposit transaction prepared');
// 2. Both-sided deposit (provide both tokens)
console.log('Calculating both-sided deposit...');
const bothSidedDeposit = await vaults.calculateDepositAmount({
vault_id: vaultId,
is_amount_a: true,
input_amount: '1000000', // 1 token A
slippage,
side: InputType.Both
});
console.log('Both-sided deposit calculation:', {
amountA: bothSidedDeposit.amount_a,
amountB: bothSidedDeposit.amount_b,
lpTokens: bothSidedDeposit.ft_amount
});
// Execute both-sided deposit
const bothDepositTx = new Transaction();
await vaults.deposit({
vault_id: vaultId,
slippage,
deposit_result: bothSidedDeposit,
return_coin: false
}, bothDepositTx);
console.log('Both-sided deposit transaction prepared');
// === WITHDRAWAL OPERATIONS ===
// 1. Both-sided withdrawal (receive both tokens)
console.log('Calculating both-sided withdrawal...');
const bothSidedWithdraw = await vaults.calculateWithdrawAmount({
vault_id: vaultId,
is_amount_a: true,
is_ft_input: true,
input_amount: oneSidedDeposit.ft_amount, // Withdraw all LP tokens
max_ft_amount: oneSidedDeposit.ft_amount,
slippage,
side: InputType.Both
});
console.log('Both-sided withdrawal calculation:', {
burnAmount: bothSidedWithdraw.burn_ft_amount,
receiveA: bothSidedWithdraw.amount_a,
receiveB: bothSidedWithdraw.amount_b
});
// Execute both-sided withdrawal
const withdrawTx = new Transaction();
await vaults.withdraw({
vault_id: vaultId,
ft_amount: bothSidedWithdraw.burn_ft_amount,
slippage,
return_coin: false
}, withdrawTx);
console.log('Both-sided withdrawal transaction prepared');
// 2. One-sided withdrawal (receive only token A)
console.log('Calculating one-sided withdrawal...');
const oneSidedWithdraw = await vaults.calculateWithdrawAmount({
vault_id: vaultId,
is_amount_a: true,
is_ft_input: false,
input_amount: '1000000', // Want to receive 1 token A
max_ft_amount: oneSidedDeposit.ft_amount,
slippage,
side: InputType.OneSide
});
console.log('One-sided withdrawal calculation:', {
burnAmount: oneSidedWithdraw.burn_ft_amount,
receiveA: oneSidedWithdraw.amount_a,
receiveB: oneSidedWithdraw.amount_b,
swapRequired: !!oneSidedWithdraw.swap_result
});
// Execute one-sided withdrawal
const oneSideWithdrawTx = new Transaction();
await vaults.withdraw({
vault_id: vaultId,
is_amount_a: true,
is_ft_input: false,
input_amount: '1000000',
max_ft_amount: oneSidedDeposit.ft_amount,
slippage,
return_coin: false
}, oneSideWithdrawTx);
console.log('One-sided withdrawal transaction prepared');
// === ADVANCED: Using coin objects ===
// Deposit with specific coin objects
const advancedDepositTx = new Transaction();
const coinA = advancedDepositTx.splitCoins(advancedDepositTx.gas, [1000000]);
const coinB = advancedDepositTx.splitCoins(advancedDepositTx.gas, [1000000]);
await vaults.deposit({
vault_id: vaultId,
coin_object_a: coinA,
coin_object_b: coinB,
slippage,
deposit_result: bothSidedDeposit,
return_coin: true // Return LP token object
}, advancedDepositTx);
console.log('Advanced deposit with coin objects prepared');
} catch (error) {
console.error('Error in deposit/withdraw operations:', error);
}
}Administrative Operations
async function adminOperations() {
const admin = Admin.createSDK({
fullNodeUrl: 'https://sui-mainnet.blockvision.org',
senderAddress: 'admin-wallet-address'
});
try {
// Create a new stable vault
const tx = await admin.newStableVault({
pool_id: 'clmm-pool-id',
treasury_cap_id: 'treasury-cap-id',
upper_price_scalling: '1.1', // 10% above current price
lower_price_scalling: '0.9', // 10% below current price
slippage_up: '0.02', // 2% slippage tolerance up
slippage_down: '0.02', // 2% slippage tolerance down
free_threshold_a: '1000000', // 1 token A threshold
free_threshold_b: '1000000', // 1 token B threshold
fee_val: '0.003', // 0.3% fee
withdraw_fee_val: '0.001', // 0.1% withdrawal fee
decimals_a: 6,
decimals_b: 6,
deposit_limit: '1000000000', // 1000 tokens limit
coin_type_a: '0x2::sui::SUI',
coin_type_b: '0x...::usdc::USDC',
coin_type_token: '0x...::lp_token::LP_TOKEN'
});
console.log('Stable vault creation transaction prepared');
// Configure vault settings
const configTx = new Transaction();
await admin.setDepositLimit('vault-id', 'vault-cap', 2000000000n, configTx);
// await admin.setSlippage('risk-admin-cap', 'vault-id', '0.03', '0.03', configTx);
console.log('Vault configuration transaction prepared');
} catch (error) {
console.error('Error in admin operations:', error);
}
}Monitoring Vault Performance
async function monitorVaultPerformance() {
const suiClient = new SuiClient({ url: 'https://sui-mainnet.blockvision.org' });
const vaults = Vaults.createSDK({
client: suiClient,
senderAddress: 'your-wallet-address'
});
const userAddress = 'user-wallet-address';
try {
// Get user's positions across all vaults
const userBalances = await vaults.getOwnerVaultsBalance(userAddress);
console.log(`User has positions in ${userBalances.length} vaults:`);
for (const balance of userBalances) {
console.log(`
Vault: ${balance.vault_id}
LP Token Balance: ${balance.lp_token_balance}
Underlying Token A: ${balance.amount_a} (${balance.coin_type_a})
Underlying Token B: ${balance.amount_b} (${balance.coin_type_b})
Position Range: ${balance.tick_lower_index} to ${balance.tick_upper_index}
`);
}
// Get detailed vault information
for (const balance of userBalances) {
const vault = await vaults.getVault(balance.vault_id);
if (vault) {
console.log(`
Vault ${vault.id} Details:
- Type: ${vault.config_type}
- Total Supply: ${vault.total_supply}
- Deposit Enabled: ${vault.is_deposit_enabled}
- Locked: ${vault.is_lock}
- Fee: ${vault.fee_val}
- Withdraw Fee: ${vault.withdraw_fee_val}
- Last Rebalance: ${new Date(parseInt(vault.last_rebalance_time) * 1000).toISOString()}
`);
}
}
} catch (error) {
console.error('Error monitoring vault performance:', error);
}
}API Reference
Vaults Class
The main class for interacting with vaults.
Creating an Instance
const vaults = Vaults.createSDK({
client: suiClient, // SuiClient instance
senderAddress: 'address' // Your wallet address
});
// Or with custom RPC URL
const vaults = Vaults.createSDK({
fullNodeUrl: 'https://custom-rpc-url',
senderAddress: 'address'
});Core Methods
getVaultList()
Retrieves all available vaults.
const vaults = await sdk.getVaultList();getVault(id: string)
Get detailed information about a specific vault.
const vault = await sdk.getVault('vault-id');getOwnerVaultsBalance(address: string)
Get user's balances across all vaults.
const balances = await sdk.getOwnerVaultsBalance('user-address');Deposit Operations
calculateDepositAmount(params)
Calculate optimal deposit amounts and required swaps.
const depositCalc = await sdk.calculateDepositAmount({
vault_id: 'vault-id',
is_amount_a: true,
input_amount: '1000000',
slippage: 0.01,
side: InputType.OneSide
});deposit(params, tx)
Execute a deposit transaction.
import { Transaction } from '@mysten/sui/transactions';
const tx = new Transaction();
const result = await sdk.deposit({
vault_id: 'vault-id',
slippage: 0.01,
deposit_result: depositCalc,
return_coin: true
}, tx);Withdrawal Operations
calculateWithdrawAmount(params)
Calculate withdrawal amounts and required swaps.
const withdrawCalc = await sdk.calculateWithdrawAmount({
vault_id: 'vault-id',
is_amount_a: true,
is_ft_input: true,
input_amount: '1000000',
max_ft_amount: '2000000',
slippage: 0.01,
side: InputType.OneSide
});withdraw(params, tx)
Execute a withdrawal transaction.
const tx = new Transaction();
const result = await sdk.withdraw({
vault_id: 'vault-id',
ft_amount: '1000000',
slippage: 0.01,
return_coin: true
}, tx);Admin Class
Administrative functions for vault management.
Creating an Instance
const admin = Admin.createSDK({
fullNodeUrl: 'https://sui-mainnet.blockvision.org',
senderAddress: 'admin-address'
});Vault Creation
newStableVault(params)
Create a new stable vault.
const tx = await admin.newStableVault({
pool_id: 'clmm-pool-id',
treasury_cap_id: 'treasury-cap-id',
upper_price_scalling: '1.1',
lower_price_scalling: '0.9',
slippage_up: '0.01',
slippage_down: '0.01',
free_threshold_a: '1000000',
free_threshold_b: '1000000',
fee_val: '0.003',
withdraw_fee_val: '0.001',
decimals_a: 6,
decimals_b: 6,
deposit_limit: '1000000000',
coin_type_a: 'coin-type-a',
coin_type_b: 'coin-type-b',
coin_type_token: 'lp-token-type'
});newUncorrelatedVault(params)
Create a new uncorrelated vault with rebalancing triggers.
const tx = await admin.newUncorrelatedVault({
// ... similar params as stable vault
lock_threshold_a: '5000000',
lock_threshold_b: '5000000',
target_adapter: 'price-adapter',
is_target_reverse: false
});Vault Configuration
setDepositLimit(vaultId, vaultCap, limit)
Update vault deposit limits.
await admin.setDepositLimit('vault-id', 'vault-cap', 1000000000n, tx);setFee(adminCap, vaultId, feeVal)
Set vault fee percentages.
await admin.setFee('admin-cap', 'vault-id', '0.003', tx);Types and Interfaces
Vault Interface
interface Vault {
id: string;
clmm_pool_id: string;
coin_type_a: string;
coin_type_b: string;
lp_token_type: string;
config_type: string;
total_supply: string;
deposit_limit: string;
is_deposit_enabled: boolean;
is_lock: boolean;
// ... additional properties
}Calculation Parameters
interface CalculateAmountParams {
vault_id: string;
is_amount_a: boolean;
input_amount: string;
slippage: number;
side: InputType;
}
enum InputType {
Both = 'both',
OneSide = 'oneSide'
}Automated Bots
The SDK includes two automated bots for production use:
Reward Bot
Automatically collects and compounds vault rewards.
# Run directly
pnpm run run:reward
# Or with Docker
docker-compose up reward-botRebalance Bot
Monitors and rebalances uncorrelated vaults when price thresholds are reached.
# Run directly
pnpm run run:rebalance
# Or with Docker
docker-compose up rebalance-botEnvironment Configuration
Create a .env file with the following variables:
# Sui Network
SUI_PRIVATE_KEY=your-base64-encoded-private-key
FULL_NODE_URL=https://sui-mainnet.blockvision.org
# Slack Notifications (for bots)
SLACK_TOKEN=xoxb-your-slack-bot-token
SLACK_CONVERSATION_ID=your-channel-id
SLACK_VAULT_REBALANCE_CONVERSATION_ID=rebalance-channel-id
# Optional
NODE_ENV=productionDocker Deployment
The SDK provides ready-to-use Docker containers:
# Build and run both bots
docker-compose up -d
# Run specific bot
docker-compose up -d reward-bot
docker-compose up -d rebalance-bot
# View logs
docker-compose logs -f reward-botSee DOCKER.md for detailed Docker setup instructions.
Error Handling
The SDK uses a comprehensive error handling system:
import { VaultsErrorCode } from 'nemo-vaults-sdk';
try {
const vault = await vaults.getVault('invalid-id');
} catch (error) {
if (error.code === VaultsErrorCode.ObjectNotFound) {
console.log('Vault not found');
}
}Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
MIT License
Support
For issues and questions:
- Create an issue on GitHub
- Check the API documentation
Development Setup
# Install dependencies
pnpm install
# Build the SDK
pnpm run build
# Run tests
pnpm test
# Build bots
pnpm run build:all