Docs

userVaultEquities - HyperCore Info Endpoint

Get user's vault equity positions on Hyperliquid including share balances, current value, unrealized gains, and vault allocation details.

Get user's equity positions across all vaults, including share balances, current value, unrealized gains, and allocation details.

Why Hyperliquid? Build on the trading-focused EVM and HyperCore ecosystem built for onchain perpetuals and market data with HyperCore market structure, sub-second finality, and direct access to trading-focused data services.

Authenticate HyperCore Info requests by sending your Dwellir API key in the x-api-key header to https://api-hyperliquid-mainnet-info.n.dwellir.com/info.

When to Use This Endpoint

The userVaultEquities endpoint is essential for portfolio trackers, wealth managers, and investors who need to:

  • Track Vault Investments — Monitor all vault positions in one place
  • Calculate Portfolio Value — Get real-time value of vault holdings
  • Analyze Performance — Track unrealized gains/losses across vaults
  • Portfolio Management — View vault allocation and diversification

Common Use Cases

1. Calculate Total Vault Portfolio Value

Get comprehensive portfolio metrics:

JavaScript
async function getVaultPortfolioMetrics(userAddress) {
  const equities = await getUserVaultEquities(userAddress);

  if (equities.length === 0) {
    return { message: 'No vault positions found' };
  }

  const totalCurrentValue = equities.reduce((sum, e) =>
    sum + parseFloat(e.currentValue), 0
  );

  const totalDeposited = equities.reduce((sum, e) =>
    sum + parseFloat(e.netDeposits), 0
  );

  const totalPnl = equities.reduce((sum, e) =>
    sum + parseFloat(e.unrealizedPnl), 0
  );

  const weightedReturn = equities.reduce((sum, e) => {
    const weight = parseFloat(e.currentValue) / totalCurrentValue;
    return sum + (parseFloat(e.pnlPercent) * weight);
  }, 0);

  return {
    totalPositions: equities.length,
    totalValue: totalCurrentValue.toFixed(2),
    totalDeposited: totalDeposited.toFixed(2),
    totalPnl: totalPnl.toFixed(2),
    totalReturnPercent: ((totalPnl / totalDeposited) * 100).toFixed(2),
    weightedReturnPercent: weightedReturn.toFixed(2),
    largestPosition: equities.reduce((max, e) =>
      parseFloat(e.currentValue) > parseFloat(max.currentValue) ? e : max
    )
  };
}

// Usage
const metrics = await getVaultPortfolioMetrics('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log('Portfolio Metrics:', metrics);
console.log(`Largest position: ${metrics.largestPosition.vaultName}`);

2. Check Withdrawal Availability

Determine which positions can be withdrawn:

JavaScript
async function checkWithdrawalAvailability(userAddress) {
  const equities = await getUserVaultEquities(userAddress);
  const now = Date.now();

  const available = [];
  const locked = [];

  equities.forEach(equity => {
    const position = {
      vaultName: equity.vaultName,
      value: parseFloat(equity.currentValue),
      shares: parseFloat(equity.shares),
      lockupExpiry: equity.lockupExpiry
    };

    if (equity.lockupExpiry <= now) {
      position.status = 'Available';
      available.push(position);
    } else {
      const daysRemaining = Math.ceil((equity.lockupExpiry - now) / (1000 * 60 * 60 * 24));
      position.status = 'Locked';
      position.daysRemaining = daysRemaining;
      locked.push(position);
    }
  });

  const availableValue = available.reduce((sum, p) => sum + p.value, 0);
  const lockedValue = locked.reduce((sum, p) => sum + p.value, 0);

  return {
    available: available,
    locked: locked,
    availableValue: availableValue.toFixed(2),
    lockedValue: lockedValue.toFixed(2),
    totalValue: (availableValue + lockedValue).toFixed(2)
  };
}

// Usage
const withdrawal = await checkWithdrawalAvailability('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log(`\nWithdrawal Status:`);
console.log(`Available: $${withdrawal.availableValue}`);
console.log(`Locked: $${withdrawal.lockedValue}`);

console.log(`\nAvailable Positions (${withdrawal.available.length}):`);
withdrawal.available.forEach(p => {
  console.log(`  ${p.vaultName}: $${p.value.toLocaleString()}`);
});

console.log(`\nLocked Positions (${withdrawal.locked.length}):`);
withdrawal.locked.forEach(p => {
  console.log(`  ${p.vaultName}: $${p.value.toLocaleString()} (${p.daysRemaining} days)`);
});

3. Analyze Vault Allocation

View portfolio diversification across vaults:

JavaScript
async function analyzeVaultAllocation(userAddress) {
  const equities = await getUserVaultEquities(userAddress);

  const totalValue = equities.reduce((sum, e) =>
    sum + parseFloat(e.currentValue), 0
  );

  const allocation = equities.map(e => {
    const value = parseFloat(e.currentValue);
    const percentage = (value / totalValue) * 100;

    return {
      vaultName: e.vaultName,
      value: value,
      percentage: percentage.toFixed(2),
      shares: parseFloat(e.shares),
      pnl: parseFloat(e.unrealizedPnl),
      pnlPercent: parseFloat(e.pnlPercent)
    };
  }).sort((a, b) => b.value - a.value);

  // Check concentration risk
  const top3Concentration = allocation.slice(0, 3).reduce((sum, a) =>
    sum + parseFloat(a.percentage), 0
  );

  return {
    allocation: allocation,
    totalValue: totalValue.toFixed(2),
    positions: allocation.length,
    top3Concentration: top3Concentration.toFixed(2),
    diversified: top3Concentration < 75
  };
}

// Usage
const analysis = await analyzeVaultAllocation('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log(`\n=== Portfolio Allocation ===`);
console.log(`Total Value: $${parseFloat(analysis.totalValue).toLocaleString()}`);
console.log(`Positions: ${analysis.positions}`);
console.log(`Top 3 Concentration: ${analysis.top3Concentration}%`);
console.log(`Diversified: ${analysis.diversified ? 'Yes' : 'No (concentrated)'}`);

console.log(`\n=== Allocation by Vault ===`);
analysis.allocation.forEach((a, i) => {
  console.log(`${i + 1}. ${a.vaultName}: ${a.percentage}% ($${a.value.toLocaleString()})`);
  console.log(`   PnL: ${a.pnlPercent > 0 ? '+' : ''}${a.pnlPercent}%`);
});

4. Track Performance Over Time

Monitor vault performance metrics:

JavaScript
async function trackVaultPerformance(userAddress) {
  const equities = await getUserVaultEquities(userAddress);

  const performance = equities.map(e => {
    const currentValue = parseFloat(e.currentValue);
    const depositValue = parseFloat(e.netDeposits);
    const pnl = parseFloat(e.unrealizedPnl);
    const pnlPercent = parseFloat(e.pnlPercent);

    // Calculate holding period
    const depositDate = new Date(e.depositTimestamp);
    const now = new Date();
    const daysHeld = Math.floor((now - depositDate) / (1000 * 60 * 60 * 24));

    // Annualized return
    const annualizedReturn = daysHeld > 0
      ? (pnlPercent / daysHeld) * 365
      : 0;

    return {
      vaultName: e.vaultName,
      currentValue: currentValue,
      depositValue: depositValue,
      pnl: pnl,
      returnPercent: pnlPercent,
      daysHeld: daysHeld,
      annualizedReturn: annualizedReturn.toFixed(2),
      dailyReturn: daysHeld > 0 ? (pnlPercent / daysHeld).toFixed(3) : '0.000'
    };
  }).sort((a, b) => parseFloat(b.annualizedReturn) - parseFloat(a.annualizedReturn));

  return performance;
}

// Usage
const performance = await trackVaultPerformance('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log(`\n=== Vault Performance ===`);
performance.forEach((p, i) => {
  console.log(`\n${i + 1}. ${p.vaultName}`);
  console.log(`   Value: $${p.currentValue.toLocaleString()}`);
  console.log(`   Return: ${p.returnPercent > 0 ? '+' : ''}${p.returnPercent}%`);
  console.log(`   Days Held: ${p.daysHeld}`);
  console.log(`   Annualized: ${p.annualizedReturn}%`);
  console.log(`   Daily Avg: ${p.dailyReturn}%`);
});

5. Identify Best and Worst Performers

Analyze which vaults are performing well:

JavaScript
async function identifyPerformers(userAddress) {
  const equities = await getUserVaultEquities(userAddress);

  // Sort by PnL percentage
  const sorted = [...equities].sort((a, b) =>
    parseFloat(b.pnlPercent) - parseFloat(a.pnlPercent)
  );

  const bestPerformers = sorted.slice(0, 3).map(e => ({
    vaultName: e.vaultName,
    pnl: parseFloat(e.unrealizedPnl),
    pnlPercent: parseFloat(e.pnlPercent),
    value: parseFloat(e.currentValue)
  }));

  const worstPerformers = sorted.slice(-3).reverse().map(e => ({
    vaultName: e.vaultName,
    pnl: parseFloat(e.unrealizedPnl),
    pnlPercent: parseFloat(e.pnlPercent),
    value: parseFloat(e.currentValue)
  }));

  // Calculate averages
  const avgPnlPercent = equities.reduce((sum, e) =>
    sum + parseFloat(e.pnlPercent), 0
  ) / equities.length;

  return {
    bestPerformers: bestPerformers,
    worstPerformers: worstPerformers,
    avgReturn: avgPnlPercent.toFixed(2),
    spread: (parseFloat(sorted[0].pnlPercent) - parseFloat(sorted[sorted.length - 1].pnlPercent)).toFixed(2)
  };
}

// Usage
const performers = await identifyPerformers('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');

console.log(`\n=== Best Performers ===`);
performers.bestPerformers.forEach((p, i) => {
  console.log(`${i + 1}. ${p.vaultName}: +${p.pnlPercent}% ($${p.pnl.toLocaleString()})`);
});

console.log(`\n=== Worst Performers ===`);
performers.worstPerformers.forEach((p, i) => {
  console.log(`${i + 1}. ${p.vaultName}: ${p.pnlPercent}% ($${p.pnl.toLocaleString()})`);
});

console.log(`\nPortfolio Statistics:`);
console.log(`Average Return: ${performers.avgReturn}%`);
console.log(`Performance Spread: ${performers.spread}%`);

Best Practices

  1. Poll responsibly — Update vault positions every 30-60 seconds for dashboards
  2. Handle empty results — Users may have no vault positions
  3. Check lockup periods — Verify withdrawal availability before transactions
  4. Track allocation — Monitor portfolio concentration and diversification
  5. Calculate returns properly — Account for deposits/withdrawals over time

Track your Hyperliquid vault investments with Dwellir's HyperCore Info Endpoint. Get your API key →