@lifi/perps-sdk-provider-hyperliquid 8.0.0 → 10.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.
Files changed (85) hide show
  1. package/dist/cjs/services/getActivity.d.ts.map +1 -1
  2. package/dist/cjs/services/getActivity.js +17 -6
  3. package/dist/cjs/services/getActivity.js.map +1 -1
  4. package/dist/cjs/services/getFills.d.ts.map +1 -1
  5. package/dist/cjs/services/getFills.js +4 -1
  6. package/dist/cjs/services/getFills.js.map +1 -1
  7. package/dist/cjs/types/fill.d.ts +1 -0
  8. package/dist/cjs/types/fill.d.ts.map +1 -1
  9. package/dist/cjs/types/ledger.d.ts +24 -1
  10. package/dist/cjs/types/ledger.d.ts.map +1 -1
  11. package/dist/cjs/types/ledger.js +8 -1
  12. package/dist/cjs/types/ledger.js.map +1 -1
  13. package/dist/cjs/utils/index.d.ts +1 -1
  14. package/dist/cjs/utils/index.d.ts.map +1 -1
  15. package/dist/cjs/utils/index.js.map +1 -1
  16. package/dist/cjs/utils/mapActivity.d.ts +2 -2
  17. package/dist/cjs/utils/mapActivity.d.ts.map +1 -1
  18. package/dist/cjs/utils/mapActivity.js +76 -50
  19. package/dist/cjs/utils/mapActivity.js.map +1 -1
  20. package/dist/cjs/utils/mapFill.d.ts.map +1 -1
  21. package/dist/cjs/utils/mapFill.js +4 -1
  22. package/dist/cjs/utils/mapFill.js.map +1 -1
  23. package/dist/cjs/utils/mapOrder.d.ts +4 -3
  24. package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
  25. package/dist/cjs/utils/mapOrder.js +4 -3
  26. package/dist/cjs/utils/mapOrder.js.map +1 -1
  27. package/dist/cjs/websocket/HyperliquidWsProvider.d.ts +1 -1
  28. package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
  29. package/dist/cjs/websocket/HyperliquidWsProvider.js +2 -26
  30. package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
  31. package/dist/esm/services/getActivity.d.ts.map +1 -1
  32. package/dist/esm/services/getActivity.js +22 -6
  33. package/dist/esm/services/getActivity.js.map +1 -1
  34. package/dist/esm/services/getFills.d.ts.map +1 -1
  35. package/dist/esm/services/getFills.js +7 -1
  36. package/dist/esm/services/getFills.js.map +1 -1
  37. package/dist/esm/types/fill.d.ts +5 -0
  38. package/dist/esm/types/fill.d.ts.map +1 -1
  39. package/dist/esm/types/ledger.d.ts +65 -1
  40. package/dist/esm/types/ledger.d.ts.map +1 -1
  41. package/dist/esm/types/ledger.js +22 -0
  42. package/dist/esm/types/ledger.js.map +1 -1
  43. package/dist/esm/utils/index.d.ts +1 -1
  44. package/dist/esm/utils/index.d.ts.map +1 -1
  45. package/dist/esm/utils/index.js.map +1 -1
  46. package/dist/esm/utils/mapActivity.d.ts +12 -7
  47. package/dist/esm/utils/mapActivity.d.ts.map +1 -1
  48. package/dist/esm/utils/mapActivity.js +106 -59
  49. package/dist/esm/utils/mapActivity.js.map +1 -1
  50. package/dist/esm/utils/mapFill.d.ts.map +1 -1
  51. package/dist/esm/utils/mapFill.js +4 -1
  52. package/dist/esm/utils/mapFill.js.map +1 -1
  53. package/dist/esm/utils/mapOrder.d.ts +10 -3
  54. package/dist/esm/utils/mapOrder.d.ts.map +1 -1
  55. package/dist/esm/utils/mapOrder.js +4 -3
  56. package/dist/esm/utils/mapOrder.js.map +1 -1
  57. package/dist/esm/websocket/HyperliquidWsProvider.d.ts +1 -1
  58. package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
  59. package/dist/esm/websocket/HyperliquidWsProvider.js +3 -27
  60. package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
  61. package/dist/types/services/getActivity.d.ts.map +1 -1
  62. package/dist/types/services/getFills.d.ts.map +1 -1
  63. package/dist/types/types/fill.d.ts +5 -0
  64. package/dist/types/types/fill.d.ts.map +1 -1
  65. package/dist/types/types/ledger.d.ts +65 -1
  66. package/dist/types/types/ledger.d.ts.map +1 -1
  67. package/dist/types/utils/index.d.ts +1 -1
  68. package/dist/types/utils/index.d.ts.map +1 -1
  69. package/dist/types/utils/mapActivity.d.ts +12 -7
  70. package/dist/types/utils/mapActivity.d.ts.map +1 -1
  71. package/dist/types/utils/mapFill.d.ts.map +1 -1
  72. package/dist/types/utils/mapOrder.d.ts +10 -3
  73. package/dist/types/utils/mapOrder.d.ts.map +1 -1
  74. package/dist/types/websocket/HyperliquidWsProvider.d.ts +1 -1
  75. package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
  76. package/package.json +3 -3
  77. package/src/services/getActivity.ts +35 -10
  78. package/src/services/getFills.ts +8 -2
  79. package/src/types/fill.ts +5 -0
  80. package/src/types/ledger.ts +84 -0
  81. package/src/utils/index.ts +1 -0
  82. package/src/utils/mapActivity.ts +122 -69
  83. package/src/utils/mapFill.ts +4 -1
  84. package/src/utils/mapOrder.ts +15 -8
  85. package/src/websocket/HyperliquidWsProvider.ts +14 -39
@@ -50,6 +50,51 @@ export type HlSendAssetDelta = {
50
50
  feeToken: string
51
51
  }
52
52
 
53
+ /**
54
+ * Hyperliquid `deposit` ledger delta. Perp-collateral deposits are always
55
+ * USDC-denominated, which is why the amount arrives in a field named `usdc`.
56
+ * @public
57
+ */
58
+ export type HlDepositDelta = {
59
+ type: 'deposit'
60
+ usdc: string
61
+ }
62
+
63
+ /**
64
+ * Hyperliquid `withdraw` ledger delta. `fee` is denominated in the withdrawn
65
+ * asset (USDC) and is absent when the venue charges none.
66
+ * @public
67
+ */
68
+ export type HlWithdrawDelta = {
69
+ type: 'withdraw'
70
+ usdc: string
71
+ fee?: string
72
+ }
73
+
74
+ /**
75
+ * One position closed by a Hyperliquid liquidation. `coin` is the venue market
76
+ * key and `szi` the signed position size.
77
+ * @public
78
+ */
79
+ export type HlLiquidatedPosition = {
80
+ coin: string
81
+ szi: string
82
+ }
83
+
84
+ /**
85
+ * Hyperliquid `liquidation` ledger delta. A cross-margin cascade reports every
86
+ * closed position in `liquidatedPositions`, so the venue itself carries the
87
+ * grouping and no timestamp heuristic is needed.
88
+ * @public
89
+ */
90
+ export type HlLiquidationDelta = {
91
+ type: 'liquidation'
92
+ liquidatedNtlPos?: string
93
+ accountValue?: string
94
+ leverageType: string
95
+ liquidatedPositions?: HlLiquidatedPosition[]
96
+ }
97
+
53
98
  /**
54
99
  * Union of known Hyperliquid non-funding ledger deltas plus an open fallback
55
100
  * for endpoint variants the provider does not map.
@@ -58,6 +103,9 @@ export type HlSendAssetDelta = {
58
103
  export type HlLedgerDelta =
59
104
  | HlSpotTransferDelta
60
105
  | HlSendAssetDelta
106
+ | HlDepositDelta
107
+ | HlWithdrawDelta
108
+ | HlLiquidationDelta
61
109
  | {
62
110
  type: string
63
111
  usdc?: string
@@ -85,6 +133,38 @@ export const isSendAssetDelta = (
85
133
  delta: HlLedgerDelta
86
134
  ): delta is HlSendAssetDelta => delta.type === 'send'
87
135
 
136
+ // `usdc` is declared only on the union's catch-all arm, so reading it off the
137
+ // union needs a widening read before the discriminant has narrowed the type.
138
+ const hasUsdcAmount = (delta: HlLedgerDelta): boolean =>
139
+ typeof (delta as { usdc?: unknown }).usdc === 'string'
140
+
141
+ /**
142
+ * Type guard for `HlDepositDelta`. The amount is part of the guard: a deposit
143
+ * row without one identifies no movement, and reporting it as a zero amount
144
+ * would read as a real zero-value deposit.
145
+ * @public
146
+ */
147
+ export const isDepositDelta = (delta: HlLedgerDelta): delta is HlDepositDelta =>
148
+ delta.type === 'deposit' && hasUsdcAmount(delta)
149
+
150
+ /**
151
+ * Type guard for `HlWithdrawDelta`. Same amount-bearing requirement as
152
+ * `isDepositDelta`.
153
+ * @public
154
+ */
155
+ export const isWithdrawDelta = (
156
+ delta: HlLedgerDelta
157
+ ): delta is HlWithdrawDelta => delta.type === 'withdraw' && hasUsdcAmount(delta)
158
+
159
+ /**
160
+ * Type guard for `HlLiquidationDelta`. Same catch-all-arm caveat as
161
+ * `isSpotTransferDelta`.
162
+ * @public
163
+ */
164
+ export const isLiquidationDelta = (
165
+ delta: HlLedgerDelta
166
+ ): delta is HlLiquidationDelta => delta.type === 'liquidation'
167
+
88
168
  /**
89
169
  * One timestamped non-funding ledger update. `time` is milliseconds since
90
170
  * epoch and `hash` is the upstream transaction identifier.
@@ -108,6 +188,10 @@ export type HlUserNonFundingLedgerUpdates = HlLedgerUpdate[]
108
188
  export type HlFundingDelta = {
109
189
  type: 'funding'
110
190
  coin: string
191
+ /**
192
+ * Signed, in USDC. Positive means the account received funding; negative
193
+ * means the account paid it. Mapped straight onto `FundingActivity.amount`.
194
+ */
111
195
  usdc: string
112
196
  szi: string
113
197
  fundingRate: string
@@ -23,6 +23,7 @@ export { classifyFillFromPosition, mapFill } from './mapFill.js'
23
23
  export { mapMarket } from './mapMarket.js'
24
24
  export { mapMarketContext } from './mapMarketContext.js'
25
25
  export {
26
+ type HlOrderLike,
26
27
  isTriggerOrder,
27
28
  isTriggerType,
28
29
  mapOpenOrder,
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  ActivityItem,
3
3
  DepositActivity,
4
+ Fee,
4
5
  FundingActivity,
5
6
  LiquidationActivity,
6
7
  MarketDisplay,
@@ -9,22 +10,55 @@ import type {
9
10
  } from '@lifi/perps-types'
10
11
  import { ActivityType } from '@lifi/perps-types'
11
12
  import type { HlFundingUpdate, HlLedgerUpdate } from '../types/index.js'
12
- import { isSendAssetDelta, isSpotTransferDelta } from '../types/index.js'
13
+ import {
14
+ isDepositDelta,
15
+ isLiquidationDelta,
16
+ isSendAssetDelta,
17
+ isSpotTransferDelta,
18
+ isWithdrawDelta,
19
+ } from '../types/index.js'
20
+
21
+ /**
22
+ * Hyperliquid settles every perp deposit and withdrawal in USDC, and charges
23
+ * the `spotTransfer` fee in USDC too — that delta carries no `feeToken`.
24
+ */
25
+ const HL_COLLATERAL_SYMBOL = 'USDC'
26
+
27
+ /**
28
+ * Hyperliquid's native token. A `nativeTokenFee` names no token on the wire,
29
+ * so the symbol comes from the venue rather than from the delta.
30
+ */
31
+ const HL_NATIVE_TOKEN_SYMBOL = 'HYPE'
32
+
33
+ /**
34
+ * Display symbol for a ledger delta's wire token (`"USDC"`, `"PURR:0x..."`).
35
+ * The colon separates the name from the token id, so the symbol is the part
36
+ * BEFORE it — the opposite half to a market coin's `dex:COIN`, which is why
37
+ * `coinAsset` cannot be reused here.
38
+ */
39
+ const ledgerTokenSymbol = (token: string): string => {
40
+ const separator = token.indexOf(':')
41
+ return separator === -1 ? token : token.slice(0, separator)
42
+ }
13
43
 
14
44
  /**
15
45
  * Map a Hyperliquid non-funding ledger entry to an ActivityItem.
16
46
  *
17
47
  * Direction for `spotTransfer` and `sendAsset` is derived from
18
48
  * `queriedAddress` matching the delta's `user` (OUT) or `destination` (IN).
19
- * Returns null for unsupported delta types and for same-user `sendAsset`
20
- * dex moves (where `user === destination === queriedAddress`).
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.
21
55
  * @public
22
56
  */
23
57
  export const mapLedgerEntry = (
24
58
  entry: HlLedgerUpdate,
25
59
  providerKey: string,
26
60
  queriedAddress: string,
27
- resolveMarket: (coin: string) => MarketDisplay
61
+ resolveMarket: (coin: string) => MarketDisplay | undefined
28
62
  ): ActivityItem | null => {
29
63
  const { delta } = entry
30
64
  const base = {
@@ -40,6 +74,13 @@ export const mapLedgerEntry = (
40
74
  const queried = queriedAddress.toLowerCase()
41
75
  const sender = delta.user.toLowerCase()
42
76
  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
+ if (sender === recipient && sender === queried) {
81
+ return null
82
+ }
83
+
43
84
  const direction: 'IN' | 'OUT' = queried === sender ? 'OUT' : 'IN'
44
85
  const counterpartyAddress = direction === 'OUT' ? recipient : sender
45
86
  const meta: Record<string, unknown> = {
@@ -48,22 +89,27 @@ export const mapLedgerEntry = (
48
89
  if (delta.usdcValue !== undefined) {
49
90
  meta.usdcValue = delta.usdcValue
50
91
  }
92
+ if (delta.nonce !== undefined) {
93
+ meta.nonce = delta.nonce
94
+ }
95
+ const fees: Fee[] = []
51
96
  if (delta.fee !== undefined) {
52
- meta.fee = delta.fee
97
+ fees.push({ amount: delta.fee, asset: HL_COLLATERAL_SYMBOL })
53
98
  }
54
99
  if (delta.nativeTokenFee !== undefined) {
55
- meta.nativeTokenFee = delta.nativeTokenFee
56
- }
57
- if (delta.nonce !== undefined) {
58
- meta.nonce = delta.nonce
100
+ fees.push({
101
+ amount: delta.nativeTokenFee,
102
+ asset: HL_NATIVE_TOKEN_SYMBOL,
103
+ })
59
104
  }
60
105
  return {
61
106
  ...base,
62
107
  type: ActivityType.TRANSFER,
63
108
  direction,
64
109
  counterpartyAddress,
65
- asset: delta.token,
110
+ asset: ledgerTokenSymbol(delta.token),
66
111
  amount: delta.amount,
112
+ ...(fees.length === 0 ? {} : { fees }),
67
113
  meta,
68
114
  explorerLink: entry.hash
69
115
  ? `https://app.hyperliquid.xyz/explorer/tx/${entry.hash}`
@@ -91,9 +137,6 @@ export const mapLedgerEntry = (
91
137
  sourceDex: delta.sourceDex,
92
138
  destinationDex: delta.destinationDex,
93
139
  usdcValue: delta.usdcValue,
94
- fee: delta.fee,
95
- nativeTokenFee: delta.nativeTokenFee,
96
- feeToken: delta.feeToken,
97
140
  nonce: delta.nonce,
98
141
  }
99
142
  return {
@@ -101,8 +144,12 @@ export const mapLedgerEntry = (
101
144
  type: ActivityType.TRANSFER,
102
145
  direction,
103
146
  counterpartyAddress,
104
- asset: delta.token,
147
+ asset: ledgerTokenSymbol(delta.token),
105
148
  amount: delta.amount,
149
+ fees: [
150
+ { amount: delta.fee, asset: ledgerTokenSymbol(delta.feeToken) },
151
+ { amount: delta.nativeTokenFee, asset: HL_NATIVE_TOKEN_SYMBOL },
152
+ ],
106
153
  meta,
107
154
  explorerLink: entry.hash
108
155
  ? `https://app.hyperliquid.xyz/explorer/tx/${entry.hash}`
@@ -110,65 +157,67 @@ export const mapLedgerEntry = (
110
157
  } satisfies TransferActivity
111
158
  }
112
159
 
113
- switch (delta.type) {
114
- case 'deposit':
115
- return {
116
- ...base,
117
- type: ActivityType.DEPOSIT,
118
- amount: delta.usdc ?? '0',
119
- explorerLink: entry.hash
120
- ? `https://scan.li.fi/tx/${entry.hash}`
121
- : undefined,
122
- } satisfies DepositActivity
123
-
124
- case 'withdraw':
125
- return {
126
- ...base,
127
- type: ActivityType.WITHDRAWAL,
128
- amount: delta.usdc ?? '0',
129
- fee: (delta as { fee?: string }).fee ?? '0',
130
- explorerLink: entry.hash
131
- ? `https://scan.li.fi/tx/${entry.hash}`
132
- : undefined,
133
- } satisfies WithdrawalActivity
160
+ if (isDepositDelta(delta)) {
161
+ return {
162
+ ...base,
163
+ type: ActivityType.DEPOSIT,
164
+ asset: HL_COLLATERAL_SYMBOL,
165
+ amount: delta.usdc,
166
+ explorerLink: entry.hash
167
+ ? `https://scan.li.fi/tx/${entry.hash}`
168
+ : undefined,
169
+ } satisfies DepositActivity
170
+ }
134
171
 
135
- case 'liquidation': {
136
- const d = delta as unknown as {
137
- type: string
138
- liquidatedNtlPos: string
139
- accountValue: string
140
- leverageType: string
141
- liquidatedPositions?: { coin: string; szi: string }[]
142
- }
143
- const liquidatedPositions = (d.liquidatedPositions ?? []).map((p) => ({
144
- market: resolveMarket(p.coin),
145
- size: p.szi,
146
- }))
147
- // Liquidation rows must point to at least one market. Drop entries with
148
- // missing/empty positions so downstream consumers can rely on that
149
- // invariant and avoid rendering a market-less liquidation card.
150
- if (liquidatedPositions.length === 0) {
151
- return null
152
- }
153
- return {
154
- ...base,
155
- type: ActivityType.LIQUIDATION,
156
- liquidatedNotionalPosition: d.liquidatedNtlPos,
157
- accountValue: d.accountValue,
158
- leverageType: d.leverageType,
159
- liquidatedPositions,
160
- } satisfies LiquidationActivity
161
- }
172
+ if (isWithdrawDelta(delta)) {
173
+ return {
174
+ ...base,
175
+ type: ActivityType.WITHDRAWAL,
176
+ asset: HL_COLLATERAL_SYMBOL,
177
+ amount: delta.usdc,
178
+ ...(delta.fee === undefined
179
+ ? {}
180
+ : { fee: { amount: delta.fee, asset: HL_COLLATERAL_SYMBOL } }),
181
+ explorerLink: entry.hash
182
+ ? `https://scan.li.fi/tx/${entry.hash}`
183
+ : undefined,
184
+ } satisfies WithdrawalActivity
185
+ }
162
186
 
163
- default:
187
+ if (isLiquidationDelta(delta)) {
188
+ const resolvedPositions = (delta.liquidatedPositions ?? []).flatMap((p) => {
189
+ const market = resolveMarket(p.coin)
190
+ return market === undefined ? [] : [{ market, size: p.szi }]
191
+ })
192
+ // Liquidation rows must point to at least one market. Drop entries with
193
+ // missing/empty positions so downstream consumers can rely on that
194
+ // invariant and avoid rendering a market-less liquidation card.
195
+ const [firstPosition, ...restPositions] = resolvedPositions
196
+ if (firstPosition === undefined) {
164
197
  return null
198
+ }
199
+ return {
200
+ ...base,
201
+ type: ActivityType.LIQUIDATION,
202
+ ...(delta.liquidatedNtlPos === undefined
203
+ ? {}
204
+ : { liquidatedNotionalPosition: delta.liquidatedNtlPos }),
205
+ ...(delta.accountValue === undefined
206
+ ? {}
207
+ : { accountValue: delta.accountValue }),
208
+ leverageType: delta.leverageType,
209
+ liquidatedPositions: [firstPosition, ...restPositions],
210
+ } satisfies LiquidationActivity
165
211
  }
212
+
213
+ return null
166
214
  }
167
215
 
168
216
  /**
169
- * Map a Hyperliquid funding ledger update to a normalized funding activity.
170
- * `amount`, `positionSize`, and `fundingRate` retain the upstream decimal
171
- * strings; `resolveMarket` supplies the provider-agnostic market metadata.
217
+ * Map a Hyperliquid funding ledger update to a normalized funding activity, or
218
+ * `null` when `resolveMarket` cannot identify the row's coin. `amount`,
219
+ * `positionSize`, and `fundingRate` retain the upstream decimal strings;
220
+ * `resolveMarket` supplies the provider-agnostic market metadata.
172
221
  *
173
222
  * `userFunding` entries all carry the zero hash, so a deterministic
174
223
  * `funding:<coin>:<ISO time>` id is synthesized — funding accrues at most
@@ -178,15 +227,19 @@ export const mapLedgerEntry = (
178
227
  export const mapFundingActivity = (
179
228
  entry: HlFundingUpdate,
180
229
  providerKey: string,
181
- resolveMarket: (coin: string) => MarketDisplay
182
- ): FundingActivity => {
230
+ resolveMarket: (coin: string) => MarketDisplay | undefined
231
+ ): FundingActivity | null => {
232
+ const market = resolveMarket(entry.delta.coin)
233
+ if (market === undefined) {
234
+ return null
235
+ }
183
236
  const timestamp = new Date(entry.time).toISOString()
184
237
  return {
185
238
  id: `funding:${entry.delta.coin}:${timestamp}`,
186
239
  provider: providerKey,
187
240
  timestamp,
188
241
  type: ActivityType.FUNDING,
189
- market: resolveMarket(entry.delta.coin),
242
+ market,
190
243
  amount: entry.delta.usdc,
191
244
  positionSize: entry.delta.szi,
192
245
  fundingRate: entry.delta.fundingRate,
@@ -40,7 +40,10 @@ export const mapFill = (fill: HlUserFill, market: MarketDisplay): Fill => ({
40
40
  status: FillStatus.FILLED,
41
41
  liquidity: fill.crossed ? LiquidityRole.TAKER : LiquidityRole.MAKER,
42
42
  filledSize: fill.sz,
43
- fee: fill.fee,
43
+ fee: {
44
+ amount: fill.fee,
45
+ asset: fill.feeToken ?? market.quoteAsset.displaySymbol,
46
+ },
44
47
  startPosition: fill.startPosition,
45
48
  explorerLink: explorerTxUrl(ExplorerChainId.HYPERLIQUID, fill.hash),
46
49
  classification:
@@ -12,6 +12,14 @@ import {
12
12
  } from '@lifi/perps-types'
13
13
  import type { HlFrontendOpenOrder, HlOrderDetail } from '../types/index.js'
14
14
 
15
+ /**
16
+ * An order as seen by the REST `frontendOpenOrders` payload, or the smaller
17
+ * shape nested in the `orderUpdates` WebSocket frame. `mapOpenOrder` and
18
+ * `mapTriggerOrder` accept either so both code paths share one mapper.
19
+ * @public
20
+ */
21
+ export type HlOrderLike = HlFrontendOpenOrder | HlOrderDetail['order']
22
+
15
23
  /**
16
24
  * Map a Hyperliquid orderType string to the OrderType enum.
17
25
  *
@@ -61,9 +69,7 @@ export const isTriggerType = (type: OrderType): boolean =>
61
69
  * 5. `orderType` — final fall-back via `isTriggerType`.
62
70
  * @public
63
71
  */
64
- export const isTriggerOrder = (
65
- o: HlFrontendOpenOrder | HlOrderDetail['order']
66
- ): boolean => {
72
+ export const isTriggerOrder = (o: HlOrderLike): boolean => {
67
73
  if ('isTrigger' in o && o.isTrigger === true) {
68
74
  return true
69
75
  }
@@ -89,20 +95,21 @@ export const isTriggerOrder = (
89
95
  * @public
90
96
  */
91
97
  export const mapOpenOrder = (
92
- o: HlFrontendOpenOrder,
98
+ o: HlOrderLike,
93
99
  market: MarketDisplay
94
100
  ): OpenOrder => ({
95
101
  orderId: String(o.oid),
96
102
  market,
97
103
  side: o.side === 'B' ? OrderSide.BUY : OrderSide.SELL,
98
104
  type: mapOrderType(o.orderType),
99
- size: o.sz,
105
+ originalSize: o.origSz,
106
+ remainingSize: o.sz,
100
107
  price: o.limitPx,
101
108
  filledSize: o.origSz
102
109
  ? (parseFloat(o.origSz) - parseFloat(o.sz)).toString()
103
110
  : '0',
104
111
  reduceOnly: o.reduceOnly ?? false,
105
- label: o.isTrigger ? o.triggerCondition : undefined,
112
+ label: 'isTrigger' in o && o.isTrigger ? o.triggerCondition : undefined,
106
113
  createdAt: new Date(o.timestamp).toISOString(),
107
114
  })
108
115
 
@@ -111,7 +118,7 @@ export const mapOpenOrder = (
111
118
  * @public
112
119
  */
113
120
  export const mapTriggerOrder = (
114
- o: HlFrontendOpenOrder,
121
+ o: HlOrderLike,
115
122
  market: MarketDisplay
116
123
  ): TriggerOrder => {
117
124
  const type = mapOrderType(o.orderType)
@@ -122,7 +129,7 @@ export const mapTriggerOrder = (
122
129
  market,
123
130
  type,
124
131
  size: o.sz,
125
- triggerPrice: o.triggerPx,
132
+ triggerPrice: o.triggerPx ?? '0',
126
133
  ...(isLimit ? { limitPrice: o.limitPx } : {}),
127
134
  label: o.triggerCondition,
128
135
  createdAt: new Date(o.timestamp).toISOString(),
@@ -16,18 +16,16 @@ import {
16
16
  type WsStatusListener,
17
17
  wsLog,
18
18
  } from '@lifi/perps-sdk'
19
- import {
20
- type AccountResponse,
21
- type Balance,
22
- type MarketContext,
23
- type OpenOrder,
24
- type OrderbookLevel,
25
- type OrderbookResponse,
26
- OrderSide,
27
- OrderType,
28
- type Position,
29
- type Subscription,
30
- type TriggerOrder,
19
+ import type {
20
+ AccountResponse,
21
+ Balance,
22
+ MarketContext,
23
+ OpenOrder,
24
+ OrderbookLevel,
25
+ OrderbookResponse,
26
+ Position,
27
+ Subscription,
28
+ TriggerOrder,
31
29
  } from '@lifi/perps-types'
32
30
  import Big from 'big.js'
33
31
  import { isAddress } from 'viem'
@@ -69,9 +67,10 @@ import {
69
67
  isTriggerOrder,
70
68
  mapFill,
71
69
  mapMarketContext,
70
+ mapOpenOrder,
72
71
  mapOrderStatus,
73
- mapOrderType,
74
72
  mapPosition,
73
+ mapTriggerOrder,
75
74
  partitionSpotBalances,
76
75
  priceStepToAggregation,
77
76
  spotAssetFromToken,
@@ -993,39 +992,15 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
993
992
  terminated.push(orderId)
994
993
  continue
995
994
  }
996
- const type = mapOrderType(o.orderType)
997
995
  // Unknown market id (absent from the synced snapshot); skip just this item.
998
996
  const market = this.registry?.get(o.coin)
999
997
  if (!market) {
1000
998
  continue
1001
999
  }
1002
- const createdAt = new Date(o.timestamp).toISOString()
1003
1000
  if (isTriggerOrder(o)) {
1004
- const isLimit =
1005
- type === OrderType.TAKE_PROFIT_LIMIT || type === OrderType.STOP_LIMIT
1006
- triggerOrders.push({
1007
- orderId,
1008
- market,
1009
- type,
1010
- size: o.sz,
1011
- triggerPrice: o.triggerPx ?? '0',
1012
- ...(isLimit ? { limitPrice: o.limitPx } : {}),
1013
- label: o.triggerCondition,
1014
- createdAt,
1015
- })
1001
+ triggerOrders.push(mapTriggerOrder(o, market))
1016
1002
  } else {
1017
- const filled = parseFloat(o.origSz) - parseFloat(o.sz)
1018
- openOrders.push({
1019
- orderId,
1020
- market,
1021
- side: o.side === 'B' ? OrderSide.BUY : OrderSide.SELL,
1022
- type,
1023
- size: o.sz,
1024
- price: o.limitPx,
1025
- filledSize: filled.toString(),
1026
- reduceOnly: o.reduceOnly ?? false,
1027
- createdAt,
1028
- })
1003
+ openOrders.push(mapOpenOrder(o, market))
1029
1004
  }
1030
1005
  }
1031
1006
  this.emit(key, {