Error Handling & Units
Every public function validates its own plain-data input, never throws, and returns { value, trace }. This page is the full statement of the result contract and the unit conventions that every input and output follows.
The result contract
value.status === 'ok' // → value.data
value.status === 'invalid-input' // → value.issues: [{ code, path, actual, expected }]
value.status === 'not-applicable' // → valid input, but the math has no value here (e.g. flat position)
value.status === 'indeterminate' // → a declared rule was incomplete for this inputokmeans the declared formula completed. Constraint checks insidevalue.datacan still report violated or not-evaluated states — read them rather than assuming anokresult is an authorization to act.invalid-inputissues carry{ code, path, actual, expected }.expectedstates the exact keys or format required, so the fix is in the error. Rebuild the offending field; do not retry blindly.not-applicableandindeterminateare answers, not failures.not-applicablemeans the calculation genuinely has no value for this state;indeterminatemeans a unique result cannot be established from the supported evidence or assumptions. Neither should be retried.
Rounding is yours to direct
Outputs are full-precision decimal strings (up to 40 significant digits). The package refuses to round until you tell it how. Before showing a price or putting it in an order, quantize it:
quantizePrice({ value, marketKind, szDecimals, rounding })Rounding direction is always chosen against the user's favor — pick 'down' for buys, 'up' for sells. The direction you chose is recorded in the trace, so the decision stays auditable.
Unit conventions
- Money is always a decimal string.
'1.25', never1.25. Convert the few official JSON numbers (maxLeverage,leverage.value) withString(). Integer counts (index,szDecimals,weiDecimals,timestampMs, tier indices) stay numbers. - Rates are decimal fractions everywhere.
'0.00045'= 4.5 bps = 0.045%. Fields that carry basis points say so in their name (slippageBps,spreadBps). - Timestamps are millisecond safe integers (
timestampMs,durationMs). - Fees are signed user cost: positive = the user pays, negative = a rebate.
- Funding
payment: positive = the position pays.accountValueDelta = -payment. - Sizes:
signedSizedescribes a position (negative = short);sizeis always positive and pairs withside: 'buy' | 'sell'.
What the package will not decide
hyperliquid-math returns values, constraint checks, assumptions, and a trace. It does not decide severity, warnings, blocking, or freshness, and it does not fetch, sign, or submit. Server-authoritative values — effective fee tier, final funding settlement, liquidation execution — are inputs or comparison evidence, never outputs. Those belong in your policy and transport layers. The complete boundary is in Field Mapping.