@lifi/perps-sdk-provider-hyperliquid 13.0.0 → 14.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/README.md +115 -0
- package/dist/cjs/HyperliquidProvider.d.ts.map +1 -1
- package/dist/cjs/HyperliquidProvider.js +1 -2
- package/dist/cjs/HyperliquidProvider.js.map +1 -1
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +2 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/services/getAccount.d.ts.map +1 -1
- package/dist/cjs/services/getAccount.js +16 -9
- package/dist/cjs/services/getAccount.js.map +1 -1
- package/dist/cjs/services/getActivity.d.ts.map +1 -1
- package/dist/cjs/services/getActivity.js +40 -7
- package/dist/cjs/services/getActivity.js.map +1 -1
- package/dist/cjs/services/getFills.d.ts.map +1 -1
- package/dist/cjs/services/getFills.js +3 -0
- package/dist/cjs/services/getFills.js.map +1 -1
- package/dist/cjs/services/getOrder.d.ts.map +1 -1
- package/dist/cjs/services/getOrder.js +14 -3
- package/dist/cjs/services/getOrder.js.map +1 -1
- package/dist/cjs/services/getOrders.d.ts +2 -7
- package/dist/cjs/services/getOrders.d.ts.map +1 -1
- package/dist/cjs/services/getOrders.js +94 -31
- package/dist/cjs/services/getOrders.js.map +1 -1
- 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/explorer.d.ts +10 -0
- package/dist/cjs/types/explorer.d.ts.map +1 -0
- package/dist/cjs/types/explorer.js +17 -0
- package/dist/cjs/types/explorer.js.map +1 -0
- package/dist/cjs/types/fill.d.ts +6 -0
- package/dist/cjs/types/fill.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +1 -0
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/ledger.d.ts +24 -1
- package/dist/cjs/types/ledger.d.ts.map +1 -1
- package/dist/cjs/types/ledger.js +5 -1
- package/dist/cjs/types/ledger.js.map +1 -1
- package/dist/cjs/types/order.d.ts +24 -0
- package/dist/cjs/types/order.d.ts.map +1 -1
- package/dist/cjs/types/ws.d.ts +14 -0
- package/dist/cjs/types/ws.d.ts.map +1 -1
- package/dist/cjs/utils/assetId.d.ts +1 -0
- package/dist/cjs/utils/assetId.d.ts.map +1 -1
- package/dist/cjs/utils/assetId.js +6 -1
- package/dist/cjs/utils/assetId.js.map +1 -1
- package/dist/cjs/utils/explorer.d.ts +7 -0
- package/dist/cjs/utils/explorer.d.ts.map +1 -0
- package/dist/cjs/utils/explorer.js +49 -0
- package/dist/cjs/utils/explorer.js.map +1 -0
- package/dist/cjs/utils/index.d.ts +4 -3
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +7 -6
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/infoClient.d.ts +1 -0
- package/dist/cjs/utils/infoClient.d.ts.map +1 -1
- package/dist/cjs/utils/infoClient.js +16 -10
- package/dist/cjs/utils/infoClient.js.map +1 -1
- package/dist/cjs/utils/mapActivity.d.ts +5 -3
- package/dist/cjs/utils/mapActivity.d.ts.map +1 -1
- package/dist/cjs/utils/mapActivity.js +116 -48
- package/dist/cjs/utils/mapActivity.js.map +1 -1
- package/dist/cjs/utils/mapFill.d.ts.map +1 -1
- package/dist/cjs/utils/mapFill.js +0 -1
- package/dist/cjs/utils/mapFill.js.map +1 -1
- package/dist/cjs/utils/mapOrder.d.ts +4 -9
- package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
- package/dist/cjs/utils/mapOrder.js +149 -135
- package/dist/cjs/utils/mapOrder.js.map +1 -1
- package/dist/cjs/utils/spotBalance.d.ts.map +1 -1
- package/dist/cjs/utils/spotBalance.js +10 -6
- package/dist/cjs/utils/spotBalance.js.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts +3 -0
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +100 -29
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/HyperliquidProvider.d.ts.map +1 -1
- package/dist/esm/HyperliquidProvider.js +1 -2
- package/dist/esm/HyperliquidProvider.js.map +1 -1
- package/dist/esm/constants.d.ts +8 -0
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +8 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/index.d.ts +1 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/services/getAccount.d.ts.map +1 -1
- package/dist/esm/services/getAccount.js +14 -10
- package/dist/esm/services/getAccount.js.map +1 -1
- package/dist/esm/services/getActivity.d.ts +2 -2
- package/dist/esm/services/getActivity.d.ts.map +1 -1
- package/dist/esm/services/getActivity.js +44 -9
- package/dist/esm/services/getActivity.js.map +1 -1
- package/dist/esm/services/getFills.d.ts.map +1 -1
- package/dist/esm/services/getFills.js +4 -1
- package/dist/esm/services/getFills.js.map +1 -1
- package/dist/esm/services/getOrder.d.ts.map +1 -1
- package/dist/esm/services/getOrder.js +15 -4
- package/dist/esm/services/getOrder.js.map +1 -1
- package/dist/esm/services/getOrders.d.ts +4 -24
- package/dist/esm/services/getOrders.d.ts.map +1 -1
- package/dist/esm/services/getOrders.js +115 -42
- package/dist/esm/services/getOrders.js.map +1 -1
- 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/explorer.d.ts +27 -0
- package/dist/esm/types/explorer.d.ts.map +1 -0
- package/dist/esm/types/explorer.js +20 -0
- package/dist/esm/types/explorer.js.map +1 -0
- package/dist/esm/types/fill.d.ts +11 -0
- package/dist/esm/types/fill.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/ledger.d.ts +28 -1
- package/dist/esm/types/ledger.d.ts.map +1 -1
- package/dist/esm/types/ledger.js +4 -0
- package/dist/esm/types/ledger.js.map +1 -1
- package/dist/esm/types/order.d.ts +26 -0
- package/dist/esm/types/order.d.ts.map +1 -1
- package/dist/esm/types/ws.d.ts +15 -0
- package/dist/esm/types/ws.d.ts.map +1 -1
- package/dist/esm/utils/assetId.d.ts +9 -0
- package/dist/esm/utils/assetId.d.ts.map +1 -1
- package/dist/esm/utils/assetId.js +13 -0
- package/dist/esm/utils/assetId.js.map +1 -1
- package/dist/esm/utils/explorer.d.ts +31 -0
- package/dist/esm/utils/explorer.d.ts.map +1 -0
- package/dist/esm/utils/explorer.js +68 -0
- package/dist/esm/utils/explorer.js.map +1 -0
- package/dist/esm/utils/index.d.ts +4 -3
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +4 -3
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/infoClient.d.ts +14 -3
- package/dist/esm/utils/infoClient.d.ts.map +1 -1
- package/dist/esm/utils/infoClient.js +29 -14
- package/dist/esm/utils/infoClient.js.map +1 -1
- package/dist/esm/utils/mapActivity.d.ts +16 -13
- package/dist/esm/utils/mapActivity.d.ts.map +1 -1
- package/dist/esm/utils/mapActivity.js +128 -72
- package/dist/esm/utils/mapActivity.js.map +1 -1
- package/dist/esm/utils/mapFill.d.ts.map +1 -1
- package/dist/esm/utils/mapFill.js +1 -2
- package/dist/esm/utils/mapFill.js.map +1 -1
- package/dist/esm/utils/mapOrder.d.ts +8 -73
- package/dist/esm/utils/mapOrder.d.ts.map +1 -1
- package/dist/esm/utils/mapOrder.js +148 -187
- package/dist/esm/utils/mapOrder.js.map +1 -1
- package/dist/esm/utils/spotBalance.d.ts +1 -1
- package/dist/esm/utils/spotBalance.d.ts.map +1 -1
- package/dist/esm/utils/spotBalance.js +12 -7
- package/dist/esm/utils/spotBalance.js.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts +5 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +105 -34
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/types/HyperliquidProvider.d.ts.map +1 -1
- package/dist/types/constants.d.ts +8 -0
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/services/getAccount.d.ts.map +1 -1
- package/dist/types/services/getActivity.d.ts +2 -2
- package/dist/types/services/getActivity.d.ts.map +1 -1
- package/dist/types/services/getFills.d.ts.map +1 -1
- package/dist/types/services/getOrder.d.ts.map +1 -1
- package/dist/types/services/getOrders.d.ts +4 -24
- package/dist/types/services/getOrders.d.ts.map +1 -1
- package/dist/types/services/getPositions.d.ts.map +1 -1
- package/dist/types/types/explorer.d.ts +27 -0
- package/dist/types/types/explorer.d.ts.map +1 -0
- package/dist/types/types/fill.d.ts +11 -0
- package/dist/types/types/fill.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/types/ledger.d.ts +28 -1
- package/dist/types/types/ledger.d.ts.map +1 -1
- package/dist/types/types/order.d.ts +26 -0
- package/dist/types/types/order.d.ts.map +1 -1
- package/dist/types/types/ws.d.ts +15 -0
- package/dist/types/types/ws.d.ts.map +1 -1
- package/dist/types/utils/assetId.d.ts +9 -0
- package/dist/types/utils/assetId.d.ts.map +1 -1
- package/dist/types/utils/explorer.d.ts +31 -0
- package/dist/types/utils/explorer.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +4 -3
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/infoClient.d.ts +14 -3
- package/dist/types/utils/infoClient.d.ts.map +1 -1
- package/dist/types/utils/mapActivity.d.ts +16 -13
- package/dist/types/utils/mapActivity.d.ts.map +1 -1
- package/dist/types/utils/mapFill.d.ts.map +1 -1
- package/dist/types/utils/mapOrder.d.ts +8 -73
- package/dist/types/utils/mapOrder.d.ts.map +1 -1
- package/dist/types/utils/spotBalance.d.ts +1 -1
- package/dist/types/utils/spotBalance.d.ts.map +1 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts +5 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/HyperliquidProvider.ts +1 -13
- package/src/constants.ts +10 -0
- package/src/index.ts +1 -2
- package/src/services/getAccount.ts +22 -14
- package/src/services/getActivity.ts +81 -6
- package/src/services/getFills.ts +4 -1
- package/src/services/getOrder.ts +29 -5
- package/src/services/getOrders.ts +185 -70
- package/src/services/getPositions.ts +4 -1
- package/src/types/explorer.ts +39 -0
- package/src/types/fill.ts +12 -0
- package/src/types/index.ts +1 -0
- package/src/types/ledger.ts +37 -0
- package/src/types/order.ts +25 -0
- package/src/types/ws.ts +16 -0
- package/src/utils/assetId.ts +16 -0
- package/src/utils/explorer.ts +93 -0
- package/src/utils/index.ts +16 -7
- package/src/utils/infoClient.ts +46 -24
- package/src/utils/mapActivity.ts +163 -75
- package/src/utils/mapFill.ts +0 -2
- package/src/utils/mapOrder.ts +163 -212
- package/src/utils/spotBalance.ts +12 -7
- package/src/websocket/HyperliquidWsProvider.ts +127 -40
- package/dist/cjs/services/getRunningTwaps.d.ts +0 -10
- package/dist/cjs/services/getRunningTwaps.d.ts.map +0 -1
- package/dist/cjs/services/getRunningTwaps.js +0 -46
- package/dist/cjs/services/getRunningTwaps.js.map +0 -1
- package/dist/esm/services/getRunningTwaps.d.ts +0 -12
- package/dist/esm/services/getRunningTwaps.d.ts.map +0 -1
- package/dist/esm/services/getRunningTwaps.js +0 -40
- package/dist/esm/services/getRunningTwaps.js.map +0 -1
- package/dist/types/services/getRunningTwaps.d.ts +0 -12
- package/dist/types/services/getRunningTwaps.d.ts.map +0 -1
- package/src/services/getRunningTwaps.ts +0 -90
package/src/utils/infoClient.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
errorCodeFromStatus,
|
|
3
3
|
fetchWithRetry,
|
|
4
|
+
isAbortError,
|
|
4
5
|
PerpsError,
|
|
5
6
|
type PerpsSDKClient,
|
|
6
7
|
type ResolvedRetryPolicy,
|
|
@@ -57,7 +58,7 @@ export const HYPERLIQUID_RETRY_DEFAULTS: ResolvedRetryPolicy = {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
|
-
* Transport options for a direct Hyperliquid
|
|
61
|
+
* Transport options for a direct Hyperliquid REST request. `policy`
|
|
61
62
|
* controls retries, `signal` cancels the request, and `fetchImpl` overrides
|
|
62
63
|
* the runtime's global `fetch` implementation.
|
|
63
64
|
* @public
|
|
@@ -87,7 +88,7 @@ export const hlInfoOptions = (
|
|
|
87
88
|
})
|
|
88
89
|
|
|
89
90
|
/**
|
|
90
|
-
* POST to
|
|
91
|
+
* POST a JSON body to a Hyperliquid REST surface and return the parsed body.
|
|
91
92
|
*
|
|
92
93
|
* Direct-to-venue: no proxy, no AJV validation, no cache. The caller's type
|
|
93
94
|
* parameter is trusted; consumers should treat the response shape as
|
|
@@ -97,20 +98,24 @@ export const hlInfoOptions = (
|
|
|
97
98
|
* Non-2xx responses raise a {@link PerpsError} tagged with the Hyperliquid
|
|
98
99
|
* provider key, carrying the code the status resolves to: `RateLimitExceeded`
|
|
99
100
|
* for a 429, `Unauthorized` for a 401, `AgentUnauthorized` for a 403, and
|
|
100
|
-
* `ThirdPartyError` for every other status.
|
|
101
|
-
*
|
|
101
|
+
* `ThirdPartyError` for every other status. A transport failure and a 2xx body
|
|
102
|
+
* that is not JSON both raise `ServerError`, so every failure but a caller
|
|
103
|
+
* abort reaches the caller as a `PerpsError`. An abort rejects untouched.
|
|
104
|
+
*
|
|
105
|
+
* @param label - Names the surface in the error message, e.g. `info request`.
|
|
106
|
+
* @internal
|
|
102
107
|
*/
|
|
103
|
-
export async function
|
|
104
|
-
|
|
108
|
+
export async function hlPostJson<T>(
|
|
109
|
+
url: string,
|
|
110
|
+
label: string,
|
|
105
111
|
body: Record<string, unknown>,
|
|
106
112
|
options?: InfoRequestOptions
|
|
107
113
|
): Promise<T> {
|
|
108
114
|
const policy = options?.policy ?? HYPERLIQUID_RETRY_DEFAULTS
|
|
109
115
|
|
|
110
|
-
let response: Response
|
|
111
116
|
try {
|
|
112
|
-
response = await fetchWithRetry(
|
|
113
|
-
|
|
117
|
+
const response = await fetchWithRetry(
|
|
118
|
+
url,
|
|
114
119
|
{
|
|
115
120
|
method: 'POST',
|
|
116
121
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -122,27 +127,44 @@ export async function infoRequest<T>(
|
|
|
122
127
|
signal: options?.signal,
|
|
123
128
|
}
|
|
124
129
|
)
|
|
130
|
+
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
const err = new PerpsError(
|
|
133
|
+
errorCodeFromStatus(
|
|
134
|
+
response.status,
|
|
135
|
+
PerpsErrorCode.ThirdPartyError,
|
|
136
|
+
HYPERLIQUID_STATUS_ERROR_CODES
|
|
137
|
+
),
|
|
138
|
+
`Hyperliquid ${label} failed: ${response.status}`
|
|
139
|
+
)
|
|
140
|
+
err.tool = PROVIDER_KEY
|
|
141
|
+
throw err
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return (await response.json()) as T
|
|
125
145
|
} catch (error) {
|
|
146
|
+
if (error instanceof PerpsError || isAbortError(error)) {
|
|
147
|
+
throw error
|
|
148
|
+
}
|
|
126
149
|
const err = new PerpsError(
|
|
127
150
|
PerpsErrorCode.ServerError,
|
|
128
|
-
error instanceof Error ? error.message :
|
|
129
|
-
)
|
|
130
|
-
err.tool = PROVIDER_KEY
|
|
131
|
-
throw err
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (!response.ok) {
|
|
135
|
-
const err = new PerpsError(
|
|
136
|
-
errorCodeFromStatus(
|
|
137
|
-
response.status,
|
|
138
|
-
PerpsErrorCode.ThirdPartyError,
|
|
139
|
-
HYPERLIQUID_STATUS_ERROR_CODES
|
|
140
|
-
),
|
|
141
|
-
`Hyperliquid info request failed: ${response.status}`
|
|
151
|
+
error instanceof Error ? error.message : `Hyperliquid ${label} failed`
|
|
142
152
|
)
|
|
143
153
|
err.tool = PROVIDER_KEY
|
|
144
154
|
throw err
|
|
145
155
|
}
|
|
156
|
+
}
|
|
146
157
|
|
|
147
|
-
|
|
158
|
+
/**
|
|
159
|
+
* POST to the Hyperliquid `/info` endpoint and return the parsed JSON body.
|
|
160
|
+
* See {@link hlPostJson} for the transport and error contract.
|
|
161
|
+
*
|
|
162
|
+
* @public
|
|
163
|
+
*/
|
|
164
|
+
export function infoRequest<T>(
|
|
165
|
+
apiUrl: string,
|
|
166
|
+
body: Record<string, unknown>,
|
|
167
|
+
options?: InfoRequestOptions
|
|
168
|
+
): Promise<T> {
|
|
169
|
+
return hlPostJson<T>(`${apiUrl}/info`, 'info request', body, options)
|
|
148
170
|
}
|
package/src/utils/mapActivity.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { type AssetRegistry, PerpsError } from '@lifi/perps-sdk'
|
|
1
2
|
import type {
|
|
2
3
|
ActivityItem,
|
|
4
|
+
Asset,
|
|
3
5
|
DepositActivity,
|
|
4
6
|
Fee,
|
|
5
7
|
FundingActivity,
|
|
@@ -8,13 +10,20 @@ import type {
|
|
|
8
10
|
TransferActivity,
|
|
9
11
|
WithdrawalActivity,
|
|
10
12
|
} from '@lifi/perps-types'
|
|
11
|
-
import { ActivityType } from '@lifi/perps-types'
|
|
12
|
-
import
|
|
13
|
+
import { ActivityType, PerpsErrorCode } from '@lifi/perps-types'
|
|
14
|
+
import Big from 'big.js'
|
|
15
|
+
import type {
|
|
16
|
+
HlFundingUpdate,
|
|
17
|
+
HlLedgerUpdate,
|
|
18
|
+
HlUserFill,
|
|
19
|
+
} from '../types/index.js'
|
|
13
20
|
import {
|
|
21
|
+
isCollateralTransferDelta,
|
|
14
22
|
isDepositDelta,
|
|
15
23
|
isLiquidationDelta,
|
|
16
24
|
isSendAssetDelta,
|
|
17
25
|
isSpotTransferDelta,
|
|
26
|
+
isVaultTransferDelta,
|
|
18
27
|
isWithdrawDelta,
|
|
19
28
|
} from '../types/index.js'
|
|
20
29
|
|
|
@@ -30,34 +39,39 @@ const HL_COLLATERAL_SYMBOL = 'USDC'
|
|
|
30
39
|
*/
|
|
31
40
|
const HL_NATIVE_TOKEN_SYMBOL = 'HYPE'
|
|
32
41
|
|
|
42
|
+
// Hyperliquid reserves spot token index 0 for USDC.
|
|
43
|
+
const HL_COLLATERAL_ASSET_ID = '0'
|
|
44
|
+
|
|
33
45
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* `coinAsset` cannot be reused here.
|
|
46
|
+
* A ledger row moves a spot asset — a perp contract cannot be sent, received
|
|
47
|
+
* or withdrawn — so the delta's token symbol resolves inside the spot asset
|
|
48
|
+
* registry. The HIP-1 ticker auction keeps those symbols unique.
|
|
38
49
|
*/
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
50
|
+
const resolveLedgerAsset = (symbol: string, registry: AssetRegistry): Asset => {
|
|
51
|
+
const asset = registry.assets.find(
|
|
52
|
+
(candidate) => candidate.displaySymbol === symbol
|
|
53
|
+
)
|
|
54
|
+
if (asset === undefined) {
|
|
55
|
+
const error = new PerpsError(
|
|
56
|
+
PerpsErrorCode.ValidationError,
|
|
57
|
+
`[hyperliquid] stale or mis-keyed asset registry: unknown spot symbol '${symbol}'`
|
|
58
|
+
)
|
|
59
|
+
error.tool = 'hyperliquid'
|
|
60
|
+
throw error
|
|
61
|
+
}
|
|
62
|
+
return asset
|
|
42
63
|
}
|
|
43
64
|
|
|
44
65
|
/**
|
|
45
|
-
* Map
|
|
46
|
-
*
|
|
47
|
-
* Direction for `spotTransfer` and `sendAsset` is derived from
|
|
48
|
-
* `queriedAddress` matching the delta's `user` (OUT) or `destination` (IN).
|
|
49
|
-
* Returns null for unsupported delta types and for same-account moves, where
|
|
50
|
-
* `user === destination === queriedAddress`.
|
|
51
|
-
*
|
|
52
|
-
* @param resolveMarket - Market identity for a venue coin, or `undefined` when
|
|
53
|
-
* the backend market list does not hold it. A liquidated position the resolver
|
|
54
|
-
* cannot identify is dropped.
|
|
66
|
+
* Map supported ledger entries; exclude same-account moves and unsupported types.
|
|
67
|
+
* Missing assets throw; unresolved liquidation markets omit only those positions.
|
|
55
68
|
* @public
|
|
56
69
|
*/
|
|
57
70
|
export const mapLedgerEntry = (
|
|
58
71
|
entry: HlLedgerUpdate,
|
|
59
72
|
providerKey: string,
|
|
60
73
|
queriedAddress: string,
|
|
74
|
+
assetRegistry: AssetRegistry,
|
|
61
75
|
resolveMarket: (coin: string) => MarketDisplay | undefined
|
|
62
76
|
): ActivityItem | null => {
|
|
63
77
|
const { delta } = entry
|
|
@@ -67,48 +81,57 @@ export const mapLedgerEntry = (
|
|
|
67
81
|
timestamp: new Date(entry.time).toISOString(),
|
|
68
82
|
}
|
|
69
83
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
if (
|
|
85
|
+
isSpotTransferDelta(delta) ||
|
|
86
|
+
isSendAssetDelta(delta) ||
|
|
87
|
+
isCollateralTransferDelta(delta)
|
|
88
|
+
) {
|
|
74
89
|
const queried = queriedAddress.toLowerCase()
|
|
75
90
|
const sender = delta.user.toLowerCase()
|
|
76
91
|
const recipient = delta.destination.toLowerCase()
|
|
77
|
-
|
|
78
|
-
// A transfer reports a movement between two accounts. A row whose sender
|
|
79
|
-
// and recipient are the queried account moves nothing between accounts.
|
|
80
92
|
if (sender === recipient && sender === queried) {
|
|
81
93
|
return null
|
|
82
94
|
}
|
|
83
|
-
|
|
84
95
|
const direction: 'IN' | 'OUT' = queried === sender ? 'OUT' : 'IN'
|
|
85
|
-
const counterpartyAddress = direction === 'OUT' ? recipient : sender
|
|
86
|
-
const meta: Record<string, unknown> = {
|
|
87
|
-
transferType: 'spotTransfer',
|
|
88
|
-
}
|
|
89
|
-
if (delta.usdcValue !== undefined) {
|
|
90
|
-
meta.usdcValue = delta.usdcValue
|
|
91
|
-
}
|
|
92
|
-
if (delta.nonce !== undefined) {
|
|
93
|
-
meta.nonce = delta.nonce
|
|
94
|
-
}
|
|
95
96
|
const fees: Fee[] = []
|
|
96
97
|
if (delta.fee !== undefined) {
|
|
97
|
-
fees.push({ amount: delta.fee, asset: HL_COLLATERAL_SYMBOL })
|
|
98
|
-
}
|
|
99
|
-
if (delta.nativeTokenFee !== undefined) {
|
|
100
98
|
fees.push({
|
|
101
|
-
amount: delta.
|
|
102
|
-
asset:
|
|
99
|
+
amount: delta.fee,
|
|
100
|
+
asset: isSendAssetDelta(delta)
|
|
101
|
+
? delta.feeToken.split(':')[0]
|
|
102
|
+
: HL_COLLATERAL_SYMBOL,
|
|
103
103
|
})
|
|
104
104
|
}
|
|
105
|
+
if (
|
|
106
|
+
!isCollateralTransferDelta(delta) &&
|
|
107
|
+
delta.nativeTokenFee !== undefined
|
|
108
|
+
) {
|
|
109
|
+
fees.push({ amount: delta.nativeTokenFee, asset: HL_NATIVE_TOKEN_SYMBOL })
|
|
110
|
+
}
|
|
111
|
+
const meta: Record<string, unknown> = {
|
|
112
|
+
transferType: isSendAssetDelta(delta) ? 'sendAsset' : delta.type,
|
|
113
|
+
}
|
|
114
|
+
if (!isCollateralTransferDelta(delta)) {
|
|
115
|
+
if (delta.usdcValue !== undefined) {
|
|
116
|
+
meta.usdcValue = delta.usdcValue
|
|
117
|
+
}
|
|
118
|
+
if (delta.nonce !== undefined) {
|
|
119
|
+
meta.nonce = delta.nonce
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (isSendAssetDelta(delta)) {
|
|
123
|
+
meta.sourceDex = delta.sourceDex
|
|
124
|
+
meta.destinationDex = delta.destinationDex
|
|
125
|
+
}
|
|
105
126
|
return {
|
|
106
127
|
...base,
|
|
107
128
|
type: ActivityType.TRANSFER,
|
|
108
129
|
direction,
|
|
109
|
-
counterpartyAddress,
|
|
110
|
-
asset:
|
|
111
|
-
|
|
130
|
+
counterpartyAddress: direction === 'OUT' ? recipient : sender,
|
|
131
|
+
asset: isCollateralTransferDelta(delta)
|
|
132
|
+
? assetRegistry.require(HL_COLLATERAL_ASSET_ID)
|
|
133
|
+
: resolveLedgerAsset(delta.token, assetRegistry),
|
|
134
|
+
amount: isCollateralTransferDelta(delta) ? delta.usdc : delta.amount,
|
|
112
135
|
...(fees.length === 0 ? {} : { fees }),
|
|
113
136
|
meta,
|
|
114
137
|
explorerLink: entry.hash
|
|
@@ -117,40 +140,44 @@ export const mapLedgerEntry = (
|
|
|
117
140
|
} satisfies TransferActivity
|
|
118
141
|
}
|
|
119
142
|
|
|
120
|
-
|
|
121
|
-
// (modelled as TRANSFER) and same-user dex moves (returned as null —
|
|
122
|
-
// overloading TRANSFER for those would lie about direction). Pre-switch
|
|
123
|
-
// narrowing for the same reason as spotTransfer.
|
|
124
|
-
if (isSendAssetDelta(delta)) {
|
|
143
|
+
if (isVaultTransferDelta(delta)) {
|
|
125
144
|
const queried = queriedAddress.toLowerCase()
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
const vault = delta.vault.toLowerCase()
|
|
146
|
+
if (delta.type === 'vaultDeposit' && queried === vault) {
|
|
147
|
+
throw new PerpsError(
|
|
148
|
+
PerpsErrorCode.ValidationError,
|
|
149
|
+
'Hyperliquid vaultDeposit identifies no depositor for the vault account'
|
|
150
|
+
)
|
|
131
151
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
destinationDex: delta.destinationDex,
|
|
139
|
-
usdcValue: delta.usdcValue,
|
|
140
|
-
nonce: delta.nonce,
|
|
152
|
+
if (
|
|
153
|
+
delta.type === 'vaultWithdraw' &&
|
|
154
|
+
delta.user.toLowerCase() === vault &&
|
|
155
|
+
queried === vault
|
|
156
|
+
) {
|
|
157
|
+
return null
|
|
141
158
|
}
|
|
142
159
|
return {
|
|
143
160
|
...base,
|
|
144
161
|
type: ActivityType.TRANSFER,
|
|
145
|
-
direction
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
direction:
|
|
163
|
+
delta.type === 'vaultDeposit' || queried === vault ? 'OUT' : 'IN',
|
|
164
|
+
counterpartyAddress:
|
|
165
|
+
delta.type === 'vaultWithdraw' && queried === vault
|
|
166
|
+
? delta.user.toLowerCase()
|
|
167
|
+
: vault,
|
|
168
|
+
asset: assetRegistry.require(HL_COLLATERAL_ASSET_ID),
|
|
169
|
+
amount:
|
|
170
|
+
delta.type === 'vaultDeposit' ? delta.usdc : delta.netWithdrawnUsd,
|
|
171
|
+
meta:
|
|
172
|
+
delta.type === 'vaultDeposit'
|
|
173
|
+
? { transferType: delta.type }
|
|
174
|
+
: {
|
|
175
|
+
transferType: delta.type,
|
|
176
|
+
requestedUsd: delta.requestedUsd,
|
|
177
|
+
commission: delta.commission,
|
|
178
|
+
closingCost: delta.closingCost,
|
|
179
|
+
basis: delta.basis,
|
|
180
|
+
},
|
|
154
181
|
explorerLink: entry.hash
|
|
155
182
|
? `https://app.hyperliquid.xyz/explorer/tx/${entry.hash}`
|
|
156
183
|
: undefined,
|
|
@@ -163,7 +190,7 @@ export const mapLedgerEntry = (
|
|
|
163
190
|
return {
|
|
164
191
|
...base,
|
|
165
192
|
type: ActivityType.DEPOSIT,
|
|
166
|
-
asset:
|
|
193
|
+
asset: assetRegistry.require(HL_COLLATERAL_ASSET_ID),
|
|
167
194
|
amount: delta.usdc,
|
|
168
195
|
explorerLink: entry.hash
|
|
169
196
|
? `https://scan.li.fi/tx/${entry.hash}`
|
|
@@ -175,7 +202,7 @@ export const mapLedgerEntry = (
|
|
|
175
202
|
return {
|
|
176
203
|
...base,
|
|
177
204
|
type: ActivityType.WITHDRAWAL,
|
|
178
|
-
asset:
|
|
205
|
+
asset: assetRegistry.require(HL_COLLATERAL_ASSET_ID),
|
|
179
206
|
amount: delta.usdc,
|
|
180
207
|
...(delta.fee === undefined
|
|
181
208
|
? {}
|
|
@@ -247,3 +274,64 @@ export const mapFundingActivity = (
|
|
|
247
274
|
fundingRate: entry.delta.fundingRate,
|
|
248
275
|
}
|
|
249
276
|
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Build one liquidation activity per liquidation order from the fills of the
|
|
280
|
+
* liquidated account. Hyperliquid attaches `liquidation` to the fills of both
|
|
281
|
+
* parties, so only fills whose `liquidatedUser` is the queried address count.
|
|
282
|
+
* A fill whose hash a ledger liquidation row already carries is the same
|
|
283
|
+
* event and is skipped. The size sign follows the closed position: a sell
|
|
284
|
+
* fill closes a long. Groups whose market does not resolve are dropped.
|
|
285
|
+
* @public
|
|
286
|
+
*/
|
|
287
|
+
export const mapLiquidationFills = (
|
|
288
|
+
fills: HlUserFill[],
|
|
289
|
+
providerKey: string,
|
|
290
|
+
queriedAddress: string,
|
|
291
|
+
resolveMarket: (coin: string) => MarketDisplay | undefined,
|
|
292
|
+
ledgerHashes: ReadonlySet<string>
|
|
293
|
+
): LiquidationActivity[] => {
|
|
294
|
+
const queried = queriedAddress.toLowerCase()
|
|
295
|
+
const byOrder = new Map<number, HlUserFill[]>()
|
|
296
|
+
for (const fill of fills) {
|
|
297
|
+
if (
|
|
298
|
+
fill.liquidation?.liquidatedUser.toLowerCase() !== queried ||
|
|
299
|
+
(fill.hash !== undefined && ledgerHashes.has(fill.hash))
|
|
300
|
+
) {
|
|
301
|
+
continue
|
|
302
|
+
}
|
|
303
|
+
const group = byOrder.get(fill.oid) ?? []
|
|
304
|
+
group.push(fill)
|
|
305
|
+
byOrder.set(fill.oid, group)
|
|
306
|
+
}
|
|
307
|
+
return [...byOrder.entries()].flatMap(([oid, group]) => {
|
|
308
|
+
const [first] = group
|
|
309
|
+
const market = resolveMarket(first.coin)
|
|
310
|
+
if (market === undefined) {
|
|
311
|
+
return []
|
|
312
|
+
}
|
|
313
|
+
let size = new Big(0)
|
|
314
|
+
let notional = new Big(0)
|
|
315
|
+
let time = first.time
|
|
316
|
+
for (const fill of group) {
|
|
317
|
+
size = size.plus(fill.sz)
|
|
318
|
+
notional = notional.plus(new Big(fill.px).times(fill.sz))
|
|
319
|
+
time = Math.max(time, fill.time)
|
|
320
|
+
}
|
|
321
|
+
return [
|
|
322
|
+
{
|
|
323
|
+
id: `liquidation:${oid}`,
|
|
324
|
+
provider: providerKey,
|
|
325
|
+
timestamp: new Date(time).toISOString(),
|
|
326
|
+
type: ActivityType.LIQUIDATION,
|
|
327
|
+
liquidatedNotionalPosition: notional.toFixed(),
|
|
328
|
+
liquidatedPositions: [
|
|
329
|
+
{
|
|
330
|
+
market,
|
|
331
|
+
size: (first.side === 'A' ? size : size.neg()).toFixed(),
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
} satisfies LiquidationActivity,
|
|
335
|
+
]
|
|
336
|
+
})
|
|
337
|
+
}
|
package/src/utils/mapFill.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
import type { Fill, MarketDisplay } from '@lifi/perps-types'
|
|
7
7
|
import {
|
|
8
8
|
FillClassification,
|
|
9
|
-
FillStatus,
|
|
10
9
|
LiquidityRole,
|
|
11
10
|
OrderSide,
|
|
12
11
|
OrderType,
|
|
@@ -42,7 +41,6 @@ export const mapFill = (fill: HlUserFill, market: MarketDisplay): Fill => {
|
|
|
42
41
|
type: fill.crossed ? undefined : OrderType.LIMIT,
|
|
43
42
|
size: fill.sz,
|
|
44
43
|
price: fill.px,
|
|
45
|
-
status: FillStatus.FILLED,
|
|
46
44
|
liquidity: fill.crossed ? LiquidityRole.TAKER : LiquidityRole.MAKER,
|
|
47
45
|
filledSize: fill.sz,
|
|
48
46
|
fee: {
|