@lifi/perps-sdk 23.1.0 → 25.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 (305) hide show
  1. package/README.md +102 -56
  2. package/dist/cjs/client/PerpsClient.d.ts +3 -2
  3. package/dist/cjs/client/PerpsClient.d.ts.map +1 -1
  4. package/dist/cjs/client/PerpsClient.js +16 -9
  5. package/dist/cjs/client/PerpsClient.js.map +1 -1
  6. package/dist/cjs/decimal/arithmetic.d.ts +15 -0
  7. package/dist/cjs/decimal/arithmetic.d.ts.map +1 -0
  8. package/dist/cjs/decimal/arithmetic.js +53 -0
  9. package/dist/cjs/decimal/arithmetic.js.map +1 -0
  10. package/dist/cjs/decimal/big.d.ts +0 -1
  11. package/dist/cjs/decimal/big.d.ts.map +1 -1
  12. package/dist/cjs/decimal/big.js +0 -4
  13. package/dist/cjs/decimal/big.js.map +1 -1
  14. package/dist/cjs/decimal/compare.d.ts +6 -2
  15. package/dist/cjs/decimal/compare.d.ts.map +1 -1
  16. package/dist/cjs/decimal/compare.js +15 -2
  17. package/dist/cjs/decimal/compare.js.map +1 -1
  18. package/dist/cjs/decimal/convert.d.ts +10 -6
  19. package/dist/cjs/decimal/convert.d.ts.map +1 -1
  20. package/dist/cjs/decimal/convert.js +34 -21
  21. package/dist/cjs/decimal/convert.js.map +1 -1
  22. package/dist/cjs/decimal/decimalStringToBig.d.ts +5 -0
  23. package/dist/cjs/decimal/decimalStringToBig.d.ts.map +1 -0
  24. package/dist/cjs/decimal/decimalStringToBig.js +25 -0
  25. package/dist/cjs/decimal/decimalStringToBig.js.map +1 -0
  26. package/dist/cjs/decimal/format.d.ts.map +1 -1
  27. package/dist/cjs/decimal/format.js +70 -52
  28. package/dist/cjs/decimal/format.js.map +1 -1
  29. package/dist/cjs/decimal/parse.d.ts +5 -4
  30. package/dist/cjs/decimal/parse.d.ts.map +1 -1
  31. package/dist/cjs/decimal/parse.js +43 -25
  32. package/dist/cjs/decimal/parse.js.map +1 -1
  33. package/dist/cjs/errors/invalidInput.d.ts +3 -0
  34. package/dist/cjs/errors/invalidInput.d.ts.map +1 -0
  35. package/dist/cjs/errors/invalidInput.js +9 -0
  36. package/dist/cjs/errors/invalidInput.js.map +1 -0
  37. package/dist/cjs/index.d.ts +15 -12
  38. package/dist/cjs/index.d.ts.map +1 -1
  39. package/dist/cjs/index.js +69 -9
  40. package/dist/cjs/index.js.map +1 -1
  41. package/dist/cjs/math/fills.d.ts +1 -1
  42. package/dist/cjs/math/fills.d.ts.map +1 -1
  43. package/dist/cjs/math/fills.js +28 -13
  44. package/dist/cjs/math/fills.js.map +1 -1
  45. package/dist/cjs/math/order.d.ts +27 -16
  46. package/dist/cjs/math/order.d.ts.map +1 -1
  47. package/dist/cjs/math/order.js +131 -134
  48. package/dist/cjs/math/order.js.map +1 -1
  49. package/dist/cjs/math/position.d.ts +85 -35
  50. package/dist/cjs/math/position.d.ts.map +1 -1
  51. package/dist/cjs/math/position.js +93 -94
  52. package/dist/cjs/math/position.js.map +1 -1
  53. package/dist/cjs/services/getGasRecommendation.js +1 -1
  54. package/dist/cjs/services/getGasRecommendation.js.map +1 -1
  55. package/dist/cjs/services/getQuote.d.ts +1 -1
  56. package/dist/cjs/services/resolveSubscribeQuote.d.ts.map +1 -1
  57. package/dist/cjs/services/resolveSubscribeQuote.js +3 -2
  58. package/dist/cjs/services/resolveSubscribeQuote.js.map +1 -1
  59. package/dist/cjs/transport/request.d.ts +1 -0
  60. package/dist/cjs/transport/request.d.ts.map +1 -1
  61. package/dist/cjs/transport/request.js +2 -2
  62. package/dist/cjs/transport/request.js.map +1 -1
  63. package/dist/cjs/types/api.d.ts +4 -0
  64. package/dist/cjs/types/api.d.ts.map +1 -1
  65. package/dist/cjs/types/provider.d.ts +9 -5
  66. package/dist/cjs/types/provider.d.ts.map +1 -1
  67. package/dist/cjs/types/withdrawal.d.ts +12 -4
  68. package/dist/cjs/types/withdrawal.d.ts.map +1 -1
  69. package/dist/cjs/utils/createSafeFunction.d.ts +2 -0
  70. package/dist/cjs/utils/createSafeFunction.d.ts.map +1 -0
  71. package/dist/cjs/utils/createSafeFunction.js +15 -0
  72. package/dist/cjs/utils/createSafeFunction.js.map +1 -0
  73. package/dist/cjs/utils/timestampToIsoString.d.ts +3 -0
  74. package/dist/cjs/utils/timestampToIsoString.d.ts.map +1 -0
  75. package/dist/cjs/utils/timestampToIsoString.js +16 -0
  76. package/dist/cjs/utils/timestampToIsoString.js.map +1 -0
  77. package/dist/cjs/utils/warnOnce.d.ts +6 -0
  78. package/dist/cjs/utils/warnOnce.d.ts.map +1 -1
  79. package/dist/cjs/utils/warnOnce.js +19 -1
  80. package/dist/cjs/utils/warnOnce.js.map +1 -1
  81. package/dist/cjs/version.d.ts +1 -1
  82. package/dist/cjs/version.js +1 -1
  83. package/dist/cjs/websocket/PerpsWsClient.d.ts +2 -0
  84. package/dist/cjs/websocket/PerpsWsClient.d.ts.map +1 -1
  85. package/dist/cjs/websocket/PerpsWsClient.js +14 -1
  86. package/dist/cjs/websocket/PerpsWsClient.js.map +1 -1
  87. package/dist/cjs/websocket/wsLog.d.ts +2 -0
  88. package/dist/cjs/websocket/wsLog.d.ts.map +1 -1
  89. package/dist/cjs/websocket/wsLog.js +9 -0
  90. package/dist/cjs/websocket/wsLog.js.map +1 -1
  91. package/dist/cjs/wire/orderAmounts.d.ts +3 -2
  92. package/dist/cjs/wire/orderAmounts.d.ts.map +1 -1
  93. package/dist/cjs/wire/orderAmounts.js +22 -21
  94. package/dist/cjs/wire/orderAmounts.js.map +1 -1
  95. package/dist/cjs/wire/refuel.d.ts +4 -1
  96. package/dist/cjs/wire/refuel.d.ts.map +1 -1
  97. package/dist/cjs/wire/refuel.js +23 -6
  98. package/dist/cjs/wire/refuel.js.map +1 -1
  99. package/dist/cjs/wire/transferable.js +3 -3
  100. package/dist/cjs/wire/transferable.js.map +1 -1
  101. package/dist/cjs/wire/withdraw.d.ts.map +1 -1
  102. package/dist/cjs/wire/withdraw.js +3 -3
  103. package/dist/cjs/wire/withdraw.js.map +1 -1
  104. package/dist/esm/client/PerpsClient.d.ts +17 -4
  105. package/dist/esm/client/PerpsClient.d.ts.map +1 -1
  106. package/dist/esm/client/PerpsClient.js +30 -8
  107. package/dist/esm/client/PerpsClient.js.map +1 -1
  108. package/dist/esm/decimal/arithmetic.d.ts +98 -0
  109. package/dist/esm/decimal/arithmetic.d.ts.map +1 -0
  110. package/dist/esm/decimal/arithmetic.js +126 -0
  111. package/dist/esm/decimal/arithmetic.js.map +1 -0
  112. package/dist/esm/decimal/big.d.ts +0 -2
  113. package/dist/esm/decimal/big.d.ts.map +1 -1
  114. package/dist/esm/decimal/big.js +0 -4
  115. package/dist/esm/decimal/big.js.map +1 -1
  116. package/dist/esm/decimal/compare.d.ts +40 -6
  117. package/dist/esm/decimal/compare.d.ts.map +1 -1
  118. package/dist/esm/decimal/compare.js +46 -6
  119. package/dist/esm/decimal/compare.js.map +1 -1
  120. package/dist/esm/decimal/convert.d.ts +50 -36
  121. package/dist/esm/decimal/convert.d.ts.map +1 -1
  122. package/dist/esm/decimal/convert.js +64 -42
  123. package/dist/esm/decimal/convert.js.map +1 -1
  124. package/dist/esm/decimal/decimalStringToBig.d.ts +25 -0
  125. package/dist/esm/decimal/decimalStringToBig.d.ts.map +1 -0
  126. package/dist/esm/decimal/decimalStringToBig.js +37 -0
  127. package/dist/esm/decimal/decimalStringToBig.js.map +1 -0
  128. package/dist/esm/decimal/format.d.ts +4 -1
  129. package/dist/esm/decimal/format.d.ts.map +1 -1
  130. package/dist/esm/decimal/format.js +71 -70
  131. package/dist/esm/decimal/format.js.map +1 -1
  132. package/dist/esm/decimal/parse.d.ts +29 -13
  133. package/dist/esm/decimal/parse.d.ts.map +1 -1
  134. package/dist/esm/decimal/parse.js +61 -44
  135. package/dist/esm/decimal/parse.js.map +1 -1
  136. package/dist/esm/errors/invalidInput.d.ts +4 -0
  137. package/dist/esm/errors/invalidInput.d.ts.map +1 -0
  138. package/dist/esm/errors/invalidInput.js +7 -0
  139. package/dist/esm/errors/invalidInput.js.map +1 -0
  140. package/dist/esm/index.d.ts +15 -12
  141. package/dist/esm/index.d.ts.map +1 -1
  142. package/dist/esm/index.js +11 -8
  143. package/dist/esm/index.js.map +1 -1
  144. package/dist/esm/math/fills.d.ts +6 -3
  145. package/dist/esm/math/fills.d.ts.map +1 -1
  146. package/dist/esm/math/fills.js +31 -16
  147. package/dist/esm/math/fills.js.map +1 -1
  148. package/dist/esm/math/order.d.ts +84 -66
  149. package/dist/esm/math/order.d.ts.map +1 -1
  150. package/dist/esm/math/order.js +178 -175
  151. package/dist/esm/math/order.js.map +1 -1
  152. package/dist/esm/math/position.d.ts +155 -98
  153. package/dist/esm/math/position.d.ts.map +1 -1
  154. package/dist/esm/math/position.js +160 -156
  155. package/dist/esm/math/position.js.map +1 -1
  156. package/dist/esm/services/getGasRecommendation.js +1 -1
  157. package/dist/esm/services/getGasRecommendation.js.map +1 -1
  158. package/dist/esm/services/getQuote.d.ts +2 -2
  159. package/dist/esm/services/getQuote.js +1 -1
  160. package/dist/esm/services/resolveSubscribeQuote.d.ts +1 -1
  161. package/dist/esm/services/resolveSubscribeQuote.d.ts.map +1 -1
  162. package/dist/esm/services/resolveSubscribeQuote.js +4 -3
  163. package/dist/esm/services/resolveSubscribeQuote.js.map +1 -1
  164. package/dist/esm/transport/request.d.ts +5 -0
  165. package/dist/esm/transport/request.d.ts.map +1 -1
  166. package/dist/esm/transport/request.js +2 -2
  167. package/dist/esm/transport/request.js.map +1 -1
  168. package/dist/esm/types/api.d.ts +9 -0
  169. package/dist/esm/types/api.d.ts.map +1 -1
  170. package/dist/esm/types/provider.d.ts +30 -16
  171. package/dist/esm/types/provider.d.ts.map +1 -1
  172. package/dist/esm/types/withdrawal.d.ts +32 -7
  173. package/dist/esm/types/withdrawal.d.ts.map +1 -1
  174. package/dist/esm/utils/createSafeFunction.d.ts +9 -0
  175. package/dist/esm/utils/createSafeFunction.d.ts.map +1 -0
  176. package/dist/esm/utils/createSafeFunction.js +19 -0
  177. package/dist/esm/utils/createSafeFunction.js.map +1 -0
  178. package/dist/esm/utils/timestampToIsoString.d.ts +15 -0
  179. package/dist/esm/utils/timestampToIsoString.d.ts.map +1 -0
  180. package/dist/esm/utils/timestampToIsoString.js +24 -0
  181. package/dist/esm/utils/timestampToIsoString.js.map +1 -0
  182. package/dist/esm/utils/warnOnce.d.ts +27 -0
  183. package/dist/esm/utils/warnOnce.d.ts.map +1 -1
  184. package/dist/esm/utils/warnOnce.js +36 -0
  185. package/dist/esm/utils/warnOnce.js.map +1 -1
  186. package/dist/esm/version.d.ts +1 -1
  187. package/dist/esm/version.js +1 -1
  188. package/dist/esm/websocket/PerpsWsClient.d.ts +7 -0
  189. package/dist/esm/websocket/PerpsWsClient.d.ts.map +1 -1
  190. package/dist/esm/websocket/PerpsWsClient.js +20 -2
  191. package/dist/esm/websocket/PerpsWsClient.js.map +1 -1
  192. package/dist/esm/websocket/wsLog.d.ts +12 -0
  193. package/dist/esm/websocket/wsLog.d.ts.map +1 -1
  194. package/dist/esm/websocket/wsLog.js +19 -0
  195. package/dist/esm/websocket/wsLog.js.map +1 -1
  196. package/dist/esm/wire/orderAmounts.d.ts +9 -7
  197. package/dist/esm/wire/orderAmounts.d.ts.map +1 -1
  198. package/dist/esm/wire/orderAmounts.js +24 -20
  199. package/dist/esm/wire/orderAmounts.js.map +1 -1
  200. package/dist/esm/wire/refuel.d.ts +24 -14
  201. package/dist/esm/wire/refuel.d.ts.map +1 -1
  202. package/dist/esm/wire/refuel.js +38 -17
  203. package/dist/esm/wire/refuel.js.map +1 -1
  204. package/dist/esm/wire/transferable.d.ts +2 -2
  205. package/dist/esm/wire/transferable.js +5 -5
  206. package/dist/esm/wire/transferable.js.map +1 -1
  207. package/dist/esm/wire/withdraw.d.ts.map +1 -1
  208. package/dist/esm/wire/withdraw.js +3 -3
  209. package/dist/esm/wire/withdraw.js.map +1 -1
  210. package/dist/types/client/PerpsClient.d.ts +17 -4
  211. package/dist/types/client/PerpsClient.d.ts.map +1 -1
  212. package/dist/types/decimal/arithmetic.d.ts +98 -0
  213. package/dist/types/decimal/arithmetic.d.ts.map +1 -0
  214. package/dist/types/decimal/big.d.ts +0 -2
  215. package/dist/types/decimal/big.d.ts.map +1 -1
  216. package/dist/types/decimal/compare.d.ts +40 -6
  217. package/dist/types/decimal/compare.d.ts.map +1 -1
  218. package/dist/types/decimal/convert.d.ts +50 -36
  219. package/dist/types/decimal/convert.d.ts.map +1 -1
  220. package/dist/types/decimal/decimalStringToBig.d.ts +25 -0
  221. package/dist/types/decimal/decimalStringToBig.d.ts.map +1 -0
  222. package/dist/types/decimal/format.d.ts +4 -1
  223. package/dist/types/decimal/format.d.ts.map +1 -1
  224. package/dist/types/decimal/parse.d.ts +29 -13
  225. package/dist/types/decimal/parse.d.ts.map +1 -1
  226. package/dist/types/errors/invalidInput.d.ts +4 -0
  227. package/dist/types/errors/invalidInput.d.ts.map +1 -0
  228. package/dist/types/index.d.ts +15 -12
  229. package/dist/types/index.d.ts.map +1 -1
  230. package/dist/types/math/fills.d.ts +6 -3
  231. package/dist/types/math/fills.d.ts.map +1 -1
  232. package/dist/types/math/order.d.ts +84 -66
  233. package/dist/types/math/order.d.ts.map +1 -1
  234. package/dist/types/math/position.d.ts +155 -98
  235. package/dist/types/math/position.d.ts.map +1 -1
  236. package/dist/types/services/getQuote.d.ts +2 -2
  237. package/dist/types/services/resolveSubscribeQuote.d.ts +1 -1
  238. package/dist/types/services/resolveSubscribeQuote.d.ts.map +1 -1
  239. package/dist/types/transport/request.d.ts +5 -0
  240. package/dist/types/transport/request.d.ts.map +1 -1
  241. package/dist/types/types/api.d.ts +9 -0
  242. package/dist/types/types/api.d.ts.map +1 -1
  243. package/dist/types/types/provider.d.ts +30 -16
  244. package/dist/types/types/provider.d.ts.map +1 -1
  245. package/dist/types/types/withdrawal.d.ts +32 -7
  246. package/dist/types/types/withdrawal.d.ts.map +1 -1
  247. package/dist/types/utils/createSafeFunction.d.ts +9 -0
  248. package/dist/types/utils/createSafeFunction.d.ts.map +1 -0
  249. package/dist/types/utils/timestampToIsoString.d.ts +15 -0
  250. package/dist/types/utils/timestampToIsoString.d.ts.map +1 -0
  251. package/dist/types/utils/warnOnce.d.ts +27 -0
  252. package/dist/types/utils/warnOnce.d.ts.map +1 -1
  253. package/dist/types/version.d.ts +1 -1
  254. package/dist/types/websocket/PerpsWsClient.d.ts +7 -0
  255. package/dist/types/websocket/PerpsWsClient.d.ts.map +1 -1
  256. package/dist/types/websocket/wsLog.d.ts +12 -0
  257. package/dist/types/websocket/wsLog.d.ts.map +1 -1
  258. package/dist/types/wire/orderAmounts.d.ts +9 -7
  259. package/dist/types/wire/orderAmounts.d.ts.map +1 -1
  260. package/dist/types/wire/refuel.d.ts +24 -14
  261. package/dist/types/wire/refuel.d.ts.map +1 -1
  262. package/dist/types/wire/transferable.d.ts +2 -2
  263. package/dist/types/wire/withdraw.d.ts.map +1 -1
  264. package/package.json +2 -2
  265. package/src/client/PerpsClient.ts +48 -10
  266. package/src/decimal/arithmetic.ts +170 -0
  267. package/src/decimal/big.ts +0 -5
  268. package/src/decimal/compare.ts +61 -11
  269. package/src/decimal/convert.ts +105 -63
  270. package/src/decimal/decimalStringToBig.ts +42 -0
  271. package/src/decimal/format.ts +81 -72
  272. package/src/decimal/parse.ts +78 -57
  273. package/src/errors/invalidInput.ts +10 -0
  274. package/src/index.ts +80 -12
  275. package/src/math/fills.ts +32 -17
  276. package/src/math/order.ts +279 -226
  277. package/src/math/position.ts +280 -196
  278. package/src/services/getGasRecommendation.ts +1 -1
  279. package/src/services/getQuote.ts +2 -2
  280. package/src/services/resolveSubscribeQuote.ts +4 -3
  281. package/src/transport/request.ts +7 -2
  282. package/src/types/api.ts +10 -0
  283. package/src/types/provider.ts +39 -16
  284. package/src/types/withdrawal.ts +35 -8
  285. package/src/utils/createSafeFunction.ts +20 -0
  286. package/src/utils/timestampToIsoString.ts +31 -0
  287. package/src/utils/warnOnce.ts +60 -0
  288. package/src/version.ts +1 -1
  289. package/src/websocket/PerpsWsClient.ts +25 -2
  290. package/src/websocket/wsLog.ts +44 -0
  291. package/src/wire/orderAmounts.ts +45 -26
  292. package/src/wire/refuel.ts +56 -20
  293. package/src/wire/transferable.ts +5 -5
  294. package/src/wire/withdraw.ts +3 -5
  295. package/dist/cjs/decimal/requireDecimal.d.ts +0 -4
  296. package/dist/cjs/decimal/requireDecimal.d.ts.map +0 -1
  297. package/dist/cjs/decimal/requireDecimal.js +0 -12
  298. package/dist/cjs/decimal/requireDecimal.js.map +0 -1
  299. package/dist/esm/decimal/requireDecimal.d.ts +0 -5
  300. package/dist/esm/decimal/requireDecimal.d.ts.map +0 -1
  301. package/dist/esm/decimal/requireDecimal.js +0 -7
  302. package/dist/esm/decimal/requireDecimal.js.map +0 -1
  303. package/dist/types/decimal/requireDecimal.d.ts +0 -5
  304. package/dist/types/decimal/requireDecimal.d.ts.map +0 -1
  305. package/src/decimal/requireDecimal.ts +0 -8
@@ -20,6 +20,11 @@ import {
20
20
  export interface RequestOptions extends RequestInit {
21
21
  /** Per-call retry override. Falls back to the resolved client-level policy. */
22
22
  retry?: RetryPolicy | false
23
+ /**
24
+ * Send `x-lifi-perps-sdk`. Defaults to `true`. The LI.FI API CORS preflight
25
+ * does not allow the header, so a browser blocks a LI.FI API call that sends it.
26
+ */
27
+ perpsSdkHeader?: boolean
23
28
  /** Successful response metadata, delivered only after JSON decoding. */
24
29
  onResponse?: (
25
30
  headers: Headers,
@@ -40,7 +45,7 @@ export async function request<T>(
40
45
  options: RequestOptions = {},
41
46
  sdkOptions?: SDKRequestOptions
42
47
  ): Promise<T> {
43
- const { retry, onResponse, ...fetchInit } = options
48
+ const { retry, onResponse, perpsSdkHeader = true, ...fetchInit } = options
44
49
  const policy =
45
50
  retry !== undefined
46
51
  ? resolveRetryPolicy(LIFI_RETRY_DEFAULTS, retry, LIFI_REQUEST_KEY)
@@ -48,7 +53,7 @@ export async function request<T>(
48
53
 
49
54
  const headers: Record<string, string> = {
50
55
  'Content-Type': 'application/json',
51
- 'x-lifi-perps-sdk': version,
56
+ ...(perpsSdkHeader && { 'x-lifi-perps-sdk': version }),
52
57
  ...(fetchInit.headers as Record<string, string>),
53
58
  }
54
59
 
package/src/types/api.ts CHANGED
@@ -293,6 +293,16 @@ export interface GetWithdrawableBalancesParams {
293
293
  address: Address
294
294
  }
295
295
 
296
+ /**
297
+ * Parameters for {@link PerpsClient.getWithdrawalTypes}.
298
+ *
299
+ * @public
300
+ */
301
+ export interface GetWithdrawalTypesParams {
302
+ provider: string
303
+ address: Address
304
+ }
305
+
296
306
  /**
297
307
  * Parameters for {@link PerpsClient.getPortfolioHistory}.
298
308
  *
@@ -37,7 +37,11 @@ import type {
37
37
  SDKRequestOptions,
38
38
  } from './config.js'
39
39
  import type { DepositFlow } from './deposit.js'
40
- import type { ProviderWithdrawableBalance, WithdrawFlow } from './withdrawal.js'
40
+ import type {
41
+ ProviderWithdrawableBalance,
42
+ WithdrawalSourceTypes,
43
+ WithdrawFlow,
44
+ } from './withdrawal.js'
41
45
 
42
46
  /**
43
47
  * Low-level SDK client: resolved config, the optional end-user wallet, and the
@@ -147,8 +151,8 @@ export interface ActionSignerContribution {
147
151
  */
148
152
  export interface LiquidationEstimateParams {
149
153
  /** Entry price in quote currency per base unit. */
150
- entryPrice: number
151
- leverage: number
154
+ entryPrice: string
155
+ leverage: string
152
156
  /** `true` for long, `false` for short. */
153
157
  isLong: boolean
154
158
  }
@@ -199,6 +203,15 @@ export interface ProviderGetWithdrawableBalancesParams {
199
203
  address: Address
200
204
  }
201
205
 
206
+ /**
207
+ * Read params for {@link PerpsProviderPlugin.getWithdrawalTypes}.
208
+ *
209
+ * @public
210
+ */
211
+ export interface ProviderGetWithdrawalTypesParams {
212
+ address: Address
213
+ }
214
+
202
215
  /**
203
216
  * Read params for {@link PerpsProvider.getPositions}.
204
217
  *
@@ -322,7 +335,7 @@ export interface ProviderGetQuoteParams {
322
335
  /** Trade direction used to choose asks for buys or bids for sells. */
323
336
  side: QuoteSide
324
337
  /** USD notional to fill. */
325
- size: number
338
+ size: string
326
339
  /** Product family used to disambiguate spot and perpetual markets. */
327
340
  type: TradeType
328
341
  }
@@ -434,20 +447,33 @@ export interface PerpsProviderPlugin {
434
447
  ): Promise<WithdrawFlow>
435
448
 
436
449
  /**
437
- * The `(asset, route)` pairs `params.address` currently has something to
450
+ * The `(asset, category)` pairs `params.address` currently has something to
438
451
  * withdraw from, keyed by provider-native asset id. Only the venue knows how
439
- * its balance payload splits across routes, so the split is owned here; the
452
+ * its balance payload splits across categories, so the split is owned here; the
440
453
  * per-asset venue minimum is applied by `PerpsClient.getWithdrawableBalances`,
441
454
  * which holds the core asset registry.
442
455
  *
443
- * Optional: a provider whose withdrawals are not a per-route selection omits
444
- * it, and `PerpsClient.getWithdrawableBalances` then resolves `undefined`.
456
+ * Optional: a provider whose withdrawals are not a per-category selection
457
+ * omits it, and `PerpsClient.getWithdrawableBalances` then resolves
458
+ * `undefined`.
445
459
  */
446
460
  getWithdrawableBalances?(
447
461
  params: ProviderGetWithdrawableBalancesParams,
448
462
  options?: SDKRequestOptions
449
463
  ): Promise<ProviderWithdrawableBalance[]>
450
464
 
465
+ /**
466
+ * The withdrawal types `params.address` can choose per withdrawable holding,
467
+ * each with its cap and the `withdrawalOptions` to send with it.
468
+ *
469
+ * Optional: a provider with one withdrawal type omits it, and
470
+ * `PerpsClient.getWithdrawalTypes` then resolves `undefined`.
471
+ */
472
+ getWithdrawalTypes?(
473
+ params: ProviderGetWithdrawalTypesParams,
474
+ options?: SDKRequestOptions
475
+ ): Promise<WithdrawalSourceTypes[]>
476
+
451
477
  getPositions(
452
478
  params: ProviderGetPositionsParams,
453
479
  options?: SDKRequestOptions
@@ -573,18 +599,15 @@ export interface PerpsProviderPlugin {
573
599
  * positions, prefer `Position.liquidationPrice` from the venue. Pure —
574
600
  * does no I/O.
575
601
  *
576
- * Numbers, in and out, on purpose: this is a display-tier estimate that
577
- * feeds a screen, not a wire amount. It is not a `snap*` method and must
578
- * not be converted to {@link DecimalString}.
579
- *
580
- * @returns The estimated liquidation price, or `undefined` when the venue's
581
- * model cannot be evaluated client-side (degenerate inputs, or `market`
582
- * lacks the margin metadata the model needs).
602
+ * @returns The estimated liquidation price, or `undefined` when `market`
603
+ * lacks the margin metadata the model needs.
604
+ * @throws {PerpsError} `ValidationError` when an input does not match the
605
+ * decimal pattern or is degenerate, such as a zero leverage.
583
606
  */
584
607
  estimateLiquidationPrice(
585
608
  market: PerpsMarket,
586
609
  params: LiquidationEstimateParams
587
- ): number | undefined
610
+ ): string | undefined
588
611
 
589
612
  /**
590
613
  * Margin that can be removed from `position` under the venue margin rules,
@@ -2,22 +2,22 @@ import type {
2
2
  ActionType,
3
3
  Asset,
4
4
  DecimalString,
5
- WithdrawalRoute,
5
+ WithdrawalAssetRef,
6
+ WithdrawalType,
6
7
  } from '@lifi/perps-types'
7
8
  import type { Address } from 'viem'
8
9
 
9
- export type { WithdrawalRoute }
10
-
11
10
  /**
12
- * One withdrawable `(asset, route)` selection as the provider reports it, keyed
13
- * by provider-native asset id and awaiting the core asset-metadata join.
11
+ * One withdrawable `(asset, category)` selection as the provider reports it,
12
+ * keyed by provider-native asset id and awaiting the core asset-metadata join.
14
13
  *
15
14
  * @public
16
15
  */
17
16
  export interface ProviderWithdrawableBalance {
18
17
  /** Provider-native `Asset.id`; never a display symbol. */
19
18
  assetId: string
20
- route: WithdrawalRoute
19
+ /** The provider category the row draws from; the same value as `Balance.categoryId`. */
20
+ categoryId: string
21
21
  /** Withdrawable amount in the asset's own units. Always greater than zero. */
22
22
  available: DecimalString
23
23
  /**
@@ -41,7 +41,7 @@ export interface ProviderWithdrawableBalance {
41
41
  }
42
42
 
43
43
  /**
44
- * One withdrawable `(asset, route)` selection a caller can act on: the amount
44
+ * One withdrawable `(asset, category)` selection a caller can act on: the amount
45
45
  * clears the asset's venue minimum, and `asset` carries the precision and
46
46
  * minimum needed to scale and validate the withdrawal.
47
47
  *
@@ -49,7 +49,8 @@ export interface ProviderWithdrawableBalance {
49
49
  */
50
50
  export interface WithdrawableBalance {
51
51
  asset: Asset
52
- route: WithdrawalRoute
52
+ /** The provider category the row draws from; the same value as `Balance.categoryId`. */
53
+ categoryId: string
53
54
  /** Withdrawable amount in the asset's own units. */
54
55
  available: DecimalString
55
56
  /**
@@ -77,6 +78,32 @@ export interface WithdrawableBalance {
77
78
  isFeeDeducted?: boolean
78
79
  }
79
80
 
81
+ /**
82
+ * One way a venue can settle a withdrawal from a holding.
83
+ *
84
+ * @public
85
+ */
86
+ export interface WithdrawalTypeOption {
87
+ type: WithdrawalType
88
+ /** Largest `amount` this type accepts from the holding, in the asset's own units. */
89
+ max: DecimalString
90
+ /**
91
+ * Provider-specific options to pass unchanged as
92
+ * `WithdrawalParams.withdrawalOptions` when the user picks this type.
93
+ */
94
+ withdrawalOptions: Record<string, unknown>
95
+ }
96
+
97
+ /**
98
+ * The withdrawal types a venue offers for one holding.
99
+ *
100
+ * @public
101
+ */
102
+ export interface WithdrawalSourceTypes {
103
+ source: WithdrawalAssetRef
104
+ options: WithdrawalTypeOption[]
105
+ }
106
+
80
107
  /**
81
108
  * The venue accepts a withdrawal to `destination` now.
82
109
  *
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Wrap a throwing function so that it gives `undefined` in place of a throw.
3
+ * The wrapper logs a warning with `name` and the error, which carries the
4
+ * stack trace.
5
+ *
6
+ * @public
7
+ */
8
+ export function createSafeFunction<Args extends unknown[], Result>(
9
+ name: string,
10
+ throwingFunction: (...args: Args) => Result
11
+ ): (...args: Args) => Result | undefined {
12
+ return (...args) => {
13
+ try {
14
+ return throwingFunction(...args)
15
+ } catch (error) {
16
+ console.warn(`[perps-sdk] ${name} failed`, error)
17
+ return undefined
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,31 @@
1
+ import { PerpsErrorCode } from '@lifi/perps-types'
2
+ import { PerpsError } from '../errors/PerpsError.js'
3
+ import { createSafeFunction } from './createSafeFunction.js'
4
+
5
+ /**
6
+ * Read a venue time (epoch milliseconds or a date string) as an ISO-8601
7
+ * string.
8
+ *
9
+ * @throws {PerpsError} `ValidationError` when `Date` cannot read `value`.
10
+ * @public
11
+ */
12
+ export function timestampToIsoString(value: string | number): string {
13
+ const time = value === '' ? Number.NaN : new Date(value).getTime()
14
+ if (Number.isNaN(time)) {
15
+ throw new PerpsError(
16
+ PerpsErrorCode.ValidationError,
17
+ `'${String(value)}' is not a valid timestamp.`
18
+ )
19
+ }
20
+ return new Date(time).toISOString()
21
+ }
22
+
23
+ /**
24
+ * {@link timestampToIsoString}, or `undefined` with a warning when it throws.
25
+ *
26
+ * @public
27
+ */
28
+ export const safeTimestampToIsoString = createSafeFunction(
29
+ 'timestampToIsoString',
30
+ timestampToIsoString
31
+ )
@@ -27,3 +27,63 @@ export const createWarnOnce = (): ((key: string, message: string) => void) => {
27
27
  console.warn(message)
28
28
  }
29
29
  }
30
+
31
+ const MAX_VALUE_CHARS = 64
32
+
33
+ /**
34
+ * Cut venue text to a fixed length, so a warner key or message built from it
35
+ * stays small.
36
+ *
37
+ * @internal
38
+ */
39
+ export const cutVenueText = (value: unknown): string => {
40
+ const text = String(value)
41
+ return text.length > MAX_VALUE_CHARS
42
+ ? `${text.slice(0, MAX_VALUE_CHARS)}…`
43
+ : text
44
+ }
45
+
46
+ /**
47
+ * Describe a skipped venue row. The venue value is cut to a fixed length, so
48
+ * a warner key built from the text stays small.
49
+ *
50
+ * @internal
51
+ */
52
+ export const skippedRowMessage = (
53
+ source: string,
54
+ row: string,
55
+ field: string,
56
+ value: unknown,
57
+ expected: string,
58
+ marketId?: string
59
+ ): string => {
60
+ const market = marketId === undefined ? '' : ` on market '${marketId}'`
61
+ return `[${source}] skipping ${row} row${market}: \`${field}\` is not a valid ${expected}: '${cutVenueText(value)}'`
62
+ }
63
+
64
+ const warnSkippedRowOnce = createWarnOnce()
65
+
66
+ /**
67
+ * Warn once for each provider, row, field, expected kind and market that a
68
+ * provider mapper skipped a venue row because a required field is not valid.
69
+ * The key holds no venue value, so a second bad value for the same field on
70
+ * the same market stays silent.
71
+ *
72
+ * @param options.expected - What the field must be. Defaults to `'decimal'`.
73
+ * @internal
74
+ */
75
+ export const warnSkippedVenueRow = (
76
+ provider: string,
77
+ row: string,
78
+ field: string,
79
+ value: unknown,
80
+ {
81
+ marketId,
82
+ expected = 'decimal',
83
+ }: { marketId?: string; expected?: string } = {}
84
+ ): void => {
85
+ warnSkippedRowOnce(
86
+ `${provider}|${row}|${field}|${expected}|${marketId ?? ''}`,
87
+ skippedRowMessage(provider, row, field, value, expected, marketId)
88
+ )
89
+ }
package/src/version.ts CHANGED
@@ -10,4 +10,4 @@ export const name = '@lifi/perps-sdk'
10
10
  *
11
11
  * @public
12
12
  */
13
- export const version = '23.1.0'
13
+ export const version = '25.0.0'
@@ -1,4 +1,8 @@
1
- import { PerpsErrorCode, type Subscription } from '@lifi/perps-types'
1
+ import {
2
+ PerpsErrorCode,
3
+ type ProvidersResponse,
4
+ type Subscription,
5
+ } from '@lifi/perps-types'
2
6
  import { PerpsError } from '../errors/PerpsError.js'
3
7
  import { getProviders } from '../services/getProviders.js'
4
8
  import type { GetQuoteParams } from '../services/getQuote.js'
@@ -70,6 +74,7 @@ export class PerpsWsClient {
70
74
  private readonly options: PerpsWsClientOptions
71
75
  private providers = new Map<string, WsProvider>()
72
76
  private initPromises = new Map<string, Promise<WsProvider>>()
77
+ private discovery: Promise<ProvidersResponse> | undefined
73
78
  private closed = false
74
79
 
75
80
  constructor(client: PerpsSDKClient, options: PerpsWsClientOptions = {}) {
@@ -220,7 +225,7 @@ export class PerpsWsClient {
220
225
  )
221
226
  }
222
227
 
223
- const { providers } = await getProviders(this.client)
228
+ const { providers } = await this.discoverProviders()
224
229
  this.assertOpen()
225
230
 
226
231
  const providerInfo = providers.find((d) => d.key === provider)
@@ -236,4 +241,22 @@ export class PerpsWsClient {
236
241
  this.providers.set(provider, wsProvider)
237
242
  return wsProvider
238
243
  }
244
+
245
+ /**
246
+ * Shares one in-flight `/providers` request between concurrent venue
247
+ * inits. The slot clears on settlement, so a later init fetches fresh
248
+ * metadata and a rejection is never cached.
249
+ */
250
+ private discoverProviders(): Promise<ProvidersResponse> {
251
+ if (this.discovery) {
252
+ return this.discovery
253
+ }
254
+ const discovery = getProviders(this.client).finally(() => {
255
+ if (this.discovery === discovery) {
256
+ this.discovery = undefined
257
+ }
258
+ })
259
+ this.discovery = discovery
260
+ return discovery
261
+ }
239
262
  }
@@ -1,3 +1,9 @@
1
+ import {
2
+ createWarnOnce,
3
+ cutVenueText,
4
+ skippedRowMessage,
5
+ } from '../utils/warnOnce.js'
6
+
1
7
  const MAX_PAYLOAD_CHARS = 512
2
8
 
3
9
  const truncate = (raw: string): string =>
@@ -5,6 +11,8 @@ const truncate = (raw: string): string =>
5
11
  ? `${raw.slice(0, MAX_PAYLOAD_CHARS)}…(${raw.length} chars)`
6
12
  : raw
7
13
 
14
+ const warnSkippedRowOnce = createWarnOnce()
15
+
8
16
  /**
9
17
  * Structured logger for WS message-handling and subscription failures, shared
10
18
  * by the provider packages so a malformed frame, a throwing mapper, or a failed
@@ -58,6 +66,42 @@ export const wsLog = {
58
66
  `[${provider}:ws] skipping item for unknown market '${marketId}'`
59
67
  )
60
68
  },
69
+ /**
70
+ * A frame row or order-book level with a required field that is not valid.
71
+ * Only that row is skipped. Logged once at `warn` for each provider, row,
72
+ * field and market; the key holds no venue value.
73
+ */
74
+ skippedRow(
75
+ provider: string,
76
+ row: string,
77
+ field: string,
78
+ value: unknown,
79
+ marketId?: string
80
+ ): void {
81
+ warnSkippedRowOnce(
82
+ `${provider}|${row}|${field}|${marketId ?? ''}`,
83
+ skippedRowMessage(
84
+ `${provider}:ws`,
85
+ row,
86
+ field,
87
+ value,
88
+ 'decimal',
89
+ marketId
90
+ )
91
+ )
92
+ },
93
+ /**
94
+ * A frame row the mapper rejected for a reason other than one field, such as
95
+ * a lifecycle state the SDK does not carry. Logged once at `warn` for each
96
+ * provider, row and reason; the reason is cut to a fixed length.
97
+ */
98
+ droppedRow(provider: string, row: string, reason: string): void {
99
+ const shown = cutVenueText(reason)
100
+ warnSkippedRowOnce(
101
+ `${provider}|${row}|dropped|${shown}`,
102
+ `[${provider}:ws] skipping ${row} row: ${shown}`
103
+ )
104
+ },
61
105
  /**
62
106
  * A background market-registry refetch rejected. Unknown-market items keep
63
107
  * being skipped until the next cooldown-gated retry, so logged at `warn`.
@@ -1,8 +1,16 @@
1
- import type { DecimalString, Market } from '@lifi/perps-types'
2
- import Big from 'big.js'
1
+ import {
2
+ type DecimalString,
3
+ type Market,
4
+ PerpsErrorCode,
5
+ } from '@lifi/perps-types'
6
+ import type Big from 'big.js'
3
7
  import { DivBig, TruncBig } from '../decimal/big.js'
8
+ import { isDecimalStringZero } from '../decimal/compare.js'
4
9
  import { isDecimalString } from '../decimal/parse.js'
10
+ import { invalidInput } from '../errors/invalidInput.js'
11
+ import { PerpsError } from '../errors/PerpsError.js'
5
12
  import type { PerpsSDKClient } from '../types/provider.js'
13
+ import { createSafeFunction } from '../utils/createSafeFunction.js'
6
14
  import { snapOrderSize } from './snap.js'
7
15
 
8
16
  /** @public */
@@ -30,14 +38,20 @@ export interface OrderAmounts {
30
38
  notional: DecimalString
31
39
  }
32
40
 
33
- function positiveDecimal(value: DecimalString): Big | null {
34
- if (!isDecimalString(value)) {
35
- return null
41
+ function requirePositiveDecimal(value: DecimalString, parameter: string): Big {
42
+ const parsed = isDecimalString(value) ? new TruncBig(value) : undefined
43
+ if (parsed === undefined || !parsed.gt(0)) {
44
+ throw invalidInput(
45
+ parameter,
46
+ `must be a positive decimal, got '${String(value)}'`
47
+ )
36
48
  }
37
- const parsed = new TruncBig(value)
38
- return parsed.gt(0) ? parsed : null
49
+ return parsed
39
50
  }
40
51
 
52
+ const lotSize = (market: Market): DecimalString =>
53
+ market.sizeIncrement ?? new TruncBig(`1e-${market.szDecimals}`).toFixed()
54
+
41
55
  /**
42
56
  * The three order-entry amounts, derived from whichever one the user typed.
43
57
  * Only `size` snaps, onto the market's venue lot grid, because an order sends
@@ -45,26 +59,22 @@ function positiveDecimal(value: DecimalString): Big | null {
45
59
  * `notional` is the snapped size × price, and a derived margin is
46
60
  * `notional ÷ leverage` in `DivBig` (40 places, half-up).
47
61
  *
48
- * @returns `null` when `amount` or `price` is not a positive
49
- * {@link DecimalString}, when `leverage` is not a positive finite number, or
50
- * when the snapped size is zero (below one lot).
51
- * @throws {PerpsError} `SDKError` when `market.providerId` names no registered
52
- * provider plugin.
62
+ * @throws {PerpsError} `ValidationError` that names `amount` or `price` when
63
+ * it is not a positive decimal, or `leverage` when it is not a finite number
64
+ * above zero. `ValidationError` with the lot size when the snapped size is
65
+ * zero (below one lot). `SDKError` when `market.providerId` names no
66
+ * registered provider plugin.
53
67
  * @public
54
68
  */
55
- export function calculateOrderAmounts(
56
- input: OrderAmountsInput
57
- ): OrderAmounts | null {
69
+ export function calculateOrderAmounts(input: OrderAmountsInput): OrderAmounts {
58
70
  const { sdk, market, held, leverage } = input
59
- const amount = positiveDecimal(input.amount)
60
- const price = positiveDecimal(input.price)
61
- if (
62
- amount === null ||
63
- price === null ||
64
- !Number.isFinite(leverage) ||
65
- leverage <= 0
66
- ) {
67
- return null
71
+ const amount = requirePositiveDecimal(input.amount, 'amount')
72
+ const price = requirePositiveDecimal(input.price, 'price')
73
+ if (!Number.isFinite(leverage) || leverage <= 0) {
74
+ throw invalidInput(
75
+ 'leverage',
76
+ `must be a finite number above zero, got ${leverage}`
77
+ )
68
78
  }
69
79
 
70
80
  const requested =
@@ -74,8 +84,11 @@ export function calculateOrderAmounts(
74
84
  ? amount.div(price).toFixed()
75
85
  : amount.times(leverage).div(price).toFixed()
76
86
  const size = snapOrderSize(sdk, market, requested)
77
- if (new Big(size).eq(0)) {
78
- return null
87
+ if (isDecimalStringZero(size)) {
88
+ throw new PerpsError(
89
+ PerpsErrorCode.ValidationError,
90
+ `The order size ${requested} is below the lot size ${lotSize(market)}.`
91
+ )
79
92
  }
80
93
 
81
94
  const notional = new TruncBig(size).times(price)
@@ -88,3 +101,9 @@ export function calculateOrderAmounts(
88
101
  notional: notional.toFixed(),
89
102
  }
90
103
  }
104
+
105
+ /** @public */
106
+ export const safeCalculateOrderAmounts = createSafeFunction(
107
+ 'calculateOrderAmounts',
108
+ calculateOrderAmounts
109
+ )