@lifi/perps-sdk-provider-hyperliquid 24.0.0 → 26.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/accountSummary.d.ts.map +1 -1
- package/dist/cjs/accountSummary.js +8 -14
- package/dist/cjs/accountSummary.js.map +1 -1
- package/dist/cjs/services/getAccount.d.ts.map +1 -1
- package/dist/cjs/services/getAccount.js +19 -16
- package/dist/cjs/services/getAccount.js.map +1 -1
- package/dist/cjs/services/getFills.d.ts.map +1 -1
- package/dist/cjs/services/getFills.js +2 -1
- package/dist/cjs/services/getFills.js.map +1 -1
- package/dist/cjs/services/getMarketSettings.d.ts.map +1 -1
- package/dist/cjs/services/getMarketSettings.js +1 -1
- package/dist/cjs/services/getMarketSettings.js.map +1 -1
- package/dist/cjs/services/getOrder.d.ts.map +1 -1
- package/dist/cjs/services/getOrder.js +14 -4
- package/dist/cjs/services/getOrder.js.map +1 -1
- package/dist/cjs/services/getOrders.d.ts.map +1 -1
- package/dist/cjs/services/getOrders.js +3 -1
- package/dist/cjs/services/getOrders.js.map +1 -1
- package/dist/cjs/services/getPortfolioHistory.d.ts.map +1 -1
- package/dist/cjs/services/getPortfolioHistory.js +15 -6
- package/dist/cjs/services/getPortfolioHistory.js.map +1 -1
- package/dist/cjs/services/getPositions.d.ts.map +1 -1
- package/dist/cjs/services/getPositions.js +4 -1
- package/dist/cjs/services/getPositions.js.map +1 -1
- package/dist/cjs/types/ws.d.ts +3 -2
- package/dist/cjs/types/ws.d.ts.map +1 -1
- package/dist/cjs/utils/liquidation.d.ts +1 -1
- package/dist/cjs/utils/liquidation.d.ts.map +1 -1
- package/dist/cjs/utils/liquidation.js +3 -4
- package/dist/cjs/utils/liquidation.js.map +1 -1
- package/dist/cjs/utils/mapActivity.d.ts.map +1 -1
- package/dist/cjs/utils/mapActivity.js +32 -23
- package/dist/cjs/utils/mapActivity.js.map +1 -1
- package/dist/cjs/utils/mapFill.d.ts +1 -1
- package/dist/cjs/utils/mapFill.d.ts.map +1 -1
- package/dist/cjs/utils/mapFill.js +14 -6
- package/dist/cjs/utils/mapFill.js.map +1 -1
- package/dist/cjs/utils/mapMarket.d.ts.map +1 -1
- package/dist/cjs/utils/mapMarket.js +8 -12
- package/dist/cjs/utils/mapMarket.js.map +1 -1
- package/dist/cjs/utils/mapMarketContext.d.ts.map +1 -1
- package/dist/cjs/utils/mapMarketContext.js +3 -12
- package/dist/cjs/utils/mapMarketContext.js.map +1 -1
- package/dist/cjs/utils/mapOrder.d.ts +1 -1
- package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
- package/dist/cjs/utils/mapOrder.js +60 -18
- package/dist/cjs/utils/mapOrder.js.map +1 -1
- package/dist/cjs/utils/mapPosition.d.ts +1 -1
- package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
- package/dist/cjs/utils/mapPosition.js +40 -14
- package/dist/cjs/utils/mapPosition.js.map +1 -1
- package/dist/cjs/utils/orderFormatting.d.ts.map +1 -1
- package/dist/cjs/utils/orderFormatting.js +4 -5
- package/dist/cjs/utils/orderFormatting.js.map +1 -1
- package/dist/cjs/utils/rowTimestamp.d.ts +2 -0
- package/dist/cjs/utils/rowTimestamp.d.ts.map +1 -0
- package/dist/cjs/utils/rowTimestamp.js +14 -0
- package/dist/cjs/utils/rowTimestamp.js.map +1 -0
- package/dist/cjs/utils/spotBalance.d.ts +3 -3
- package/dist/cjs/utils/spotBalance.d.ts.map +1 -1
- package/dist/cjs/utils/spotBalance.js +6 -5
- package/dist/cjs/utils/spotBalance.js.map +1 -1
- package/dist/cjs/utils/spotCollateral.d.ts.map +1 -1
- package/dist/cjs/utils/spotCollateral.js +3 -2
- package/dist/cjs/utils/spotCollateral.js.map +1 -1
- package/dist/cjs/utils/transferMargin.d.ts.map +1 -1
- package/dist/cjs/utils/transferMargin.js +15 -23
- package/dist/cjs/utils/transferMargin.js.map +1 -1
- package/dist/cjs/utils/venueTotals.d.ts +5 -5
- package/dist/cjs/utils/venueTotals.d.ts.map +1 -1
- package/dist/cjs/utils/venueTotals.js +10 -11
- package/dist/cjs/utils/venueTotals.js.map +1 -1
- package/dist/cjs/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/cjs/utils/withdrawableBalances.js +10 -10
- package/dist/cjs/utils/withdrawableBalances.js.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +109 -89
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/accountSummary.d.ts +2 -1
- package/dist/esm/accountSummary.d.ts.map +1 -1
- package/dist/esm/accountSummary.js +11 -13
- package/dist/esm/accountSummary.js.map +1 -1
- package/dist/esm/services/getAccount.d.ts.map +1 -1
- package/dist/esm/services/getAccount.js +24 -21
- package/dist/esm/services/getAccount.js.map +1 -1
- package/dist/esm/services/getFills.d.ts.map +1 -1
- package/dist/esm/services/getFills.js +2 -1
- package/dist/esm/services/getFills.js.map +1 -1
- package/dist/esm/services/getMarketSettings.d.ts.map +1 -1
- package/dist/esm/services/getMarketSettings.js +2 -2
- package/dist/esm/services/getMarketSettings.js.map +1 -1
- package/dist/esm/services/getOrder.d.ts.map +1 -1
- package/dist/esm/services/getOrder.js +14 -4
- package/dist/esm/services/getOrder.js.map +1 -1
- package/dist/esm/services/getOrders.d.ts.map +1 -1
- package/dist/esm/services/getOrders.js +5 -2
- package/dist/esm/services/getOrders.js.map +1 -1
- package/dist/esm/services/getPortfolioHistory.d.ts.map +1 -1
- package/dist/esm/services/getPortfolioHistory.js +17 -7
- package/dist/esm/services/getPortfolioHistory.js.map +1 -1
- package/dist/esm/services/getPositions.d.ts.map +1 -1
- package/dist/esm/services/getPositions.js +4 -1
- package/dist/esm/services/getPositions.js.map +1 -1
- package/dist/esm/services/getWithdrawableBalances.d.ts +1 -1
- package/dist/esm/services/getWithdrawableBalances.js +1 -1
- package/dist/esm/types/ws.d.ts +3 -2
- package/dist/esm/types/ws.d.ts.map +1 -1
- package/dist/esm/utils/liquidation.d.ts +1 -1
- package/dist/esm/utils/liquidation.d.ts.map +1 -1
- package/dist/esm/utils/liquidation.js +4 -5
- package/dist/esm/utils/liquidation.js.map +1 -1
- package/dist/esm/utils/mapActivity.d.ts +2 -1
- package/dist/esm/utils/mapActivity.d.ts.map +1 -1
- package/dist/esm/utils/mapActivity.js +35 -22
- package/dist/esm/utils/mapActivity.js.map +1 -1
- package/dist/esm/utils/mapFill.d.ts +3 -2
- package/dist/esm/utils/mapFill.d.ts.map +1 -1
- package/dist/esm/utils/mapFill.js +18 -9
- package/dist/esm/utils/mapFill.js.map +1 -1
- package/dist/esm/utils/mapMarket.d.ts +2 -2
- package/dist/esm/utils/mapMarket.d.ts.map +1 -1
- package/dist/esm/utils/mapMarket.js +10 -11
- package/dist/esm/utils/mapMarket.js.map +1 -1
- package/dist/esm/utils/mapMarketContext.d.ts.map +1 -1
- package/dist/esm/utils/mapMarketContext.js +3 -9
- package/dist/esm/utils/mapMarketContext.js.map +1 -1
- package/dist/esm/utils/mapOrder.d.ts +5 -2
- package/dist/esm/utils/mapOrder.d.ts.map +1 -1
- package/dist/esm/utils/mapOrder.js +65 -17
- package/dist/esm/utils/mapOrder.js.map +1 -1
- package/dist/esm/utils/mapPosition.d.ts +4 -2
- package/dist/esm/utils/mapPosition.d.ts.map +1 -1
- package/dist/esm/utils/mapPosition.js +43 -12
- package/dist/esm/utils/mapPosition.js.map +1 -1
- package/dist/esm/utils/orderFormatting.d.ts.map +1 -1
- package/dist/esm/utils/orderFormatting.js +6 -6
- package/dist/esm/utils/orderFormatting.js.map +1 -1
- package/dist/esm/utils/rowTimestamp.d.ts +6 -0
- package/dist/esm/utils/rowTimestamp.d.ts.map +1 -0
- package/dist/esm/utils/rowTimestamp.js +14 -0
- package/dist/esm/utils/rowTimestamp.js.map +1 -0
- package/dist/esm/utils/spotBalance.d.ts +5 -5
- package/dist/esm/utils/spotBalance.d.ts.map +1 -1
- package/dist/esm/utils/spotBalance.js +9 -8
- package/dist/esm/utils/spotBalance.js.map +1 -1
- package/dist/esm/utils/spotCollateral.d.ts.map +1 -1
- package/dist/esm/utils/spotCollateral.js +3 -2
- package/dist/esm/utils/spotCollateral.js.map +1 -1
- package/dist/esm/utils/transferMargin.d.ts +2 -1
- package/dist/esm/utils/transferMargin.d.ts.map +1 -1
- package/dist/esm/utils/transferMargin.js +18 -22
- package/dist/esm/utils/transferMargin.js.map +1 -1
- package/dist/esm/utils/venueTotals.d.ts +10 -5
- package/dist/esm/utils/venueTotals.d.ts.map +1 -1
- package/dist/esm/utils/venueTotals.js +13 -7
- package/dist/esm/utils/venueTotals.js.map +1 -1
- package/dist/esm/utils/withdrawableBalances.d.ts +6 -4
- package/dist/esm/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/esm/utils/withdrawableBalances.js +17 -15
- package/dist/esm/utils/withdrawableBalances.js.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts +2 -0
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +119 -88
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/types/accountSummary.d.ts +2 -1
- package/dist/types/accountSummary.d.ts.map +1 -1
- package/dist/types/services/getAccount.d.ts.map +1 -1
- package/dist/types/services/getFills.d.ts.map +1 -1
- package/dist/types/services/getMarketSettings.d.ts.map +1 -1
- package/dist/types/services/getOrder.d.ts.map +1 -1
- package/dist/types/services/getOrders.d.ts.map +1 -1
- package/dist/types/services/getPortfolioHistory.d.ts.map +1 -1
- package/dist/types/services/getPositions.d.ts.map +1 -1
- package/dist/types/services/getWithdrawableBalances.d.ts +1 -1
- package/dist/types/types/ws.d.ts +3 -2
- package/dist/types/types/ws.d.ts.map +1 -1
- package/dist/types/utils/liquidation.d.ts +1 -1
- package/dist/types/utils/liquidation.d.ts.map +1 -1
- package/dist/types/utils/mapActivity.d.ts +2 -1
- package/dist/types/utils/mapActivity.d.ts.map +1 -1
- package/dist/types/utils/mapFill.d.ts +3 -2
- package/dist/types/utils/mapFill.d.ts.map +1 -1
- package/dist/types/utils/mapMarket.d.ts +2 -2
- package/dist/types/utils/mapMarket.d.ts.map +1 -1
- package/dist/types/utils/mapMarketContext.d.ts.map +1 -1
- package/dist/types/utils/mapOrder.d.ts +5 -2
- package/dist/types/utils/mapOrder.d.ts.map +1 -1
- package/dist/types/utils/mapPosition.d.ts +4 -2
- package/dist/types/utils/mapPosition.d.ts.map +1 -1
- package/dist/types/utils/orderFormatting.d.ts.map +1 -1
- package/dist/types/utils/rowTimestamp.d.ts +6 -0
- package/dist/types/utils/rowTimestamp.d.ts.map +1 -0
- package/dist/types/utils/spotBalance.d.ts +5 -5
- package/dist/types/utils/spotBalance.d.ts.map +1 -1
- package/dist/types/utils/spotCollateral.d.ts.map +1 -1
- package/dist/types/utils/transferMargin.d.ts +2 -1
- package/dist/types/utils/transferMargin.d.ts.map +1 -1
- package/dist/types/utils/venueTotals.d.ts +10 -5
- package/dist/types/utils/venueTotals.d.ts.map +1 -1
- package/dist/types/utils/withdrawableBalances.d.ts +6 -4
- package/dist/types/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts +2 -0
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/HyperliquidProvider.ts +1 -1
- package/src/accountSummary.ts +35 -23
- package/src/services/getAccount.ts +50 -33
- package/src/services/getFills.ts +2 -1
- package/src/services/getMarketSettings.ts +6 -2
- package/src/services/getOrder.ts +18 -7
- package/src/services/getOrders.ts +6 -3
- package/src/services/getPortfolioHistory.ts +38 -7
- package/src/services/getPositions.ts +4 -3
- package/src/services/getWithdrawableBalances.ts +1 -1
- package/src/types/ws.ts +3 -2
- package/src/utils/liquidation.ts +14 -8
- package/src/utils/mapActivity.ts +42 -20
- package/src/utils/mapFill.ts +22 -9
- package/src/utils/mapMarket.ts +12 -10
- package/src/utils/mapMarketContext.ts +6 -8
- package/src/utils/mapOrder.ts +81 -20
- package/src/utils/mapPosition.ts +67 -13
- package/src/utils/orderFormatting.ts +9 -8
- package/src/utils/rowTimestamp.ts +15 -0
- package/src/utils/spotBalance.ts +19 -16
- package/src/utils/spotCollateral.ts +15 -2
- package/src/utils/transferMargin.ts +36 -20
- package/src/utils/venueTotals.ts +54 -13
- package/src/utils/withdrawableBalances.ts +33 -15
- package/src/websocket/HyperliquidWsProvider.ts +169 -102
- package/dist/cjs/utils/decimal.d.ts +0 -3
- package/dist/cjs/utils/decimal.d.ts.map +0 -1
- package/dist/cjs/utils/decimal.js +0 -19
- package/dist/cjs/utils/decimal.js.map +0 -1
- package/dist/esm/utils/decimal.d.ts +0 -10
- package/dist/esm/utils/decimal.d.ts.map +0 -1
- package/dist/esm/utils/decimal.js +0 -19
- package/dist/esm/utils/decimal.js.map +0 -1
- package/dist/types/utils/decimal.d.ts +0 -10
- package/dist/types/utils/decimal.d.ts.map +0 -1
- package/src/utils/decimal.ts +0 -21
|
@@ -2,20 +2,22 @@ import {
|
|
|
2
2
|
calculateTransferable,
|
|
3
3
|
getMarketRegistry,
|
|
4
4
|
getMarketsContext,
|
|
5
|
+
isDecimalStringGreaterThan,
|
|
5
6
|
type ProviderGetAccountParams,
|
|
6
|
-
parseDecimal,
|
|
7
7
|
type SDKRequestOptions,
|
|
8
|
+
subtractDecimalString,
|
|
8
9
|
toPerpsMarketDisplay,
|
|
10
|
+
unknownToDecimalString,
|
|
9
11
|
} from '@lifi/perps-sdk'
|
|
10
12
|
import type {
|
|
11
13
|
AccountResponse,
|
|
12
14
|
Asset,
|
|
13
15
|
Balance,
|
|
16
|
+
DecimalString,
|
|
14
17
|
HyperliquidAccountConfig,
|
|
15
18
|
HyperliquidDexAccountState,
|
|
16
19
|
Position,
|
|
17
20
|
} from '@lifi/perps-types'
|
|
18
|
-
import type Big from 'big.js'
|
|
19
21
|
import { PROVIDER_KEY } from '../constants.js'
|
|
20
22
|
import type { HyperliquidContext } from '../context.js'
|
|
21
23
|
import type {
|
|
@@ -26,19 +28,17 @@ import type {
|
|
|
26
28
|
HlUserFees,
|
|
27
29
|
} from '../types/index.js'
|
|
28
30
|
import { isUnifiedAbstraction } from '../utils/abstractionMode.js'
|
|
29
|
-
import { toWireBig } from '../utils/decimal.js'
|
|
30
31
|
import {
|
|
31
32
|
assetIsOutcome,
|
|
32
33
|
partitionSpotBalances,
|
|
33
34
|
perpsDexNames,
|
|
34
|
-
perpsTotals,
|
|
35
35
|
spotAssetFromToken,
|
|
36
36
|
spotBalance,
|
|
37
37
|
spotPriceById,
|
|
38
|
-
sumUnrealizedPnl,
|
|
39
38
|
} from '../utils/index.js'
|
|
40
39
|
import { hlInfoOptions, infoRequest } from '../utils/infoClient.js'
|
|
41
40
|
import { isOpenAssetPosition, mapPosition } from '../utils/mapPosition.js'
|
|
41
|
+
import { safeSumDecimalStrings } from '../utils/venueTotals.js'
|
|
42
42
|
import { requireAccountExists } from './getAccountExists.js'
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -48,12 +48,6 @@ import { requireAccountExists } from './getAccountExists.js'
|
|
|
48
48
|
*/
|
|
49
49
|
export type GetAccountParams = ProviderGetAccountParams
|
|
50
50
|
|
|
51
|
-
// `marginSummary` covers the whole account (cross AND isolated positions);
|
|
52
|
-
// `crossMarginSummary` is the cross-only subset and would drop isolated
|
|
53
|
-
// equity/margin.
|
|
54
|
-
const getAccountValue = (state: HlClearinghouseState): Big =>
|
|
55
|
-
toWireBig(state.marginSummary.accountValue, 'marginSummary.accountValue')
|
|
56
|
-
|
|
57
51
|
/** Venue buying power for the quote asset the perps dex settles in. */
|
|
58
52
|
const getAvailableAfterMaintenance = (
|
|
59
53
|
spotState: HlSpotClearinghouseState,
|
|
@@ -73,21 +67,28 @@ const buildBalances = (
|
|
|
73
67
|
spotState: HlSpotClearinghouseState,
|
|
74
68
|
stateByDex: Map<string, HlClearinghouseState>,
|
|
75
69
|
quoteAssetIds: ReadonlySet<string>,
|
|
76
|
-
priceById:
|
|
70
|
+
priceById: ReadonlyMap<string, DecimalString>,
|
|
77
71
|
quoteAssetByCategory: Map<string, Asset>
|
|
78
72
|
): BalancePartition => {
|
|
79
73
|
const { balances, collateralBalances } = partitionSpotBalances(
|
|
80
74
|
spotState.balances
|
|
81
75
|
.filter((b) => !assetIsOutcome(b.coin))
|
|
82
76
|
.map((b) => {
|
|
83
|
-
const total =
|
|
77
|
+
const total = unknownToDecimalString(
|
|
78
|
+
b.total,
|
|
79
|
+
'spotClearinghouseState.total',
|
|
80
|
+
PROVIDER_KEY
|
|
81
|
+
)
|
|
82
|
+
const hold = unknownToDecimalString(
|
|
83
|
+
b.hold,
|
|
84
|
+
'spotClearinghouseState.hold',
|
|
85
|
+
PROVIDER_KEY
|
|
86
|
+
)
|
|
84
87
|
return {
|
|
85
|
-
...spotBalance(spotAssetFromToken(b),
|
|
88
|
+
...spotBalance(spotAssetFromToken(b), total, priceById),
|
|
86
89
|
transferable: calculateTransferable(
|
|
90
|
+
subtractDecimalString(total, hold),
|
|
87
91
|
total
|
|
88
|
-
.minus(toWireBig(b.hold, 'spotClearinghouseState.hold'))
|
|
89
|
-
.toFixed(),
|
|
90
|
-
total.toFixed()
|
|
91
92
|
),
|
|
92
93
|
}
|
|
93
94
|
}),
|
|
@@ -101,8 +102,15 @@ const buildBalances = (
|
|
|
101
102
|
if (!isUnifiedAbstraction(abstraction)) {
|
|
102
103
|
for (const [dex, state] of stateByDex) {
|
|
103
104
|
const categoryId = dex || PROVIDER_KEY
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
// `marginSummary` covers the whole account (cross AND isolated positions);
|
|
106
|
+
// `crossMarginSummary` is the cross-only subset and would drop isolated
|
|
107
|
+
// equity/margin.
|
|
108
|
+
const value = unknownToDecimalString(
|
|
109
|
+
state.marginSummary.accountValue,
|
|
110
|
+
'marginSummary.accountValue',
|
|
111
|
+
PROVIDER_KEY
|
|
112
|
+
)
|
|
113
|
+
if (!isDecimalStringGreaterThan(value, '0')) {
|
|
106
114
|
continue
|
|
107
115
|
}
|
|
108
116
|
collateralBalances.push({
|
|
@@ -110,15 +118,16 @@ const buildBalances = (
|
|
|
110
118
|
// Always present: every dex in `stateByDex` derives from `markets`,
|
|
111
119
|
// which is what populates `quoteAssetByCategory`.
|
|
112
120
|
asset: quoteAssetByCategory.get(categoryId)!,
|
|
113
|
-
units: value
|
|
114
|
-
valueUsd: value
|
|
121
|
+
units: value,
|
|
122
|
+
valueUsd: value,
|
|
115
123
|
price: '1',
|
|
116
124
|
transferable: calculateTransferable(
|
|
117
|
-
|
|
125
|
+
unknownToDecimalString(
|
|
118
126
|
state.withdrawable,
|
|
119
|
-
'clearinghouseState.withdrawable'
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
'clearinghouseState.withdrawable',
|
|
128
|
+
PROVIDER_KEY
|
|
129
|
+
),
|
|
130
|
+
value
|
|
122
131
|
),
|
|
123
132
|
})
|
|
124
133
|
}
|
|
@@ -209,9 +218,7 @@ export const getAccount = async (
|
|
|
209
218
|
|
|
210
219
|
const priceById = spotPriceById(
|
|
211
220
|
markets,
|
|
212
|
-
new Map(
|
|
213
|
-
prices.map((p) => [p.marketId, parseDecimal(p.markPrice) ?? Number.NaN])
|
|
214
|
-
)
|
|
221
|
+
new Map(prices.map((p) => [p.marketId, p.markPrice]))
|
|
215
222
|
)
|
|
216
223
|
|
|
217
224
|
const positions: Position[] = stateResults.flatMap((state) =>
|
|
@@ -219,12 +226,13 @@ export const getAccount = async (
|
|
|
219
226
|
.filter(
|
|
220
227
|
(ap) => !assetIsOutcome(ap.position.coin) && isOpenAssetPosition(ap)
|
|
221
228
|
)
|
|
222
|
-
.
|
|
223
|
-
mapPosition(
|
|
229
|
+
.flatMap((ap) => {
|
|
230
|
+
const position = mapPosition(
|
|
224
231
|
ap,
|
|
225
232
|
toPerpsMarketDisplay(registry.require(ap.position.coin))
|
|
226
233
|
)
|
|
227
|
-
|
|
234
|
+
return position === undefined ? [] : [position]
|
|
235
|
+
})
|
|
228
236
|
)
|
|
229
237
|
|
|
230
238
|
const stateByDex = new Map<string, HlClearinghouseState>()
|
|
@@ -266,14 +274,23 @@ export const getAccount = async (
|
|
|
266
274
|
quoteAssetByCategory
|
|
267
275
|
)
|
|
268
276
|
|
|
277
|
+
const marginUsed = safeSumDecimalStrings(
|
|
278
|
+
dexStates.flatMap(({ marginSummary }) =>
|
|
279
|
+
marginSummary === undefined ? [] : [marginSummary.totalMarginUsed]
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
const unrealizedPnl = safeSumDecimalStrings(
|
|
283
|
+
positions.map((position) => position.unrealizedPnl)
|
|
284
|
+
)
|
|
285
|
+
|
|
269
286
|
return {
|
|
270
287
|
provider: PROVIDER_KEY,
|
|
271
288
|
address: params.address,
|
|
272
289
|
balances,
|
|
273
290
|
collateralBalances,
|
|
274
291
|
positions,
|
|
275
|
-
marginUsed:
|
|
276
|
-
unrealizedPnl:
|
|
292
|
+
...(marginUsed === undefined ? {} : { marginUsed }),
|
|
293
|
+
...(unrealizedPnl === undefined ? {} : { unrealizedPnl }),
|
|
277
294
|
feeTier: {
|
|
278
295
|
maker: feesResult.userAddRate ?? '0',
|
|
279
296
|
taker: feesResult.userCrossRate ?? '0',
|
package/src/services/getFills.ts
CHANGED
|
@@ -67,7 +67,8 @@ export const getFills = async (
|
|
|
67
67
|
return []
|
|
68
68
|
}
|
|
69
69
|
const market = registry.get(fill.coin)
|
|
70
|
-
|
|
70
|
+
const mapped = market && mapFill(fill, market)
|
|
71
|
+
return mapped ? [mapped] : []
|
|
71
72
|
})
|
|
72
73
|
return { items, saturated: false }
|
|
73
74
|
},
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
numberToDecimalString,
|
|
3
|
+
PerpsError,
|
|
4
|
+
type SDKRequestOptions,
|
|
5
|
+
} from '@lifi/perps-sdk'
|
|
2
6
|
import {
|
|
3
7
|
MarginMode,
|
|
4
8
|
type MarketRef,
|
|
@@ -66,6 +70,6 @@ export const getMarketSettings = async (
|
|
|
66
70
|
return {
|
|
67
71
|
marginMode:
|
|
68
72
|
leverage.type === 'isolated' ? MarginMode.ISOLATED : MarginMode.CROSS,
|
|
69
|
-
leverage: leverage.value,
|
|
73
|
+
leverage: numberToDecimalString(leverage.value),
|
|
70
74
|
}
|
|
71
75
|
}
|
package/src/services/getOrder.ts
CHANGED
|
@@ -24,6 +24,15 @@ import { requireAccountExists } from './getAccountExists.js'
|
|
|
24
24
|
*/
|
|
25
25
|
export type GetOrderParams = ProviderGetOrderParams
|
|
26
26
|
|
|
27
|
+
const orderNotFound = (id: string): PerpsError => {
|
|
28
|
+
const err = new PerpsError(
|
|
29
|
+
PerpsErrorCode.OrderNotFound,
|
|
30
|
+
`Order not found: ${id}`
|
|
31
|
+
)
|
|
32
|
+
err.tool = PROVIDER_KEY
|
|
33
|
+
return err
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
/**
|
|
28
37
|
* Read getOrder direct from the Hyperliquid REST API.
|
|
29
38
|
*
|
|
@@ -70,17 +79,16 @@ export const getOrder = async (
|
|
|
70
79
|
if (twap !== undefined) {
|
|
71
80
|
const registry = getMarketRegistry(client, PROVIDER_KEY)
|
|
72
81
|
await registry.sync()
|
|
73
|
-
|
|
82
|
+
const order = mapOrder(twap, registry.require(twap.state.coin))
|
|
83
|
+
if (order === undefined) {
|
|
84
|
+
throw orderNotFound(params.id)
|
|
85
|
+
}
|
|
86
|
+
return order
|
|
74
87
|
}
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
if (status.status !== 'order' || assetIsOutcome(status.order.order.coin)) {
|
|
78
|
-
|
|
79
|
-
PerpsErrorCode.OrderNotFound,
|
|
80
|
-
`Order not found: ${params.id}`
|
|
81
|
-
)
|
|
82
|
-
err.tool = PROVIDER_KEY
|
|
83
|
-
throw err
|
|
91
|
+
throw orderNotFound(params.id)
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
const registry = getMarketRegistry(client, PROVIDER_KEY)
|
|
@@ -89,6 +97,9 @@ export const getOrder = async (
|
|
|
89
97
|
status.order,
|
|
90
98
|
registry.require(status.order.order.coin)
|
|
91
99
|
)
|
|
100
|
+
if (order === undefined) {
|
|
101
|
+
throw orderNotFound(params.id)
|
|
102
|
+
}
|
|
92
103
|
const [linked] = await withExplorerLinks([order], params.address, infoOpts)
|
|
93
104
|
return linked
|
|
94
105
|
}
|
|
@@ -39,7 +39,7 @@ const warnOnce = (key: string): void => {
|
|
|
39
39
|
const mapRow = (
|
|
40
40
|
coin: string,
|
|
41
41
|
registry: MarketRegistry,
|
|
42
|
-
map: (market: MarketDisplay) => Order
|
|
42
|
+
map: (market: MarketDisplay) => Order | undefined
|
|
43
43
|
): Order | undefined => {
|
|
44
44
|
if (assetIsOutcome(coin)) {
|
|
45
45
|
return undefined
|
|
@@ -114,14 +114,17 @@ export const getOrders = async (
|
|
|
114
114
|
rows.set(key, order)
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
const seenHistorical = new Set<string>()
|
|
117
118
|
for (const detail of historical) {
|
|
118
119
|
const key = String(detail.order.oid)
|
|
119
120
|
// The feed carries one row per lifecycle transition, newest first, and a
|
|
120
121
|
// terminal row shares its timestamp with the `open` row beneath it, so
|
|
121
|
-
// only the first row of an id states that order's current status
|
|
122
|
-
|
|
122
|
+
// only the first row of an id states that order's current status, even
|
|
123
|
+
// when the mapper skips that row.
|
|
124
|
+
if (seenHistorical.has(key)) {
|
|
123
125
|
continue
|
|
124
126
|
}
|
|
127
|
+
seenHistorical.add(key)
|
|
125
128
|
keep(
|
|
126
129
|
key,
|
|
127
130
|
mapRow(detail.order.coin, registry, (market) => mapOrder(detail, market))
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import { PerpsError, type SDKRequestOptions } from '@lifi/perps-sdk'
|
|
2
1
|
import {
|
|
2
|
+
PerpsError,
|
|
3
|
+
type SDKRequestOptions,
|
|
4
|
+
warnSkippedVenueRow,
|
|
5
|
+
} from '@lifi/perps-sdk'
|
|
6
|
+
import {
|
|
7
|
+
type DecimalString,
|
|
3
8
|
PerpsErrorCode,
|
|
4
9
|
type PortfolioHistoryPoint,
|
|
5
10
|
type PortfolioHistoryRange,
|
|
6
11
|
type PortfolioHistoryResponse,
|
|
7
12
|
} from '@lifi/perps-types'
|
|
8
13
|
import type { Address } from 'viem'
|
|
14
|
+
import { PROVIDER_KEY } from '../constants.js'
|
|
9
15
|
import type { HyperliquidContext } from '../context.js'
|
|
10
16
|
import type {
|
|
11
17
|
HlAbstractionMode,
|
|
@@ -40,19 +46,39 @@ const PERP_PERIOD_BY_RANGE: Record<PortfolioHistoryRange, HlPortfolioPeriod> = {
|
|
|
40
46
|
all: 'perpAllTime',
|
|
41
47
|
}
|
|
42
48
|
|
|
49
|
+
/** The samples with a finite timestamp; each other sample is skipped. */
|
|
50
|
+
const validSamples = (
|
|
51
|
+
samples: HlPortfolioWindow['pnlHistory'],
|
|
52
|
+
row: string
|
|
53
|
+
): [number, DecimalString][] =>
|
|
54
|
+
samples.flatMap(([timestamp, value]): [number, DecimalString][] => {
|
|
55
|
+
if (!Number.isFinite(timestamp)) {
|
|
56
|
+
warnSkippedVenueRow(
|
|
57
|
+
PROVIDER_KEY,
|
|
58
|
+
row,
|
|
59
|
+
'timestamp',
|
|
60
|
+
timestamp,
|
|
61
|
+
'timestamp'
|
|
62
|
+
)
|
|
63
|
+
return []
|
|
64
|
+
}
|
|
65
|
+
return [[timestamp, value]]
|
|
66
|
+
})
|
|
67
|
+
|
|
43
68
|
/**
|
|
44
69
|
* Join the window's two series on their timestamps. `pnlHistory` is cumulative
|
|
45
70
|
* from the window's start, so a point with no PnL sample carries the last
|
|
46
71
|
* sampled value — `'0'` before the first one.
|
|
47
72
|
*/
|
|
48
73
|
const joinWindow = (
|
|
49
|
-
|
|
74
|
+
accountValueHistory: [number, DecimalString][],
|
|
75
|
+
pnlHistory: [number, DecimalString][],
|
|
50
76
|
period: HlPortfolioPeriod
|
|
51
77
|
): PortfolioHistoryPoint[] => {
|
|
52
|
-
const pnlByTimestamp = new Map(
|
|
78
|
+
const pnlByTimestamp = new Map(pnlHistory)
|
|
53
79
|
let matched = 0
|
|
54
80
|
let cumulative = '0'
|
|
55
|
-
const points =
|
|
81
|
+
const points = accountValueHistory.map(([timestamp, accountValue]) => {
|
|
56
82
|
const sample = pnlByTimestamp.get(timestamp)
|
|
57
83
|
if (sample !== undefined) {
|
|
58
84
|
matched += 1
|
|
@@ -60,7 +86,7 @@ const joinWindow = (
|
|
|
60
86
|
}
|
|
61
87
|
return { timestamp, accountValue, pnl: cumulative }
|
|
62
88
|
})
|
|
63
|
-
if (points.length > 0 &&
|
|
89
|
+
if (points.length > 0 && pnlHistory.length > 0 && matched === 0) {
|
|
64
90
|
throw new PerpsError(
|
|
65
91
|
PerpsErrorCode.ThirdPartyError,
|
|
66
92
|
`Hyperliquid portfolio window '${period}' samples PnL on no ` +
|
|
@@ -111,10 +137,15 @@ export async function getPortfolioHistory(
|
|
|
111
137
|
)
|
|
112
138
|
}
|
|
113
139
|
|
|
140
|
+
const pnlHistory = validSamples(window.pnlHistory, 'portfolio PnL sample')
|
|
114
141
|
return {
|
|
115
142
|
range: params.range,
|
|
116
|
-
points: joinWindow(
|
|
143
|
+
points: joinWindow(
|
|
144
|
+
validSamples(window.accountValueHistory, 'portfolio value sample'),
|
|
145
|
+
pnlHistory,
|
|
146
|
+
period
|
|
147
|
+
),
|
|
117
148
|
volume: window.vlm,
|
|
118
|
-
totalPnl:
|
|
149
|
+
totalPnl: pnlHistory.at(-1)?.[1],
|
|
119
150
|
}
|
|
120
151
|
}
|
|
@@ -67,12 +67,13 @@ export const getPositions = async (
|
|
|
67
67
|
.filter(
|
|
68
68
|
(ap) => !assetIsOutcome(ap.position.coin) && isOpenAssetPosition(ap)
|
|
69
69
|
)
|
|
70
|
-
.
|
|
71
|
-
mapPosition(
|
|
70
|
+
.flatMap((ap) => {
|
|
71
|
+
const position = mapPosition(
|
|
72
72
|
ap,
|
|
73
73
|
toPerpsMarketDisplay(registry.require(ap.position.coin))
|
|
74
74
|
)
|
|
75
|
-
|
|
75
|
+
return position === undefined ? [] : [position]
|
|
76
|
+
})
|
|
76
77
|
)
|
|
77
78
|
|
|
78
79
|
if (params.marketId !== undefined) {
|
|
@@ -27,7 +27,7 @@ export type GetWithdrawableBalancesParams =
|
|
|
27
27
|
ProviderGetWithdrawableBalancesParams
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* The `(asset,
|
|
30
|
+
* The `(asset, category)` pairs `params.address` can withdraw from Hyperliquid,
|
|
31
31
|
* read from the venue's own `withdrawable` and spot `total`/`hold` figures.
|
|
32
32
|
* Hyperliquid charges its flat withdrawal fee in USDC, so the backend's
|
|
33
33
|
* `withdrawalFeeUsd` is the fee in quote-asset units on every USDC row.
|
package/src/types/ws.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Hyperliquid WebSocket incoming message types.
|
|
2
2
|
|
|
3
|
+
import type { DecimalString } from '@lifi/perps-types'
|
|
3
4
|
import type { HlClearinghouseState, HlSpotBalance } from './account.js'
|
|
4
5
|
import type { HlCandle, HlL2Book } from './asset.js'
|
|
5
6
|
import type { HlUserFill } from './fill.js'
|
|
@@ -77,8 +78,8 @@ export type HlWsMessage = {
|
|
|
77
78
|
* @public
|
|
78
79
|
*/
|
|
79
80
|
export type HlWsFastAssetCtx = {
|
|
80
|
-
markPx?:
|
|
81
|
-
midPx?:
|
|
81
|
+
markPx?: DecimalString
|
|
82
|
+
midPx?: DecimalString | null
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
/**
|
package/src/utils/liquidation.ts
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
* - margin_available = isolated_margin - maintenance_margin_required
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
divideDecimalString,
|
|
17
|
+
numberToDecimalString,
|
|
18
|
+
safeEstimateLiquidationPrice,
|
|
19
|
+
} from '@lifi/perps-sdk'
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
22
|
* Calculate the maintenance margin fraction for a Hyperliquid asset.
|
|
@@ -56,19 +60,21 @@ export function calculateMaintenanceMarginRate(
|
|
|
56
60
|
* @public
|
|
57
61
|
*/
|
|
58
62
|
export function calculateLiquidationPrice(
|
|
59
|
-
entryPrice:
|
|
60
|
-
leverage:
|
|
63
|
+
entryPrice: string,
|
|
64
|
+
leverage: string,
|
|
61
65
|
isLong: boolean,
|
|
62
66
|
maxLeverage: number
|
|
63
|
-
):
|
|
64
|
-
|
|
65
|
-
if (mmr === undefined) {
|
|
67
|
+
): string | undefined {
|
|
68
|
+
if (maxLeverage === 0) {
|
|
66
69
|
return undefined
|
|
67
70
|
}
|
|
68
|
-
return
|
|
71
|
+
return safeEstimateLiquidationPrice({
|
|
69
72
|
entryPrice,
|
|
70
73
|
leverage,
|
|
71
74
|
isLong,
|
|
72
|
-
maintenanceMarginRate:
|
|
75
|
+
maintenanceMarginRate: divideDecimalString(
|
|
76
|
+
'1',
|
|
77
|
+
numberToDecimalString(2 * maxLeverage)
|
|
78
|
+
),
|
|
73
79
|
})
|
|
74
80
|
}
|
package/src/utils/mapActivity.ts
CHANGED
|
@@ -3,6 +3,10 @@ import {
|
|
|
3
3
|
ExplorerChainId,
|
|
4
4
|
explorerTxUrl,
|
|
5
5
|
PerpsError,
|
|
6
|
+
safeAddDecimalString,
|
|
7
|
+
safeMultiplyDecimalString,
|
|
8
|
+
safeSubtractDecimalString,
|
|
9
|
+
warnSkippedVenueRow,
|
|
6
10
|
} from '@lifi/perps-sdk'
|
|
7
11
|
import type {
|
|
8
12
|
ActivityItem,
|
|
@@ -16,7 +20,6 @@ import type {
|
|
|
16
20
|
WithdrawalActivity,
|
|
17
21
|
} from '@lifi/perps-types'
|
|
18
22
|
import { ActivityType, PerpsErrorCode } from '@lifi/perps-types'
|
|
19
|
-
import Big from 'big.js'
|
|
20
23
|
import { zeroHash } from 'viem'
|
|
21
24
|
import type {
|
|
22
25
|
HlBorrowLendOperation,
|
|
@@ -35,6 +38,7 @@ import {
|
|
|
35
38
|
isVaultTransferDelta,
|
|
36
39
|
isWithdrawDelta,
|
|
37
40
|
} from '../types/index.js'
|
|
41
|
+
import { rowTimestampToIsoStringOrUndefined } from './rowTimestamp.js'
|
|
38
42
|
|
|
39
43
|
/**
|
|
40
44
|
* Hyperliquid settles every perp deposit and withdrawal in USDC, and charges
|
|
@@ -96,11 +100,12 @@ export const mapLedgerEntry = (
|
|
|
96
100
|
resolveMarket: (coin: string) => MarketDisplay | undefined
|
|
97
101
|
): ActivityItem | null => {
|
|
98
102
|
const { delta } = entry
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
const timestamp = rowTimestampToIsoStringOrUndefined(entry.time)
|
|
104
|
+
if (timestamp === undefined) {
|
|
105
|
+
warnSkippedVenueRow(providerKey, 'ledger', 'time', entry.time, 'timestamp')
|
|
106
|
+
return null
|
|
103
107
|
}
|
|
108
|
+
const base = { id: entry.hash, provider: providerKey, timestamp }
|
|
104
109
|
|
|
105
110
|
if (
|
|
106
111
|
isSpotTransferDelta(delta) ||
|
|
@@ -315,7 +320,11 @@ export const mapFundingActivity = (
|
|
|
315
320
|
if (market === undefined) {
|
|
316
321
|
return null
|
|
317
322
|
}
|
|
318
|
-
const timestamp =
|
|
323
|
+
const timestamp = rowTimestampToIsoStringOrUndefined(entry.time)
|
|
324
|
+
if (timestamp === undefined) {
|
|
325
|
+
warnSkippedVenueRow(providerKey, 'funding', 'time', entry.time, 'timestamp')
|
|
326
|
+
return null
|
|
327
|
+
}
|
|
319
328
|
return {
|
|
320
329
|
id: `funding:${entry.delta.coin}:${timestamp}`,
|
|
321
330
|
provider: providerKey,
|
|
@@ -334,7 +343,8 @@ export const mapFundingActivity = (
|
|
|
334
343
|
* parties, so only fills whose `liquidatedUser` is the queried address count.
|
|
335
344
|
* A fill whose hash a ledger liquidation row already carries is the same
|
|
336
345
|
* event and is skipped. The size sign follows the closed position: a sell
|
|
337
|
-
* fill closes a long. Groups whose market does not resolve are
|
|
346
|
+
* fill closes a long. Groups whose market or time does not resolve are
|
|
347
|
+
* dropped; an invalid fill size or price leaves the derived field absent.
|
|
338
348
|
* @public
|
|
339
349
|
*/
|
|
340
350
|
export const mapLiquidationFills = (
|
|
@@ -363,26 +373,38 @@ export const mapLiquidationFills = (
|
|
|
363
373
|
if (market === undefined) {
|
|
364
374
|
return []
|
|
365
375
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
376
|
+
const size = group.reduce<string | undefined>(
|
|
377
|
+
(sum, fill) =>
|
|
378
|
+
sum === undefined ? undefined : safeAddDecimalString(sum, fill.sz),
|
|
379
|
+
'0'
|
|
380
|
+
)
|
|
381
|
+
const notional = group.reduce<string | undefined>((sum, fill) => {
|
|
382
|
+
const fillNotional = safeMultiplyDecimalString(fill.px, fill.sz)
|
|
383
|
+
return sum === undefined || fillNotional === undefined
|
|
384
|
+
? undefined
|
|
385
|
+
: safeAddDecimalString(sum, fillNotional)
|
|
386
|
+
}, '0')
|
|
387
|
+
const time = Math.max(...group.map((fill) => fill.time))
|
|
388
|
+
const timestamp = rowTimestampToIsoStringOrUndefined(time)
|
|
389
|
+
if (timestamp === undefined) {
|
|
390
|
+
warnSkippedVenueRow(providerKey, 'liquidation', 'time', time, 'timestamp')
|
|
391
|
+
return []
|
|
373
392
|
}
|
|
393
|
+
const closedSize =
|
|
394
|
+
size === undefined || first.side === 'A'
|
|
395
|
+
? size
|
|
396
|
+
: safeSubtractDecimalString('0', size)
|
|
374
397
|
return [
|
|
375
398
|
{
|
|
376
399
|
id: `liquidation:${oid}`,
|
|
377
400
|
provider: providerKey,
|
|
378
|
-
timestamp
|
|
401
|
+
timestamp,
|
|
379
402
|
type: ActivityType.LIQUIDATION,
|
|
380
|
-
|
|
403
|
+
...(notional === undefined
|
|
404
|
+
? {}
|
|
405
|
+
: { liquidatedNotionalPosition: notional }),
|
|
381
406
|
liquidatedPositions: [
|
|
382
|
-
{
|
|
383
|
-
market,
|
|
384
|
-
size: (first.side === 'A' ? size : size.neg()).toFixed(),
|
|
385
|
-
},
|
|
407
|
+
{ market, ...(closedSize === undefined ? {} : { size: closedSize }) },
|
|
386
408
|
],
|
|
387
409
|
} satisfies LiquidationActivity,
|
|
388
410
|
]
|
package/src/utils/mapFill.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
classifyFillFromPosition,
|
|
3
3
|
ExplorerChainId,
|
|
4
4
|
explorerTxUrl,
|
|
5
|
+
warnSkippedVenueRow,
|
|
5
6
|
} from '@lifi/perps-sdk'
|
|
6
7
|
import type { Fill, MarketDisplay } from '@lifi/perps-types'
|
|
7
8
|
import {
|
|
@@ -10,20 +11,32 @@ import {
|
|
|
10
11
|
OrderSide,
|
|
11
12
|
OrderType,
|
|
12
13
|
} from '@lifi/perps-types'
|
|
13
|
-
import { SPOT_MARKET_ID } from '../constants.js'
|
|
14
|
+
import { PROVIDER_KEY, SPOT_MARKET_ID } from '../constants.js'
|
|
14
15
|
import type { HlUserFill } from '../types/index.js'
|
|
16
|
+
import { rowTimestampToIsoStringOrUndefined } from './rowTimestamp.js'
|
|
15
17
|
|
|
16
18
|
/** Re-export the shared fill-position classifier used by Hyperliquid mappings. @public */
|
|
17
19
|
export { classifyFillFromPosition }
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Spot-ness comes from the resolved market's category, not the coin string —
|
|
21
|
-
* HL's canonical spot pair 0 is addressed as `PURR/USDC`, not `@0`.
|
|
23
|
+
* HL's canonical spot pair 0 is addressed as `PURR/USDC`, not `@0`. A fill with
|
|
24
|
+
* an invalid time gives `undefined`.
|
|
22
25
|
* @public
|
|
23
26
|
*/
|
|
24
|
-
export const mapFill = (
|
|
27
|
+
export const mapFill = (
|
|
28
|
+
fill: HlUserFill,
|
|
29
|
+
market: MarketDisplay
|
|
30
|
+
): Fill | undefined => {
|
|
31
|
+
const size = fill.sz
|
|
32
|
+
const createdAt = rowTimestampToIsoStringOrUndefined(fill.time)
|
|
33
|
+
if (createdAt === undefined) {
|
|
34
|
+
warnSkippedVenueRow(PROVIDER_KEY, 'fill', 'time', fill.time, 'timestamp')
|
|
35
|
+
return undefined
|
|
36
|
+
}
|
|
25
37
|
// HL charges the builder portion in the same token as the total fee.
|
|
26
38
|
const feeAsset = fill.feeToken ?? market.quoteAsset.displaySymbol
|
|
39
|
+
const side = fill.side === 'B' ? OrderSide.BUY : OrderSide.SELL
|
|
27
40
|
|
|
28
41
|
return {
|
|
29
42
|
...(market.categoryId === SPOT_MARKET_ID
|
|
@@ -33,16 +46,16 @@ export const mapFill = (fill: HlUserFill, market: MarketDisplay): Fill => {
|
|
|
33
46
|
orderId: String(fill.oid),
|
|
34
47
|
clientOrderId: fill.cloid,
|
|
35
48
|
market,
|
|
36
|
-
side
|
|
49
|
+
side,
|
|
37
50
|
// HL fills don't carry the originating order type. A maker fill (crossed:
|
|
38
51
|
// false) can only come from a resting order, so it's necessarily a limit;
|
|
39
52
|
// a taker fill (crossed: true) may be a market OR an aggressive limit order,
|
|
40
53
|
// which the payload can't distinguish, so the type is left undefined.
|
|
41
54
|
type: fill.crossed ? undefined : OrderType.LIMIT,
|
|
42
|
-
size
|
|
55
|
+
size,
|
|
43
56
|
price: fill.px,
|
|
44
57
|
liquidity: fill.crossed ? LiquidityRole.TAKER : LiquidityRole.MAKER,
|
|
45
|
-
filledSize:
|
|
58
|
+
filledSize: size,
|
|
46
59
|
fee: {
|
|
47
60
|
amount: fill.fee,
|
|
48
61
|
asset: feeAsset,
|
|
@@ -55,10 +68,10 @@ export const mapFill = (fill: HlUserFill, market: MarketDisplay): Fill => {
|
|
|
55
68
|
explorerLink: explorerTxUrl(ExplorerChainId.HYPERLIQUID, fill.hash),
|
|
56
69
|
classification:
|
|
57
70
|
market.categoryId === SPOT_MARKET_ID
|
|
58
|
-
?
|
|
71
|
+
? side === OrderSide.BUY
|
|
59
72
|
? FillClassification.SPOT_BUY
|
|
60
73
|
: FillClassification.SPOT_SELL
|
|
61
|
-
: classifyFillFromPosition(fill.startPosition,
|
|
62
|
-
createdAt
|
|
74
|
+
: classifyFillFromPosition(fill.startPosition, side, size),
|
|
75
|
+
createdAt,
|
|
63
76
|
}
|
|
64
77
|
}
|