@lifi/perps-sdk-provider-lighter 35.0.0 → 36.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 (248) hide show
  1. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  2. package/dist/cjs/LighterProvider.js +101 -58
  3. package/dist/cjs/LighterProvider.js.map +1 -1
  4. package/dist/cjs/accountSummary.d.ts +1 -2
  5. package/dist/cjs/accountSummary.d.ts.map +1 -1
  6. package/dist/cjs/accountSummary.js +9 -16
  7. package/dist/cjs/accountSummary.js.map +1 -1
  8. package/dist/cjs/availableToTrade.d.ts +1 -2
  9. package/dist/cjs/availableToTrade.d.ts.map +1 -1
  10. package/dist/cjs/availableToTrade.js +8 -12
  11. package/dist/cjs/availableToTrade.js.map +1 -1
  12. package/dist/cjs/constants.d.ts +1 -0
  13. package/dist/cjs/constants.d.ts.map +1 -1
  14. package/dist/cjs/constants.js +2 -1
  15. package/dist/cjs/constants.js.map +1 -1
  16. package/dist/cjs/index.d.ts +1 -1
  17. package/dist/cjs/index.d.ts.map +1 -1
  18. package/dist/cjs/index.js +2 -1
  19. package/dist/cjs/index.js.map +1 -1
  20. package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
  21. package/dist/cjs/signers/LighterSigner.js +2 -6
  22. package/dist/cjs/signers/LighterSigner.js.map +1 -1
  23. package/dist/cjs/types/submit.d.ts +5 -0
  24. package/dist/cjs/types/submit.d.ts.map +1 -1
  25. package/dist/cjs/utils/index.d.ts +3 -3
  26. package/dist/cjs/utils/index.d.ts.map +1 -1
  27. package/dist/cjs/utils/index.js +5 -6
  28. package/dist/cjs/utils/index.js.map +1 -1
  29. package/dist/cjs/utils/mapFill.d.ts +1 -1
  30. package/dist/cjs/utils/mapFill.d.ts.map +1 -1
  31. package/dist/cjs/utils/mapFill.js +44 -31
  32. package/dist/cjs/utils/mapFill.js.map +1 -1
  33. package/dist/cjs/utils/mapOpenPositions.d.ts +3 -1
  34. package/dist/cjs/utils/mapOpenPositions.d.ts.map +1 -1
  35. package/dist/cjs/utils/mapOpenPositions.js +20 -4
  36. package/dist/cjs/utils/mapOpenPositions.js.map +1 -1
  37. package/dist/cjs/utils/mapOrder.d.ts +1 -1
  38. package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
  39. package/dist/cjs/utils/mapOrder.js +64 -26
  40. package/dist/cjs/utils/mapOrder.js.map +1 -1
  41. package/dist/cjs/utils/mapPortfolioHistory.d.ts +1 -2
  42. package/dist/cjs/utils/mapPortfolioHistory.d.ts.map +1 -1
  43. package/dist/cjs/utils/mapPortfolioHistory.js +29 -21
  44. package/dist/cjs/utils/mapPortfolioHistory.js.map +1 -1
  45. package/dist/cjs/utils/mapPosition.d.ts +3 -3
  46. package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
  47. package/dist/cjs/utils/mapPosition.js +35 -35
  48. package/dist/cjs/utils/mapPosition.js.map +1 -1
  49. package/dist/cjs/utils/rowTimestamp.d.ts +2 -0
  50. package/dist/cjs/utils/rowTimestamp.d.ts.map +1 -0
  51. package/dist/cjs/utils/rowTimestamp.js +14 -0
  52. package/dist/cjs/utils/rowTimestamp.js.map +1 -0
  53. package/dist/cjs/utils/settlementPool.d.ts +2 -3
  54. package/dist/cjs/utils/settlementPool.d.ts.map +1 -1
  55. package/dist/cjs/utils/settlementPool.js +8 -7
  56. package/dist/cjs/utils/settlementPool.js.map +1 -1
  57. package/dist/cjs/utils/spotPrice.d.ts +3 -4
  58. package/dist/cjs/utils/spotPrice.d.ts.map +1 -1
  59. package/dist/cjs/utils/spotPrice.js +6 -11
  60. package/dist/cjs/utils/spotPrice.js.map +1 -1
  61. package/dist/cjs/utils/time.d.ts.map +1 -1
  62. package/dist/cjs/utils/time.js +3 -2
  63. package/dist/cjs/utils/time.js.map +1 -1
  64. package/dist/cjs/utils/transferMargin.d.ts.map +1 -1
  65. package/dist/cjs/utils/transferMargin.js +7 -15
  66. package/dist/cjs/utils/transferMargin.js.map +1 -1
  67. package/dist/cjs/utils/withdrawableBalances.d.ts +1 -1
  68. package/dist/cjs/utils/withdrawableBalances.d.ts.map +1 -1
  69. package/dist/cjs/utils/withdrawableBalances.js +12 -17
  70. package/dist/cjs/utils/withdrawableBalances.js.map +1 -1
  71. package/dist/cjs/utils/withdrawalTypes.d.ts +17 -0
  72. package/dist/cjs/utils/withdrawalTypes.d.ts.map +1 -0
  73. package/dist/cjs/utils/withdrawalTypes.js +58 -0
  74. package/dist/cjs/utils/withdrawalTypes.js.map +1 -0
  75. package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
  76. package/dist/cjs/websocket/LighterWsProvider.js +46 -58
  77. package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
  78. package/dist/cjs/websocket/orderBookSide.d.ts +19 -0
  79. package/dist/cjs/websocket/orderBookSide.d.ts.map +1 -0
  80. package/dist/cjs/websocket/orderBookSide.js +71 -0
  81. package/dist/cjs/websocket/orderBookSide.js.map +1 -0
  82. package/dist/esm/LighterProvider.d.ts.map +1 -1
  83. package/dist/esm/LighterProvider.js +116 -62
  84. package/dist/esm/LighterProvider.js.map +1 -1
  85. package/dist/esm/accountSummary.d.ts +1 -2
  86. package/dist/esm/accountSummary.d.ts.map +1 -1
  87. package/dist/esm/accountSummary.js +10 -14
  88. package/dist/esm/accountSummary.js.map +1 -1
  89. package/dist/esm/availableToTrade.d.ts +1 -2
  90. package/dist/esm/availableToTrade.d.ts.map +1 -1
  91. package/dist/esm/availableToTrade.js +9 -10
  92. package/dist/esm/availableToTrade.js.map +1 -1
  93. package/dist/esm/constants.d.ts +8 -0
  94. package/dist/esm/constants.d.ts.map +1 -1
  95. package/dist/esm/constants.js +8 -0
  96. package/dist/esm/constants.js.map +1 -1
  97. package/dist/esm/index.d.ts +1 -1
  98. package/dist/esm/index.d.ts.map +1 -1
  99. package/dist/esm/index.js +1 -1
  100. package/dist/esm/index.js.map +1 -1
  101. package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
  102. package/dist/esm/signers/LighterSigner.js +3 -4
  103. package/dist/esm/signers/LighterSigner.js.map +1 -1
  104. package/dist/esm/types/submit.d.ts +14 -0
  105. package/dist/esm/types/submit.d.ts.map +1 -1
  106. package/dist/esm/utils/index.d.ts +3 -3
  107. package/dist/esm/utils/index.d.ts.map +1 -1
  108. package/dist/esm/utils/index.js +2 -3
  109. package/dist/esm/utils/index.js.map +1 -1
  110. package/dist/esm/utils/mapFill.d.ts +1 -1
  111. package/dist/esm/utils/mapFill.d.ts.map +1 -1
  112. package/dist/esm/utils/mapFill.js +51 -35
  113. package/dist/esm/utils/mapFill.js.map +1 -1
  114. package/dist/esm/utils/mapOpenPositions.d.ts +17 -3
  115. package/dist/esm/utils/mapOpenPositions.d.ts.map +1 -1
  116. package/dist/esm/utils/mapOpenPositions.js +31 -5
  117. package/dist/esm/utils/mapOpenPositions.js.map +1 -1
  118. package/dist/esm/utils/mapOrder.d.ts +6 -2
  119. package/dist/esm/utils/mapOrder.d.ts.map +1 -1
  120. package/dist/esm/utils/mapOrder.js +70 -25
  121. package/dist/esm/utils/mapOrder.js.map +1 -1
  122. package/dist/esm/utils/mapPortfolioHistory.d.ts +6 -3
  123. package/dist/esm/utils/mapPortfolioHistory.d.ts.map +1 -1
  124. package/dist/esm/utils/mapPortfolioHistory.js +34 -19
  125. package/dist/esm/utils/mapPortfolioHistory.js.map +1 -1
  126. package/dist/esm/utils/mapPosition.d.ts +12 -8
  127. package/dist/esm/utils/mapPosition.d.ts.map +1 -1
  128. package/dist/esm/utils/mapPosition.js +45 -38
  129. package/dist/esm/utils/mapPosition.js.map +1 -1
  130. package/dist/esm/utils/rowTimestamp.d.ts +6 -0
  131. package/dist/esm/utils/rowTimestamp.d.ts.map +1 -0
  132. package/dist/esm/utils/rowTimestamp.js +14 -0
  133. package/dist/esm/utils/rowTimestamp.js.map +1 -0
  134. package/dist/esm/utils/settlementPool.d.ts +2 -3
  135. package/dist/esm/utils/settlementPool.d.ts.map +1 -1
  136. package/dist/esm/utils/settlementPool.js +8 -7
  137. package/dist/esm/utils/settlementPool.js.map +1 -1
  138. package/dist/esm/utils/spotPrice.d.ts +3 -4
  139. package/dist/esm/utils/spotPrice.d.ts.map +1 -1
  140. package/dist/esm/utils/spotPrice.js +6 -8
  141. package/dist/esm/utils/spotPrice.js.map +1 -1
  142. package/dist/esm/utils/time.d.ts +10 -2
  143. package/dist/esm/utils/time.d.ts.map +1 -1
  144. package/dist/esm/utils/time.js +13 -4
  145. package/dist/esm/utils/time.js.map +1 -1
  146. package/dist/esm/utils/transferMargin.d.ts.map +1 -1
  147. package/dist/esm/utils/transferMargin.js +8 -13
  148. package/dist/esm/utils/transferMargin.js.map +1 -1
  149. package/dist/esm/utils/withdrawableBalances.d.ts +5 -3
  150. package/dist/esm/utils/withdrawableBalances.d.ts.map +1 -1
  151. package/dist/esm/utils/withdrawableBalances.js +17 -17
  152. package/dist/esm/utils/withdrawableBalances.js.map +1 -1
  153. package/dist/esm/utils/withdrawalTypes.d.ts +45 -0
  154. package/dist/esm/utils/withdrawalTypes.d.ts.map +1 -0
  155. package/dist/esm/utils/withdrawalTypes.js +68 -0
  156. package/dist/esm/utils/withdrawalTypes.js.map +1 -0
  157. package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
  158. package/dist/esm/websocket/LighterWsProvider.js +48 -57
  159. package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
  160. package/dist/esm/websocket/orderBookSide.d.ts +33 -0
  161. package/dist/esm/websocket/orderBookSide.d.ts.map +1 -0
  162. package/dist/esm/websocket/orderBookSide.js +76 -0
  163. package/dist/esm/websocket/orderBookSide.js.map +1 -0
  164. package/dist/types/LighterProvider.d.ts.map +1 -1
  165. package/dist/types/accountSummary.d.ts +1 -2
  166. package/dist/types/accountSummary.d.ts.map +1 -1
  167. package/dist/types/availableToTrade.d.ts +1 -2
  168. package/dist/types/availableToTrade.d.ts.map +1 -1
  169. package/dist/types/constants.d.ts +8 -0
  170. package/dist/types/constants.d.ts.map +1 -1
  171. package/dist/types/index.d.ts +1 -1
  172. package/dist/types/index.d.ts.map +1 -1
  173. package/dist/types/signers/LighterSigner.d.ts.map +1 -1
  174. package/dist/types/types/submit.d.ts +14 -0
  175. package/dist/types/types/submit.d.ts.map +1 -1
  176. package/dist/types/utils/index.d.ts +3 -3
  177. package/dist/types/utils/index.d.ts.map +1 -1
  178. package/dist/types/utils/mapFill.d.ts +1 -1
  179. package/dist/types/utils/mapFill.d.ts.map +1 -1
  180. package/dist/types/utils/mapOpenPositions.d.ts +17 -3
  181. package/dist/types/utils/mapOpenPositions.d.ts.map +1 -1
  182. package/dist/types/utils/mapOrder.d.ts +6 -2
  183. package/dist/types/utils/mapOrder.d.ts.map +1 -1
  184. package/dist/types/utils/mapPortfolioHistory.d.ts +6 -3
  185. package/dist/types/utils/mapPortfolioHistory.d.ts.map +1 -1
  186. package/dist/types/utils/mapPosition.d.ts +12 -8
  187. package/dist/types/utils/mapPosition.d.ts.map +1 -1
  188. package/dist/types/utils/rowTimestamp.d.ts +6 -0
  189. package/dist/types/utils/rowTimestamp.d.ts.map +1 -0
  190. package/dist/types/utils/settlementPool.d.ts +2 -3
  191. package/dist/types/utils/settlementPool.d.ts.map +1 -1
  192. package/dist/types/utils/spotPrice.d.ts +3 -4
  193. package/dist/types/utils/spotPrice.d.ts.map +1 -1
  194. package/dist/types/utils/time.d.ts +10 -2
  195. package/dist/types/utils/time.d.ts.map +1 -1
  196. package/dist/types/utils/transferMargin.d.ts.map +1 -1
  197. package/dist/types/utils/withdrawableBalances.d.ts +5 -3
  198. package/dist/types/utils/withdrawableBalances.d.ts.map +1 -1
  199. package/dist/types/utils/withdrawalTypes.d.ts +45 -0
  200. package/dist/types/utils/withdrawalTypes.d.ts.map +1 -0
  201. package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
  202. package/dist/types/websocket/orderBookSide.d.ts +33 -0
  203. package/dist/types/websocket/orderBookSide.d.ts.map +1 -0
  204. package/package.json +3 -3
  205. package/src/LighterProvider.ts +236 -100
  206. package/src/accountSummary.ts +41 -22
  207. package/src/availableToTrade.ts +38 -15
  208. package/src/constants.ts +9 -0
  209. package/src/index.ts +1 -0
  210. package/src/signers/LighterSigner.ts +11 -4
  211. package/src/types/submit.ts +15 -0
  212. package/src/utils/index.ts +9 -3
  213. package/src/utils/mapFill.ts +82 -43
  214. package/src/utils/mapOpenPositions.ts +45 -6
  215. package/src/utils/mapOrder.ts +99 -28
  216. package/src/utils/mapPortfolioHistory.ts +78 -24
  217. package/src/utils/mapPosition.ts +67 -44
  218. package/src/utils/rowTimestamp.ts +15 -0
  219. package/src/utils/settlementPool.ts +36 -12
  220. package/src/utils/spotPrice.ts +18 -12
  221. package/src/utils/time.ts +14 -4
  222. package/src/utils/transferMargin.ts +28 -17
  223. package/src/utils/withdrawableBalances.ts +34 -20
  224. package/src/utils/withdrawalTypes.ts +125 -0
  225. package/src/websocket/LighterWsProvider.ts +75 -92
  226. package/src/websocket/orderBookSide.ts +106 -0
  227. package/dist/cjs/utils/decimal.d.ts +0 -5
  228. package/dist/cjs/utils/decimal.d.ts.map +0 -1
  229. package/dist/cjs/utils/decimal.js +0 -38
  230. package/dist/cjs/utils/decimal.js.map +0 -1
  231. package/dist/cjs/utils/liquidation.d.ts +0 -4
  232. package/dist/cjs/utils/liquidation.d.ts.map +0 -1
  233. package/dist/cjs/utils/liquidation.js +0 -16
  234. package/dist/cjs/utils/liquidation.js.map +0 -1
  235. package/dist/esm/utils/decimal.d.ts +0 -15
  236. package/dist/esm/utils/decimal.d.ts.map +0 -1
  237. package/dist/esm/utils/decimal.js +0 -39
  238. package/dist/esm/utils/decimal.js.map +0 -1
  239. package/dist/esm/utils/liquidation.d.ts +0 -22
  240. package/dist/esm/utils/liquidation.d.ts.map +0 -1
  241. package/dist/esm/utils/liquidation.js +0 -31
  242. package/dist/esm/utils/liquidation.js.map +0 -1
  243. package/dist/types/utils/decimal.d.ts +0 -15
  244. package/dist/types/utils/decimal.d.ts.map +0 -1
  245. package/dist/types/utils/liquidation.d.ts +0 -22
  246. package/dist/types/utils/liquidation.d.ts.map +0 -1
  247. package/src/utils/decimal.ts +0 -52
  248. package/src/utils/liquidation.ts +0 -39
@@ -0,0 +1,33 @@
1
+ import type { LtWsOrderBook } from '../types/index.js';
2
+ /**
3
+ * Orders two decimal-string prices: a negative result puts `a` before `b`.
4
+ *
5
+ * @throws {PerpsError} `ValidationError` when a price is not a decimal string.
6
+ */
7
+ export type PriceOrder = (a: string, b: string) => number;
8
+ export declare const bidOrder: PriceOrder;
9
+ export declare const askOrder: PriceOrder;
10
+ /**
11
+ * One side of a maintained order book, keyed by the wire price string. Levels
12
+ * stay in `order` across updates, so a read copies them without a sort.
13
+ */
14
+ export declare class OrderBookSide {
15
+ private readonly order;
16
+ private readonly providerKey;
17
+ private readonly byPrice;
18
+ private readonly levels;
19
+ constructor(order: PriceOrder, providerKey: string);
20
+ /**
21
+ * Applies snapshot or delta levels; a zero size deletes the level. A level
22
+ * with an invalid size also deletes the level at its price, so the book
23
+ * never keeps a size the venue has replaced.
24
+ */
25
+ apply(updates: LtWsOrderBook['bids']): void;
26
+ toLevels(): Array<{
27
+ price: string;
28
+ size: string;
29
+ }>;
30
+ private remove;
31
+ private bound;
32
+ }
33
+ //# sourceMappingURL=orderBookSide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orderBookSide.d.ts","sourceRoot":"","sources":["../../../src/websocket/orderBookSide.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;AAEzD,eAAO,MAAM,QAAQ,EAAE,UAAkD,CAAA;AACzE,eAAO,MAAM,QAAQ,EAAE,UAAkD,CAAA;AAOzE;;;GAGG;AACH,qBAAa,aAAa;IAKtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAL9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAGtB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM;IAGtC;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI;IAgC3C,QAAQ,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAIlD,OAAO,CAAC,MAAM;IAed,OAAO,CAAC,KAAK;CAad"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/perps-sdk-provider-lighter",
3
- "version": "35.0.0",
3
+ "version": "36.0.0",
4
4
  "description": "Lighter provider plugin for @lifi/perps-sdk",
5
5
  "homepage": "https://github.com/lifinance/perps-sdk",
6
6
  "bugs": {
@@ -44,10 +44,10 @@
44
44
  "dependencies": {
45
45
  "big.js": "^7.0.1",
46
46
  "viem": "^2.55.18",
47
- "@lifi/perps-types": "^20.1.0"
47
+ "@lifi/perps-types": "^21.0.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@lifi/perps-sdk": "^23.0.0"
50
+ "@lifi/perps-sdk": "^24.0.0"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
@@ -2,6 +2,7 @@ import {
2
2
  ACTIVE_ORDER_STATUSES,
3
3
  calculateTransferable,
4
4
  type DepositFlow,
5
+ estimateLiquidationPriceAtMarketRate,
5
6
  explorerTxUrl,
6
7
  explorerTxUrlFromBase,
7
8
  getAssetRegistry,
@@ -9,7 +10,7 @@ import {
9
10
  getMarketsContext,
10
11
  getProviders,
11
12
  isActiveOrderStatus,
12
- isDecimalString,
13
+ isDecimalStringGreaterThan,
13
14
  localStorageAdapter,
14
15
  numberToDecimalString,
15
16
  PerpsError,
@@ -28,6 +29,7 @@ import {
28
29
  type ProviderGetPositionsParams,
29
30
  type ProviderGetQuoteParams,
30
31
  type ProviderGetWithdrawableBalancesParams,
32
+ type ProviderGetWithdrawalTypesParams,
31
33
  type ProviderWithdrawableBalance,
32
34
  paginateActivity,
33
35
  resolveQuote,
@@ -35,7 +37,13 @@ import {
35
37
  type SDKRequestOptions,
36
38
  type SignActionsContext,
37
39
  type StorageAdapter,
40
+ safeAbsDecimalString,
41
+ safeAddDecimalString,
42
+ safeMultiplyDecimalString,
43
+ subtractDecimalString,
38
44
  toPerpsMarketDisplay,
45
+ unknownToDecimalString,
46
+ type WithdrawalSourceTypes,
39
47
  } from '@lifi/perps-sdk'
40
48
  import type {
41
49
  AccountConfig,
@@ -70,7 +78,6 @@ import {
70
78
  MarginMode,
71
79
  PerpsErrorCode,
72
80
  } from '@lifi/perps-types'
73
- import Big from 'big.js'
74
81
  import type { Address } from 'viem'
75
82
  import {
76
83
  boundAccountTiers,
@@ -111,6 +118,7 @@ import type {
111
118
  LtAccountPnL,
112
119
  LtDepositHistoryItem,
113
120
  LtDepositHistoryResponse,
121
+ LtFastwithdrawInfoResponse,
114
122
  LtLiquidation,
115
123
  LtLiquidationsResponse,
116
124
  LtOrder,
@@ -119,6 +127,7 @@ import type {
119
127
  LtPositionFundingsResponse,
120
128
  LtTradesResponse,
121
129
  LtTransfer,
130
+ LtTransferFeeInfoResponse,
122
131
  LtTransferHistoryResponse,
123
132
  LtWithdrawHistoryItem,
124
133
  LtWithdrawHistoryResponse,
@@ -142,11 +151,13 @@ import {
142
151
  } from './utils/apiClient.js'
143
152
  import { isAssetMarginEnabled } from './utils/assetCollateral.js'
144
153
  import {
145
- estimateLiquidationPrice,
146
154
  fetchDetailedAccount,
155
+ type LighterFastWithdrawal,
147
156
  leverageFromImf,
148
157
  lighterAsset,
158
+ lighterFastWithdrawal,
149
159
  lighterWithdrawableBalances,
160
+ lighterWithdrawalTypes,
150
161
  mapFill,
151
162
  mapOpenPositions,
152
163
  mapOrder,
@@ -154,11 +165,10 @@ import {
154
165
  positionRemovableMargin,
155
166
  snapOrderPrice,
156
167
  snapOrderSize,
157
- toBigOrNull,
158
168
  toIsoFromMs,
159
169
  toIsoFromSeconds,
160
- toRequiredBig,
161
170
  } from './utils/index.js'
171
+ import { requireOpenPositions } from './utils/mapOpenPositions.js'
162
172
  import {
163
173
  fetchRegisteredApiKey,
164
174
  normalizeLighterPublicKey,
@@ -174,6 +184,14 @@ import { wireList } from './utils/wireList.js'
174
184
 
175
185
  const ZERO_FEE_TIER = { maker: '0', taker: '0' }
176
186
 
187
+ /** The sum of `values`, or `undefined` when any term is not a decimal string. */
188
+ const safeSum = (values: readonly string[]): string | undefined =>
189
+ values.reduce<string | undefined>(
190
+ (sum, value) =>
191
+ sum === undefined ? undefined : safeAddDecimalString(sum, value),
192
+ '0'
193
+ )
194
+
177
195
  const tickToFeeString = (tick: number): string =>
178
196
  numberToDecimalString(tick / LIGHTER_FEE_TICK_SCALE)
179
197
 
@@ -638,6 +656,86 @@ export const createLighterProvider = (
638
656
  }
639
657
  }
640
658
 
659
+ /**
660
+ * {@link retryOnRevoked}, then one retry with the standard token when the
661
+ * venue rejects the read-only one. The fallback sits outside
662
+ * `retryOnRevoked`, so a revocation the standard token reports never
663
+ * replaces the read-only one. The key is re-read at retry time because
664
+ * `REGISTER_API_KEY` can rotate it.
665
+ */
666
+ const retryWithStandardToken = <T>(
667
+ address: Address,
668
+ apiKey: LighterApiKey | null,
669
+ token: string,
670
+ run: (token: string) => Promise<T>
671
+ ): Promise<T> =>
672
+ retryOnRevoked(address, token, run).catch(async (err: unknown) => {
673
+ if (!(err instanceof LighterAuthRejectedError) || apiKey === null) {
674
+ throw err
675
+ }
676
+ const current = (await keyStore.get(address)) ?? apiKey
677
+ return run(
678
+ await getStandardAuthToken(address, current.apiKeyPrivateKey, {
679
+ apiKeyIndex: current.apiKeyIndex,
680
+ accountIndex: current.accountIndex,
681
+ })
682
+ )
683
+ })
684
+
685
+ const perpsCategoryId = async (): Promise<string> => {
686
+ const { providers } = await getProviders(requireClient())
687
+ return (
688
+ providers
689
+ .find((p) => p.key === providerKey)
690
+ ?.categories.find((c) => c.quoteAsset !== null)?.id ?? providerKey
691
+ )
692
+ }
693
+
694
+ /**
695
+ * The fast-withdraw terms for `accountIndex`, or `undefined` when no token
696
+ * resolves, a read fails, or Lighter offers no fast withdrawal.
697
+ */
698
+ const readFastWithdrawal = async (
699
+ client: LighterApiClient,
700
+ address: Address,
701
+ accountIndex: number
702
+ ): Promise<LighterFastWithdrawal | undefined> => {
703
+ try {
704
+ const apiKey = await keyStore.get(address)
705
+ const token = await resolveAuthToken(address, apiKey ?? undefined)
706
+ if (token === undefined) {
707
+ return undefined
708
+ }
709
+ const info = await retryWithStandardToken(address, apiKey, token, (t) =>
710
+ client.getAuthed<LtFastwithdrawInfoResponse>(
711
+ '/api/v1/fastwithdraw/info',
712
+ t,
713
+ { account_index: accountIndex }
714
+ )
715
+ )
716
+ if (info.code !== 200 || !(info.to_account_index > 0)) {
717
+ return undefined
718
+ }
719
+ const feeInfo = await retryWithStandardToken(
720
+ address,
721
+ apiKey,
722
+ token,
723
+ (t) =>
724
+ client.getAuthed<LtTransferFeeInfoResponse>(
725
+ '/api/v1/transferFeeInfo',
726
+ t,
727
+ {
728
+ account_index: accountIndex,
729
+ to_account_index: info.to_account_index,
730
+ }
731
+ )
732
+ )
733
+ return lighterFastWithdrawal(info, feeInfo)
734
+ } catch {
735
+ return undefined
736
+ }
737
+ }
738
+
641
739
  const fetchAccountLimits = (
642
740
  client: LighterApiClient,
643
741
  accountIndex: number,
@@ -830,7 +928,10 @@ export const createLighterProvider = (
830
928
  `The backend market '${marketId}' carries no positive Lighter default leverage`
831
929
  )
832
930
  }
833
- return { marginMode: MarginMode.CROSS, leverage }
931
+ return {
932
+ marginMode: MarginMode.CROSS,
933
+ leverage: numberToDecimalString(leverage),
934
+ }
834
935
  }
835
936
 
836
937
  const resolveAccountExists = async (
@@ -994,26 +1095,22 @@ export const createLighterProvider = (
994
1095
  ? readOnlyTokenManager.get(params.address, localKey.accountIndex)
995
1096
  : Promise.resolve(undefined),
996
1097
  ])
997
- const positions: Position[] = mapOpenPositions(account.positions, (id) =>
998
- toPerpsMarketDisplay(registry.require(String(id)))
1098
+ const positions: Position[] = requireOpenPositions(
1099
+ account.positions,
1100
+ (id) => toPerpsMarketDisplay(registry.require(String(id)))
999
1101
  )
1000
1102
 
1001
- const totalMarginUsed = positions.reduce(
1002
- (sum, p) => sum.plus(toRequiredBig(p.marginUsed, 'marginUsed')),
1003
- new Big(0)
1004
- )
1005
- const totalUnrealizedPnl = positions.reduce(
1006
- (sum, p) => sum.plus(toRequiredBig(p.unrealizedPnl, 'unrealizedPnl')),
1007
- new Big(0)
1008
- )
1103
+ const totalMarginUsed = safeSum(positions.map((p) => p.marginUsed))
1104
+ const totalUnrealizedPnl = safeSum(positions.map((p) => p.unrealizedPnl))
1009
1105
 
1010
1106
  const instanceMeta = providers.find((p) => p.key === providerKey)
1011
1107
  const categories = instanceMeta?.categories ?? []
1012
1108
  const perpsCategory = categories.find((c) => c.quoteAsset !== null)
1013
1109
 
1014
- const availableBalance = toRequiredBig(
1110
+ const availableBalance = unknownToDecimalString(
1015
1111
  account.available_balance,
1016
- 'available_balance'
1112
+ 'available_balance',
1113
+ providerKey
1017
1114
  )
1018
1115
  // Each asset has a spot route (`balance`) and a perps route
1019
1116
  // (`margin_balance`). The instance's settlement asset is valued 1:1; an
@@ -1023,15 +1120,24 @@ export const createLighterProvider = (
1023
1120
  account.account_trading_mode === LT_ACCOUNT_TRADING_MODE_UNIFIED &&
1024
1121
  asset.asset_id === collateral.assetIndex
1025
1122
  const heldAssets = account.assets.filter((asset) =>
1026
- (isPooled(asset)
1027
- ? pooledSettlementUnits(asset)
1028
- : toRequiredBig(asset.balance, 'balance')
1029
- ).gt(0)
1123
+ isDecimalStringGreaterThan(
1124
+ isPooled(asset)
1125
+ ? pooledSettlementUnits(asset)
1126
+ : unknownToDecimalString(asset.balance, 'balance', providerKey),
1127
+ '0'
1128
+ )
1030
1129
  )
1031
1130
  const marginAssets = account.assets.filter(
1032
1131
  (asset) =>
1033
1132
  !isPooled(asset) &&
1034
- toRequiredBig(asset.margin_balance, 'margin_balance').gt(0)
1133
+ isDecimalStringGreaterThan(
1134
+ unknownToDecimalString(
1135
+ asset.margin_balance,
1136
+ 'margin_balance',
1137
+ providerKey
1138
+ ),
1139
+ '0'
1140
+ )
1035
1141
  )
1036
1142
  const spotPrices = spotPriceByAssetId(
1037
1143
  registry.markets,
@@ -1060,7 +1166,7 @@ export const createLighterProvider = (
1060
1166
  asset,
1061
1167
  units,
1062
1168
  valueUsd,
1063
- ...(price === undefined ? {} : { price: price.toFixed() }),
1169
+ ...(price === undefined ? {} : { price }),
1064
1170
  }
1065
1171
  }
1066
1172
  const registryAsset = (a: LtAccountAsset): Asset =>
@@ -1079,46 +1185,51 @@ export const createLighterProvider = (
1079
1185
  // account's free margin; every other perps-route asset releases none.
1080
1186
  const collateralBalances: Balance[] = marginAssets.map((a) => {
1081
1187
  const isSettlement = a.asset_id === collateral.assetIndex
1082
- const marginBalance = toRequiredBig(
1188
+ const marginBalance = unknownToDecimalString(
1083
1189
  a.margin_balance,
1084
- 'margin_balance'
1085
- ).toFixed()
1190
+ 'margin_balance',
1191
+ providerKey
1192
+ )
1086
1193
  return {
1087
1194
  ...toBalance(
1088
1195
  a,
1089
1196
  perpsCategory?.id ?? providerKey,
1090
1197
  isSettlement ? settlementAsset : registryAsset(a),
1091
- isDecimalString(a.margin_balance) ? a.margin_balance : marginBalance
1198
+ marginBalance
1092
1199
  ),
1093
1200
  transferable: isSettlement
1094
- ? calculateTransferable(availableBalance.toFixed(), marginBalance)
1201
+ ? calculateTransferable(availableBalance, marginBalance)
1095
1202
  : '0',
1096
1203
  }
1097
1204
  })
1098
1205
  const balances: Balance[] = heldAssets.map((a) => {
1099
1206
  if (isPooled(a)) {
1100
- const units = pooledSettlementUnits(a).toFixed()
1207
+ const units = pooledSettlementUnits(a)
1101
1208
  return {
1102
1209
  ...toBalance(a, LIGHTER_SPOT_CATEGORY_ID, registryAsset(a), units),
1103
1210
  transferable: calculateTransferable(
1104
- pooledSettlementSpendable(a, availableBalance).toFixed(),
1211
+ pooledSettlementSpendable(a, availableBalance),
1105
1212
  units
1106
1213
  ),
1107
1214
  }
1108
1215
  }
1109
- const balance = toRequiredBig(a.balance, 'balance')
1216
+ const balance = unknownToDecimalString(
1217
+ a.balance,
1218
+ 'balance',
1219
+ providerKey
1220
+ )
1110
1221
  return {
1111
- ...toBalance(
1112
- a,
1113
- LIGHTER_SPOT_CATEGORY_ID,
1114
- registryAsset(a),
1115
- isDecimalString(a.balance) ? a.balance : balance.toFixed()
1116
- ),
1222
+ ...toBalance(a, LIGHTER_SPOT_CATEGORY_ID, registryAsset(a), balance),
1117
1223
  transferable: calculateTransferable(
1224
+ subtractDecimalString(
1225
+ balance,
1226
+ unknownToDecimalString(
1227
+ a.locked_balance,
1228
+ 'locked_balance',
1229
+ providerKey
1230
+ )
1231
+ ),
1118
1232
  balance
1119
- .minus(toRequiredBig(a.locked_balance, 'locked_balance'))
1120
- .toFixed(),
1121
- balance.toFixed()
1122
1233
  ),
1123
1234
  }
1124
1235
  })
@@ -1169,8 +1280,12 @@ export const createLighterProvider = (
1169
1280
  balances,
1170
1281
  collateralBalances,
1171
1282
  positions,
1172
- marginUsed: totalMarginUsed.toFixed(),
1173
- unrealizedPnl: totalUnrealizedPnl.toFixed(),
1283
+ ...(totalMarginUsed === undefined
1284
+ ? {}
1285
+ : { marginUsed: totalMarginUsed }),
1286
+ ...(totalUnrealizedPnl === undefined
1287
+ ? {}
1288
+ : { unrealizedPnl: totalUnrealizedPnl }),
1174
1289
  feeTier:
1175
1290
  limitsResult === undefined
1176
1291
  ? ZERO_FEE_TIER
@@ -1200,11 +1315,41 @@ export const createLighterProvider = (
1200
1315
  params: ProviderGetWithdrawableBalancesParams,
1201
1316
  opts?: SDKRequestOptions
1202
1317
  ): Promise<ProviderWithdrawableBalance[]> {
1203
- const account = await fetchDetailedAccount(
1204
- apiClient(opts),
1205
- params.address
1318
+ const [account, categoryId] = await Promise.all([
1319
+ fetchDetailedAccount(apiClient(opts), params.address),
1320
+ perpsCategoryId(),
1321
+ ])
1322
+ return lighterWithdrawableBalances(
1323
+ account,
1324
+ collateral.assetIndex,
1325
+ categoryId
1326
+ )
1327
+ },
1328
+
1329
+ async getWithdrawalTypes(
1330
+ params: ProviderGetWithdrawalTypesParams,
1331
+ opts?: SDKRequestOptions
1332
+ ): Promise<WithdrawalSourceTypes[]> {
1333
+ const client = apiClient(opts)
1334
+ const [account, categoryId] = await Promise.all([
1335
+ fetchDetailedAccount(client, params.address),
1336
+ perpsCategoryId(),
1337
+ ])
1338
+ const rows = lighterWithdrawableBalances(
1339
+ account,
1340
+ collateral.assetIndex,
1341
+ categoryId
1342
+ )
1343
+ const fast = await readFastWithdrawal(
1344
+ client,
1345
+ params.address,
1346
+ account.index
1347
+ )
1348
+ return lighterWithdrawalTypes(
1349
+ rows,
1350
+ { categoryId, asset: { id: String(collateral.assetIndex) } },
1351
+ fast
1206
1352
  )
1207
- return lighterWithdrawableBalances(account, collateral.assetIndex)
1208
1353
  },
1209
1354
 
1210
1355
  async getPositions(
@@ -1249,18 +1394,20 @@ export const createLighterProvider = (
1249
1394
  }
1250
1395
  const account = await plugin.getAccount({ address: params.address }, opts)
1251
1396
  const config = lighterConfig(account)
1252
- const crossFreeCollateral = toRequiredBig(
1253
- config.crossAssetValue,
1254
- 'crossAssetValue'
1255
- ).minus(
1256
- toRequiredBig(
1257
- config.crossInitialMarginRequirement,
1258
- 'crossInitialMarginRequirement'
1259
- )
1260
- )
1261
1397
  return lighterAvailableToTrade(
1262
1398
  market,
1263
- crossFreeCollateral.toFixed(),
1399
+ subtractDecimalString(
1400
+ unknownToDecimalString(
1401
+ config.crossAssetValue,
1402
+ 'crossAssetValue',
1403
+ providerKey
1404
+ ),
1405
+ unknownToDecimalString(
1406
+ config.crossInitialMarginRequirement,
1407
+ 'crossInitialMarginRequirement',
1408
+ providerKey
1409
+ )
1410
+ ),
1264
1411
  account.positions
1265
1412
  )
1266
1413
  },
@@ -1291,10 +1438,11 @@ export const createLighterProvider = (
1291
1438
  row === undefined
1292
1439
  ? undefined
1293
1440
  : leverageFromImf(
1294
- toRequiredBig(
1441
+ unknownToDecimalString(
1295
1442
  row.initial_margin_fraction,
1296
- 'initial_margin_fraction'
1297
- ).toFixed()
1443
+ 'initial_margin_fraction',
1444
+ providerKey
1445
+ )
1298
1446
  )
1299
1447
  if (row === undefined || leverage === undefined) {
1300
1448
  return resolveDefaultMarketSettings(marketId)
@@ -1378,7 +1526,7 @@ export const createLighterProvider = (
1378
1526
  continue
1379
1527
  }
1380
1528
  const order = mapOrder(raw, market)
1381
- if (statuses.has(order.status)) {
1529
+ if (order !== undefined && statuses.has(order.status)) {
1382
1530
  orders.push(order)
1383
1531
  }
1384
1532
  }
@@ -1423,8 +1571,15 @@ export const createLighterProvider = (
1423
1571
  PerpsErrorCode.OrderNotFound,
1424
1572
  `Lighter order ${params.id} not found for ${params.address}`
1425
1573
  )
1426
- const detail = (order: LtOrder): Order =>
1574
+ const mapDetail = (order: LtOrder): Order | undefined =>
1427
1575
  mapOrder(order, registry.require(String(order.market_index)))
1576
+ const detail = (order: LtOrder): Order => {
1577
+ const mapped = mapDetail(order)
1578
+ if (mapped === undefined) {
1579
+ throw notFound()
1580
+ }
1581
+ return mapped
1582
+ }
1428
1583
 
1429
1584
  // A tx-hash route would require mapping the caller's executeAction tx
1430
1585
  // hash → wasm nonce → matching order, which the LI.FI backend did via
@@ -1464,7 +1619,7 @@ export const createLighterProvider = (
1464
1619
  // client order index can match more than one row. Prefer the live one.
1465
1620
  const matches = orders
1466
1621
  .filter((o) => String(o.client_order_index) === clientOrderIndex)
1467
- .map(detail)
1622
+ .flatMap((o) => mapDetail(o) ?? [])
1468
1623
  const hit =
1469
1624
  matches.find((o) => isActiveOrderStatus(o.status)) ?? matches[0]
1470
1625
  if (hit === undefined) {
@@ -1536,10 +1691,8 @@ export const createLighterProvider = (
1536
1691
  // resolves, so its rows stay.
1537
1692
  const items = wireList(response.trades).flatMap((t): Fill[] => {
1538
1693
  const market = registry.get(String(t.market_id))
1539
- if (market === undefined) {
1540
- return []
1541
- }
1542
- return [mapFill(t, account.index, market)]
1694
+ const mapped = market && mapFill(t, account.index, market)
1695
+ return mapped ? [mapped] : []
1543
1696
  })
1544
1697
 
1545
1698
  return {
@@ -1583,34 +1736,18 @@ export const createLighterProvider = (
1583
1736
  const read = (tok: string) =>
1584
1737
  client.getAuthed<LtAccountPnL>('/api/v1/pnl', tok, queryParams)
1585
1738
 
1586
- // The read-only token may not be accepted on `/pnl`; the standard token
1587
- // is, so a read signed from the SDK's own key retries once with it. The
1588
- // fallback sits outside `retryOnRevoked`, so a revocation the standard
1589
- // token reports never replaces the read-only one. The key is re-read at
1590
- // retry time because `REGISTER_API_KEY` can rotate it.
1591
- const response = await retryOnRevoked(params.address, token, read).catch(
1592
- async (err: unknown) => {
1593
- if (!(err instanceof LighterAuthRejectedError) || apiKey === null) {
1594
- throw err
1595
- }
1596
- const current = (await keyStore.get(params.address)) ?? apiKey
1597
- return read(
1598
- await getStandardAuthToken(
1599
- params.address,
1600
- current.apiKeyPrivateKey,
1601
- {
1602
- apiKeyIndex: current.apiKeyIndex,
1603
- accountIndex: current.accountIndex,
1604
- }
1605
- )
1606
- )
1607
- }
1739
+ // The read-only token may not be accepted on `/pnl`; the standard token is.
1740
+ const response = await retryWithStandardToken(
1741
+ params.address,
1742
+ apiKey,
1743
+ token,
1744
+ read
1608
1745
  )
1609
1746
 
1610
1747
  return mapPortfolioHistory(
1611
1748
  params.range,
1612
1749
  wireList(response.pnl),
1613
- new Big(getAccountSummary(account, account.positions).portfolioValue)
1750
+ getAccountSummary(account, account.positions).portfolioValue
1614
1751
  )
1615
1752
  },
1616
1753
 
@@ -1706,8 +1843,12 @@ export const createLighterProvider = (
1706
1843
  if (market === undefined) {
1707
1844
  return []
1708
1845
  }
1709
- const price = toBigOrNull(l.trade.price)
1710
- const size = toBigOrNull(l.trade.size)
1846
+ const notional = safeMultiplyDecimalString(
1847
+ l.trade.price,
1848
+ l.trade.size
1849
+ )
1850
+ const liquidatedNotionalPosition =
1851
+ notional === undefined ? undefined : safeAbsDecimalString(notional)
1711
1852
  const marginMode = wireList(l.info.positions).find(
1712
1853
  (p) => p.market_id === l.market_id
1713
1854
  )?.margin_mode
@@ -1728,14 +1869,9 @@ export const createLighterProvider = (
1728
1869
  provider: providerKey,
1729
1870
  timestamp: toIsoFromMs(l.executed_at),
1730
1871
  type: ActivityType.LIQUIDATION,
1731
- ...(price === null || size === null
1872
+ ...(liquidatedNotionalPosition === undefined
1732
1873
  ? {}
1733
- : {
1734
- liquidatedNotionalPosition: price
1735
- .times(size)
1736
- .abs()
1737
- .toFixed(),
1738
- }),
1874
+ : { liquidatedNotionalPosition }),
1739
1875
  // The account value at liquidation time is the pre-trade
1740
1876
  // snapshot, not the settled one Lighter also reports.
1741
1877
  ...(accountValue === undefined ? {} : { accountValue }),
@@ -1826,7 +1962,7 @@ export const createLighterProvider = (
1826
1962
 
1827
1963
  snapOrderSize,
1828
1964
 
1829
- estimateLiquidationPrice,
1965
+ estimateLiquidationPrice: estimateLiquidationPriceAtMarketRate,
1830
1966
 
1831
1967
  positionRemovableMargin,
1832
1968