src/account/types.ts
v0.3.0 · 2.9 KB
// Raw info-endpoint shapes as Hyperliquid sends them. All numbers are decimal strings unless noted.
// These types describe the expected wire format; the parsers never trust them and validate at runtime.
export interface MarginSummaryRaw {
/** Equity of this dex including unrealized PnL. On a Unified Account this is margin in use, not capital. */
accountValue: string;
totalNtlPos: string;
totalRawUsd: string;
totalMarginUsed: string;
}
export interface LeverageRaw {
type: 'cross' | 'isolated';
/** Leverage multiple (a JSON number, unlike other fields). */
value: number;
/** Isolated only. */
rawUsd?: string;
}
export interface PositionRaw {
/** HIP-3 coins already carry the dex prefix, e.g. `xyz:NVDA`. */
coin: string;
/** Signed size: > 0 long, < 0 short. */
szi: string;
leverage: LeverageRaw;
/** Average entry price; may be null. */
entryPx: string | null;
/** Absolute notional at MARK price. */
positionValue: string;
unrealizedPnl: string;
/** ROE as reported by HL: the denominator is ENTRY margin. Do not use it for stops. */
returnOnEquity: string;
liquidationPx: string | null;
marginUsed: string;
maxLeverage?: number;
cumFunding?: { allTime: string; sinceOpen: string; sinceChange: string };
}
export interface ClearinghouseStateRaw {
marginSummary: MarginSummaryRaw;
crossMarginSummary: MarginSummaryRaw;
crossMaintenanceMarginUsed?: string;
withdrawable: string;
assetPositions: Array<{ type?: string; position: PositionRaw }>;
time: number;
}
export interface SpotBalanceRaw {
coin: string;
token?: number;
/** Token units, not USD. */
total: string;
/** Reserve. On portfolio margin this is "reserve minus borrow capacity" and can be negative. */
hold: string;
/** USD entry notional; "0" for stablecoins (not null). */
entryNtl?: string;
/** Real reserve on portfolio-margin / unified accounts; present only there. */
spotHold?: string;
borrowed?: string;
ltv?: string;
supplied?: string;
}
export interface SpotClearinghouseStateRaw {
balances: SpotBalanceRaw[];
portfolioMarginEnabled?: boolean;
[key: string]: unknown;
}
/** One perp dex answer inside a snapshot. `dex === ""` is the main perp dex. */
export interface PerpDexState {
dex: string;
/** Raw `clearinghouseState` answer for this dex (validated when the snapshot was fetched). */
state: unknown;
}
/** Spot leg of a snapshot. A failed spot read never throws: perp-only consumers (guards) keep working. */
export type SpotRead = { ok: true; state: unknown } | { ok: false; error: string };
/** Perp state of every requested dex plus the spot state, all read in one `Promise.all`. */
export interface AccountSnapshot {
/** Lowercased account address. */
user: `0x${string}`;
/** One entry per dex; the main dex (`""`) is always first. */
perp: PerpDexState[];
spot: SpotRead;
/** `Date.now()` when the reads were started. */
fetchedAt: number;
}