JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 240
  • Score
    100M100P100Q90034F
  • License MIT

A TypeScript SDK for interacting with Nemo Vaults on the Sui blockchain

Package Exports

  • @nemoprotocol/vaults-sdk

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 @nemoprotocol/vaults-sdk
# or
yarn add @nemoprotocol/vaults-sdk
# or
pnpm add @nemoprotocol/vaults-sdk

Quick Start

import { Vaults, Admin } from '@nemoprotocol/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
});

// 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

  1. Stable Vaults: Optimized for stable asset pairs with minimal price volatility
  2. Uncorrelated Vaults: Designed for assets with low correlation, includes rebalancing triggers
  3. 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 '@nemoprotocol/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
});

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
  });

  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', // input vault token amount 
      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', // input vault token amount
      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
  });

  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
});

// Or with custom RPC URL
const vaults = Vaults.createSDK({
  fullNodeUrl: 'https://custom-rpc-url'
});

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');
getOwnerVaultBalance(address: string, vaultId: string)

Get a user's balance for a specific vault including LP token decimals.

const balance = await sdk.getOwnerVaultBalance('user-address', 'vault-id');
getPositionAssets(vaultId: string)

Get position token amounts with current prices and USD values for a specific vault.

const positionAssets = await sdk.getPositionAssets('vault-id');
console.log('Position Assets:', {
  amountA: positionAssets.amount_a,
  amountB: positionAssets.amount_b,
  priceA: positionAssets.price_a,
  priceB: positionAssets.price_b,
  totalValueUSD: positionAssets.total_value_usd,
  lpUsdPrice: positionAssets.lp_usd_price
});
getRemainingCap(vaultId: string)

Get remaining deposit capacity for a specific vault.

const remainingCap = await sdk.getRemainingCap('vault-id');
console.log('Remaining Capacity:', {
  depositLimitUSD: remainingCap.deposit_limit_usd,
  currentPositionValueUSD: remainingCap.current_position_value_usd,
  remainingCapUSD: remainingCap.remaining_cap_usd
});
getVaultMarketHolders(vaultId?: string)

Get all vault market holders with their aggregated USD values across all vault markets.

const holders = await sdk.getVaultMarketHolders('vault-id');
console.log('Vault Market Holders:', holders);
// Output: [
//   { address: '0x123...', usdValue: '100.5000000000000000' },
//   { address: '0x456...', usdValue: '210.7500000000000000' }
// ]
getVaultStatus()

Get the current status of all vaults including rebalancing status and configuration details.

const vaultStatus = await sdk.getVaultStatus();
console.log('Vault Status:', vaultStatus);
// Output: [
//   {
//     vaultId: '0x123...',
//     isRebalancing: false,
//     vaultName: 'SUI-USDC Vault',
//     disable: false,
//   }
// ]

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-bot

Rebalance Bot

Monitors and rebalances uncorrelated vaults when price thresholds are reached.

# Run directly  
pnpm run run:rebalance

# Or with Docker
docker-compose up rebalance-bot

Environment 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=production

Docker 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-bot

See DOCKER.md for detailed Docker setup instructions.

Error Handling

The SDK uses a comprehensive error handling system:

import { VaultsErrorCode } from '@nemoprotocol/vaults-sdk';

try {
  const vault = await vaults.getVault('invalid-id');
} catch (error) {
  if (error.code === VaultsErrorCode.ObjectNotFound) {
    console.log('Vault not found');
  }
}

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License

Support

For issues and questions:

Development Setup

# Install dependencies
pnpm install

# Build the SDK
pnpm run build

# Run tests
pnpm test

# Build bots
pnpm run build:all