@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
@@ -1,4 +1,6 @@
1
1
  import type { DecimalString } from '@lifi/perps-types'
2
+ import Big from 'big.js'
3
+ import { decimalStringToBig } from './decimalStringToBig.js'
2
4
 
3
5
  /**
4
6
  * Options shared by the human-facing display formatters.
@@ -8,7 +10,10 @@ import type { DecimalString } from '@lifi/perps-types'
8
10
  export interface FormatOptions {
9
11
  /** Fixed number of decimal places. Defaults are per-formatter. */
10
12
  decimals?: number
11
- /** Rendered when the value is null/undefined/NaN/non-finite. Defaults to `'—'`. */
13
+ /**
14
+ * Rendered when the value is null, undefined, blank or a non-finite number.
15
+ * A string that is not a decimal is shown unchanged. Defaults to `'—'`.
16
+ */
12
17
  placeholder?: string
13
18
  /** BCP 47 locale controlling digit grouping and separators (e.g. `'en-US'`). */
14
19
  locale?: string
@@ -33,76 +38,62 @@ const DEFAULT_PLACEHOLDER = '—'
33
38
  type FormatInput = number | DecimalString | string | null | undefined
34
39
 
35
40
  /**
36
- * Extra decimal places used to normalise IEEE-754 representation noise before
37
- * truncating. `toFixed` at this higher precision cleans values like
38
- * `0.28999999…` back to `0.29`; truncation then chops the guard digits.
39
- */
40
- const FLOAT_GUARD_DIGITS = 9
41
-
42
- /**
43
- * Tolerantly coerce a display input to a finite number.
44
- *
45
- * Strips `$`, `,`, and surrounding whitespace from strings. Returns `null`
46
- * when the value is null/undefined/blank or does not resolve to a finite
47
- * number, so callers can render a placeholder instead of `$0.00` or `$NaN`.
41
+ * Read a display input as a `Big`. `null` means the formatter renders the
42
+ * placeholder; a string that does not match the decimal pattern is returned
43
+ * unchanged for display.
48
44
  */
49
- function toFiniteNumber(value: FormatInput): number | null {
50
- let n: number
51
- if (typeof value === 'string') {
52
- const cleaned = value.replace(/[$,\s]/g, '')
53
- if (!cleaned) {
54
- return null
55
- }
56
- n = Number(cleaned)
57
- } else if (typeof value === 'number') {
58
- n = value
59
- } else {
45
+ function toBig(value: FormatInput): Big | null | string {
46
+ if (typeof value === 'number') {
47
+ return Number.isFinite(value) ? new Big(value) : null
48
+ }
49
+ if (typeof value !== 'string' || value.trim() === '') {
60
50
  return null
61
51
  }
62
- return Number.isFinite(n) ? n : null
52
+ try {
53
+ return decimalStringToBig(value)
54
+ } catch {
55
+ return value
56
+ }
63
57
  }
64
58
 
65
- /**
66
- * Truncate a non-negative value toward zero to `decimals` places using its
67
- * decimal string, never float scaling. Representation noise is first
68
- * normalised by `toFixed` at {@link FLOAT_GUARD_DIGITS} extra precision, then
69
- * the guard digits are chopped: `99.999` at 2dp → `99.99`, `0.29` → `0.29`.
70
- */
71
- function truncateAbs(abs: number, decimals: number): number {
72
- // `toFixed` emits exponent notation at >= 1e21; every double that large is an integer.
73
- if (Number.isInteger(abs)) {
74
- return abs
75
- }
76
- const s = abs.toFixed(Math.min(decimals + FLOAT_GUARD_DIGITS, 100))
77
- const dot = s.indexOf('.')
78
- const cut = decimals === 0 ? dot : dot + 1 + decimals
79
- return Number(s.slice(0, cut))
59
+ function decimalSeparator(locale: string | undefined): string {
60
+ return (
61
+ new Intl.NumberFormat(locale)
62
+ .formatToParts(1.5)
63
+ .find((part) => part.type === 'decimal')?.value ?? '.'
64
+ )
80
65
  }
81
66
 
82
67
  /**
83
- * Reduce `n` to `decimals` places then split into a sign and the
68
+ * Reduce `value` to `decimals` places then split into a sign and the
84
69
  * locale-formatted absolute body. The sign is derived from the reduced value
85
70
  * so magnitudes that collapse to zero render without a spurious `-`/`+`.
86
71
  * `signed` emits `+` for positives; `rounding` selects half-up or truncation.
87
72
  */
88
73
  function signAndBody(
89
- n: number,
74
+ value: Big,
90
75
  decimals: number,
91
76
  locale: string | undefined,
92
77
  grouping: boolean,
93
78
  rounding: RoundingMode,
94
79
  signed: boolean
95
80
  ): { sign: '+' | '-' | ''; body: string } {
96
- const reduced =
97
- rounding === 'floor'
98
- ? (n < 0 ? -1 : 1) * truncateAbs(Math.abs(n), decimals)
99
- : Number(n.toFixed(decimals))
100
- const sign = reduced < 0 ? '-' : signed && reduced > 0 ? '+' : ''
101
- const body = Math.abs(reduced).toLocaleString(locale, {
102
- minimumFractionDigits: decimals,
103
- maximumFractionDigits: decimals,
104
- useGrouping: grouping,
105
- })
81
+ const reduced = value.round(
82
+ decimals,
83
+ rounding === 'floor' ? Big.roundDown : Big.roundHalfUp
84
+ )
85
+ const sign = reduced.lt(0) ? '-' : signed && reduced.gt(0) ? '+' : ''
86
+ const [integerPart = '0', fractionPart] = reduced
87
+ .abs()
88
+ .toFixed(decimals)
89
+ .split('.')
90
+ const integerBody = grouping
91
+ ? BigInt(integerPart).toLocaleString(locale)
92
+ : integerPart
93
+ const body =
94
+ fractionPart === undefined
95
+ ? integerBody
96
+ : `${integerBody}${decimalSeparator(locale)}${fractionPart}`
106
97
  return { sign, body }
107
98
  }
108
99
 
@@ -110,14 +101,14 @@ function signAndBody(
110
101
  * Auto-detect a sensible number of decimal places from a value's magnitude:
111
102
  * `>=1` → 2, `>=0.1` → 4, `>=0.01` → 5, otherwise 6.
112
103
  */
113
- function autoDecimals(abs: number): number {
114
- if (abs >= 1) {
104
+ function autoDecimals(abs: Big): number {
105
+ if (abs.gte(1)) {
115
106
  return 2
116
107
  }
117
- if (abs >= 0.1) {
108
+ if (abs.gte('0.1')) {
118
109
  return 4
119
110
  }
120
- if (abs >= 0.01) {
111
+ if (abs.gte('0.01')) {
121
112
  return 5
122
113
  }
123
114
  return 6
@@ -145,10 +136,13 @@ export function formatNumber(
145
136
  locale,
146
137
  rounding = 'halfUp',
147
138
  } = options
148
- const n = toFiniteNumber(value)
139
+ const n = toBig(value)
149
140
  if (n === null) {
150
141
  return placeholder
151
142
  }
143
+ if (typeof n === 'string') {
144
+ return n
145
+ }
152
146
  const { sign, body } = signAndBody(n, decimals, locale, true, rounding, false)
153
147
  return `${sign}${body}`
154
148
  }
@@ -171,10 +165,13 @@ export function formatUsd(
171
165
  locale,
172
166
  rounding = 'halfUp',
173
167
  } = options
174
- const n = toFiniteNumber(value)
168
+ const n = toBig(value)
175
169
  if (n === null) {
176
170
  return placeholder
177
171
  }
172
+ if (typeof n === 'string') {
173
+ return n
174
+ }
178
175
  const { sign, body } = signAndBody(n, decimals, locale, true, rounding, false)
179
176
  return `${sign}$${body}`
180
177
  }
@@ -198,10 +195,13 @@ export function formatSignedUsd(
198
195
  locale,
199
196
  rounding = 'halfUp',
200
197
  } = options
201
- const n = toFiniteNumber(value)
198
+ const n = toBig(value)
202
199
  if (n === null) {
203
200
  return placeholder
204
201
  }
202
+ if (typeof n === 'string') {
203
+ return n
204
+ }
205
205
  const { sign, body } = signAndBody(n, decimals, locale, true, rounding, true)
206
206
  return `${sign}$${body}`
207
207
  }
@@ -225,10 +225,13 @@ export function formatSignedPercent(
225
225
  locale,
226
226
  rounding = 'halfUp',
227
227
  } = options
228
- const n = toFiniteNumber(value)
228
+ const n = toBig(value)
229
229
  if (n === null) {
230
230
  return placeholder
231
231
  }
232
+ if (typeof n === 'string') {
233
+ return n
234
+ }
232
235
  const { sign, body } = signAndBody(n, decimals, locale, false, rounding, true)
233
236
  return `${sign}${body}%`
234
237
  }
@@ -252,17 +255,20 @@ export function formatPrice(
252
255
  locale,
253
256
  rounding = 'halfUp',
254
257
  } = options
255
- const n = toFiniteNumber(value)
258
+ const n = toBig(value)
256
259
  if (n === null) {
257
260
  return placeholder
258
261
  }
259
- const abs = Math.abs(n)
262
+ if (typeof n === 'string') {
263
+ return n
264
+ }
265
+ const abs = n.abs()
260
266
  const decimals = options.decimals ?? autoDecimals(abs)
261
267
  const { sign, body } = signAndBody(
262
268
  n,
263
269
  decimals,
264
270
  locale,
265
- abs >= 1000,
271
+ abs.gte(1000),
266
272
  rounding,
267
273
  false
268
274
  )
@@ -283,20 +289,23 @@ export function formatCompactUsd(
283
289
  options: FormatOptions = {}
284
290
  ): string {
285
291
  const { decimals = 2, placeholder = DEFAULT_PLACEHOLDER } = options
286
- const n = toFiniteNumber(value)
292
+ const n = toBig(value)
287
293
  if (n === null) {
288
294
  return placeholder
289
295
  }
290
- const sign = n < 0 ? '-' : ''
291
- const abs = Math.abs(n)
292
- if (abs >= 1_000_000_000) {
293
- return `${sign}$${(abs / 1_000_000_000).toFixed(decimals)}B`
296
+ if (typeof n === 'string') {
297
+ return n
298
+ }
299
+ const sign = n.lt(0) ? '-' : ''
300
+ const abs = n.abs()
301
+ if (abs.gte(1_000_000_000)) {
302
+ return `${sign}$${abs.div(1_000_000_000).toFixed(decimals)}B`
294
303
  }
295
- if (abs >= 1_000_000) {
296
- return `${sign}$${(abs / 1_000_000).toFixed(decimals)}M`
304
+ if (abs.gte(1_000_000)) {
305
+ return `${sign}$${abs.div(1_000_000).toFixed(decimals)}M`
297
306
  }
298
- if (abs >= 1_000) {
299
- return `${sign}$${(abs / 1_000).toFixed(decimals)}K`
307
+ if (abs.gte(1_000)) {
308
+ return `${sign}$${abs.div(1_000).toFixed(decimals)}K`
300
309
  }
301
310
  return `${sign}$${abs.toFixed(decimals)}`
302
311
  }
@@ -1,87 +1,108 @@
1
- import {
2
- DECIMAL_PATTERN,
3
- type DecimalString,
4
- PerpsErrorCode,
5
- } from '@lifi/perps-types'
1
+ import { DECIMAL_PATTERN, PerpsErrorCode } from '@lifi/perps-types'
2
+ import Big from 'big.js'
6
3
  import { PerpsError } from '../errors/PerpsError.js'
4
+ import { createSafeFunction } from '../utils/createSafeFunction.js'
5
+ import { decimalStringToBig } from './decimalStringToBig.js'
7
6
 
8
7
  /**
9
- * Parse a string to a float, stripping common formatting artefacts.
8
+ * Read a decimal string as a JS float, for a chart or pixel value only. A
9
+ * float holds about 15 significant digits, so the result can lose precision;
10
+ * never use it for an amount sent to a venue.
10
11
  *
11
- * Handles:
12
- * - Currency prefixes/suffixes ($, USD, etc.)
13
- * - Explicit sign prefixes (+/-)
14
- * - Thousands separators (commas)
15
- * - Percentage suffixes (%)
16
- * - Whitespace
17
- *
18
- * @returns Parsed number; `0` for empty/blank input, `NaN` when a non-empty
19
- * string contains no parseable number
12
+ * @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern
13
+ * or is too large for a finite float.
14
+ * @public
20
15
  */
21
- function toFloat(value: string): number {
22
- if (!value) {
23
- return 0
24
- }
25
- const cleaned = value.trim().replace(/[$%]/g, '').replace(/,/g, '').trim()
26
- if (!cleaned) {
27
- return 0
16
+ export function decimalStringToNumber(value: string): number {
17
+ const parsed = decimalStringToBig(value).toNumber()
18
+ if (!Number.isFinite(parsed)) {
19
+ throw new PerpsError(
20
+ PerpsErrorCode.ValidationError,
21
+ `'${value}' is too large for a finite number.`
22
+ )
28
23
  }
29
- return parseFloat(cleaned)
24
+ return parsed
30
25
  }
31
26
 
32
- const FORMATTED_NUMBER =
33
- /^(?:[+-]\s*)?(?:\$\s*)?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?(?:\s*(?:%|USD))?$/i
27
+ /**
28
+ * {@link decimalStringToNumber}, or `undefined` with a warning when it throws.
29
+ *
30
+ * @public
31
+ */
32
+ export const safeDecimalStringToNumber = createSafeFunction(
33
+ 'decimalStringToNumber',
34
+ decimalStringToNumber
35
+ )
34
36
 
35
37
  /**
36
- * Parse an optional decimal field, tolerating currency symbols, grouping
37
- * separators and a percentage suffix around the number.
38
- * Gives back `undefined` for a missing, malformed or non-finite value, and `0` for an empty string.
38
+ * Narrows an unknown value to a {@link DecimalString}. No characters are
39
+ * removed first.
39
40
  *
40
41
  * @public
41
42
  */
42
- export function parseDecimal(
43
- value: DecimalString | string | null | undefined
44
- ): number | undefined {
45
- if (value == null) {
43
+ export function isDecimalString(value: unknown): value is string {
44
+ return typeof value === 'string' && DECIMAL_PATTERN.test(value)
45
+ }
46
+
47
+ const MAX_SPELLED_EXPONENT = 1000
48
+
49
+ function spellDecimal(value: unknown): string | undefined {
50
+ if (isDecimalString(value)) {
51
+ return value
52
+ }
53
+ if (typeof value !== 'string' && typeof value !== 'number') {
54
+ return undefined
55
+ }
56
+ if (typeof value === 'number' && !Number.isFinite(value)) {
46
57
  return undefined
47
58
  }
48
- if (value.trim() === '') {
49
- return toFloat(value)
59
+ let parsed: Big
60
+ try {
61
+ parsed = new Big(value)
62
+ } catch {
63
+ return undefined
50
64
  }
51
- if (!FORMATTED_NUMBER.test(value.trim())) {
65
+ // Spelling out an unbounded exponent builds a string of that many digits.
66
+ if (Math.abs(parsed.e) > MAX_SPELLED_EXPONENT) {
52
67
  return undefined
53
68
  }
54
- const parsed = toFloat(value)
55
- return Number.isFinite(parsed) ? parsed : undefined
69
+ return (parsed.eq(0) ? new Big(0) : parsed).toFixed()
56
70
  }
57
71
 
58
72
  /**
59
- * Narrows an unknown value to a {@link DecimalString}.
73
+ * Read a venue value (a string or a number) as a decimal string, for a
74
+ * money-path value that must not go on wrong. A number or an exponent string
75
+ * is spelled out in full; no `$`, `%` or `,` is removed.
60
76
  *
77
+ * @param tool - Provider key set on the error.
78
+ * @throws {PerpsError} `SDKError` naming `field` when `value` is not a finite
79
+ * decimal.
61
80
  * @public
62
81
  */
63
- export function isDecimalString(value: unknown): value is DecimalString {
64
- return typeof value === 'string' && DECIMAL_PATTERN.test(value)
82
+ export function unknownToDecimalString(
83
+ value: unknown,
84
+ field: string,
85
+ tool: string
86
+ ): string {
87
+ const decimal = spellDecimal(value)
88
+ if (decimal !== undefined) {
89
+ return decimal
90
+ }
91
+ const error = new PerpsError(
92
+ PerpsErrorCode.SDKError,
93
+ `${tool} field \`${field}\` is not a valid decimal: '${String(value)}'`
94
+ )
95
+ error.tool = tool
96
+ throw error
65
97
  }
66
98
 
67
99
  /**
68
- * Check a decimal input against the {@link DecimalString} contract, naming
69
- * the field it came from, so a malformed amount fails at the SDK boundary
70
- * instead of inside big.js.
100
+ * The safe pair of {@link unknownToDecimalString}: `undefined` and a warning
101
+ * in place of a throw.
71
102
  *
72
- * @returns `value`, unchanged.
73
- * @throws {PerpsError} `ValidationError` naming `field`.
74
103
  * @public
75
104
  */
76
- export function validateDecimalString(
77
- value: DecimalString,
78
- field: string
79
- ): DecimalString {
80
- if (!isDecimalString(value)) {
81
- throw new PerpsError(
82
- PerpsErrorCode.ValidationError,
83
- `Invalid \`${field}\`: '${value}' is not a decimal string.`
84
- )
85
- }
86
- return value
87
- }
105
+ export const safeUnknownToDecimalString = createSafeFunction(
106
+ 'unknownToDecimalString',
107
+ unknownToDecimalString
108
+ )
@@ -0,0 +1,10 @@
1
+ import { PerpsErrorCode } from '@lifi/perps-types'
2
+ import { PerpsError } from './PerpsError.js'
3
+
4
+ /** A `ValidationError` that names the input parameter and the rule it breaks. */
5
+ export function invalidInput(parameter: string, rule: string): PerpsError {
6
+ return new PerpsError(
7
+ PerpsErrorCode.ValidationError,
8
+ `\`${parameter}\` ${rule}.`
9
+ )
10
+ }
package/src/index.ts CHANGED
@@ -17,13 +17,40 @@ export {
17
17
  } from './client/createPerpsClient.js'
18
18
  export { PerpsClient } from './client/PerpsClient.js'
19
19
  export { requireProvider } from './client/requireProvider.js'
20
- export { isDecimalStringGreaterThan } from './decimal/compare.js'
21
- export type { BaseUnitsRounding } from './decimal/convert.js'
22
20
  export {
23
- baseUnitsToDecimal,
24
- decimalToBaseUnits,
21
+ absDecimalString,
22
+ addDecimalString,
23
+ addDecimalStrings,
24
+ divideDecimalString,
25
+ divideDecimalStringRoundDown,
26
+ multiplyDecimalString,
27
+ safeAbsDecimalString,
28
+ safeAddDecimalString,
29
+ safeAddDecimalStrings,
30
+ safeDivideDecimalString,
31
+ safeDivideDecimalStringRoundDown,
32
+ safeMultiplyDecimalString,
33
+ safeSubtractDecimalString,
34
+ subtractDecimalString,
35
+ } from './decimal/arithmetic.js'
36
+ export {
37
+ compareDecimalStrings,
38
+ isDecimalStringGreaterThan,
39
+ isDecimalStringZero,
40
+ safeCompareDecimalStrings,
41
+ safeIsDecimalStringGreaterThan,
42
+ safeIsDecimalStringZero,
43
+ } from './decimal/compare.js'
44
+ export type { DecimalRounding } from './decimal/convert.js'
45
+ export {
46
+ decimalStringToScaledInteger,
25
47
  numberToDecimalString,
26
- truncateDecimal,
48
+ roundDecimalString,
49
+ safeDecimalStringToScaledInteger,
50
+ safeNumberToDecimalString,
51
+ safeRoundDecimalString,
52
+ safeScaledIntegerToDecimalString,
53
+ scaledIntegerToDecimalString,
27
54
  } from './decimal/convert.js'
28
55
  export type { FormatOptions, RoundingMode } from './decimal/format.js'
29
56
  export {
@@ -35,9 +62,11 @@ export {
35
62
  formatUsd,
36
63
  } from './decimal/format.js'
37
64
  export {
65
+ decimalStringToNumber,
38
66
  isDecimalString,
39
- parseDecimal,
40
- validateDecimalString,
67
+ safeDecimalStringToNumber,
68
+ safeUnknownToDecimalString,
69
+ unknownToDecimalString,
41
70
  } from './decimal/parse.js'
42
71
  export { PerpsErrorMessage } from './errors/constants.js'
43
72
  export { PerpsError } from './errors/PerpsError.js'
@@ -48,7 +77,7 @@ export {
48
77
  } from './math/fills.js'
49
78
  export type { ExpectedPnl } from './math/order.js'
50
79
  export {
51
- applySlippage,
80
+ applySlippageToPrice,
52
81
  buildQuote,
53
82
  calculateExpectedPnl,
54
83
  calculateRealizedPnlPercent,
@@ -59,6 +88,17 @@ export {
59
88
  estimateRealizedPnl,
60
89
  findMatchingPosition,
61
90
  resolveCloseSize,
91
+ safeApplySlippageToPrice,
92
+ safeBuildQuote,
93
+ safeCalculateExpectedPnl,
94
+ safeCalculateRealizedPnlPercent,
95
+ safeCalculateSize,
96
+ safeCalculateTriggerPercent,
97
+ safeCalculateTriggerPrice,
98
+ safeEstimateFees,
99
+ safeEstimateRealizedPnl,
100
+ safeResolveCloseSize,
101
+ safeWalkOrderbook,
62
102
  walkOrderbook,
63
103
  } from './math/order.js'
64
104
  export {
@@ -71,10 +111,24 @@ export {
71
111
  calculateUnrealizedPnl,
72
112
  estimateAverageEntryPrice,
73
113
  estimateLiquidationPrice,
114
+ estimateLiquidationPriceAtMarketRate,
74
115
  estimateNewLeverage,
75
116
  estimateUnrealizedPnl,
76
117
  positionSupportsMarginAdjustment,
77
118
  positionSupportsMarginRemoval,
119
+ safeCalculateEffectiveLeverage,
120
+ safeCalculateLiquidationDistance,
121
+ safeCalculateNotionalValue,
122
+ safeCalculateRealizedPnl,
123
+ safeCalculateRequiredMargin,
124
+ safeCalculateRoe,
125
+ safeCalculateUnrealizedPnl,
126
+ safeEstimateAverageEntryPrice,
127
+ safeEstimateLiquidationPrice,
128
+ safeEstimateLiquidationPriceAtMarketRate,
129
+ safeEstimateNewLeverage,
130
+ safeEstimateUnrealizedPnl,
131
+ safeWouldImmediatelyLiquidate,
78
132
  wouldImmediatelyLiquidate,
79
133
  } from './math/position.js'
80
134
  // Registries
@@ -177,6 +231,7 @@ export type {
177
231
  GetPortfolioHistoryParams,
178
232
  GetSetupParams,
179
233
  GetWithdrawableBalancesParams,
234
+ GetWithdrawalTypesParams,
180
235
  GetWithdrawFlowParams,
181
236
  ModifyOrdersParams,
182
237
  PerpsClientOptions,
@@ -223,6 +278,7 @@ export type {
223
278
  ProviderGetPositionsParams,
224
279
  ProviderGetQuoteParams,
225
280
  ProviderGetWithdrawableBalancesParams,
281
+ ProviderGetWithdrawalTypesParams,
226
282
  ProviderGetWithdrawFlowParams,
227
283
  QuoteListener,
228
284
  SignActionProgress,
@@ -231,12 +287,14 @@ export type {
231
287
  export type {
232
288
  ProviderWithdrawableBalance,
233
289
  WithdrawableBalance,
234
- WithdrawalRoute,
290
+ WithdrawalSourceTypes,
291
+ WithdrawalTypeOption,
235
292
  WithdrawFlow,
236
293
  WithdrawFlowReady,
237
294
  WithdrawFlowSetupRequired,
238
295
  } from './types/withdrawal.js'
239
296
  export { paginateActivity } from './utils/activityPaging.js'
297
+ export { createSafeFunction } from './utils/createSafeFunction.js'
240
298
  export {
241
299
  ETHEREUM_NATIVE_GAS,
242
300
  ETHEREUM_USDC,
@@ -269,7 +327,11 @@ export {
269
327
  signTypedData,
270
328
  signTypedDataWithSigner,
271
329
  } from './utils/signTypedData.js'
272
- export { createWarnOnce } from './utils/warnOnce.js'
330
+ export {
331
+ safeTimestampToIsoString,
332
+ timestampToIsoString,
333
+ } from './utils/timestampToIsoString.js'
334
+ export { createWarnOnce, warnSkippedVenueRow } from './utils/warnOnce.js'
273
335
  // Version
274
336
  export { name, version } from './version.js'
275
337
  export { cachePromise } from './websocket/cachePromise.js'
@@ -299,9 +361,15 @@ export type {
299
361
  OrderAmounts,
300
362
  OrderAmountsInput,
301
363
  } from './wire/orderAmounts.js'
302
- export { calculateOrderAmounts } from './wire/orderAmounts.js'
364
+ export {
365
+ calculateOrderAmounts,
366
+ safeCalculateOrderAmounts,
367
+ } from './wire/orderAmounts.js'
303
368
  export type { RefuelAmountInput } from './wire/refuel.js'
304
- export { calculateRefuelAmount } from './wire/refuel.js'
369
+ export {
370
+ calculateRefuelAmount,
371
+ REFUEL_FEE_MARGIN_PERCENT,
372
+ } from './wire/refuel.js'
305
373
  export { snapOrderPrice, snapOrderSize } from './wire/snap.js'
306
374
  export { calculateTransferable } from './wire/transferable.js'
307
375
  export { calculateWithdrawMax } from './wire/withdraw.js'