// Hyperliquid API Types for Open Broker // ============ Configuration ============ export interface OpenBrokerConfig { baseUrl: string; privateKey: `0x${string}`; walletAddress: string; // Address derived from private key (the signer) accountAddress: string; // Address to trade on behalf of (may differ if using API wallet) isApiWallet: boolean; // True if walletAddress != accountAddress isReadOnly: boolean; // True if using default key (no trading capability) builderAddress: string; builderFee: number; // tenths of bps (10 = 1 bps) slippageBps: number; vaultAddress?: string; // Explicit vault address for vault trading (ERC4626 / native vaults via CoreWriter) verbose: boolean; // Debug logging — set from VERBOSE env var by loadConfig() } // ============ Builder ============ export interface BuilderInfo { b: string; // builder address (lowercase) f: number; // fee in tenths of bps } // ============ Order Types ============ export type OrderType = | { limit: { tif: 'Gtc' | 'Ioc' | 'Alo' } } | { trigger: { triggerPx: string; isMarket: boolean; tpsl: 'tp' | 'sl' } }; export interface OrderRequest { coin: string; is_buy: boolean; sz: number; limit_px: number; order_type: OrderType; reduce_only?: boolean; cloid?: string; } export interface OrderWire { a: number; // asset index b: boolean; // is_buy p: string; // price s: string; // size r: boolean; // reduce_only t: OrderType; c?: string; // cloid } export interface OrderResponse { status: 'ok' | 'err'; response?: { type: 'order'; data: { statuses: Array<{ resting?: { oid: number }; filled?: { totalSz: string; avgPx: string; oid: number }; error?: string; [key: string]: unknown; // Catch any other fields }>; }; } | string; // API can return string error message error?: string; } // ============ Cancel Types ============ export interface CancelRequest { coin: string; oid: number; } export interface CancelResponse { status: 'ok' | 'err'; response?: { type: 'cancel'; data: { statuses: string[] }; }; } // ============ Market Data Types ============ // Shape matches the upstream @nktkas/hyperliquid SDK response. Fields like // `onlyIsolated` and `premium` are absent-or-null in practice for some assets, // so they're modelled as optional / nullable. Index signature absorbs any // additional SDK fields we don't consume here (marginTableId, growthMode, …). export interface AssetMeta { name: string; szDecimals: number; maxLeverage: number; onlyIsolated?: boolean; isDelisted?: boolean; marginTableId?: number; [key: string]: unknown; } export interface AssetCtx { funding: string; openInterest: string; prevDayPx: string; dayNtlVlm: string; premium: string | null; oraclePx: string; markPx: string; midPx?: string | null; impactPxs?: [string, string] | string[] | null; dayBaseVlm?: string; [key: string]: unknown; } export interface Meta { universe: AssetMeta[]; } export interface MetaAndAssetCtxs { meta: Meta; assetCtxs: AssetCtx[]; } // ============ Outcome / HIP-4 Types ============ export interface OutcomeSideSpec { name: string; token?: number; } export interface OutcomeMetaEntry { outcome: number; name: string; description: string; sideSpecs: OutcomeSideSpec[]; quoteToken?: string; venue?: string; deployerFeeScale?: string; } export interface OutcomeQuestion { question: number; name: string; description: string; fallbackOutcome: number; namedOutcomes: number[]; settledNamedOutcomes?: number[]; } export interface OutcomeMetaResponse { outcomes: OutcomeMetaEntry[]; questions?: OutcomeQuestion[]; } export interface OutcomeMarket { outcome: number; name: string; description: string; parsedDescription: Record; rawName?: string; rawDescription?: string; quoteToken?: string; venue?: string; deployerFeeScale?: string; sides: Array<{ side: 0 | 1; name: string; encoding: number; coin: string; tokenName: string; assetId: number; token?: number; szDecimals?: number; midPx?: string; markPx?: string; prevDayPx?: string; dayNtlVlm?: string; }>; question?: OutcomeQuestion; } // ============ Account Types ============ export interface Position { coin: string; /** * Canonical Hyperliquid asset index (native: meta index; HIP-3: * 100000 + perp_dex_index*10000 + index_in_meta). Stamped by `getUserStateAll` * so consumers can key positions by a unique integer rather than the coin string * (whose HIP-3 prefix may differ between endpoints). Undefined if unresolvable. */ assetId?: number; szi: string; // signed size (negative = short) entryPx: string; positionValue: string; unrealizedPnl: string; returnOnEquity: string; liquidationPx: string | null; leverage: { type: 'cross' | 'isolated'; value: number; rawUsd?: string; }; marginUsed: string; maxLeverage: number; } export interface AssetPosition { position: Position; type: 'oneWay'; } export interface MarginSummary { accountValue: string; totalNtlPos: string; totalRawUsd: string; totalMarginUsed: string; withdrawable: string; } export interface ClearinghouseState { assetPositions: AssetPosition[]; crossMarginSummary: MarginSummary; marginSummary: MarginSummary; crossMaintenanceMarginUsed: string; } // ============ Funding Types ============ export interface FundingInfo { coin: string; fundingRate: string; // hourly rate annualizedRate: number; // calculated premium: string; openInterest: string; markPx: string; oraclePx: string; } // ============ Open Orders ============ export interface OpenOrder { coin: string; oid: number; cloid?: string; side: 'B' | 'A'; // Bid or Ask sz: string; limitPx: string; orderType: string; origSz: string; timestamp: number; } /** * Open order from the `frontendOpenOrders` info endpoint — same as OpenOrder * plus the trigger/reduce-only display fields (needed to distinguish resting * TP/SL protection from plain limit orders). */ export interface FrontendOpenOrder { coin: string; side: 'B' | 'A'; limitPx: string; sz: string; oid: number; timestamp: number; origSz: string; triggerCondition: string; isTrigger: boolean; triggerPx: string; isPositionTpsl: boolean; reduceOnly: boolean; orderType: string; tif: string | null; cloid: string | null; } // ============ API Request/Response ============ export interface InfoRequest { type: string; user?: string; [key: string]: unknown; } export interface ExchangeRequest { action: Record; nonce: number; signature: { r: string; s: string; v: number; }; vaultAddress?: string | null; }