@lifi/perps-sdk-provider-hyperliquid 11.0.0 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/services/getAccount.d.ts.map +1 -1
- package/dist/cjs/services/getAccount.js +7 -3
- package/dist/cjs/services/getAccount.js.map +1 -1
- package/dist/cjs/utils/decimal.d.ts +3 -0
- package/dist/cjs/utils/decimal.d.ts.map +1 -0
- package/dist/cjs/utils/decimal.js +19 -0
- package/dist/cjs/utils/decimal.js.map +1 -0
- package/dist/cjs/utils/infoClient.d.ts.map +1 -1
- package/dist/cjs/utils/infoClient.js +5 -1
- package/dist/cjs/utils/infoClient.js.map +1 -1
- package/dist/cjs/utils/mapMarketContext.d.ts +2 -2
- package/dist/cjs/utils/mapMarketContext.d.ts.map +1 -1
- package/dist/cjs/utils/mapMarketContext.js +21 -4
- package/dist/cjs/utils/mapMarketContext.js.map +1 -1
- package/dist/cjs/utils/spotCollateral.d.ts.map +1 -1
- package/dist/cjs/utils/spotCollateral.js +4 -0
- package/dist/cjs/utils/spotCollateral.js.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +7 -9
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/services/getAccount.d.ts.map +1 -1
- package/dist/esm/services/getAccount.js +7 -3
- package/dist/esm/services/getAccount.js.map +1 -1
- package/dist/esm/utils/decimal.d.ts +10 -0
- package/dist/esm/utils/decimal.d.ts.map +1 -0
- package/dist/esm/utils/decimal.js +19 -0
- package/dist/esm/utils/decimal.js.map +1 -0
- package/dist/esm/utils/infoClient.d.ts +4 -1
- package/dist/esm/utils/infoClient.d.ts.map +1 -1
- package/dist/esm/utils/infoClient.js +10 -3
- package/dist/esm/utils/infoClient.js.map +1 -1
- package/dist/esm/utils/mapMarketContext.d.ts +7 -4
- package/dist/esm/utils/mapMarketContext.d.ts.map +1 -1
- package/dist/esm/utils/mapMarketContext.js +27 -6
- package/dist/esm/utils/mapMarketContext.js.map +1 -1
- package/dist/esm/utils/spotCollateral.d.ts.map +1 -1
- package/dist/esm/utils/spotCollateral.js +4 -0
- package/dist/esm/utils/spotCollateral.js.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +7 -9
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/types/services/getAccount.d.ts.map +1 -1
- package/dist/types/utils/decimal.d.ts +10 -0
- package/dist/types/utils/decimal.d.ts.map +1 -0
- package/dist/types/utils/infoClient.d.ts +4 -1
- package/dist/types/utils/infoClient.d.ts.map +1 -1
- package/dist/types/utils/mapMarketContext.d.ts +7 -4
- package/dist/types/utils/mapMarketContext.d.ts.map +1 -1
- package/dist/types/utils/spotCollateral.d.ts.map +1 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/services/getAccount.ts +9 -4
- package/src/utils/decimal.ts +21 -0
- package/src/utils/infoClient.ts +15 -2
- package/src/utils/mapMarketContext.ts +32 -7
- package/src/utils/spotCollateral.ts +4 -0
- package/src/websocket/HyperliquidWsProvider.ts +14 -10
package/src/utils/infoClient.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
errorCodeFromStatus,
|
|
2
3
|
fetchWithRetry,
|
|
3
4
|
PerpsError,
|
|
4
5
|
type PerpsSDKClient,
|
|
@@ -28,6 +29,11 @@ const normalizeInfoValue = (value: unknown): unknown => {
|
|
|
28
29
|
return value
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
const HYPERLIQUID_STATUS_ERROR_CODES = {
|
|
33
|
+
401: PerpsErrorCode.Unauthorized,
|
|
34
|
+
403: PerpsErrorCode.AgentUnauthorized,
|
|
35
|
+
} as const
|
|
36
|
+
|
|
31
37
|
/** @internal */
|
|
32
38
|
export const HYPERLIQUID_RETRY_DEFAULTS: ResolvedRetryPolicy = {
|
|
33
39
|
enabled: true,
|
|
@@ -88,7 +94,10 @@ export const hlInfoOptions = (
|
|
|
88
94
|
* upstream-controlled and normalise into `@lifi/perps-types` shapes before
|
|
89
95
|
* surfacing.
|
|
90
96
|
*
|
|
91
|
-
* Non-2xx responses raise a {@link PerpsError} with the Hyperliquid
|
|
97
|
+
* Non-2xx responses raise a {@link PerpsError} tagged with the Hyperliquid
|
|
98
|
+
* provider key, carrying the code the status resolves to: `RateLimitExceeded`
|
|
99
|
+
* for a 429, `Unauthorized` for a 401, `AgentUnauthorized` for a 403, and
|
|
100
|
+
* `ThirdPartyError` for every other status.
|
|
92
101
|
* @public
|
|
93
102
|
*/
|
|
94
103
|
export async function infoRequest<T>(
|
|
@@ -124,7 +133,11 @@ export async function infoRequest<T>(
|
|
|
124
133
|
|
|
125
134
|
if (!response.ok) {
|
|
126
135
|
const err = new PerpsError(
|
|
127
|
-
|
|
136
|
+
errorCodeFromStatus(
|
|
137
|
+
response.status,
|
|
138
|
+
PerpsErrorCode.ThirdPartyError,
|
|
139
|
+
HYPERLIQUID_STATUS_ERROR_CODES
|
|
140
|
+
),
|
|
128
141
|
`Hyperliquid info request failed: ${response.status}`
|
|
129
142
|
)
|
|
130
143
|
err.tool = PROVIDER_KEY
|
|
@@ -1,30 +1,55 @@
|
|
|
1
1
|
import type { MarketContext } from '@lifi/perps-types'
|
|
2
|
-
import
|
|
2
|
+
import Big from 'big.js'
|
|
3
|
+
import type { HlWsFastAssetCtx, HlWsPerpAssetCtx } from '../types/index.js'
|
|
3
4
|
|
|
4
5
|
const NEXT_FUNDING_INTERVAL_MS = 60 * 60 * 1000 // 1 hour
|
|
5
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Convert venue base-unit open interest to a quote-asset notional. A mark that
|
|
9
|
+
* is not a positive number leaves the notional unknown rather than zero.
|
|
10
|
+
*/
|
|
11
|
+
const toOpenInterestNotional = (
|
|
12
|
+
openInterest: string,
|
|
13
|
+
markPrice: string
|
|
14
|
+
): string | undefined => {
|
|
15
|
+
try {
|
|
16
|
+
const mark = new Big(markPrice)
|
|
17
|
+
if (mark.lte(0)) {
|
|
18
|
+
return undefined
|
|
19
|
+
}
|
|
20
|
+
return new Big(openInterest).times(mark).toFixed()
|
|
21
|
+
} catch {
|
|
22
|
+
return undefined
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
6
26
|
/**
|
|
7
27
|
* Map a Hyperliquid perp asset context from the `allDexsAssetCtxs` feed to a
|
|
8
|
-
* {@link MarketContext}
|
|
9
|
-
*
|
|
28
|
+
* {@link MarketContext}, with mid and mark overlaid from a `fastAssetCtxs`
|
|
29
|
+
* context where one is given. `midPx` is null when the book is empty; mid then
|
|
30
|
+
* falls back to the mark so the context always carries a usable mid. The
|
|
31
|
+
* open-interest notional follows the emitted mark, so it never mixes the two
|
|
32
|
+
* feeds' prices.
|
|
10
33
|
* @public
|
|
11
34
|
*/
|
|
12
35
|
export const mapMarketContext = (
|
|
13
36
|
marketId: string,
|
|
14
|
-
ctx: HlWsPerpAssetCtx
|
|
37
|
+
ctx: HlWsPerpAssetCtx,
|
|
38
|
+
fast?: HlWsFastAssetCtx
|
|
15
39
|
): MarketContext => {
|
|
16
40
|
const now = Date.now()
|
|
17
41
|
const nextFundingTime =
|
|
18
42
|
Math.ceil(now / NEXT_FUNDING_INTERVAL_MS) * NEXT_FUNDING_INTERVAL_MS
|
|
43
|
+
const markPrice = fast?.markPx != null ? fast.markPx : ctx.markPx
|
|
19
44
|
|
|
20
45
|
return {
|
|
21
46
|
marketId,
|
|
22
|
-
midPrice: ctx.midPx ?? ctx.markPx,
|
|
23
|
-
markPrice
|
|
47
|
+
midPrice: fast?.midPx != null ? fast.midPx : (ctx.midPx ?? ctx.markPx),
|
|
48
|
+
markPrice,
|
|
24
49
|
oraclePrice: ctx.oraclePx,
|
|
25
50
|
prevDayPrice: ctx.prevDayPx,
|
|
26
51
|
volume24h: ctx.dayNtlVlm,
|
|
27
|
-
openInterest: ctx.openInterest,
|
|
52
|
+
openInterest: toOpenInterestNotional(ctx.openInterest, markPrice),
|
|
28
53
|
funding: {
|
|
29
54
|
rate: ctx.funding,
|
|
30
55
|
nextFundingTime,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Balance } from '@lifi/perps-types'
|
|
2
|
+
import { toWireBig } from './decimal.js'
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Portfolio-margin collateral beyond the category quote assets, keyed by spot
|
|
@@ -37,6 +38,9 @@ export const partitionSpotBalances = (
|
|
|
37
38
|
const collateralBalances: Balance[] = []
|
|
38
39
|
const balances: Balance[] = []
|
|
39
40
|
for (const balance of spotBalances) {
|
|
41
|
+
if (!toWireBig(balance.units, 'spotBalance.units').gt(0)) {
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
40
44
|
if (quoteAssetIds.has(balance.asset.id)) {
|
|
41
45
|
collateralBalances.push(balance)
|
|
42
46
|
continue
|
|
@@ -58,6 +58,7 @@ import type {
|
|
|
58
58
|
HlWsUserFillsData,
|
|
59
59
|
} from '../types/index.js'
|
|
60
60
|
import { HlAbstractionMode } from '../types/index.js'
|
|
61
|
+
import { toWireBig } from '../utils/decimal.js'
|
|
61
62
|
import {
|
|
62
63
|
decodeCompressedJson,
|
|
63
64
|
decodeFastAssetCtxs,
|
|
@@ -786,12 +787,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
786
787
|
perpCtx = byMarketId[marketId] ?? perpCtx
|
|
787
788
|
}
|
|
788
789
|
if (perpCtx !== undefined) {
|
|
789
|
-
|
|
790
|
-
return {
|
|
791
|
-
...base,
|
|
792
|
-
midPrice: fast?.midPx != null ? fast.midPx : base.midPrice,
|
|
793
|
-
markPrice: fast?.markPx != null ? fast.markPx : base.markPrice,
|
|
794
|
-
}
|
|
790
|
+
return mapMarketContext(marketId, perpCtx, fast)
|
|
795
791
|
}
|
|
796
792
|
const midPrice = fast?.midPx ?? fast?.markPx
|
|
797
793
|
const markPrice = fast?.markPx ?? fast?.midPx
|
|
@@ -1254,10 +1250,18 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
1254
1250
|
const user = data.user.toLowerCase()
|
|
1255
1251
|
const markets = this.registry?.activeMarkets ?? []
|
|
1256
1252
|
const priceById = spotPriceById(markets, this.mergedMids())
|
|
1257
|
-
const rows = data.spotState.balances
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1253
|
+
const rows = data.spotState.balances
|
|
1254
|
+
.filter((balance) =>
|
|
1255
|
+
toWireBig(balance.total, 'spotState.balances.total').gt(0)
|
|
1256
|
+
)
|
|
1257
|
+
.map((balance) => ({
|
|
1258
|
+
balance: spotBalance(
|
|
1259
|
+
spotAssetFromToken(balance),
|
|
1260
|
+
balance.total,
|
|
1261
|
+
priceById
|
|
1262
|
+
),
|
|
1263
|
+
hold: balance.hold,
|
|
1264
|
+
}))
|
|
1261
1265
|
this.emit(`spotState:${user}`, {
|
|
1262
1266
|
channel: 'spotBalances',
|
|
1263
1267
|
data: rows.map(({ balance, hold }) => ({ ...balance, locked: hold })),
|