@lifi/perps-types 0.1.1-alpha.9 → 0.2.0-alpha.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 (206) hide show
  1. package/package.json +18 -4
  2. package/providers/lighter/package.json +5 -0
  3. package/src/_cjs/{market.js → action.js} +1 -1
  4. package/src/_cjs/action.js.map +1 -0
  5. package/src/_cjs/{trading.js → asset.js} +1 -1
  6. package/src/_cjs/asset.js.map +1 -0
  7. package/src/_cjs/enums.js +81 -15
  8. package/src/_cjs/enums.js.map +1 -1
  9. package/src/_cjs/index.js +3 -4
  10. package/src/_cjs/index.js.map +1 -1
  11. package/src/_cjs/providers/_shared/fillClassification.js +37 -0
  12. package/src/_cjs/providers/_shared/fillClassification.js.map +1 -0
  13. package/src/_cjs/providers/hyperliquid/assetId.js +11 -9
  14. package/src/_cjs/providers/hyperliquid/assetId.js.map +1 -1
  15. package/src/_cjs/providers/hyperliquid/mappers/_market.js +15 -0
  16. package/src/_cjs/providers/hyperliquid/mappers/_market.js.map +1 -0
  17. package/src/_cjs/providers/hyperliquid/mappers/activity.js +80 -8
  18. package/src/_cjs/providers/hyperliquid/mappers/activity.js.map +1 -1
  19. package/src/_cjs/providers/hyperliquid/mappers/{market.js → asset.js} +10 -9
  20. package/src/_cjs/providers/hyperliquid/mappers/asset.js.map +1 -0
  21. package/src/_cjs/providers/hyperliquid/mappers/fill.js +36 -0
  22. package/src/_cjs/providers/hyperliquid/mappers/fill.js.map +1 -0
  23. package/src/_cjs/providers/hyperliquid/mappers/index.js +9 -7
  24. package/src/_cjs/providers/hyperliquid/mappers/index.js.map +1 -1
  25. package/src/_cjs/providers/hyperliquid/mappers/order.js +86 -9
  26. package/src/_cjs/providers/hyperliquid/mappers/order.js.map +1 -1
  27. package/src/_cjs/providers/hyperliquid/mappers/position.js +8 -5
  28. package/src/_cjs/providers/hyperliquid/mappers/position.js.map +1 -1
  29. package/src/_cjs/providers/hyperliquid/mappers/shared.js +0 -10
  30. package/src/_cjs/providers/hyperliquid/mappers/shared.js.map +1 -1
  31. package/src/_cjs/providers/hyperliquid/types.js +18 -0
  32. package/src/_cjs/providers/hyperliquid/types.js.map +1 -1
  33. package/src/_cjs/{authorization.js → providers/lighter/apiTypes.js} +1 -1
  34. package/src/_cjs/providers/lighter/apiTypes.js.map +1 -0
  35. package/src/_cjs/providers/lighter/index.js +20 -0
  36. package/src/_cjs/providers/lighter/index.js.map +1 -0
  37. package/src/_cjs/providers/lighter/mappers/fill.js +34 -0
  38. package/src/_cjs/providers/lighter/mappers/fill.js.map +1 -0
  39. package/src/_cjs/providers/lighter/mappers/index.js +13 -0
  40. package/src/_cjs/providers/lighter/mappers/index.js.map +1 -0
  41. package/src/_cjs/providers/lighter/mappers/order.js +142 -0
  42. package/src/_cjs/providers/lighter/mappers/order.js.map +1 -0
  43. package/src/_cjs/providers/lighter/mappers/position.js +35 -0
  44. package/src/_cjs/providers/lighter/mappers/position.js.map +1 -0
  45. package/src/_cjs/providers/lighter/types.js +23 -0
  46. package/src/_cjs/providers/lighter/types.js.map +1 -0
  47. package/src/_cjs/{withdrawal.js → providers.js} +1 -1
  48. package/src/_cjs/providers.js.map +1 -0
  49. package/src/_esm/action.js +2 -0
  50. package/src/_esm/action.js.map +1 -0
  51. package/src/_esm/asset.js +2 -0
  52. package/src/_esm/asset.js.map +1 -0
  53. package/src/_esm/enums.js +90 -14
  54. package/src/_esm/enums.js.map +1 -1
  55. package/src/_esm/index.js +3 -4
  56. package/src/_esm/index.js.map +1 -1
  57. package/src/_esm/providers/_shared/fillClassification.js +43 -0
  58. package/src/_esm/providers/_shared/fillClassification.js.map +1 -0
  59. package/src/_esm/providers/hyperliquid/assetId.js +13 -11
  60. package/src/_esm/providers/hyperliquid/assetId.js.map +1 -1
  61. package/src/_esm/providers/hyperliquid/mappers/_market.js +22 -0
  62. package/src/_esm/providers/hyperliquid/mappers/_market.js.map +1 -0
  63. package/src/_esm/providers/hyperliquid/mappers/activity.js +92 -13
  64. package/src/_esm/providers/hyperliquid/mappers/activity.js.map +1 -1
  65. package/src/_esm/providers/hyperliquid/mappers/{market.js → asset.js} +8 -7
  66. package/src/_esm/providers/hyperliquid/mappers/asset.js.map +1 -0
  67. package/src/_esm/providers/hyperliquid/mappers/fill.js +32 -0
  68. package/src/_esm/providers/hyperliquid/mappers/fill.js.map +1 -0
  69. package/src/_esm/providers/hyperliquid/mappers/index.js +3 -4
  70. package/src/_esm/providers/hyperliquid/mappers/index.js.map +1 -1
  71. package/src/_esm/providers/hyperliquid/mappers/order.js +88 -8
  72. package/src/_esm/providers/hyperliquid/mappers/order.js.map +1 -1
  73. package/src/_esm/providers/hyperliquid/mappers/position.js +8 -5
  74. package/src/_esm/providers/hyperliquid/mappers/position.js.map +1 -1
  75. package/src/_esm/providers/hyperliquid/mappers/shared.js +1 -12
  76. package/src/_esm/providers/hyperliquid/mappers/shared.js.map +1 -1
  77. package/src/_esm/providers/hyperliquid/types.js +32 -2
  78. package/src/_esm/providers/hyperliquid/types.js.map +1 -1
  79. package/src/_esm/providers/lighter/apiTypes.js +5 -0
  80. package/src/_esm/providers/lighter/apiTypes.js.map +1 -0
  81. package/src/_esm/providers/lighter/index.js +4 -0
  82. package/src/_esm/providers/lighter/index.js.map +1 -0
  83. package/src/_esm/providers/lighter/mappers/fill.js +39 -0
  84. package/src/_esm/providers/lighter/mappers/fill.js.map +1 -0
  85. package/src/_esm/providers/lighter/mappers/index.js +4 -0
  86. package/src/_esm/providers/lighter/mappers/index.js.map +1 -0
  87. package/src/_esm/providers/lighter/mappers/order.js +162 -0
  88. package/src/_esm/providers/lighter/mappers/order.js.map +1 -0
  89. package/src/_esm/providers/lighter/mappers/position.js +38 -0
  90. package/src/_esm/providers/lighter/mappers/position.js.map +1 -0
  91. package/src/_esm/providers/lighter/types.js +26 -0
  92. package/src/_esm/providers/lighter/types.js.map +1 -0
  93. package/src/_esm/providers.js +2 -0
  94. package/src/_esm/providers.js.map +1 -0
  95. package/src/_types/account.d.ts +178 -23
  96. package/src/_types/account.d.ts.map +1 -1
  97. package/src/_types/action.d.ts +261 -0
  98. package/src/_types/action.d.ts.map +1 -0
  99. package/src/_types/{market.d.ts → asset.d.ts} +23 -34
  100. package/src/_types/asset.d.ts.map +1 -0
  101. package/src/_types/enums.d.ts +76 -6
  102. package/src/_types/enums.d.ts.map +1 -1
  103. package/src/_types/index.d.ts +3 -4
  104. package/src/_types/index.d.ts.map +1 -1
  105. package/src/_types/providers/_shared/fillClassification.d.ts +12 -0
  106. package/src/_types/providers/_shared/fillClassification.d.ts.map +1 -0
  107. package/src/_types/providers/hyperliquid/assetId.d.ts +8 -6
  108. package/src/_types/providers/hyperliquid/assetId.d.ts.map +1 -1
  109. package/src/_types/providers/hyperliquid/mappers/_market.d.ts +13 -0
  110. package/src/_types/providers/hyperliquid/mappers/_market.d.ts.map +1 -0
  111. package/src/_types/providers/hyperliquid/mappers/activity.d.ts +7 -7
  112. package/src/_types/providers/hyperliquid/mappers/activity.d.ts.map +1 -1
  113. package/src/_types/providers/hyperliquid/mappers/asset.d.ts +4 -0
  114. package/src/_types/providers/hyperliquid/mappers/asset.d.ts.map +1 -0
  115. package/src/_types/providers/hyperliquid/mappers/fill.d.ts +6 -0
  116. package/src/_types/providers/hyperliquid/mappers/fill.d.ts.map +1 -0
  117. package/src/_types/providers/hyperliquid/mappers/index.d.ts +3 -4
  118. package/src/_types/providers/hyperliquid/mappers/index.d.ts.map +1 -1
  119. package/src/_types/providers/hyperliquid/mappers/order.d.ts +15 -3
  120. package/src/_types/providers/hyperliquid/mappers/order.d.ts.map +1 -1
  121. package/src/_types/providers/hyperliquid/mappers/position.d.ts +1 -1
  122. package/src/_types/providers/hyperliquid/mappers/position.d.ts.map +1 -1
  123. package/src/_types/providers/hyperliquid/mappers/shared.d.ts +0 -6
  124. package/src/_types/providers/hyperliquid/mappers/shared.d.ts.map +1 -1
  125. package/src/_types/providers/hyperliquid/types.d.ts +90 -2
  126. package/src/_types/providers/hyperliquid/types.d.ts.map +1 -1
  127. package/src/_types/providers/lighter/apiTypes.d.ts +76 -0
  128. package/src/_types/providers/lighter/apiTypes.d.ts.map +1 -0
  129. package/src/_types/providers/lighter/index.d.ts +4 -0
  130. package/src/_types/providers/lighter/index.d.ts.map +1 -0
  131. package/src/_types/providers/lighter/mappers/fill.d.ts +9 -0
  132. package/src/_types/providers/lighter/mappers/fill.d.ts.map +1 -0
  133. package/src/_types/providers/lighter/mappers/index.d.ts +4 -0
  134. package/src/_types/providers/lighter/mappers/index.d.ts.map +1 -0
  135. package/src/_types/providers/lighter/mappers/order.d.ts +35 -0
  136. package/src/_types/providers/lighter/mappers/order.d.ts.map +1 -0
  137. package/src/_types/providers/lighter/mappers/position.d.ts +8 -0
  138. package/src/_types/providers/lighter/mappers/position.d.ts.map +1 -0
  139. package/src/_types/providers/lighter/types.d.ts +90 -0
  140. package/src/_types/providers/lighter/types.d.ts.map +1 -0
  141. package/src/_types/providers.d.ts +145 -0
  142. package/src/_types/providers.d.ts.map +1 -0
  143. package/src/_types/subscriptions.d.ts +23 -18
  144. package/src/_types/subscriptions.d.ts.map +1 -1
  145. package/src/_types/typedData.d.ts +13 -5
  146. package/src/_types/typedData.d.ts.map +1 -1
  147. package/src/account.ts +193 -22
  148. package/src/action.ts +324 -0
  149. package/src/asset.ts +88 -0
  150. package/src/enums.ts +85 -3
  151. package/src/index.ts +3 -4
  152. package/src/providers/_shared/fillClassification.ts +50 -0
  153. package/src/providers/hyperliquid/assetId.ts +18 -12
  154. package/src/providers/hyperliquid/mappers/_market.ts +21 -0
  155. package/src/providers/hyperliquid/mappers/activity.ts +98 -13
  156. package/src/providers/hyperliquid/mappers/{market.ts → asset.ts} +10 -12
  157. package/src/providers/hyperliquid/mappers/fill.ts +41 -0
  158. package/src/providers/hyperliquid/mappers/index.ts +9 -4
  159. package/src/providers/hyperliquid/mappers/order.ts +95 -14
  160. package/src/providers/hyperliquid/mappers/position.ts +8 -10
  161. package/src/providers/hyperliquid/mappers/shared.ts +0 -15
  162. package/src/providers/hyperliquid/types.ts +128 -4
  163. package/src/providers/lighter/apiTypes.ts +87 -0
  164. package/src/providers/lighter/index.ts +3 -0
  165. package/src/providers/lighter/mappers/fill.ts +57 -0
  166. package/src/providers/lighter/mappers/index.ts +8 -0
  167. package/src/providers/lighter/mappers/order.ts +184 -0
  168. package/src/providers/lighter/mappers/position.ts +46 -0
  169. package/src/providers/lighter/types.ts +111 -0
  170. package/src/providers.ts +153 -0
  171. package/src/subscriptions.ts +21 -20
  172. package/src/typedData.ts +15 -5
  173. package/src/_cjs/authorization.js.map +0 -1
  174. package/src/_cjs/market.js.map +0 -1
  175. package/src/_cjs/providers/hyperliquid/mappers/history.js +0 -22
  176. package/src/_cjs/providers/hyperliquid/mappers/history.js.map +0 -1
  177. package/src/_cjs/providers/hyperliquid/mappers/market.js.map +0 -1
  178. package/src/_cjs/trading.js.map +0 -1
  179. package/src/_cjs/withdrawal.js.map +0 -1
  180. package/src/_esm/authorization.js +0 -2
  181. package/src/_esm/authorization.js.map +0 -1
  182. package/src/_esm/market.js +0 -2
  183. package/src/_esm/market.js.map +0 -1
  184. package/src/_esm/providers/hyperliquid/mappers/history.js +0 -18
  185. package/src/_esm/providers/hyperliquid/mappers/history.js.map +0 -1
  186. package/src/_esm/providers/hyperliquid/mappers/market.js.map +0 -1
  187. package/src/_esm/trading.js +0 -2
  188. package/src/_esm/trading.js.map +0 -1
  189. package/src/_esm/withdrawal.js +0 -2
  190. package/src/_esm/withdrawal.js.map +0 -1
  191. package/src/_types/authorization.d.ts +0 -39
  192. package/src/_types/authorization.d.ts.map +0 -1
  193. package/src/_types/market.d.ts.map +0 -1
  194. package/src/_types/providers/hyperliquid/mappers/history.d.ts +0 -4
  195. package/src/_types/providers/hyperliquid/mappers/history.d.ts.map +0 -1
  196. package/src/_types/providers/hyperliquid/mappers/market.d.ts +0 -4
  197. package/src/_types/providers/hyperliquid/mappers/market.d.ts.map +0 -1
  198. package/src/_types/trading.d.ts +0 -80
  199. package/src/_types/trading.d.ts.map +0 -1
  200. package/src/_types/withdrawal.d.ts +0 -37
  201. package/src/_types/withdrawal.d.ts.map +0 -1
  202. package/src/authorization.ts +0 -46
  203. package/src/market.ts +0 -97
  204. package/src/providers/hyperliquid/mappers/history.ts +0 -25
  205. package/src/trading.ts +0 -97
  206. package/src/withdrawal.ts +0 -44
package/src/enums.ts CHANGED
@@ -5,6 +5,7 @@ export enum PerpsErrorCode {
5
5
  ValidationError = 2002,
6
6
  TimeoutError = 2003,
7
7
  ThirdPartyError = 2004,
8
+ SDKError = 2005,
8
9
 
9
10
  // Auth errors (2010-2019)
10
11
  SignatureInvalid = 2010,
@@ -17,6 +18,7 @@ export enum PerpsErrorCode {
17
18
  MarketNotFound = 2023,
18
19
  OrderNotFound = 2024,
19
20
  PositionNotFound = 2025,
21
+ AccountNotFound = 2026,
20
22
 
21
23
  // Nonce errors (2040-2049)
22
24
  InvalidNonce = 2040,
@@ -38,6 +40,11 @@ export enum OrderSide {
38
40
  export enum OrderType {
39
41
  MARKET = 'MARKET',
40
42
  LIMIT = 'LIMIT',
43
+ STOP_MARKET = 'STOP_MARKET',
44
+ STOP_LIMIT = 'STOP_LIMIT',
45
+ TAKE_PROFIT_MARKET = 'TAKE_PROFIT_MARKET',
46
+ TAKE_PROFIT_LIMIT = 'TAKE_PROFIT_LIMIT',
47
+ TRIGGER_ONLY = 'TRIGGER_ONLY',
41
48
  }
42
49
 
43
50
  export enum PositionSide {
@@ -68,18 +75,46 @@ export enum OrderStatus {
68
75
  TRIGGERED = 'TRIGGERED',
69
76
  }
70
77
 
71
- export enum HistoryItemStatus {
78
+ export enum FillStatus {
72
79
  FILLED = 'FILLED',
73
80
  PARTIALLY_FILLED = 'PARTIALLY_FILLED',
74
81
  CANCELLED = 'CANCELLED',
75
82
  REJECTED = 'REJECTED',
76
83
  }
77
84
 
78
- export enum OrderActionType {
79
- UPDATE_LEVERAGE = 'updateLeverage',
85
+ export enum LiquidityRole {
86
+ MAKER = 'maker',
87
+ TAKER = 'taker',
88
+ }
89
+
90
+ export enum ActionType {
91
+ APPROVE_AGENT = 'approveAgent',
92
+ APPROVE_BUILDER_FEE = 'approveBuilderFee',
93
+ /**
94
+ * Generic account-level operating mode (e.g. Hyperliquid abstraction
95
+ * variants, Lighter UTA / Simple). HL maps it to the appropriate
96
+ * EIP-712 typed-data builder internally.
97
+ */
98
+ ACCOUNT_MODE = 'accountMode',
99
+ /**
100
+ * Generic account-level fee/latency tier (e.g. Lighter standard /
101
+ * premium). Providers that have no tiering (Hyperliquid) omit this
102
+ * action from their descriptor list.
103
+ */
104
+ ACCOUNT_TYPE = 'accountType',
105
+ SEND_ASSET = 'sendAsset',
106
+ WITHDRAWAL = 'withdrawal',
107
+ TRANSFER = 'transfer',
80
108
  PLACE_ORDER = 'placeOrder',
81
109
  PLACE_TRIGGER_ORDER = 'placeTriggerOrder',
82
110
  CANCEL_ORDER = 'cancelOrder',
111
+ CANCEL_ALL_ORDERS = 'cancelAllOrders',
112
+ MODIFY_ORDER = 'modifyOrder',
113
+ UPDATE_LEVERAGE = 'updateLeverage',
114
+ UPDATE_POSITION_MARGIN = 'updatePositionMargin',
115
+ REGISTER_API_KEY = 'registerApiKey',
116
+ APPROVE_READ_ONLY_TOKEN = 'approveReadOnlyToken',
117
+ DEPOSIT = 'deposit',
83
118
  }
84
119
 
85
120
  export enum TriggerCondition {
@@ -103,4 +138,51 @@ export enum ActivityType {
103
138
  WITHDRAWAL = 'WITHDRAWAL',
104
139
  LIQUIDATION = 'LIQUIDATION',
105
140
  FUNDING = 'FUNDING',
141
+ TRANSFER = 'TRANSFER',
142
+ }
143
+
144
+ export enum FillClassification {
145
+ OPENED_LONG = 'Opened Long',
146
+ OPENED_SHORT = 'Opened Short',
147
+ INCREASED_LONG = 'Increased Long',
148
+ INCREASED_SHORT = 'Increased Short',
149
+ REDUCED_LONG = 'Reduced Long',
150
+ REDUCED_SHORT = 'Reduced Short',
151
+ CLOSED_LONG = 'Closed Long',
152
+ CLOSED_SHORT = 'Closed Short',
153
+ SWITCHED_LONG = 'Switched Long',
154
+ SWITCHED_SHORT = 'Switched Short',
155
+ SPOT_BUY = 'Spot Buy',
156
+ SPOT_SELL = 'Spot Sell',
157
+ }
158
+
159
+ export enum LiquidationClassification {
160
+ LIQUIDATED = 'Liquidated',
161
+ }
162
+
163
+ export enum FundingClassification {
164
+ FUNDING = 'Funding',
165
+ }
166
+
167
+ export enum TransferClassification {
168
+ DEPOSIT = 'Deposit',
169
+ WITHDRAWAL = 'Withdrawal',
170
+ }
171
+
172
+ export type ActivityClassification =
173
+ | FillClassification
174
+ | LiquidationClassification
175
+ | FundingClassification
176
+ | TransferClassification
177
+
178
+ export enum PerpsSigner {
179
+ USER = 'USER',
180
+ AGENT = 'AGENT',
181
+ API_KEY = 'API_KEY',
182
+ }
183
+
184
+ export enum SigningMethod {
185
+ EIP712 = 'eip712',
186
+ WASM_BLOB = 'wasmBlob',
187
+ EVM_TX = 'evmTx',
106
188
  }
package/src/index.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  export * from './typedData.js'
2
2
  export * from './enums.js'
3
- export * from './market.js'
4
- export * from './authorization.js'
3
+ export * from './providers.js'
4
+ export * from './asset.js'
5
+ export * from './action.js'
5
6
  export * from './account.js'
6
- export * from './trading.js'
7
- export * from './withdrawal.js'
8
7
  export * from './errors.js'
9
8
  export * from './subscriptions.js'
@@ -0,0 +1,50 @@
1
+ import { FillClassification } from '../../enums.js'
2
+
3
+ /**
4
+ * Classify a perpetual fill into the Open/Close/Increase/Reduce/Switch
5
+ * taxonomy from `FillClassification`.
6
+ *
7
+ * @param startPosition Signed position held BEFORE this fill (`> 0` long,
8
+ * `< 0` short, `0` flat).
9
+ * @param side Hyperliquid-style: `'B'` for buy, anything else for sell.
10
+ * @param sz Unsigned fill size, parsed with `parseFloat`.
11
+ */
12
+ export function classifyFillFromPosition(
13
+ startPosition: string,
14
+ side: string,
15
+ sz: string
16
+ ): FillClassification {
17
+ const start = parseFloat(startPosition)
18
+ const delta = side === 'B' ? parseFloat(sz) : -parseFloat(sz)
19
+ const end = start + delta
20
+
21
+ if (start === 0) {
22
+ return end > 0
23
+ ? FillClassification.OPENED_LONG
24
+ : FillClassification.OPENED_SHORT
25
+ }
26
+
27
+ if (start > 0) {
28
+ if (end === 0) {
29
+ return FillClassification.CLOSED_LONG
30
+ }
31
+ if (end < 0) {
32
+ return FillClassification.SWITCHED_SHORT
33
+ }
34
+ if (end > start) {
35
+ return FillClassification.INCREASED_LONG
36
+ }
37
+ return FillClassification.REDUCED_LONG
38
+ }
39
+
40
+ if (end === 0) {
41
+ return FillClassification.CLOSED_SHORT
42
+ }
43
+ if (end > 0) {
44
+ return FillClassification.SWITCHED_LONG
45
+ }
46
+ if (end < start) {
47
+ return FillClassification.INCREASED_SHORT
48
+ }
49
+ return FillClassification.REDUCED_SHORT
50
+ }
@@ -1,26 +1,32 @@
1
+ /** Spot asset IDs use the @pairIndex format (e.g. "@230"). */
2
+ export const assetIsSpot = (assetId: string): boolean => assetId.startsWith('@')
3
+
1
4
  /**
2
- * Calculate the asset ID for a given DEX index and asset index.
5
+ * Calculate the asset ID for a given provider index and asset index.
3
6
  *
4
- * Main DEX (dex = ''): assetId = indexInDex
5
- * HIP-3 DEXes (dex = 'xyz'): assetId = 100_000 + perpDexIndex * 10_000 + indexInDex
7
+ * Main provider (provider = ''): assetId = indexInProvider
8
+ * HIP-3 providers (provider = 'xyz'): assetId = 100_000 + perpDexIndex * 10_000 + indexInProvider
6
9
  */
7
10
  export const calculateAssetId = (
8
- dexIndex: number,
9
- indexInDex: number
11
+ providerIndex: number,
12
+ indexInProvider: number
10
13
  ): number => {
11
- if (dexIndex === 0) {
12
- return indexInDex
14
+ if (providerIndex === 0) {
15
+ return indexInProvider
13
16
  }
14
- return 100_000 + dexIndex * 10_000 + indexInDex
17
+ return 100_000 + providerIndex * 10_000 + indexInProvider
15
18
  }
16
19
 
17
20
  /**
18
- * Get the DEX index from the given list of dex names.
21
+ * Get the provider index from the given list of provider names.
19
22
  */
20
- export const getDexIndex = (dex: string, dexNames: string[]): number => {
21
- const index = dexNames.indexOf(dex)
23
+ export const getProviderIndex = (
24
+ provider: string,
25
+ providerNames: string[]
26
+ ): number => {
27
+ const index = providerNames.indexOf(provider)
22
28
  if (index === -1) {
23
- throw new Error(`Unknown sub-dex: ${dex}`)
29
+ throw new Error(`Unknown sub-provider: ${provider}`)
24
30
  }
25
31
  return index
26
32
  }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Derive the `AssetIdentity.market` value (a `/providers.markets[].id`) from
3
+ * a Hyperliquid `assetId`:
4
+ * - `"BTC"` → main USDC perp dex → `"hyperliquid"`
5
+ * - `"xyz:PURR"` → HIP-3 sub-dex → `"xyz"`
6
+ * - `"@142"` → spot pair → `"spot"`
7
+ *
8
+ * Must stay in lockstep with `lifi-perps-backend`'s `toProviderMarketId` /
9
+ * `buildAssetMarketLookup` — they define the same `/providers.markets[].id`
10
+ * taxonomy on the wire.
11
+ */
12
+ export const deriveMarket = (assetId: string): string => {
13
+ if (assetId.startsWith('@')) {
14
+ return 'spot'
15
+ }
16
+ const colon = assetId.indexOf(':')
17
+ if (colon > 0) {
18
+ return assetId.slice(0, colon)
19
+ }
20
+ return 'hyperliquid'
21
+ }
@@ -5,38 +5,116 @@ import type {
5
5
  WithdrawalActivity,
6
6
  LiquidationActivity,
7
7
  FundingActivity,
8
+ TransferActivity,
8
9
  } from '../../../account.js'
10
+ import { isSendAssetDelta, isSpotTransferDelta } from '../types.js'
9
11
  import type { HlLedgerUpdate, HlFundingUpdate } from '../types.js'
12
+ import { deriveMarket } from './_market.js'
10
13
 
11
14
  /**
12
15
  * Map a Hyperliquid non-funding ledger entry to an ActivityItem.
13
- * Returns null for unsupported delta types (accountClassTransfer,
14
- * internalTransfer, subAccountTransfer, spotTransfer).
16
+ *
17
+ * Direction for `spotTransfer` and `sendAsset` is derived from
18
+ * `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`).
15
21
  */
16
22
  export const mapLedgerEntry = (
17
23
  entry: HlLedgerUpdate,
18
- dexKey: string
24
+ providerKey: string,
25
+ queriedAddress: string
19
26
  ): ActivityItem | null => {
20
27
  const { delta } = entry
21
28
  const base = {
22
29
  id: entry.hash,
23
- dex: dexKey,
30
+ provider: providerKey,
24
31
  timestamp: new Date(entry.time).toISOString(),
25
32
  }
26
33
 
34
+ // Handled before the switch: the catch-all arm of `HlLedgerDelta` is a
35
+ // structural supertype of the concrete delta, so a `switch (delta.type)`
36
+ // cannot narrow off the discriminant. The user-defined type guard does.
37
+ if (isSpotTransferDelta(delta)) {
38
+ const queried = queriedAddress.toLowerCase()
39
+ const sender = delta.user.toLowerCase()
40
+ const recipient = delta.destination.toLowerCase()
41
+ const direction: 'IN' | 'OUT' = queried === sender ? 'OUT' : 'IN'
42
+ const counterpartyAddress = direction === 'OUT' ? recipient : sender
43
+ const meta: Record<string, unknown> = {
44
+ transferType: 'spotTransfer',
45
+ }
46
+ if (delta.usdcValue !== undefined) {
47
+ meta.usdcValue = delta.usdcValue
48
+ }
49
+ if (delta.fee !== undefined) {
50
+ meta.fee = delta.fee
51
+ }
52
+ if (delta.nativeTokenFee !== undefined) {
53
+ meta.nativeTokenFee = delta.nativeTokenFee
54
+ }
55
+ if (delta.nonce !== undefined) {
56
+ meta.nonce = delta.nonce
57
+ }
58
+ return {
59
+ ...base,
60
+ type: ActivityType.TRANSFER,
61
+ direction,
62
+ counterpartyAddress,
63
+ asset: delta.token,
64
+ amount: delta.amount,
65
+ meta,
66
+ } satisfies TransferActivity
67
+ }
68
+
69
+ // `sendAsset` (wire `type === 'send'`) covers cross-user transfers
70
+ // (modelled as TRANSFER) and same-user dex moves (returned as null —
71
+ // overloading TRANSFER for those would lie about direction). Pre-switch
72
+ // narrowing for the same reason as spotTransfer.
73
+ if (isSendAssetDelta(delta)) {
74
+ const queried = queriedAddress.toLowerCase()
75
+ const sender = delta.user.toLowerCase()
76
+ const recipient = delta.destination.toLowerCase()
77
+
78
+ if (sender === recipient && sender === queried) {
79
+ return null
80
+ }
81
+
82
+ const direction: 'IN' | 'OUT' = queried === sender ? 'OUT' : 'IN'
83
+ const counterpartyAddress = direction === 'OUT' ? recipient : sender
84
+ const meta: Record<string, unknown> = {
85
+ transferType: 'sendAsset',
86
+ sourceDex: delta.sourceDex,
87
+ destinationDex: delta.destinationDex,
88
+ usdcValue: delta.usdcValue,
89
+ fee: delta.fee,
90
+ nativeTokenFee: delta.nativeTokenFee,
91
+ feeToken: delta.feeToken,
92
+ nonce: delta.nonce,
93
+ }
94
+ return {
95
+ ...base,
96
+ type: ActivityType.TRANSFER,
97
+ direction,
98
+ counterpartyAddress,
99
+ asset: delta.token,
100
+ amount: delta.amount,
101
+ meta,
102
+ } satisfies TransferActivity
103
+ }
104
+
27
105
  switch (delta.type) {
28
106
  case 'deposit':
29
107
  return {
30
108
  ...base,
31
109
  type: ActivityType.DEPOSIT,
32
- amount: delta.usdc,
110
+ amount: delta.usdc ?? '0',
33
111
  } satisfies DepositActivity
34
112
 
35
113
  case 'withdraw':
36
114
  return {
37
115
  ...base,
38
116
  type: ActivityType.WITHDRAWAL,
39
- amount: delta.usdc,
117
+ amount: delta.usdc ?? '0',
40
118
  fee: (delta as { fee?: string }).fee ?? '0',
41
119
  } satisfies WithdrawalActivity
42
120
 
@@ -55,7 +133,12 @@ export const mapLedgerEntry = (
55
133
  accountValue: d.accountValue,
56
134
  leverageType: d.leverageType,
57
135
  liquidatedPositions: (d.liquidatedPositions ?? []).map((p) => ({
58
- symbol: p.coin,
136
+ asset: {
137
+ assetId: p.coin,
138
+ market: deriveMarket(p.coin),
139
+ displaySymbol: p.coin,
140
+ displayQuote: null,
141
+ },
59
142
  size: p.szi,
60
143
  })),
61
144
  } satisfies LiquidationActivity
@@ -66,18 +149,20 @@ export const mapLedgerEntry = (
66
149
  }
67
150
  }
68
151
 
69
- /**
70
- * Map a Hyperliquid funding entry to a FundingActivity.
71
- */
72
152
  export const mapFundingActivity = (
73
153
  entry: HlFundingUpdate,
74
- dexKey: string
154
+ providerKey: string
75
155
  ): FundingActivity => ({
76
156
  id: entry.hash,
77
- dex: dexKey,
157
+ provider: providerKey,
78
158
  timestamp: new Date(entry.time).toISOString(),
79
159
  type: ActivityType.FUNDING,
80
- symbol: entry.delta.coin,
160
+ asset: {
161
+ assetId: entry.delta.coin,
162
+ market: deriveMarket(entry.delta.coin),
163
+ displaySymbol: entry.delta.coin,
164
+ displayQuote: null,
165
+ },
81
166
  amount: entry.delta.usdc,
82
167
  positionSize: entry.delta.szi,
83
168
  fundingRate: entry.delta.fundingRate,
@@ -1,26 +1,23 @@
1
- import type { Market } from '../../../market.js'
2
- import { calculateAssetId } from '../assetId.js'
1
+ import type { Asset } from '../../../asset.js'
3
2
  import type { HlAssetCtx, HlUniverseItem } from '../types.js'
3
+ import { deriveMarket } from './_market.js'
4
4
 
5
5
  const NEXT_FUNDING_INTERVAL_MS = 60 * 60 * 1000 // 1 hour
6
6
 
7
- export const mapMarket = (
7
+ export const mapAsset = (
8
8
  universe: HlUniverseItem,
9
- assetCtx: HlAssetCtx,
10
- dexIndex: number,
11
- indexInDex: number,
12
- dexKey: string
13
- ): Market => {
9
+ assetCtx: HlAssetCtx
10
+ ): Asset => {
14
11
  const now = Date.now()
15
12
  const nextFundingTime =
16
13
  Math.ceil(now / NEXT_FUNDING_INTERVAL_MS) * NEXT_FUNDING_INTERVAL_MS
17
14
 
18
15
  return {
19
- symbol: universe.name,
20
- name: universe.name,
16
+ assetId: universe.name,
17
+ market: deriveMarket(universe.name),
18
+ displaySymbol: universe.name,
19
+ displayQuote: null,
21
20
  logoURI: `https://app.hyperliquid.xyz/coins/${universe.name}.svg`,
22
- assetId: calculateAssetId(dexIndex, indexInDex),
23
- dex: dexKey,
24
21
  szDecimals: universe.szDecimals,
25
22
  maxLeverage: universe.maxLeverage,
26
23
  onlyIsolated: universe.onlyIsolated === true,
@@ -30,6 +27,7 @@ export const mapMarket = (
30
27
  },
31
28
  openInterest: assetCtx.openInterest,
32
29
  volume24h: assetCtx.dayNtlVlm,
30
+ prevDayPrice: assetCtx.prevDayPx,
33
31
  markPrice: assetCtx.markPx,
34
32
  }
35
33
  }
@@ -0,0 +1,41 @@
1
+ import {
2
+ FillClassification,
3
+ FillStatus,
4
+ LiquidityRole,
5
+ OrderSide,
6
+ OrderType,
7
+ } from '../../../enums.js'
8
+ import type { Fill } from '../../../account.js'
9
+ import type { HlUserFill } from '../types.js'
10
+ import { assetIsSpot } from '../assetId.js'
11
+ import { classifyFillFromPosition } from '../../_shared/fillClassification.js'
12
+ import { deriveMarket } from './_market.js'
13
+
14
+ export { classifyFillFromPosition }
15
+
16
+ export const mapFill = (fill: HlUserFill): Fill => ({
17
+ id: String(fill.tid),
18
+ orderId: String(fill.oid),
19
+ asset: {
20
+ assetId: fill.coin,
21
+ market: deriveMarket(fill.coin),
22
+ displaySymbol: fill.coin,
23
+ displayQuote: null,
24
+ },
25
+ side: fill.side === 'B' ? OrderSide.BUY : OrderSide.SELL,
26
+ type: fill.dir?.includes('Limit') ? OrderType.LIMIT : OrderType.MARKET,
27
+ size: fill.sz,
28
+ price: fill.px,
29
+ status: FillStatus.FILLED,
30
+ liquidity: fill.crossed ? LiquidityRole.TAKER : LiquidityRole.MAKER,
31
+ filledSize: fill.sz,
32
+ fee: fill.fee,
33
+ realizedPnl: fill.closedPnl === '0' ? null : fill.closedPnl,
34
+ startPosition: fill.startPosition,
35
+ classification: assetIsSpot(fill.coin)
36
+ ? fill.side === 'B'
37
+ ? FillClassification.SPOT_BUY
38
+ : FillClassification.SPOT_SELL
39
+ : classifyFillFromPosition(fill.startPosition, fill.side, fill.sz),
40
+ createdAt: new Date(fill.time).toISOString(),
41
+ })
@@ -1,6 +1,11 @@
1
- export { resolveAssetIdFromLookup } from './shared.js'
2
- export { mapMarket } from './market.js'
3
- export { mapOpenOrder, mapOrder } from './order.js'
1
+ export { mapAsset } from './asset.js'
2
+ export {
3
+ isTriggerType,
4
+ mapOpenOrder,
5
+ mapOrder,
6
+ mapOrderType,
7
+ mapTriggerOrder,
8
+ } from './order.js'
4
9
  export { mapPosition } from './position.js'
5
- export { mapHistoryItem } from './history.js'
10
+ export { classifyFillFromPosition, mapFill } from './fill.js'
6
11
  export { mapLedgerEntry, mapFundingActivity } from './activity.js'
@@ -4,32 +4,76 @@ import {
4
4
  OrderType,
5
5
  TimeInForce,
6
6
  } from '../../../enums.js'
7
- import type { OpenOrder } from '../../../account.js'
8
- import type { Order } from '../../../trading.js'
7
+ import type { OpenOrder, TriggerOrder } from '../../../account.js'
8
+ import type { Order } from '../../../action.js'
9
9
  import type { HlFrontendOpenOrder, HlOrderDetail } from '../types.js'
10
+ import { deriveMarket } from './_market.js'
10
11
 
11
- import { resolveAssetIdFromLookup } from './shared.js'
12
+ /** Map a Hyperliquid orderType string to the OrderType enum. */
13
+ export const mapOrderType = (orderType: string): OrderType => {
14
+ switch (orderType) {
15
+ case 'Take Profit Market':
16
+ return OrderType.TAKE_PROFIT_MARKET
17
+ case 'Take Profit Limit':
18
+ return OrderType.TAKE_PROFIT_LIMIT
19
+ case 'Stop Market':
20
+ return OrderType.STOP_MARKET
21
+ case 'Stop Limit':
22
+ return OrderType.STOP_LIMIT
23
+ case 'Market':
24
+ return OrderType.MARKET
25
+ default:
26
+ return OrderType.LIMIT
27
+ }
28
+ }
29
+
30
+ export const isTriggerType = (type: OrderType): boolean =>
31
+ type === OrderType.TAKE_PROFIT_MARKET ||
32
+ type === OrderType.TAKE_PROFIT_LIMIT ||
33
+ type === OrderType.STOP_MARKET ||
34
+ type === OrderType.STOP_LIMIT
12
35
 
13
- export const mapOpenOrder = (
14
- o: HlFrontendOpenOrder,
15
- dexKey: string,
16
- assetIdLookup: Map<string, number>
17
- ): OpenOrder => ({
36
+ export const mapOpenOrder = (o: HlFrontendOpenOrder): OpenOrder => ({
18
37
  id: String(o.oid),
19
- symbol: o.coin,
20
- assetId: resolveAssetIdFromLookup(assetIdLookup, o.coin),
21
- dex: dexKey,
38
+ asset: {
39
+ assetId: o.coin,
40
+ market: deriveMarket(o.coin),
41
+ displaySymbol: o.coin,
42
+ displayQuote: null,
43
+ },
22
44
  side: o.side === 'B' ? OrderSide.BUY : OrderSide.SELL,
23
- type: o.orderType === 'Limit' ? OrderType.LIMIT : OrderType.MARKET,
45
+ type: mapOrderType(o.orderType),
24
46
  size: o.sz,
25
47
  price: o.limitPx,
26
48
  filledSize: o.origSz
27
49
  ? (parseFloat(o.origSz) - parseFloat(o.sz)).toString()
28
50
  : '0',
29
51
  reduceOnly: o.reduceOnly ?? false,
52
+ label: o.isTrigger ? o.triggerCondition : undefined,
30
53
  createdAt: new Date(o.timestamp).toISOString(),
31
54
  })
32
55
 
56
+ export const mapTriggerOrder = (o: HlFrontendOpenOrder): TriggerOrder => {
57
+ const type = mapOrderType(o.orderType)
58
+ const isLimit =
59
+ type === OrderType.TAKE_PROFIT_LIMIT || type === OrderType.STOP_LIMIT
60
+ return {
61
+ id: String(o.oid),
62
+ asset: {
63
+ assetId: o.coin,
64
+ market: deriveMarket(o.coin),
65
+ displaySymbol: o.coin,
66
+ displayQuote: null,
67
+ },
68
+ type,
69
+ size: o.sz,
70
+ triggerPrice: o.triggerPx,
71
+ ...(isLimit ? { limitPrice: o.limitPx } : {}),
72
+ label: o.triggerCondition,
73
+ createdAt: new Date(o.timestamp).toISOString(),
74
+ }
75
+ }
76
+
33
77
  const mapOrderStatus = (status: string): OrderStatus => {
34
78
  switch (status) {
35
79
  case 'open':
@@ -51,6 +95,37 @@ const mapOrderStatus = (status: string): OrderStatus => {
51
95
  }
52
96
  }
53
97
 
98
+ /**
99
+ * Map a raw Hyperliquid order status to a short English sentence
100
+ * describing *why* the order ended in a terminal non-FILLED state. Bare
101
+ * `canceled`/`cancelled`/`rejected` carry no actionable detail and
102
+ * return `undefined`; so do non-terminal and unknown values.
103
+ */
104
+ export const mapStatusReason = (status: string): string | undefined => {
105
+ switch (status) {
106
+ case 'iocCanceled':
107
+ return 'Order cancelled: not enough liquidity to fill immediately.'
108
+ case 'reduceOnlyCanceled':
109
+ return 'Order cancelled: would not reduce your position.'
110
+ case 'marginCanceled':
111
+ return 'Order cancelled: insufficient margin.'
112
+ case 'liquidatedCanceled':
113
+ return 'Order cancelled: account was liquidated.'
114
+ case 'siblingFilledCanceled':
115
+ return 'Order cancelled: sibling OCO order filled first.'
116
+ case 'selfTradeCanceled':
117
+ return 'Order cancelled: would self-trade against your own resting order.'
118
+ case 'tickRejected':
119
+ return 'Order rejected: price did not match the tick size.'
120
+ case 'minTradeNtlRejected':
121
+ return 'Order rejected: notional value below the minimum trade size.'
122
+ case 'delistedRejected':
123
+ return 'Order rejected: market has been delisted.'
124
+ default:
125
+ return undefined
126
+ }
127
+ }
128
+
54
129
  const mapTimeInForce = (tif: string | undefined): TimeInForce | undefined => {
55
130
  switch (tif) {
56
131
  case 'Gtc':
@@ -70,9 +145,14 @@ export const mapOrder = (detail: HlOrderDetail): Order => {
70
145
 
71
146
  return {
72
147
  orderId: String(o.oid),
73
- symbol: o.coin,
148
+ asset: {
149
+ assetId: o.coin,
150
+ market: deriveMarket(o.coin),
151
+ displaySymbol: o.coin,
152
+ displayQuote: null,
153
+ },
74
154
  side: o.side === 'B' ? OrderSide.BUY : OrderSide.SELL,
75
- type: o.orderType === 'Limit' ? OrderType.LIMIT : OrderType.MARKET,
155
+ type: mapOrderType(o.orderType),
76
156
  price: o.limitPx,
77
157
  originalSize: o.origSz,
78
158
  remainingSize: o.sz,
@@ -82,6 +162,7 @@ export const mapOrder = (detail: HlOrderDetail): Order => {
82
162
  isTrigger: o.triggerCondition !== undefined && o.triggerCondition !== 'N/A',
83
163
  triggerPrice: o.triggerPx ?? undefined,
84
164
  status: mapOrderStatus(detail.status),
165
+ statusReason: mapStatusReason(detail.status),
85
166
  createdAt: new Date(o.timestamp).toISOString(),
86
167
  updatedAt: new Date(detail.statusTimestamp).toISOString(),
87
168
  }