@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
@@ -30,8 +30,9 @@ import {
30
30
  PerpsSigner,
31
31
  SigningMethod,
32
32
  } from '@lifi/perps-types'
33
- import Big from 'big.js'
34
33
  import type { Address } from 'viem'
34
+ import { isDecimalStringGreaterThan } from '../decimal/compare.js'
35
+ import { unknownToDecimalString } from '../decimal/parse.js'
35
36
  import { PerpsError } from '../errors/PerpsError.js'
36
37
  import { getAssetRegistry, toAssetDisplay } from '../registry/assetRegistry.js'
37
38
  import { getMarketRegistry } from '../registry/marketRegistry.js'
@@ -60,6 +61,7 @@ import type {
60
61
  GetPortfolioHistoryParams,
61
62
  GetSetupParams,
62
63
  GetWithdrawableBalancesParams,
64
+ GetWithdrawalTypesParams,
63
65
  GetWithdrawFlowParams,
64
66
  ModifyOrdersParams,
65
67
  PerpsClientOptions,
@@ -85,7 +87,11 @@ import type {
85
87
  SignActionProgress,
86
88
  SignActionsContext,
87
89
  } from '../types/provider.js'
88
- import type { WithdrawableBalance, WithdrawFlow } from '../types/withdrawal.js'
90
+ import type {
91
+ WithdrawableBalance,
92
+ WithdrawalSourceTypes,
93
+ WithdrawFlow,
94
+ } from '../types/withdrawal.js'
89
95
  import { isUserFacingSetupStep } from '../utils/setupActions.js'
90
96
  import { signTypedDataWithSigner } from '../utils/signTypedData.js'
91
97
  import {
@@ -219,7 +225,10 @@ function assertAllSucceeded(results: ActionResult[]): void {
219
225
 
220
226
  function isNonNegativeDecimal(value: string): boolean {
221
227
  try {
222
- return new Big(value).gte(0)
228
+ return !isDecimalStringGreaterThan(
229
+ '0',
230
+ unknownToDecimalString(value, 'withdrawalFee', 'perps-sdk')
231
+ )
223
232
  } catch {
224
233
  return false
225
234
  }
@@ -838,8 +847,9 @@ export class PerpsClient {
838
847
  }
839
848
 
840
849
  /**
841
- * The `(asset, route)` selections `params.address` can actually withdraw at
842
- * `params.provider`. The venue owns how its balances split across routes;
850
+ * The `(asset, category)` selections `params.address` can actually withdraw
851
+ * at `params.provider`. The venue owns how its balances split across
852
+ * categories;
843
853
  * this join adds the core `/assets` metadata — precision, L1 identity and
844
854
  * the per-asset minimum — and drops every row the minimum rules out, plus
845
855
  * any row whose asset the provider's registry does not carry, since without
@@ -878,22 +888,31 @@ export class PerpsClient {
878
888
  }
879
889
  const minimum = asset.minWithdrawalAmount
880
890
  if (minimum !== undefined) {
881
- let floor: Big
891
+ let floor: string
882
892
  try {
883
- floor = new Big(minimum)
893
+ floor = unknownToDecimalString(
894
+ minimum,
895
+ 'minWithdrawalAmount',
896
+ 'perps-sdk'
897
+ )
884
898
  } catch {
885
899
  throw new PerpsError(
886
900
  PerpsErrorCode.SDKError,
887
901
  `Asset '${asset.id}' field \`minWithdrawalAmount\` is not a valid decimal.`
888
902
  )
889
903
  }
890
- if (new Big(row.available).lt(floor)) {
904
+ if (isDecimalStringGreaterThan(floor, row.available)) {
891
905
  return []
892
906
  }
893
907
  }
894
908
  if (row.withdrawalFee === undefined) {
895
909
  return [
896
- { asset, route: row.route, available: row.available, max: row.max },
910
+ {
911
+ asset,
912
+ categoryId: row.categoryId,
913
+ available: row.available,
914
+ max: row.max,
915
+ },
897
916
  ]
898
917
  }
899
918
  if (!isNonNegativeDecimal(row.withdrawalFee)) {
@@ -905,7 +924,7 @@ export class PerpsClient {
905
924
  return [
906
925
  {
907
926
  asset,
908
- route: row.route,
927
+ categoryId: row.categoryId,
909
928
  available: row.available,
910
929
  max: row.max,
911
930
  withdrawalFee: row.withdrawalFee,
@@ -917,6 +936,25 @@ export class PerpsClient {
917
936
  })
918
937
  }
919
938
 
939
+ /**
940
+ * The withdrawal types `params.address` can choose per holding at
941
+ * `params.provider`, each with its cap and the `withdrawalOptions` to pass
942
+ * unchanged in `WithdrawalParams`.
943
+ *
944
+ * @returns `undefined` when the registered plugin declares no withdrawal
945
+ * types read.
946
+ * @throws {PerpsError} When the provider plugin is not registered, or when
947
+ * the plugin read fails.
948
+ * @public
949
+ */
950
+ async getWithdrawalTypes(
951
+ params: GetWithdrawalTypesParams,
952
+ options?: SDKRequestOptions
953
+ ): Promise<WithdrawalSourceTypes[] | undefined> {
954
+ const plugin = this.requireProvider(params.provider)
955
+ return plugin.getWithdrawalTypes?.({ address: params.address }, options)
956
+ }
957
+
920
958
  /**
921
959
  * The account's portfolio value and cumulative PnL over `params.range` at
922
960
  * `params.provider`, read directly from the venue.
@@ -0,0 +1,170 @@
1
+ import { PerpsErrorCode } from '@lifi/perps-types'
2
+ import type Big from 'big.js'
3
+ import { PerpsError } from '../errors/PerpsError.js'
4
+ import { createSafeFunction } from '../utils/createSafeFunction.js'
5
+ import { DivBig, TruncBig } from './big.js'
6
+ import { bigToDecimalString, decimalStringToBig } from './decimalStringToBig.js'
7
+
8
+ /**
9
+ * Exact `a + b`.
10
+ *
11
+ * @throws {PerpsError} `ValidationError` when an input does not match the decimal pattern.
12
+ * @public
13
+ */
14
+ export function addDecimalString(a: string, b: string): string {
15
+ return bigToDecimalString(decimalStringToBig(a).plus(decimalStringToBig(b)))
16
+ }
17
+
18
+ /**
19
+ * {@link addDecimalString}, or `undefined` with a warning when it throws.
20
+ *
21
+ * @public
22
+ */
23
+ export const safeAddDecimalString = createSafeFunction(
24
+ 'addDecimalString',
25
+ addDecimalString
26
+ )
27
+
28
+ /**
29
+ * Exact sum of every value; `'0'` for an empty list.
30
+ *
31
+ * @throws {PerpsError} `ValidationError` when a value does not match the
32
+ * decimal pattern.
33
+ * @public
34
+ */
35
+ export function addDecimalStrings(values: readonly string[]): string {
36
+ return bigToDecimalString(
37
+ values.reduce<Big>(
38
+ (sum, value) => sum.plus(decimalStringToBig(value)),
39
+ decimalStringToBig('0')
40
+ )
41
+ )
42
+ }
43
+
44
+ /**
45
+ * {@link addDecimalStrings}, or `undefined` with a warning when it throws.
46
+ * One bad value gives `undefined`, never a partial sum.
47
+ *
48
+ * @public
49
+ */
50
+ export const safeAddDecimalStrings = createSafeFunction(
51
+ 'addDecimalStrings',
52
+ addDecimalStrings
53
+ )
54
+
55
+ /**
56
+ * Exact `a - b`.
57
+ *
58
+ * @throws {PerpsError} `ValidationError` when an input does not match the decimal pattern.
59
+ * @public
60
+ */
61
+ export function subtractDecimalString(a: string, b: string): string {
62
+ return bigToDecimalString(decimalStringToBig(a).minus(decimalStringToBig(b)))
63
+ }
64
+
65
+ /**
66
+ * {@link subtractDecimalString}, or `undefined` with a warning when it throws.
67
+ *
68
+ * @public
69
+ */
70
+ export const safeSubtractDecimalString = createSafeFunction(
71
+ 'subtractDecimalString',
72
+ subtractDecimalString
73
+ )
74
+
75
+ /**
76
+ * Exact `a × b`.
77
+ *
78
+ * @throws {PerpsError} `ValidationError` when an input does not match the decimal pattern.
79
+ * @public
80
+ */
81
+ export function multiplyDecimalString(a: string, b: string): string {
82
+ return bigToDecimalString(decimalStringToBig(a).times(decimalStringToBig(b)))
83
+ }
84
+
85
+ /**
86
+ * {@link multiplyDecimalString}, or `undefined` with a warning when it throws.
87
+ *
88
+ * @public
89
+ */
90
+ export const safeMultiplyDecimalString = createSafeFunction(
91
+ 'multiplyDecimalString',
92
+ multiplyDecimalString
93
+ )
94
+
95
+ function requireNonZeroDivisor(divisor: string): Big {
96
+ const parsed = decimalStringToBig(divisor)
97
+ if (parsed.eq(0)) {
98
+ throw new PerpsError(
99
+ PerpsErrorCode.ValidationError,
100
+ `Division by zero: divisor '${divisor}'.`
101
+ )
102
+ }
103
+ return parsed
104
+ }
105
+
106
+ /**
107
+ * `a ÷ b` to 40 decimal places, rounded half up.
108
+ *
109
+ * @throws {PerpsError} `ValidationError` when an input does not match the
110
+ * decimal pattern or `b` is zero.
111
+ * @public
112
+ */
113
+ export function divideDecimalString(a: string, b: string): string {
114
+ const divisor = requireNonZeroDivisor(b)
115
+ return bigToDecimalString(new DivBig(decimalStringToBig(a)).div(divisor))
116
+ }
117
+
118
+ /**
119
+ * {@link divideDecimalString}, or `undefined` with a warning when it throws.
120
+ *
121
+ * @public
122
+ */
123
+ export const safeDivideDecimalString = createSafeFunction(
124
+ 'divideDecimalString',
125
+ divideDecimalString
126
+ )
127
+
128
+ /**
129
+ * `a ÷ b` to 40 decimal places, truncated toward zero, so a derived amount
130
+ * never exceeds the exact quotient.
131
+ *
132
+ * @throws {PerpsError} `ValidationError` when an input does not match the
133
+ * decimal pattern or `b` is zero.
134
+ * @public
135
+ */
136
+ export function divideDecimalStringRoundDown(a: string, b: string): string {
137
+ const divisor = requireNonZeroDivisor(b)
138
+ return bigToDecimalString(new TruncBig(decimalStringToBig(a)).div(divisor))
139
+ }
140
+
141
+ /**
142
+ * {@link divideDecimalStringRoundDown}, or `undefined` with a warning when it
143
+ * throws.
144
+ *
145
+ * @public
146
+ */
147
+ export const safeDivideDecimalStringRoundDown = createSafeFunction(
148
+ 'divideDecimalStringRoundDown',
149
+ divideDecimalStringRoundDown
150
+ )
151
+
152
+ /**
153
+ * Exact `|value|`.
154
+ *
155
+ * @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern.
156
+ * @public
157
+ */
158
+ export function absDecimalString(value: string): string {
159
+ return bigToDecimalString(decimalStringToBig(value).abs())
160
+ }
161
+
162
+ /**
163
+ * {@link absDecimalString}, or `undefined` with a warning when it throws.
164
+ *
165
+ * @public
166
+ */
167
+ export const safeAbsDecimalString = createSafeFunction(
168
+ 'absDecimalString',
169
+ absDecimalString
170
+ )
@@ -14,8 +14,3 @@ DivBig.DP = 40
14
14
  export const TruncBig = Big()
15
15
  TruncBig.DP = 40
16
16
  TruncBig.RM = Big.roundDown
17
-
18
- /** True when every value is a finite number, so `new DivBig(value)` cannot throw. */
19
- export function areFinite(...values: number[]): boolean {
20
- return values.every(Number.isFinite)
21
- }
@@ -1,17 +1,67 @@
1
- import type { DecimalString } from '@lifi/perps-types'
2
- import { requireDecimal } from './requireDecimal.js'
1
+ import { createSafeFunction } from '../utils/createSafeFunction.js'
2
+ import { decimalStringToBig } from './decimalStringToBig.js'
3
3
 
4
4
  /**
5
- * Exact `a > b` on two {@link DecimalString}s, with no float rounding, so a
6
- * funds gate can tell `'1.0000000000000001'` from `'1'`. The other relations
7
- * follow from it: `a <= b` is `!isDecimalStringGreaterThan(a, b)`.
5
+ * Exact `a > b` on two decimal strings, with no float rounding, so a funds
6
+ * gate can tell `'1.0000000000000001'` from `'1'`. The other relations follow
7
+ * from it: `a <= b` is `!isDecimalStringGreaterThan(a, b)`.
8
8
  *
9
- * @throws {PerpsError} `ValidationError` when either operand is not a decimal string.
9
+ * @throws {PerpsError} `ValidationError` when either operand does not match the decimal pattern.
10
10
  * @public
11
11
  */
12
- export function isDecimalStringGreaterThan(
13
- a: DecimalString,
14
- b: DecimalString
15
- ): boolean {
16
- return requireDecimal(a, 'a').gt(requireDecimal(b, 'b'))
12
+ export function isDecimalStringGreaterThan(a: string, b: string): boolean {
13
+ return decimalStringToBig(a).gt(decimalStringToBig(b))
17
14
  }
15
+
16
+ /**
17
+ * {@link isDecimalStringGreaterThan}, or `undefined` with a warning when it
18
+ * throws.
19
+ *
20
+ * @public
21
+ */
22
+ export const safeIsDecimalStringGreaterThan = createSafeFunction(
23
+ 'isDecimalStringGreaterThan',
24
+ isDecimalStringGreaterThan
25
+ )
26
+
27
+ /**
28
+ * Exact `value == 0`, so a flat-position check never reads `'0.0'` as
29
+ * non-zero.
30
+ *
31
+ * @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern.
32
+ * @public
33
+ */
34
+ export function isDecimalStringZero(value: string): boolean {
35
+ return decimalStringToBig(value).eq(0)
36
+ }
37
+
38
+ /**
39
+ * {@link isDecimalStringZero}, or `undefined` with a warning when it throws.
40
+ *
41
+ * @public
42
+ */
43
+ export const safeIsDecimalStringZero = createSafeFunction(
44
+ 'isDecimalStringZero',
45
+ isDecimalStringZero
46
+ )
47
+
48
+ /**
49
+ * Exact three-way compare for a sort: `-1` when `a < b`, `0` when equal, `1`
50
+ * when `a > b`.
51
+ *
52
+ * @throws {PerpsError} `ValidationError` when either operand does not match the decimal pattern.
53
+ * @public
54
+ */
55
+ export function compareDecimalStrings(a: string, b: string): -1 | 0 | 1 {
56
+ return decimalStringToBig(a).cmp(decimalStringToBig(b))
57
+ }
58
+
59
+ /**
60
+ * {@link compareDecimalStrings}, or `undefined` with a warning when it throws.
61
+ *
62
+ * @public
63
+ */
64
+ export const safeCompareDecimalStrings = createSafeFunction(
65
+ 'compareDecimalStrings',
66
+ compareDecimalStrings
67
+ )
@@ -1,44 +1,92 @@
1
- import { type DecimalString, PerpsErrorCode } from '@lifi/perps-types'
1
+ import { PerpsErrorCode } from '@lifi/perps-types'
2
2
  import Big from 'big.js'
3
3
  import { formatUnits } from 'viem'
4
4
  import { PerpsError } from '../errors/PerpsError.js'
5
- import { requireDecimal } from './requireDecimal.js'
5
+ import { createSafeFunction } from '../utils/createSafeFunction.js'
6
+ import { bigToDecimalString, decimalStringToBig } from './decimalStringToBig.js'
7
+ import { isDecimalString } from './parse.js'
6
8
 
7
9
  /**
8
- * Off-grid resolution for {@link decimalToBaseUnits}:
9
- * - `truncate` — toward zero, for sizes and collateral amounts. The wire
10
- * value never exceeds the caller's intent.
11
- * - `round` — half away from zero, for prices, which snap to the nearest
12
- * tick.
10
+ * Off-grid resolution for {@link roundDecimalString}:
11
+ * - `truncate`: toward zero, for sizes and collateral amounts. The result
12
+ * never exceeds the caller's intent.
13
+ * - `round`: half away from zero, for prices, which snap to the nearest tick.
14
+ * - `up`: away from zero, for an amount that must cover a target.
13
15
  * @public
14
16
  */
15
- export type BaseUnitsRounding = 'truncate' | 'round'
17
+ export type DecimalRounding = 'truncate' | 'round' | 'up'
18
+
19
+ const BIG_ROUNDING = {
20
+ truncate: Big.roundDown,
21
+ round: Big.roundHalfUp,
22
+ up: Big.roundUp,
23
+ } as const
16
24
 
17
25
  /**
18
- * Scale a decimal string to a scaled integer in exact decimal arithmetic — an
19
- * on-grid input maps to its exact scaled integer with no binary float
20
- * artifacts (`'0.29'` at 2 decimals is 29, never 28). Off-grid input resolves
21
- * per `rounding`; there is no silent default.
26
+ * Round a decimal string to `decimals` places with exact decimal arithmetic.
27
+ * The result has no trailing zeros: `roundDecimalString('1.50', 1, 'round')`
28
+ * is `'1.5'`.
22
29
  *
23
- * @throws {PerpsError} `ValidationError` when `value` is not a
24
- * {@link DecimalString}, `decimals` is not a non-negative integer, or the scaled
25
- * result's magnitude exceeds `Number.MAX_SAFE_INTEGER`.
30
+ * @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern,
31
+ * or `decimals` is not a non-negative integer.
26
32
  * @public
27
33
  */
28
- export const decimalToBaseUnits = (
29
- value: DecimalString,
34
+ export function roundDecimalString(
35
+ value: string,
30
36
  decimals: number,
31
- rounding: BaseUnitsRounding
32
- ): number => {
37
+ rounding: DecimalRounding
38
+ ): string {
39
+ if (!Number.isInteger(decimals) || decimals < 0) {
40
+ throw new PerpsError(
41
+ PerpsErrorCode.ValidationError,
42
+ `Invalid decimals for rounding: ${decimals}`
43
+ )
44
+ }
45
+ return bigToDecimalString(
46
+ decimalStringToBig(value).round(decimals, BIG_ROUNDING[rounding])
47
+ )
48
+ }
49
+
50
+ /**
51
+ * {@link roundDecimalString}, or `undefined` with a warning when it throws.
52
+ *
53
+ * @public
54
+ */
55
+ export const safeRoundDecimalString = createSafeFunction(
56
+ 'roundDecimalString',
57
+ roundDecimalString
58
+ )
59
+
60
+ /**
61
+ * Scale a decimal string to an integer at `decimals` places in exact decimal
62
+ * arithmetic: `'0.29'` at 2 decimals is 29, never 28. Off-grid input resolves
63
+ * per `rounding`. No `$`, `%` or `,` is removed first.
64
+ *
65
+ * @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern,
66
+ * `decimals` is not a non-negative integer, or the result's magnitude
67
+ * exceeds `Number.MAX_SAFE_INTEGER`.
68
+ * @public
69
+ */
70
+ export function decimalStringToScaledInteger(
71
+ value: string,
72
+ decimals: number,
73
+ rounding: DecimalRounding
74
+ ): number {
75
+ if (!isDecimalString(value)) {
76
+ throw new PerpsError(
77
+ PerpsErrorCode.ValidationError,
78
+ `'${value}' does not match the decimal pattern.`
79
+ )
80
+ }
33
81
  if (!Number.isInteger(decimals) || decimals < 0) {
34
82
  throw new PerpsError(
35
83
  PerpsErrorCode.ValidationError,
36
84
  `Invalid decimals for integer scaling: ${decimals}`
37
85
  )
38
86
  }
39
- const scaled = requireDecimal(value, 'decimalToBaseUnits(value)')
87
+ const scaled = new Big(value)
40
88
  .times(new Big(10).pow(decimals))
41
- .round(0, rounding === 'truncate' ? Big.roundDown : Big.roundHalfUp)
89
+ .round(0, BIG_ROUNDING[rounding])
42
90
  if (scaled.abs().gt(Number.MAX_SAFE_INTEGER)) {
43
91
  throw new PerpsError(
44
92
  PerpsErrorCode.ValidationError,
@@ -48,72 +96,56 @@ export const decimalToBaseUnits = (
48
96
  return scaled.toNumber()
49
97
  }
50
98
 
51
- const BASE_UNITS_PATTERN = /^-?\d+$/
99
+ /**
100
+ * {@link decimalStringToScaledInteger}, or `undefined` with a warning when it
101
+ * throws.
102
+ *
103
+ * @public
104
+ */
105
+ export const safeDecimalStringToScaledInteger = createSafeFunction(
106
+ 'decimalStringToScaledInteger',
107
+ decimalStringToScaledInteger
108
+ )
109
+
110
+ export const BASE_UNITS_PATTERN = /^-?\d+$/
52
111
 
53
112
  /**
54
- * Convert a base-unit amount (integer string) to a decimal string.
113
+ * Convert a scaled integer string (a token amount in base units) to a decimal
114
+ * string: `scaledIntegerToDecimalString('1000000', 6)` is `'1'`.
55
115
  *
56
- * @param amount - Amount in base units (e.g. "1000000" for 1 USDC)
57
- * @param decimals - Token decimals (e.g. 6 for USDC)
58
116
  * @throws {PerpsError} `ValidationError` when `amount` is not an integer
59
117
  * string, or `decimals` is not a non-negative integer.
60
- * @example
61
- * ```ts
62
- * baseUnitsToDecimal('1000000', 6) // '1'
63
- * ```
64
118
  * @public
65
119
  */
66
- export function baseUnitsToDecimal(
67
- amount: DecimalString,
120
+ export function scaledIntegerToDecimalString(
121
+ amount: string,
68
122
  decimals: number
69
- ): DecimalString {
123
+ ): string {
70
124
  if (!Number.isInteger(decimals) || decimals < 0) {
71
125
  throw new PerpsError(
72
126
  PerpsErrorCode.ValidationError,
73
- `Invalid \`baseUnitsToDecimal(decimals)\`: ${decimals} is not a non-negative integer.`
127
+ `Invalid \`scaledIntegerToDecimalString(decimals)\`: ${decimals} is not a non-negative integer.`
74
128
  )
75
129
  }
76
130
  if (!BASE_UNITS_PATTERN.test(amount)) {
77
131
  throw new PerpsError(
78
132
  PerpsErrorCode.ValidationError,
79
- `Invalid \`baseUnitsToDecimal(amount)\`: '${amount}' is not an integer base-unit string.`
133
+ `Invalid \`scaledIntegerToDecimalString(amount)\`: '${amount}' is not an integer base-unit string.`
80
134
  )
81
135
  }
82
136
  return formatUnits(BigInt(amount), decimals)
83
137
  }
84
138
 
85
139
  /**
86
- * Round `value` down to `decimals` and pad the result to exactly that many
87
- * decimal places. The padding is the point: this seeds a fixed-decimal input,
88
- * where `'500.00'` and `'500'` are two renderings of one amount and the field
89
- * wants the first. For a canonical wire amount with no trailing zeros, read
90
- * the amount off `calculateOrderAmounts` or a provider snap instead.
91
- *
92
- * Exact decimal arithmetic throughout, so there is no 2^53 ceiling and no
93
- * float artifact: `'0.01'` at 18 decimals gives
94
- * `'0.010000000000000000'`, which `Number#toFixed` cannot.
140
+ * {@link scaledIntegerToDecimalString}, or `undefined` with a warning when it
141
+ * throws.
95
142
  *
96
- * @throws {PerpsError} `ValidationError` when `value` is not a
97
- * {@link DecimalString}, or `decimals` is not a non-negative integer.
98
143
  * @public
99
144
  */
100
- export function truncateDecimal(
101
- value: DecimalString,
102
- decimals: number
103
- ): DecimalString {
104
- if (!Number.isInteger(decimals) || decimals < 0) {
105
- throw new PerpsError(
106
- PerpsErrorCode.ValidationError,
107
- `Invalid decimals for truncation: ${decimals}`
108
- )
109
- }
110
- const truncated = requireDecimal(value, 'truncateDecimal(value)').round(
111
- decimals,
112
- Big.roundDown
113
- )
114
- // big.js carries the sign through a round to zero; '-0.00' is not a spelling.
115
- return (truncated.eq(0) ? new Big(0) : truncated).toFixed(decimals)
116
- }
145
+ export const safeScaledIntegerToDecimalString = createSafeFunction(
146
+ 'scaledIntegerToDecimalString',
147
+ scaledIntegerToDecimalString
148
+ )
117
149
 
118
150
  /**
119
151
  * Spell a `number` as a {@link DecimalString} in plain notation: `1e-7`
@@ -125,7 +157,7 @@ export function truncateDecimal(
125
157
  * @throws {PerpsError} `ValidationError` when `value` is `NaN` or infinite.
126
158
  * @public
127
159
  */
128
- export function numberToDecimalString(value: number): DecimalString {
160
+ export function numberToDecimalString(value: number): string {
129
161
  if (!Number.isFinite(value)) {
130
162
  throw new PerpsError(
131
163
  PerpsErrorCode.ValidationError,
@@ -135,3 +167,13 @@ export function numberToDecimalString(value: number): DecimalString {
135
167
  const parsed = new Big(value)
136
168
  return (parsed.eq(0) ? new Big(0) : parsed).toFixed()
137
169
  }
170
+
171
+ /**
172
+ * {@link numberToDecimalString}, or `undefined` with a warning when it throws.
173
+ *
174
+ * @public
175
+ */
176
+ export const safeNumberToDecimalString = createSafeFunction(
177
+ 'numberToDecimalString',
178
+ numberToDecimalString
179
+ )
@@ -0,0 +1,42 @@
1
+ import { DECIMAL_PATTERN, PerpsErrorCode } from '@lifi/perps-types'
2
+ import Big from 'big.js'
3
+ import { PerpsError } from '../errors/PerpsError.js'
4
+ import { DivBig } from './big.js'
5
+
6
+ /**
7
+ * Read a decimal string as a `Big`. The string must match `DECIMAL_PATTERN`,
8
+ * so `'$1,234.5'`, `'0.05%'` and the exponent form `'1e5'` are rejected.
9
+ *
10
+ * @throws {PerpsError} `ValidationError` when `value` does not match the
11
+ * decimal pattern.
12
+ * @internal
13
+ */
14
+ export function decimalStringToBig(value: string): Big {
15
+ if (typeof value !== 'string' || !DECIMAL_PATTERN.test(value)) {
16
+ throw new PerpsError(
17
+ PerpsErrorCode.ValidationError,
18
+ `'${String(value)}' does not match the decimal pattern.`
19
+ )
20
+ }
21
+ return new Big(value)
22
+ }
23
+
24
+ /**
25
+ * Spell a `Big` as a canonical decimal string, with no exponent and no `-0`.
26
+ *
27
+ * @internal
28
+ */
29
+ export function bigToDecimalString(value: Big): string {
30
+ return value.eq(0) ? '0' : value.toFixed()
31
+ }
32
+
33
+ /**
34
+ * {@link decimalStringToBig} as a `DivBig`, so a later `div` keeps 40 decimal
35
+ * places.
36
+ *
37
+ * @throws {PerpsError} `ValidationError` as {@link decimalStringToBig}.
38
+ * @internal
39
+ */
40
+ export function decimalStringToDivBig(value: string): Big {
41
+ return new DivBig(decimalStringToBig(value))
42
+ }