@lifi/perps-sdk-provider-hyperliquid 5.0.0 → 6.0.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/HyperliquidProvider.d.ts.map +1 -1
- package/dist/cjs/HyperliquidProvider.js +4 -0
- package/dist/cjs/HyperliquidProvider.js.map +1 -1
- package/dist/cjs/services/getAccount.d.ts.map +1 -1
- package/dist/cjs/services/getAccount.js +1 -1
- package/dist/cjs/services/getAccount.js.map +1 -1
- package/dist/cjs/services/getMarketSettings.d.ts +10 -0
- package/dist/cjs/services/getMarketSettings.d.ts.map +1 -0
- package/dist/cjs/services/getMarketSettings.js +26 -0
- package/dist/cjs/services/getMarketSettings.js.map +1 -0
- package/dist/cjs/services/getPositions.d.ts.map +1 -1
- package/dist/cjs/services/getPositions.js +1 -1
- package/dist/cjs/services/getPositions.js.map +1 -1
- package/dist/cjs/types/account.d.ts +11 -0
- package/dist/cjs/types/account.d.ts.map +1 -1
- package/dist/cjs/types/account.js.map +1 -1
- package/dist/cjs/types/asset.d.ts +1 -0
- package/dist/cjs/types/asset.d.ts.map +1 -1
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +3 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/mapMarket.d.ts.map +1 -1
- package/dist/cjs/utils/mapMarket.js +6 -1
- package/dist/cjs/utils/mapMarket.js.map +1 -1
- package/dist/cjs/utils/mapPosition.d.ts +2 -2
- package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
- package/dist/cjs/utils/mapPosition.js +17 -10
- package/dist/cjs/utils/mapPosition.js.map +1 -1
- package/dist/cjs/utils/marketDisplay.d.ts.map +1 -1
- package/dist/cjs/utils/marketDisplay.js +6 -3
- package/dist/cjs/utils/marketDisplay.js.map +1 -1
- package/dist/cjs/utils/transferMargin.d.ts +3 -0
- package/dist/cjs/utils/transferMargin.d.ts.map +1 -0
- package/dist/cjs/utils/transferMargin.js +41 -0
- package/dist/cjs/utils/transferMargin.js.map +1 -0
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +3 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/HyperliquidProvider.d.ts.map +1 -1
- package/dist/esm/HyperliquidProvider.js +4 -0
- package/dist/esm/HyperliquidProvider.js.map +1 -1
- package/dist/esm/services/getAccount.d.ts +3 -2
- package/dist/esm/services/getAccount.d.ts.map +1 -1
- package/dist/esm/services/getAccount.js +5 -4
- package/dist/esm/services/getAccount.js.map +1 -1
- package/dist/esm/services/getMarketSettings.d.ts +21 -0
- package/dist/esm/services/getMarketSettings.d.ts.map +1 -0
- package/dist/esm/services/getMarketSettings.js +29 -0
- package/dist/esm/services/getMarketSettings.js.map +1 -0
- package/dist/esm/services/getPositions.d.ts.map +1 -1
- package/dist/esm/services/getPositions.js +2 -2
- package/dist/esm/services/getPositions.js.map +1 -1
- package/dist/esm/types/account.d.ts +17 -0
- package/dist/esm/types/account.d.ts.map +1 -1
- package/dist/esm/types/account.js.map +1 -1
- package/dist/esm/types/asset.d.ts +2 -0
- package/dist/esm/types/asset.d.ts.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/mapMarket.d.ts.map +1 -1
- package/dist/esm/utils/mapMarket.js +8 -1
- package/dist/esm/utils/mapMarket.js.map +1 -1
- package/dist/esm/utils/mapPosition.d.ts +2 -2
- package/dist/esm/utils/mapPosition.d.ts.map +1 -1
- package/dist/esm/utils/mapPosition.js +14 -10
- package/dist/esm/utils/mapPosition.js.map +1 -1
- package/dist/esm/utils/marketDisplay.d.ts +4 -1
- package/dist/esm/utils/marketDisplay.d.ts.map +1 -1
- package/dist/esm/utils/marketDisplay.js +10 -4
- package/dist/esm/utils/marketDisplay.js.map +1 -1
- package/dist/esm/utils/transferMargin.d.ts +14 -0
- package/dist/esm/utils/transferMargin.d.ts.map +1 -0
- package/dist/esm/utils/transferMargin.js +46 -0
- package/dist/esm/utils/transferMargin.js.map +1 -0
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +4 -2
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/types/HyperliquidProvider.d.ts.map +1 -1
- package/dist/types/services/getAccount.d.ts +3 -2
- package/dist/types/services/getAccount.d.ts.map +1 -1
- package/dist/types/services/getMarketSettings.d.ts +21 -0
- package/dist/types/services/getMarketSettings.d.ts.map +1 -0
- package/dist/types/services/getPositions.d.ts.map +1 -1
- package/dist/types/types/account.d.ts +17 -0
- package/dist/types/types/account.d.ts.map +1 -1
- package/dist/types/types/asset.d.ts +2 -0
- package/dist/types/types/asset.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/mapMarket.d.ts.map +1 -1
- package/dist/types/utils/mapPosition.d.ts +2 -2
- package/dist/types/utils/mapPosition.d.ts.map +1 -1
- package/dist/types/utils/marketDisplay.d.ts +4 -1
- package/dist/types/utils/marketDisplay.d.ts.map +1 -1
- package/dist/types/utils/transferMargin.d.ts +14 -0
- package/dist/types/utils/transferMargin.d.ts.map +1 -0
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/HyperliquidProvider.ts +16 -0
- package/src/services/getAccount.ts +10 -3
- package/src/services/getMarketSettings.ts +56 -0
- package/src/services/getPositions.ts +11 -2
- package/src/types/account.ts +15 -0
- package/src/types/asset.ts +2 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/mapMarket.ts +10 -1
- package/src/utils/mapPosition.ts +18 -14
- package/src/utils/marketDisplay.ts +13 -4
- package/src/utils/transferMargin.ts +69 -0
- package/src/websocket/HyperliquidWsProvider.ts +4 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transferMargin.d.ts","sourceRoot":"","sources":["../../../src/utils/transferMargin.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,QAAQ,EAEb,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAA;AAyB1B;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,QAAQ,GACjB,yBAAyB,GAAG,SAAS,CAuBvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperliquidWsProvider.d.ts","sourceRoot":"","sources":["../../../src/websocket/HyperliquidWsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAGlB,KAAK,oBAAoB,
|
|
1
|
+
{"version":3,"file":"HyperliquidWsProvider.d.ts","sourceRoot":"","sources":["../../../src/websocket/HyperliquidWsProvider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifi/perps-sdk-provider-hyperliquid",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Hyperliquid provider plugin for @lifi/perps-sdk",
|
|
5
5
|
"homepage": "https://github.com/lifinance/perps-sdk",
|
|
6
6
|
"bugs": {
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"big.js": "^7.0.1",
|
|
50
50
|
"viem": "^2.48.8",
|
|
51
|
-
"@lifi/perps-types": "^
|
|
51
|
+
"@lifi/perps-types": "^4.0.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@lifi/perps-sdk": "^
|
|
54
|
+
"@lifi/perps-sdk": "^6.0.0"
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public"
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
type ProviderGetAccountParams,
|
|
12
12
|
type ProviderGetActivityParams,
|
|
13
13
|
type ProviderGetFillsParams,
|
|
14
|
+
type ProviderGetMarketSettingsParams,
|
|
14
15
|
type ProviderGetOrderParams,
|
|
15
16
|
type ProviderGetOrdersParams,
|
|
16
17
|
type ProviderGetPositionsParams,
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
type ActivitiesResponse,
|
|
31
32
|
type FillsResponse,
|
|
32
33
|
type Market,
|
|
34
|
+
type MarketSettings,
|
|
33
35
|
type Order,
|
|
34
36
|
type OrdersResponse,
|
|
35
37
|
PerpsErrorCode,
|
|
@@ -56,6 +58,7 @@ import { getAccount } from './services/getAccount.js'
|
|
|
56
58
|
import { getAccountExists } from './services/getAccountExists.js'
|
|
57
59
|
import { getActivity } from './services/getActivity.js'
|
|
58
60
|
import { getFills } from './services/getFills.js'
|
|
61
|
+
import { getMarketSettings } from './services/getMarketSettings.js'
|
|
59
62
|
import { getOrder } from './services/getOrder.js'
|
|
60
63
|
import { getOrders } from './services/getOrders.js'
|
|
61
64
|
import { getPositions } from './services/getPositions.js'
|
|
@@ -68,6 +71,7 @@ import type { HlExtraAgents } from './types/index.js'
|
|
|
68
71
|
import { hlInfoOptions, infoRequest } from './utils/infoClient.js'
|
|
69
72
|
import { calculateLiquidationPrice } from './utils/liquidation.js'
|
|
70
73
|
import { formatOrderPrice, formatOrderSize } from './utils/orderFormatting.js'
|
|
74
|
+
import { positionMarginConstraints } from './utils/transferMargin.js'
|
|
71
75
|
|
|
72
76
|
/**
|
|
73
77
|
* Options for {@link hyperliquidProvider}.
|
|
@@ -288,6 +292,16 @@ export function hyperliquidProvider(
|
|
|
288
292
|
opts
|
|
289
293
|
),
|
|
290
294
|
|
|
295
|
+
getMarketSettings: (
|
|
296
|
+
params: ProviderGetMarketSettingsParams,
|
|
297
|
+
opts?: SDKRequestOptions
|
|
298
|
+
): Promise<MarketSettings | undefined> =>
|
|
299
|
+
getMarketSettings(
|
|
300
|
+
contextRef.require(),
|
|
301
|
+
{ address: params.address, market: params.market },
|
|
302
|
+
opts
|
|
303
|
+
),
|
|
304
|
+
|
|
291
305
|
getOrders: (
|
|
292
306
|
params: ProviderGetOrdersParams,
|
|
293
307
|
opts?: SDKRequestOptions
|
|
@@ -383,6 +397,8 @@ export function hyperliquidProvider(
|
|
|
383
397
|
market.maxLeverage
|
|
384
398
|
),
|
|
385
399
|
|
|
400
|
+
positionMarginConstraints,
|
|
401
|
+
|
|
386
402
|
projectConfig: (
|
|
387
403
|
config: AccountConfig,
|
|
388
404
|
setup: ProviderAction[],
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type ProviderGetAccountParams,
|
|
5
5
|
type SDKRequestOptions,
|
|
6
6
|
stringToFloat,
|
|
7
|
+
toPerpsMarketDisplay,
|
|
7
8
|
} from '@lifi/perps-sdk'
|
|
8
9
|
import type {
|
|
9
10
|
AccountResponse,
|
|
@@ -133,8 +134,9 @@ const buildBalances = (
|
|
|
133
134
|
* the typed `HyperliquidAccountConfig`.
|
|
134
135
|
*
|
|
135
136
|
* Issues `userFees`, `userAbstraction`, `extraAgents`,
|
|
136
|
-
* `spotClearinghouseState` and one `clearinghouseState` per
|
|
137
|
-
*
|
|
137
|
+
* `spotClearinghouseState` and one `clearinghouseState` per perps sub-dex that
|
|
138
|
+
* still has a live market, all concurrently. USDC parked manually on a
|
|
139
|
+
* sub-dex whose every market is delisted is therefore not reported.
|
|
138
140
|
*
|
|
139
141
|
* `config.builderFeeApproval` is intentionally omitted — that field
|
|
140
142
|
* compares the venue's `maxBuilderFee` against the integrator-specific
|
|
@@ -213,7 +215,12 @@ export const getAccount = async (
|
|
|
213
215
|
const positions: Position[] = stateResults.flatMap((state) =>
|
|
214
216
|
state.assetPositions
|
|
215
217
|
.filter(isOpenAssetPosition)
|
|
216
|
-
.map((ap) =>
|
|
218
|
+
.map((ap) =>
|
|
219
|
+
mapPosition(
|
|
220
|
+
ap,
|
|
221
|
+
toPerpsMarketDisplay(registry.require(ap.position.coin))
|
|
222
|
+
)
|
|
223
|
+
)
|
|
217
224
|
)
|
|
218
225
|
|
|
219
226
|
const stateByDex = new Map<string, HlClearinghouseState>()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { SDKRequestOptions } from '@lifi/perps-sdk'
|
|
2
|
+
import {
|
|
3
|
+
MarginMode,
|
|
4
|
+
type MarketRef,
|
|
5
|
+
type MarketSettings,
|
|
6
|
+
} from '@lifi/perps-types'
|
|
7
|
+
import type { Address } from 'viem'
|
|
8
|
+
import { SPOT_MARKET_ID } from '../constants.js'
|
|
9
|
+
import type { HyperliquidContext } from '../context.js'
|
|
10
|
+
import type { HlActiveAssetData } from '../types/index.js'
|
|
11
|
+
import { hlInfoOptions, infoRequest } from '../utils/infoClient.js'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parameters for {@link getMarketSettings}.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export interface GetMarketSettingsParams {
|
|
19
|
+
address: Address
|
|
20
|
+
market: MarketRef
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The user's venue-stored margin mode and leverage for one perps market,
|
|
25
|
+
* read from `activeAssetData` — present whether or not a position is open.
|
|
26
|
+
* @throws {PerpsError} On Hyperliquid REST error, network, or parsing failures.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export const getMarketSettings = async (
|
|
30
|
+
{ client, apiUrl }: HyperliquidContext,
|
|
31
|
+
params: GetMarketSettingsParams,
|
|
32
|
+
options?: SDKRequestOptions
|
|
33
|
+
): Promise<MarketSettings | undefined> => {
|
|
34
|
+
// Spot markets carry no leverage state on the venue.
|
|
35
|
+
if (params.market.categoryId === SPOT_MARKET_ID) {
|
|
36
|
+
return undefined
|
|
37
|
+
}
|
|
38
|
+
const data = await infoRequest<HlActiveAssetData>(
|
|
39
|
+
apiUrl,
|
|
40
|
+
{
|
|
41
|
+
type: 'activeAssetData',
|
|
42
|
+
user: params.address,
|
|
43
|
+
coin: params.market.marketId,
|
|
44
|
+
},
|
|
45
|
+
hlInfoOptions(client, options)
|
|
46
|
+
)
|
|
47
|
+
const leverage = data.leverage
|
|
48
|
+
if (!leverage) {
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
marginMode:
|
|
53
|
+
leverage.type === 'isolated' ? MarginMode.ISOLATED : MarginMode.CROSS,
|
|
54
|
+
leverage: leverage.value,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
getMarketRegistry,
|
|
3
|
+
type SDKRequestOptions,
|
|
4
|
+
toPerpsMarketDisplay,
|
|
5
|
+
} from '@lifi/perps-sdk'
|
|
2
6
|
import type { PositionsResponse } from '@lifi/perps-types'
|
|
3
7
|
import type { Address } from 'viem'
|
|
4
8
|
import { PROVIDER_KEY } from '../constants.js'
|
|
@@ -58,7 +62,12 @@ export const getPositions = async (
|
|
|
58
62
|
let positions = stateResults.flatMap((state) =>
|
|
59
63
|
state.assetPositions
|
|
60
64
|
.filter(isOpenAssetPosition)
|
|
61
|
-
.map((ap) =>
|
|
65
|
+
.map((ap) =>
|
|
66
|
+
mapPosition(
|
|
67
|
+
ap,
|
|
68
|
+
toPerpsMarketDisplay(registry.require(ap.position.coin))
|
|
69
|
+
)
|
|
70
|
+
)
|
|
62
71
|
)
|
|
63
72
|
|
|
64
73
|
if (params.marketId !== undefined) {
|
package/src/types/account.ts
CHANGED
|
@@ -67,6 +67,21 @@ export type HlPreTransferCheck = {
|
|
|
67
67
|
userExists: boolean
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* `activeAssetData` info response: the user's live per-asset trading state.
|
|
72
|
+
* `leverage` reflects the venue-stored setting whether or not a position is
|
|
73
|
+
* open on the asset.
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export type HlActiveAssetData = {
|
|
77
|
+
user: string
|
|
78
|
+
coin: string
|
|
79
|
+
leverage: { type: 'cross' | 'isolated'; value: number }
|
|
80
|
+
maxTradeSzs: [string, string]
|
|
81
|
+
availableToTrade: [string, string]
|
|
82
|
+
markPx: string
|
|
83
|
+
}
|
|
84
|
+
|
|
70
85
|
/**
|
|
71
86
|
* Possible values returned by the `userAbstraction` info endpoint.
|
|
72
87
|
* `null` means abstraction has never been set; `'default'`/`'disabled'` are
|
package/src/types/asset.ts
CHANGED
package/src/utils/index.ts
CHANGED
package/src/utils/mapMarket.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PerpsMarket } from '@lifi/perps-types'
|
|
2
|
+
import { PositionMarginAdjustment } from '@lifi/perps-types'
|
|
2
3
|
import { PROVIDER_KEY } from '../constants.js'
|
|
3
4
|
import type { HlUniverseItem } from '../types/index.js'
|
|
4
5
|
import { calculateMaintenanceMarginRate } from './liquidation.js'
|
|
@@ -31,6 +32,14 @@ export const mapMarket = (
|
|
|
31
32
|
szDecimals: universe.szDecimals,
|
|
32
33
|
priceDecimals: getMaxPriceDecimals(universe.szDecimals),
|
|
33
34
|
maxLeverage: universe.maxLeverage,
|
|
34
|
-
onlyIsolated:
|
|
35
|
+
onlyIsolated:
|
|
36
|
+
universe.marginMode !== undefined || universe.onlyIsolated === true,
|
|
37
|
+
// Deprecated `onlyIsolated` cannot distinguish strict-isolated from
|
|
38
|
+
// no-cross, so the ambiguous legacy shape fails closed as add-only.
|
|
39
|
+
positionMarginAdjustment:
|
|
40
|
+
universe.marginMode === 'noCross' ||
|
|
41
|
+
(universe.marginMode === undefined && universe.onlyIsolated !== true)
|
|
42
|
+
? PositionMarginAdjustment.ADD_AND_REMOVE
|
|
43
|
+
: PositionMarginAdjustment.ADD_ONLY,
|
|
35
44
|
maintenanceMarginRate: calculateMaintenanceMarginRate(universe.maxLeverage),
|
|
36
45
|
})
|
package/src/utils/mapPosition.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PerpsMarketDisplay, Position } from '@lifi/perps-types'
|
|
2
2
|
import { MarginMode, PositionSide } from '@lifi/perps-types'
|
|
3
|
+
import Big from 'big.js'
|
|
3
4
|
import type { HlAssetPosition } from '../types/index.js'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -14,27 +15,30 @@ export const isOpenAssetPosition = (ap: HlAssetPosition): boolean =>
|
|
|
14
15
|
/** @public */
|
|
15
16
|
export const mapPosition = (
|
|
16
17
|
ap: HlAssetPosition,
|
|
17
|
-
market:
|
|
18
|
+
market: PerpsMarketDisplay
|
|
18
19
|
): Position => {
|
|
19
20
|
const pos = ap.position
|
|
20
|
-
const szi =
|
|
21
|
+
const szi = new Big(pos.szi)
|
|
22
|
+
const positionValue = new Big(pos.positionValue).abs()
|
|
23
|
+
const leverage = new Big(pos.leverage.value)
|
|
24
|
+
const marginMode =
|
|
25
|
+
pos.leverage.type === 'cross' ? MarginMode.CROSS : MarginMode.ISOLATED
|
|
26
|
+
const marginUsed =
|
|
27
|
+
marginMode === MarginMode.ISOLATED
|
|
28
|
+
? new Big(pos.marginUsed).minus(pos.unrealizedPnl).toFixed()
|
|
29
|
+
: pos.marginUsed
|
|
21
30
|
|
|
22
31
|
return {
|
|
23
32
|
market,
|
|
24
|
-
side: szi
|
|
25
|
-
size:
|
|
33
|
+
side: szi.gte(0) ? PositionSide.LONG : PositionSide.SHORT,
|
|
34
|
+
size: szi.abs().toFixed(),
|
|
26
35
|
entryPrice: pos.entryPx ?? '0',
|
|
27
|
-
markPrice:
|
|
28
|
-
pos.positionValue && szi !== 0
|
|
29
|
-
? (parseFloat(pos.positionValue) / Math.abs(szi)).toString()
|
|
30
|
-
: '0',
|
|
36
|
+
markPrice: szi.eq(0) ? '0' : positionValue.div(szi.abs()).toFixed(),
|
|
31
37
|
liquidationPrice: pos.liquidationPx ?? '0',
|
|
32
38
|
unrealizedPnl: pos.unrealizedPnl,
|
|
33
39
|
leverage: ap.position.leverage.value,
|
|
34
|
-
marginUsed
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
? MarginMode.CROSS
|
|
38
|
-
: MarginMode.ISOLATED,
|
|
40
|
+
marginUsed,
|
|
41
|
+
initialMarginRequirement: positionValue.div(leverage).toFixed(),
|
|
42
|
+
marginMode,
|
|
39
43
|
}
|
|
40
44
|
}
|
|
@@ -28,16 +28,25 @@ export const coinAsset = (coin: string): Asset =>
|
|
|
28
28
|
/**
|
|
29
29
|
* Distinct wire `dex` names to fan `clearinghouseState` / `frontendOpenOrders`
|
|
30
30
|
* reads across, derived from the backend market list. Spot is excluded (it has
|
|
31
|
-
* no clearinghouseState); the main perp dex maps to the empty string.
|
|
31
|
+
* no clearinghouseState); the main perp dex maps to the empty string. A dex
|
|
32
|
+
* whose every market is delisted is excluded too — delisting force-settles
|
|
33
|
+
* positions and cancels orders, so the only state it can still hold is USDC a
|
|
34
|
+
* user parked there manually, which no read then surfaces.
|
|
32
35
|
* @public
|
|
33
36
|
*/
|
|
34
37
|
export const perpsDexNames = (markets: readonly Market[]): string[] => {
|
|
35
|
-
const
|
|
38
|
+
const hasLiveMarket = new Map<string, boolean>()
|
|
36
39
|
for (const m of markets) {
|
|
37
40
|
if (m.categoryId === SPOT_MARKET_ID) {
|
|
38
41
|
continue
|
|
39
42
|
}
|
|
40
|
-
|
|
43
|
+
const name = m.categoryId === MAIN_MARKET_ID ? MAIN_DEX_NAME : m.categoryId
|
|
44
|
+
hasLiveMarket.set(
|
|
45
|
+
name,
|
|
46
|
+
(hasLiveMarket.get(name) ?? false) || m.isDelisted !== true
|
|
47
|
+
)
|
|
41
48
|
}
|
|
42
|
-
return [...
|
|
49
|
+
return [...hasLiveMarket]
|
|
50
|
+
.filter(([, hasLive]) => hasLive)
|
|
51
|
+
.map(([name]) => name)
|
|
43
52
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { PerpsError } from '@lifi/perps-sdk'
|
|
2
|
+
import {
|
|
3
|
+
MarginMode,
|
|
4
|
+
PerpsErrorCode,
|
|
5
|
+
type Position,
|
|
6
|
+
PositionMarginAdjustment,
|
|
7
|
+
type PositionMarginConstraints,
|
|
8
|
+
} from '@lifi/perps-types'
|
|
9
|
+
import Big from 'big.js'
|
|
10
|
+
|
|
11
|
+
const NOTIONAL_FLOOR_RATIO = '0.1'
|
|
12
|
+
const AMOUNT_INCREMENT = '0.000001'
|
|
13
|
+
|
|
14
|
+
function positivePositionAmount(value: string, field: string): Big {
|
|
15
|
+
let amount: Big
|
|
16
|
+
try {
|
|
17
|
+
amount = new Big(value)
|
|
18
|
+
} catch {
|
|
19
|
+
throw new PerpsError(
|
|
20
|
+
PerpsErrorCode.ValidationError,
|
|
21
|
+
`Invalid decimal string on Position.${field}: '${value}'`
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
if (amount.lte(0)) {
|
|
25
|
+
throw new PerpsError(
|
|
26
|
+
PerpsErrorCode.ValidationError,
|
|
27
|
+
`Position.${field} must be greater than zero.`
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
return amount
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Hyperliquid's exact documented transfer-margin requirement:
|
|
35
|
+
* `max(initial_margin_required, 0.1 * total_position_value)`.
|
|
36
|
+
*
|
|
37
|
+
* Strict-isolated markets still return constraints because margin can be
|
|
38
|
+
* added; their market capability prevents removal. Cross positions and
|
|
39
|
+
* markets without individual margin adjustment return `undefined`.
|
|
40
|
+
*
|
|
41
|
+
* @see https://hyperliquid.gitbook.io/hyperliquid-docs/trading/margining
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export function positionMarginConstraints(
|
|
45
|
+
position: Position
|
|
46
|
+
): PositionMarginConstraints | undefined {
|
|
47
|
+
if (
|
|
48
|
+
position.marginMode !== MarginMode.ISOLATED ||
|
|
49
|
+
position.market.positionMarginAdjustment === PositionMarginAdjustment.NONE
|
|
50
|
+
) {
|
|
51
|
+
return undefined
|
|
52
|
+
}
|
|
53
|
+
const initialMargin = positivePositionAmount(
|
|
54
|
+
position.initialMarginRequirement,
|
|
55
|
+
'initialMarginRequirement'
|
|
56
|
+
)
|
|
57
|
+
const notional = positivePositionAmount(position.size, 'size').times(
|
|
58
|
+
positivePositionAmount(position.markPrice, 'markPrice')
|
|
59
|
+
)
|
|
60
|
+
const notionalFloor = notional.times(NOTIONAL_FLOOR_RATIO)
|
|
61
|
+
const minimumMargin = initialMargin.gt(notionalFloor)
|
|
62
|
+
? initialMargin
|
|
63
|
+
: notionalFloor
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
minimumMarginRequirement: minimumMargin.toFixed(),
|
|
67
|
+
amountIncrement: AMOUNT_INCREMENT,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
resolveSubscribeQuote,
|
|
11
11
|
type SubscriptionListener,
|
|
12
12
|
summarizeAccount,
|
|
13
|
+
toPerpsMarketDisplay,
|
|
13
14
|
WsProviderBase,
|
|
14
15
|
type WsProviderFactory,
|
|
15
16
|
type WsStatusListener,
|
|
@@ -1060,7 +1061,9 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
1060
1061
|
return []
|
|
1061
1062
|
}
|
|
1062
1063
|
const market = this.registry?.get(ap.position.coin)
|
|
1063
|
-
return market
|
|
1064
|
+
return market
|
|
1065
|
+
? [mapPosition(ap as HlAssetPosition, toPerpsMarketDisplay(market))]
|
|
1066
|
+
: []
|
|
1064
1067
|
})
|
|
1065
1068
|
)
|
|
1066
1069
|
this.emit(`positions:${data.user.toLowerCase()}`, {
|