userVaultEquities
Get user's equity positions across all vaults, including share balances, current value, unrealized gains, and allocation details.
Why Hyperliquid? Build on the dominant perpetuals DEX with 70% market share, $2.7T+ lifetime volume, and $2B TVL with 200K orders/second throughput, zero gas fees, sub-second finality, and fully onchain Central Limit Order Book (CLOB).
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
Request#
Endpoint#
POST https://api-hyperliquid-mainnet-info.n.dwellir.com/info
Headers#
| Header | Value | Required |
|---|---|---|
Content-Type | application/json | Yes |
X-Api-Key | Your API key | Yes |
Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "userVaultEquities" |
user | string | Yes | User's Ethereum wallet address |
Example Request#
{
"type": "userVaultEquities",
"user": "0x66e7293b07744b2d92384d33a0f86b9c333d8597"
}
Response#
Success Response#
[
{
"vaultAddress": "0x115849ce84370f25cadcf0d348510d73837e1aa5",
"equity": "9773.685144",
"lockedUntilTimestamp": 1770368683304
}
]
Response Fields#
The response is an array of vault equity objects. Each object contains:
| Field | Type | Description |
|---|---|---|
vaultAddress | string | Ethereum address of the vault contract |
equity | string | User's current equity value in the vault (USD) |
lockedUntilTimestamp | integer | Unix timestamp (milliseconds) when vault funds unlock |
Code Examples#
- cURL
- JavaScript
- Python
- Go
curl -X POST 'https://api-hyperliquid-mainnet-info.n.dwellir.com/info' \
-H 'X-Api-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"type": "userVaultEquities",
"user": "0x63E8c7C149556D5f34F833419A287bb9Ef81487f"
}'
const ENDPOINT = 'https://api-hyperliquid-mainnet-info.n.dwellir.com/info';
const API_KEY = 'your-api-key-here';
async function getUserVaultEquities(userAddress) {
const response = await fetch(ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': API_KEY
},
body: JSON.stringify({
type: 'userVaultEquities',
user: userAddress
})
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
}
// Usage
const equities = await getUserVaultEquities('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log(`Active vault positions: ${equities.length}`);
// Calculate portfolio metrics
const totalValue = equities.reduce((sum, e) => sum + parseFloat(e.currentValue), 0);
const totalPnl = equities.reduce((sum, e) => sum + parseFloat(e.unrealizedPnl), 0);
const totalDeposits = equities.reduce((sum, e) => sum + parseFloat(e.netDeposits), 0);
console.log(`\nPortfolio Summary:`);
console.log(`Total Value: $${totalValue.toLocaleString()}`);
console.log(`Total PnL: $${totalPnl.toLocaleString()}`);
console.log(`Total Return: ${((totalPnl / totalDeposits) * 100).toFixed(2)}%`);
// List positions
console.log(`\nVault Positions:`);
equities.forEach(e => {
console.log(`\n${e.vaultName}:`);
console.log(` Shares: ${e.shares}`);
console.log(` Value: $${parseFloat(e.currentValue).toLocaleString()}`);
console.log(` PnL: $${e.unrealizedPnl} (${e.pnlPercent}%)`);
});
import requests
from typing import List, Dict
from datetime import datetime
ENDPOINT = 'https://api-hyperliquid-mainnet-info.n.dwellir.com/info'
API_KEY = 'your-api-key-here'
def get_user_vault_equities(user_address: str) -> List[Dict]:
"""Get user's vault equity positions"""
response = requests.post(
ENDPOINT,
json={
'type': 'userVaultEquities',
'user': user_address
},
headers={
'Content-Type': 'application/json',
'X-Api-Key': API_KEY
},
timeout=10
)
response.raise_for_status()
return response.json()
# Usage
equities = get_user_vault_equities('0x63E8c7C149556D5f34F833419A287bb9Ef81487f')
print(f"Active vault positions: {len(equities)}\n")
# Calculate portfolio metrics
total_value = sum(float(e['currentValue']) for e in equities)
total_pnl = sum(float(e['unrealizedPnl']) for e in equities)
total_deposits = sum(float(e['netDeposits']) for e in equities)
print("=== Portfolio Summary ===")
print(f"Total Value: ${total_value:,.2f}")
print(f"Total PnL: ${total_pnl:,.2f}")
print(f"Total Return: {(total_pnl / total_deposits * 100):.2f}%")
print("\n=== Vault Positions ===")
for equity in equities:
print(f"\n{equity['vaultName']}:")
print(f" Shares: {equity['shares']}")
print(f" Value: ${float(equity['currentValue']):,.2f}")
print(f" PnL: ${equity['unrealizedPnl']} ({equity['pnlPercent']}%)")
# Check lockup status
lockup_expiry = datetime.fromtimestamp(int(equity['lockupExpiry']) / 1000)
if datetime.now() < lockup_expiry:
days_left = (lockup_expiry - datetime.now()).days
print(f" Lockup: {days_left} days remaining")
else:
print(f" Lockup: Expired (withdrawable)")
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
const (
Endpoint = "https://api-hyperliquid-mainnet-info.n.dwellir.com/info"
APIKey = "your-api-key-here"
)
type UserVaultEquitiesRequest struct {
Type string `json:"type"`
User string `json:"user"`
}
type VaultEquity struct {
VaultAddress string `json:"vaultAddress"`
VaultName string `json:"vaultName"`
Shares string `json:"shares"`
SharePrice string `json:"sharePrice"`
CurrentValue string `json:"currentValue"`
DepositValue string `json:"depositValue"`
UnrealizedPnl string `json:"unrealizedPnl"`
PnlPercent string `json:"pnlPercent"`
AllTimeDeposits string `json:"allTimeDeposits"`
AllTimeWithdrawals string `json:"allTimeWithdrawals"`
NetDeposits string `json:"netDeposits"`
DepositTimestamp int64 `json:"depositTimestamp"`
LockupExpiry int64 `json:"lockupExpiry"`
}
func getUserVaultEquities(userAddress string) ([]VaultEquity, error) {
reqBody, _ := json.Marshal(UserVaultEquitiesRequest{
Type: "userVaultEquities",
User: userAddress,
})
req, _ := http.NewRequest("POST", Endpoint, bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Api-Key", APIKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var equities []VaultEquity
if err := json.Unmarshal(body, &equities); err != nil {
return nil, err
}
return equities, nil
}
func main() {
equities, err := getUserVaultEquities("0x63E8c7C149556D5f34F833419A287bb9Ef81487f")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Active vault positions: %d\n\n", len(equities))
// Calculate totals
var totalValue, totalPnl float64
for _, equity := range equities {
value, _ := strconv.ParseFloat(equity.CurrentValue, 64)
pnl, _ := strconv.ParseFloat(equity.UnrealizedPnl, 64)
totalValue += value
totalPnl += pnl
}
fmt.Printf("Portfolio Summary:\n")
fmt.Printf("Total Value: $%.2f\n", totalValue)
fmt.Printf("Total PnL: $%.2f\n\n", totalPnl)
fmt.Println("=== Vault Positions ===")
for _, equity := range equities {
fmt.Printf("\n%s:\n", equity.VaultName)
fmt.Printf(" Shares: %s\n", equity.Shares)
fmt.Printf(" Value: $%s\n", equity.CurrentValue)
fmt.Printf(" PnL: $%s (%s%%)\n", equity.UnrealizedPnl, equity.PnlPercent)
// Check lockup
lockupTime := time.Unix(equity.LockupExpiry/1000, 0)
if time.Now().Before(lockupTime) {
daysLeft := int(time.Until(lockupTime).Hours() / 24)
fmt.Printf(" Lockup: %d days remaining\n", daysLeft)
} else {
fmt.Println(" Lockup: Expired (withdrawable)")
}
}
}
Common Use Cases#
1. Calculate Total Vault Portfolio Value#
Get comprehensive portfolio metrics:
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:
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:
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:
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:
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}%`);
Error Handling#
Common Errors#
| Error | Cause | Solution |
|---|---|---|
401 Unauthorized | Invalid API key | Verify your API key is correct |
400 Bad Request | Missing or invalid user address | Ensure valid Ethereum address format |
429 Too Many Requests | Rate limit exceeded | Implement request throttling |
500 Internal Server Error | Server issue | Retry with exponential backoff |
Error Response Example#
{
"error": "Missing required parameter: user",
"code": "MISSING_PARAMETER"
}
Robust Error Handling#
async function safeGetUserVaultEquities(userAddress, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await getUserVaultEquities(userAddress);
} catch (error) {
if (error.response?.status === 429) {
// Rate limit - exponential backoff
const delay = Math.pow(2, i) * 1000;
await new Promise(r => setTimeout(r, delay));
} else if (error.response?.status === 400) {
throw new Error('Invalid user address');
} else if (i === maxRetries - 1) {
throw error;
}
}
}
}
Best Practices#
- Poll responsibly — Update vault positions every 30-60 seconds for dashboards
- Handle empty results — Users may have no vault positions
- Check lockup periods — Verify withdrawal availability before transactions
- Track allocation — Monitor portfolio concentration and diversification
- Calculate returns properly — Account for deposits/withdrawals over time
Related Endpoints#
- leadingVaults — Discover top-performing vaults
- vaultSummaries — Get comprehensive vault information
- clearinghouseState — Get user's perpetual account state
- spotClearinghouseState — Get spot trading balances
Track your Hyperliquid vault investments with Dwellir's HyperCore Info Endpoint. Get your API key →