@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.
- package/README.md +102 -56
- package/dist/cjs/client/PerpsClient.d.ts +3 -2
- package/dist/cjs/client/PerpsClient.d.ts.map +1 -1
- package/dist/cjs/client/PerpsClient.js +16 -9
- package/dist/cjs/client/PerpsClient.js.map +1 -1
- package/dist/cjs/decimal/arithmetic.d.ts +15 -0
- package/dist/cjs/decimal/arithmetic.d.ts.map +1 -0
- package/dist/cjs/decimal/arithmetic.js +53 -0
- package/dist/cjs/decimal/arithmetic.js.map +1 -0
- package/dist/cjs/decimal/big.d.ts +0 -1
- package/dist/cjs/decimal/big.d.ts.map +1 -1
- package/dist/cjs/decimal/big.js +0 -4
- package/dist/cjs/decimal/big.js.map +1 -1
- package/dist/cjs/decimal/compare.d.ts +6 -2
- package/dist/cjs/decimal/compare.d.ts.map +1 -1
- package/dist/cjs/decimal/compare.js +15 -2
- package/dist/cjs/decimal/compare.js.map +1 -1
- package/dist/cjs/decimal/convert.d.ts +10 -6
- package/dist/cjs/decimal/convert.d.ts.map +1 -1
- package/dist/cjs/decimal/convert.js +34 -21
- package/dist/cjs/decimal/convert.js.map +1 -1
- package/dist/cjs/decimal/decimalStringToBig.d.ts +5 -0
- package/dist/cjs/decimal/decimalStringToBig.d.ts.map +1 -0
- package/dist/cjs/decimal/decimalStringToBig.js +25 -0
- package/dist/cjs/decimal/decimalStringToBig.js.map +1 -0
- package/dist/cjs/decimal/format.d.ts.map +1 -1
- package/dist/cjs/decimal/format.js +70 -52
- package/dist/cjs/decimal/format.js.map +1 -1
- package/dist/cjs/decimal/parse.d.ts +5 -4
- package/dist/cjs/decimal/parse.d.ts.map +1 -1
- package/dist/cjs/decimal/parse.js +43 -25
- package/dist/cjs/decimal/parse.js.map +1 -1
- package/dist/cjs/errors/invalidInput.d.ts +3 -0
- package/dist/cjs/errors/invalidInput.d.ts.map +1 -0
- package/dist/cjs/errors/invalidInput.js +9 -0
- package/dist/cjs/errors/invalidInput.js.map +1 -0
- package/dist/cjs/index.d.ts +15 -12
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +69 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/math/fills.d.ts +1 -1
- package/dist/cjs/math/fills.d.ts.map +1 -1
- package/dist/cjs/math/fills.js +28 -13
- package/dist/cjs/math/fills.js.map +1 -1
- package/dist/cjs/math/order.d.ts +27 -16
- package/dist/cjs/math/order.d.ts.map +1 -1
- package/dist/cjs/math/order.js +131 -134
- package/dist/cjs/math/order.js.map +1 -1
- package/dist/cjs/math/position.d.ts +85 -35
- package/dist/cjs/math/position.d.ts.map +1 -1
- package/dist/cjs/math/position.js +93 -94
- package/dist/cjs/math/position.js.map +1 -1
- package/dist/cjs/services/getGasRecommendation.js +1 -1
- package/dist/cjs/services/getGasRecommendation.js.map +1 -1
- package/dist/cjs/services/getQuote.d.ts +1 -1
- package/dist/cjs/services/resolveSubscribeQuote.d.ts.map +1 -1
- package/dist/cjs/services/resolveSubscribeQuote.js +3 -2
- package/dist/cjs/services/resolveSubscribeQuote.js.map +1 -1
- package/dist/cjs/transport/request.d.ts +1 -0
- package/dist/cjs/transport/request.d.ts.map +1 -1
- package/dist/cjs/transport/request.js +2 -2
- package/dist/cjs/transport/request.js.map +1 -1
- package/dist/cjs/types/api.d.ts +4 -0
- package/dist/cjs/types/api.d.ts.map +1 -1
- package/dist/cjs/types/provider.d.ts +9 -5
- package/dist/cjs/types/provider.d.ts.map +1 -1
- package/dist/cjs/types/withdrawal.d.ts +12 -4
- package/dist/cjs/types/withdrawal.d.ts.map +1 -1
- package/dist/cjs/utils/createSafeFunction.d.ts +2 -0
- package/dist/cjs/utils/createSafeFunction.d.ts.map +1 -0
- package/dist/cjs/utils/createSafeFunction.js +15 -0
- package/dist/cjs/utils/createSafeFunction.js.map +1 -0
- package/dist/cjs/utils/timestampToIsoString.d.ts +3 -0
- package/dist/cjs/utils/timestampToIsoString.d.ts.map +1 -0
- package/dist/cjs/utils/timestampToIsoString.js +16 -0
- package/dist/cjs/utils/timestampToIsoString.js.map +1 -0
- package/dist/cjs/utils/warnOnce.d.ts +6 -0
- package/dist/cjs/utils/warnOnce.d.ts.map +1 -1
- package/dist/cjs/utils/warnOnce.js +19 -1
- package/dist/cjs/utils/warnOnce.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/websocket/PerpsWsClient.d.ts +2 -0
- package/dist/cjs/websocket/PerpsWsClient.d.ts.map +1 -1
- package/dist/cjs/websocket/PerpsWsClient.js +14 -1
- package/dist/cjs/websocket/PerpsWsClient.js.map +1 -1
- package/dist/cjs/websocket/wsLog.d.ts +2 -0
- package/dist/cjs/websocket/wsLog.d.ts.map +1 -1
- package/dist/cjs/websocket/wsLog.js +9 -0
- package/dist/cjs/websocket/wsLog.js.map +1 -1
- package/dist/cjs/wire/orderAmounts.d.ts +3 -2
- package/dist/cjs/wire/orderAmounts.d.ts.map +1 -1
- package/dist/cjs/wire/orderAmounts.js +22 -21
- package/dist/cjs/wire/orderAmounts.js.map +1 -1
- package/dist/cjs/wire/refuel.d.ts +4 -1
- package/dist/cjs/wire/refuel.d.ts.map +1 -1
- package/dist/cjs/wire/refuel.js +23 -6
- package/dist/cjs/wire/refuel.js.map +1 -1
- package/dist/cjs/wire/transferable.js +3 -3
- package/dist/cjs/wire/transferable.js.map +1 -1
- package/dist/cjs/wire/withdraw.d.ts.map +1 -1
- package/dist/cjs/wire/withdraw.js +3 -3
- package/dist/cjs/wire/withdraw.js.map +1 -1
- package/dist/esm/client/PerpsClient.d.ts +17 -4
- package/dist/esm/client/PerpsClient.d.ts.map +1 -1
- package/dist/esm/client/PerpsClient.js +30 -8
- package/dist/esm/client/PerpsClient.js.map +1 -1
- package/dist/esm/decimal/arithmetic.d.ts +98 -0
- package/dist/esm/decimal/arithmetic.d.ts.map +1 -0
- package/dist/esm/decimal/arithmetic.js +126 -0
- package/dist/esm/decimal/arithmetic.js.map +1 -0
- package/dist/esm/decimal/big.d.ts +0 -2
- package/dist/esm/decimal/big.d.ts.map +1 -1
- package/dist/esm/decimal/big.js +0 -4
- package/dist/esm/decimal/big.js.map +1 -1
- package/dist/esm/decimal/compare.d.ts +40 -6
- package/dist/esm/decimal/compare.d.ts.map +1 -1
- package/dist/esm/decimal/compare.js +46 -6
- package/dist/esm/decimal/compare.js.map +1 -1
- package/dist/esm/decimal/convert.d.ts +50 -36
- package/dist/esm/decimal/convert.d.ts.map +1 -1
- package/dist/esm/decimal/convert.js +64 -42
- package/dist/esm/decimal/convert.js.map +1 -1
- package/dist/esm/decimal/decimalStringToBig.d.ts +25 -0
- package/dist/esm/decimal/decimalStringToBig.d.ts.map +1 -0
- package/dist/esm/decimal/decimalStringToBig.js +37 -0
- package/dist/esm/decimal/decimalStringToBig.js.map +1 -0
- package/dist/esm/decimal/format.d.ts +4 -1
- package/dist/esm/decimal/format.d.ts.map +1 -1
- package/dist/esm/decimal/format.js +71 -70
- package/dist/esm/decimal/format.js.map +1 -1
- package/dist/esm/decimal/parse.d.ts +29 -13
- package/dist/esm/decimal/parse.d.ts.map +1 -1
- package/dist/esm/decimal/parse.js +61 -44
- package/dist/esm/decimal/parse.js.map +1 -1
- package/dist/esm/errors/invalidInput.d.ts +4 -0
- package/dist/esm/errors/invalidInput.d.ts.map +1 -0
- package/dist/esm/errors/invalidInput.js +7 -0
- package/dist/esm/errors/invalidInput.js.map +1 -0
- package/dist/esm/index.d.ts +15 -12
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +11 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/math/fills.d.ts +6 -3
- package/dist/esm/math/fills.d.ts.map +1 -1
- package/dist/esm/math/fills.js +31 -16
- package/dist/esm/math/fills.js.map +1 -1
- package/dist/esm/math/order.d.ts +84 -66
- package/dist/esm/math/order.d.ts.map +1 -1
- package/dist/esm/math/order.js +178 -175
- package/dist/esm/math/order.js.map +1 -1
- package/dist/esm/math/position.d.ts +155 -98
- package/dist/esm/math/position.d.ts.map +1 -1
- package/dist/esm/math/position.js +160 -156
- package/dist/esm/math/position.js.map +1 -1
- package/dist/esm/services/getGasRecommendation.js +1 -1
- package/dist/esm/services/getGasRecommendation.js.map +1 -1
- package/dist/esm/services/getQuote.d.ts +2 -2
- package/dist/esm/services/getQuote.js +1 -1
- package/dist/esm/services/resolveSubscribeQuote.d.ts +1 -1
- package/dist/esm/services/resolveSubscribeQuote.d.ts.map +1 -1
- package/dist/esm/services/resolveSubscribeQuote.js +4 -3
- package/dist/esm/services/resolveSubscribeQuote.js.map +1 -1
- package/dist/esm/transport/request.d.ts +5 -0
- package/dist/esm/transport/request.d.ts.map +1 -1
- package/dist/esm/transport/request.js +2 -2
- package/dist/esm/transport/request.js.map +1 -1
- package/dist/esm/types/api.d.ts +9 -0
- package/dist/esm/types/api.d.ts.map +1 -1
- package/dist/esm/types/provider.d.ts +30 -16
- package/dist/esm/types/provider.d.ts.map +1 -1
- package/dist/esm/types/withdrawal.d.ts +32 -7
- package/dist/esm/types/withdrawal.d.ts.map +1 -1
- package/dist/esm/utils/createSafeFunction.d.ts +9 -0
- package/dist/esm/utils/createSafeFunction.d.ts.map +1 -0
- package/dist/esm/utils/createSafeFunction.js +19 -0
- package/dist/esm/utils/createSafeFunction.js.map +1 -0
- package/dist/esm/utils/timestampToIsoString.d.ts +15 -0
- package/dist/esm/utils/timestampToIsoString.d.ts.map +1 -0
- package/dist/esm/utils/timestampToIsoString.js +24 -0
- package/dist/esm/utils/timestampToIsoString.js.map +1 -0
- package/dist/esm/utils/warnOnce.d.ts +27 -0
- package/dist/esm/utils/warnOnce.d.ts.map +1 -1
- package/dist/esm/utils/warnOnce.js +36 -0
- package/dist/esm/utils/warnOnce.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/websocket/PerpsWsClient.d.ts +7 -0
- package/dist/esm/websocket/PerpsWsClient.d.ts.map +1 -1
- package/dist/esm/websocket/PerpsWsClient.js +20 -2
- package/dist/esm/websocket/PerpsWsClient.js.map +1 -1
- package/dist/esm/websocket/wsLog.d.ts +12 -0
- package/dist/esm/websocket/wsLog.d.ts.map +1 -1
- package/dist/esm/websocket/wsLog.js +19 -0
- package/dist/esm/websocket/wsLog.js.map +1 -1
- package/dist/esm/wire/orderAmounts.d.ts +9 -7
- package/dist/esm/wire/orderAmounts.d.ts.map +1 -1
- package/dist/esm/wire/orderAmounts.js +24 -20
- package/dist/esm/wire/orderAmounts.js.map +1 -1
- package/dist/esm/wire/refuel.d.ts +24 -14
- package/dist/esm/wire/refuel.d.ts.map +1 -1
- package/dist/esm/wire/refuel.js +38 -17
- package/dist/esm/wire/refuel.js.map +1 -1
- package/dist/esm/wire/transferable.d.ts +2 -2
- package/dist/esm/wire/transferable.js +5 -5
- package/dist/esm/wire/transferable.js.map +1 -1
- package/dist/esm/wire/withdraw.d.ts.map +1 -1
- package/dist/esm/wire/withdraw.js +3 -3
- package/dist/esm/wire/withdraw.js.map +1 -1
- package/dist/types/client/PerpsClient.d.ts +17 -4
- package/dist/types/client/PerpsClient.d.ts.map +1 -1
- package/dist/types/decimal/arithmetic.d.ts +98 -0
- package/dist/types/decimal/arithmetic.d.ts.map +1 -0
- package/dist/types/decimal/big.d.ts +0 -2
- package/dist/types/decimal/big.d.ts.map +1 -1
- package/dist/types/decimal/compare.d.ts +40 -6
- package/dist/types/decimal/compare.d.ts.map +1 -1
- package/dist/types/decimal/convert.d.ts +50 -36
- package/dist/types/decimal/convert.d.ts.map +1 -1
- package/dist/types/decimal/decimalStringToBig.d.ts +25 -0
- package/dist/types/decimal/decimalStringToBig.d.ts.map +1 -0
- package/dist/types/decimal/format.d.ts +4 -1
- package/dist/types/decimal/format.d.ts.map +1 -1
- package/dist/types/decimal/parse.d.ts +29 -13
- package/dist/types/decimal/parse.d.ts.map +1 -1
- package/dist/types/errors/invalidInput.d.ts +4 -0
- package/dist/types/errors/invalidInput.d.ts.map +1 -0
- package/dist/types/index.d.ts +15 -12
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/math/fills.d.ts +6 -3
- package/dist/types/math/fills.d.ts.map +1 -1
- package/dist/types/math/order.d.ts +84 -66
- package/dist/types/math/order.d.ts.map +1 -1
- package/dist/types/math/position.d.ts +155 -98
- package/dist/types/math/position.d.ts.map +1 -1
- package/dist/types/services/getQuote.d.ts +2 -2
- package/dist/types/services/resolveSubscribeQuote.d.ts +1 -1
- package/dist/types/services/resolveSubscribeQuote.d.ts.map +1 -1
- package/dist/types/transport/request.d.ts +5 -0
- package/dist/types/transport/request.d.ts.map +1 -1
- package/dist/types/types/api.d.ts +9 -0
- package/dist/types/types/api.d.ts.map +1 -1
- package/dist/types/types/provider.d.ts +30 -16
- package/dist/types/types/provider.d.ts.map +1 -1
- package/dist/types/types/withdrawal.d.ts +32 -7
- package/dist/types/types/withdrawal.d.ts.map +1 -1
- package/dist/types/utils/createSafeFunction.d.ts +9 -0
- package/dist/types/utils/createSafeFunction.d.ts.map +1 -0
- package/dist/types/utils/timestampToIsoString.d.ts +15 -0
- package/dist/types/utils/timestampToIsoString.d.ts.map +1 -0
- package/dist/types/utils/warnOnce.d.ts +27 -0
- package/dist/types/utils/warnOnce.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/websocket/PerpsWsClient.d.ts +7 -0
- package/dist/types/websocket/PerpsWsClient.d.ts.map +1 -1
- package/dist/types/websocket/wsLog.d.ts +12 -0
- package/dist/types/websocket/wsLog.d.ts.map +1 -1
- package/dist/types/wire/orderAmounts.d.ts +9 -7
- package/dist/types/wire/orderAmounts.d.ts.map +1 -1
- package/dist/types/wire/refuel.d.ts +24 -14
- package/dist/types/wire/refuel.d.ts.map +1 -1
- package/dist/types/wire/transferable.d.ts +2 -2
- package/dist/types/wire/withdraw.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/client/PerpsClient.ts +48 -10
- package/src/decimal/arithmetic.ts +170 -0
- package/src/decimal/big.ts +0 -5
- package/src/decimal/compare.ts +61 -11
- package/src/decimal/convert.ts +105 -63
- package/src/decimal/decimalStringToBig.ts +42 -0
- package/src/decimal/format.ts +81 -72
- package/src/decimal/parse.ts +78 -57
- package/src/errors/invalidInput.ts +10 -0
- package/src/index.ts +80 -12
- package/src/math/fills.ts +32 -17
- package/src/math/order.ts +279 -226
- package/src/math/position.ts +280 -196
- package/src/services/getGasRecommendation.ts +1 -1
- package/src/services/getQuote.ts +2 -2
- package/src/services/resolveSubscribeQuote.ts +4 -3
- package/src/transport/request.ts +7 -2
- package/src/types/api.ts +10 -0
- package/src/types/provider.ts +39 -16
- package/src/types/withdrawal.ts +35 -8
- package/src/utils/createSafeFunction.ts +20 -0
- package/src/utils/timestampToIsoString.ts +31 -0
- package/src/utils/warnOnce.ts +60 -0
- package/src/version.ts +1 -1
- package/src/websocket/PerpsWsClient.ts +25 -2
- package/src/websocket/wsLog.ts +44 -0
- package/src/wire/orderAmounts.ts +45 -26
- package/src/wire/refuel.ts +56 -20
- package/src/wire/transferable.ts +5 -5
- package/src/wire/withdraw.ts +3 -5
- package/dist/cjs/decimal/requireDecimal.d.ts +0 -4
- package/dist/cjs/decimal/requireDecimal.d.ts.map +0 -1
- package/dist/cjs/decimal/requireDecimal.js +0 -12
- package/dist/cjs/decimal/requireDecimal.js.map +0 -1
- package/dist/esm/decimal/requireDecimal.d.ts +0 -5
- package/dist/esm/decimal/requireDecimal.d.ts.map +0 -1
- package/dist/esm/decimal/requireDecimal.js +0 -7
- package/dist/esm/decimal/requireDecimal.js.map +0 -1
- package/dist/types/decimal/requireDecimal.d.ts +0 -5
- package/dist/types/decimal/requireDecimal.d.ts.map +0 -1
- package/src/decimal/requireDecimal.ts +0 -8
|
@@ -1,55 +1,63 @@
|
|
|
1
|
-
import { type DecimalString } from '@lifi/perps-types';
|
|
2
1
|
/**
|
|
3
|
-
* Off-grid resolution for {@link
|
|
4
|
-
* - `truncate
|
|
5
|
-
*
|
|
6
|
-
* - `round
|
|
7
|
-
*
|
|
2
|
+
* Off-grid resolution for {@link roundDecimalString}:
|
|
3
|
+
* - `truncate`: toward zero, for sizes and collateral amounts. The result
|
|
4
|
+
* never exceeds the caller's intent.
|
|
5
|
+
* - `round`: half away from zero, for prices, which snap to the nearest tick.
|
|
6
|
+
* - `up`: away from zero, for an amount that must cover a target.
|
|
8
7
|
* @public
|
|
9
8
|
*/
|
|
10
|
-
export type
|
|
9
|
+
export type DecimalRounding = 'truncate' | 'round' | 'up';
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* per `rounding`; there is no silent default.
|
|
11
|
+
* Round a decimal string to `decimals` places with exact decimal arithmetic.
|
|
12
|
+
* The result has no trailing zeros: `roundDecimalString('1.50', 1, 'round')`
|
|
13
|
+
* is `'1.5'`.
|
|
16
14
|
*
|
|
17
|
-
* @throws {PerpsError} `ValidationError` when `value`
|
|
18
|
-
*
|
|
19
|
-
* result's magnitude exceeds `Number.MAX_SAFE_INTEGER`.
|
|
15
|
+
* @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern,
|
|
16
|
+
* or `decimals` is not a non-negative integer.
|
|
20
17
|
* @public
|
|
21
18
|
*/
|
|
22
|
-
export declare
|
|
19
|
+
export declare function roundDecimalString(value: string, decimals: number, rounding: DecimalRounding): string;
|
|
23
20
|
/**
|
|
24
|
-
*
|
|
21
|
+
* {@link roundDecimalString}, or `undefined` with a warning when it throws.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export declare const safeRoundDecimalString: (value: string, decimals: number, rounding: DecimalRounding) => string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Scale a decimal string to an integer at `decimals` places in exact decimal
|
|
28
|
+
* arithmetic: `'0.29'` at 2 decimals is 29, never 28. Off-grid input resolves
|
|
29
|
+
* per `rounding`. No `$`, `%` or `,` is removed first.
|
|
30
|
+
*
|
|
31
|
+
* @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern,
|
|
32
|
+
* `decimals` is not a non-negative integer, or the result's magnitude
|
|
33
|
+
* exceeds `Number.MAX_SAFE_INTEGER`.
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export declare function decimalStringToScaledInteger(value: string, decimals: number, rounding: DecimalRounding): number;
|
|
37
|
+
/**
|
|
38
|
+
* {@link decimalStringToScaledInteger}, or `undefined` with a warning when it
|
|
39
|
+
* throws.
|
|
40
|
+
*
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
export declare const safeDecimalStringToScaledInteger: (value: string, decimals: number, rounding: DecimalRounding) => number | undefined;
|
|
44
|
+
export declare const BASE_UNITS_PATTERN: RegExp;
|
|
45
|
+
/**
|
|
46
|
+
* Convert a scaled integer string (a token amount in base units) to a decimal
|
|
47
|
+
* string: `scaledIntegerToDecimalString('1000000', 6)` is `'1'`.
|
|
25
48
|
*
|
|
26
|
-
* @param amount - Amount in base units (e.g. "1000000" for 1 USDC)
|
|
27
|
-
* @param decimals - Token decimals (e.g. 6 for USDC)
|
|
28
49
|
* @throws {PerpsError} `ValidationError` when `amount` is not an integer
|
|
29
50
|
* string, or `decimals` is not a non-negative integer.
|
|
30
|
-
* @example
|
|
31
|
-
* ```ts
|
|
32
|
-
* baseUnitsToDecimal('1000000', 6) // '1'
|
|
33
|
-
* ```
|
|
34
51
|
* @public
|
|
35
52
|
*/
|
|
36
|
-
export declare function
|
|
53
|
+
export declare function scaledIntegerToDecimalString(amount: string, decimals: number): string;
|
|
37
54
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* where `'500.00'` and `'500'` are two renderings of one amount and the field
|
|
41
|
-
* wants the first. For a canonical wire amount with no trailing zeros, read
|
|
42
|
-
* the amount off `calculateOrderAmounts` or a provider snap instead.
|
|
43
|
-
*
|
|
44
|
-
* Exact decimal arithmetic throughout, so there is no 2^53 ceiling and no
|
|
45
|
-
* float artifact: `'0.01'` at 18 decimals gives
|
|
46
|
-
* `'0.010000000000000000'`, which `Number#toFixed` cannot.
|
|
55
|
+
* {@link scaledIntegerToDecimalString}, or `undefined` with a warning when it
|
|
56
|
+
* throws.
|
|
47
57
|
*
|
|
48
|
-
* @throws {PerpsError} `ValidationError` when `value` is not a
|
|
49
|
-
* {@link DecimalString}, or `decimals` is not a non-negative integer.
|
|
50
58
|
* @public
|
|
51
59
|
*/
|
|
52
|
-
export declare
|
|
60
|
+
export declare const safeScaledIntegerToDecimalString: (amount: string, decimals: number) => string | undefined;
|
|
53
61
|
/**
|
|
54
62
|
* Spell a `number` as a {@link DecimalString} in plain notation: `1e-7`
|
|
55
63
|
* becomes `'0.0000001'`, never `'1e-7'`. The boundary helper for a venue or
|
|
@@ -60,5 +68,11 @@ export declare function truncateDecimal(value: DecimalString, decimals: number):
|
|
|
60
68
|
* @throws {PerpsError} `ValidationError` when `value` is `NaN` or infinite.
|
|
61
69
|
* @public
|
|
62
70
|
*/
|
|
63
|
-
export declare function numberToDecimalString(value: number):
|
|
71
|
+
export declare function numberToDecimalString(value: number): string;
|
|
72
|
+
/**
|
|
73
|
+
* {@link numberToDecimalString}, or `undefined` with a warning when it throws.
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
export declare const safeNumberToDecimalString: (value: number) => string | undefined;
|
|
64
78
|
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../../src/decimal/convert.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../../src/decimal/convert.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAA;AAQzD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,eAAe,GACxB,MAAM,CAUR;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,oFAGlC,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,eAAe,GACxB,MAAM,CAuBR;AAED;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,oFAG5C,CAAA;AAED,eAAO,MAAM,kBAAkB,QAAY,CAAA;AAE3C;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,CAcR;AAED;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,0DAG5C,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,uCAGrC,CAAA"}
|
|
@@ -2,76 +2,92 @@ 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 {
|
|
5
|
+
import { createSafeFunction } from '../utils/createSafeFunction.js';
|
|
6
|
+
import { bigToDecimalString, decimalStringToBig } from './decimalStringToBig.js';
|
|
7
|
+
import { isDecimalString } from './parse.js';
|
|
8
|
+
const BIG_ROUNDING = {
|
|
9
|
+
truncate: Big.roundDown,
|
|
10
|
+
round: Big.roundHalfUp,
|
|
11
|
+
up: Big.roundUp,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Round a decimal string to `decimals` places with exact decimal arithmetic.
|
|
15
|
+
* The result has no trailing zeros: `roundDecimalString('1.50', 1, 'round')`
|
|
16
|
+
* is `'1.5'`.
|
|
17
|
+
*
|
|
18
|
+
* @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern,
|
|
19
|
+
* or `decimals` is not a non-negative integer.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export function roundDecimalString(value, decimals, rounding) {
|
|
23
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
24
|
+
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid decimals for rounding: ${decimals}`);
|
|
25
|
+
}
|
|
26
|
+
return bigToDecimalString(decimalStringToBig(value).round(decimals, BIG_ROUNDING[rounding]));
|
|
27
|
+
}
|
|
6
28
|
/**
|
|
7
|
-
*
|
|
8
|
-
* on-grid input maps to its exact scaled integer with no binary float
|
|
9
|
-
* artifacts (`'0.29'` at 2 decimals is 29, never 28). Off-grid input resolves
|
|
10
|
-
* per `rounding`; there is no silent default.
|
|
29
|
+
* {@link roundDecimalString}, or `undefined` with a warning when it throws.
|
|
11
30
|
*
|
|
12
|
-
* @throws {PerpsError} `ValidationError` when `value` is not a
|
|
13
|
-
* {@link DecimalString}, `decimals` is not a non-negative integer, or the scaled
|
|
14
|
-
* result's magnitude exceeds `Number.MAX_SAFE_INTEGER`.
|
|
15
31
|
* @public
|
|
16
32
|
*/
|
|
17
|
-
export const
|
|
33
|
+
export const safeRoundDecimalString = createSafeFunction('roundDecimalString', roundDecimalString);
|
|
34
|
+
/**
|
|
35
|
+
* Scale a decimal string to an integer at `decimals` places in exact decimal
|
|
36
|
+
* arithmetic: `'0.29'` at 2 decimals is 29, never 28. Off-grid input resolves
|
|
37
|
+
* per `rounding`. No `$`, `%` or `,` is removed first.
|
|
38
|
+
*
|
|
39
|
+
* @throws {PerpsError} `ValidationError` when `value` does not match the decimal pattern,
|
|
40
|
+
* `decimals` is not a non-negative integer, or the result's magnitude
|
|
41
|
+
* exceeds `Number.MAX_SAFE_INTEGER`.
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export function decimalStringToScaledInteger(value, decimals, rounding) {
|
|
45
|
+
if (!isDecimalString(value)) {
|
|
46
|
+
throw new PerpsError(PerpsErrorCode.ValidationError, `'${value}' does not match the decimal pattern.`);
|
|
47
|
+
}
|
|
18
48
|
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
19
49
|
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid decimals for integer scaling: ${decimals}`);
|
|
20
50
|
}
|
|
21
|
-
const scaled =
|
|
51
|
+
const scaled = new Big(value)
|
|
22
52
|
.times(new Big(10).pow(decimals))
|
|
23
|
-
.round(0, rounding
|
|
53
|
+
.round(0, BIG_ROUNDING[rounding]);
|
|
24
54
|
if (scaled.abs().gt(Number.MAX_SAFE_INTEGER)) {
|
|
25
55
|
throw new PerpsError(PerpsErrorCode.ValidationError, `Scaled value ${scaled.toFixed()} exceeds Number.MAX_SAFE_INTEGER and cannot be encoded exactly.`);
|
|
26
56
|
}
|
|
27
57
|
return scaled.toNumber();
|
|
28
|
-
}
|
|
29
|
-
const BASE_UNITS_PATTERN = /^-?\d+$/;
|
|
58
|
+
}
|
|
30
59
|
/**
|
|
31
|
-
*
|
|
60
|
+
* {@link decimalStringToScaledInteger}, or `undefined` with a warning when it
|
|
61
|
+
* throws.
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
export const safeDecimalStringToScaledInteger = createSafeFunction('decimalStringToScaledInteger', decimalStringToScaledInteger);
|
|
66
|
+
export const BASE_UNITS_PATTERN = /^-?\d+$/;
|
|
67
|
+
/**
|
|
68
|
+
* Convert a scaled integer string (a token amount in base units) to a decimal
|
|
69
|
+
* string: `scaledIntegerToDecimalString('1000000', 6)` is `'1'`.
|
|
32
70
|
*
|
|
33
|
-
* @param amount - Amount in base units (e.g. "1000000" for 1 USDC)
|
|
34
|
-
* @param decimals - Token decimals (e.g. 6 for USDC)
|
|
35
71
|
* @throws {PerpsError} `ValidationError` when `amount` is not an integer
|
|
36
72
|
* string, or `decimals` is not a non-negative integer.
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* baseUnitsToDecimal('1000000', 6) // '1'
|
|
40
|
-
* ```
|
|
41
73
|
* @public
|
|
42
74
|
*/
|
|
43
|
-
export function
|
|
75
|
+
export function scaledIntegerToDecimalString(amount, decimals) {
|
|
44
76
|
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
45
|
-
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid \`
|
|
77
|
+
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid \`scaledIntegerToDecimalString(decimals)\`: ${decimals} is not a non-negative integer.`);
|
|
46
78
|
}
|
|
47
79
|
if (!BASE_UNITS_PATTERN.test(amount)) {
|
|
48
|
-
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid \`
|
|
80
|
+
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid \`scaledIntegerToDecimalString(amount)\`: '${amount}' is not an integer base-unit string.`);
|
|
49
81
|
}
|
|
50
82
|
return formatUnits(BigInt(amount), decimals);
|
|
51
83
|
}
|
|
52
84
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* where `'500.00'` and `'500'` are two renderings of one amount and the field
|
|
56
|
-
* wants the first. For a canonical wire amount with no trailing zeros, read
|
|
57
|
-
* the amount off `calculateOrderAmounts` or a provider snap instead.
|
|
58
|
-
*
|
|
59
|
-
* Exact decimal arithmetic throughout, so there is no 2^53 ceiling and no
|
|
60
|
-
* float artifact: `'0.01'` at 18 decimals gives
|
|
61
|
-
* `'0.010000000000000000'`, which `Number#toFixed` cannot.
|
|
85
|
+
* {@link scaledIntegerToDecimalString}, or `undefined` with a warning when it
|
|
86
|
+
* throws.
|
|
62
87
|
*
|
|
63
|
-
* @throws {PerpsError} `ValidationError` when `value` is not a
|
|
64
|
-
* {@link DecimalString}, or `decimals` is not a non-negative integer.
|
|
65
88
|
* @public
|
|
66
89
|
*/
|
|
67
|
-
export
|
|
68
|
-
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
69
|
-
throw new PerpsError(PerpsErrorCode.ValidationError, `Invalid decimals for truncation: ${decimals}`);
|
|
70
|
-
}
|
|
71
|
-
const truncated = requireDecimal(value, 'truncateDecimal(value)').round(decimals, Big.roundDown);
|
|
72
|
-
// big.js carries the sign through a round to zero; '-0.00' is not a spelling.
|
|
73
|
-
return (truncated.eq(0) ? new Big(0) : truncated).toFixed(decimals);
|
|
74
|
-
}
|
|
90
|
+
export const safeScaledIntegerToDecimalString = createSafeFunction('scaledIntegerToDecimalString', scaledIntegerToDecimalString);
|
|
75
91
|
/**
|
|
76
92
|
* Spell a `number` as a {@link DecimalString} in plain notation: `1e-7`
|
|
77
93
|
* becomes `'0.0000001'`, never `'1e-7'`. The boundary helper for a venue or
|
|
@@ -89,4 +105,10 @@ export function numberToDecimalString(value) {
|
|
|
89
105
|
const parsed = new Big(value);
|
|
90
106
|
return (parsed.eq(0) ? new Big(0) : parsed).toFixed();
|
|
91
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* {@link numberToDecimalString}, or `undefined` with a warning when it throws.
|
|
110
|
+
*
|
|
111
|
+
* @public
|
|
112
|
+
*/
|
|
113
|
+
export const safeNumberToDecimalString = createSafeFunction('numberToDecimalString', numberToDecimalString);
|
|
92
114
|
//# sourceMappingURL=convert.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../../src/decimal/convert.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../../src/decimal/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Big from 'big.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read a decimal string as a `Big`. The string must match `DECIMAL_PATTERN`,
|
|
4
|
+
* so `'$1,234.5'`, `'0.05%'` and the exponent form `'1e5'` are rejected.
|
|
5
|
+
*
|
|
6
|
+
* @throws {PerpsError} `ValidationError` when `value` does not match the
|
|
7
|
+
* decimal pattern.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function decimalStringToBig(value: string): Big;
|
|
11
|
+
/**
|
|
12
|
+
* Spell a `Big` as a canonical decimal string, with no exponent and no `-0`.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function bigToDecimalString(value: Big): string;
|
|
17
|
+
/**
|
|
18
|
+
* {@link decimalStringToBig} as a `DivBig`, so a later `div` keeps 40 decimal
|
|
19
|
+
* places.
|
|
20
|
+
*
|
|
21
|
+
* @throws {PerpsError} `ValidationError` as {@link decimalStringToBig}.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare function decimalStringToDivBig(value: string): Big;
|
|
25
|
+
//# sourceMappingURL=decimalStringToBig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimalStringToBig.d.ts","sourceRoot":"","sources":["../../../src/decimal/decimalStringToBig.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,QAAQ,CAAA;AAIxB;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAQrD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAExD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
* Read a decimal string as a `Big`. The string must match `DECIMAL_PATTERN`,
|
|
7
|
+
* so `'$1,234.5'`, `'0.05%'` and the exponent form `'1e5'` are rejected.
|
|
8
|
+
*
|
|
9
|
+
* @throws {PerpsError} `ValidationError` when `value` does not match the
|
|
10
|
+
* decimal pattern.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export function decimalStringToBig(value) {
|
|
14
|
+
if (typeof value !== 'string' || !DECIMAL_PATTERN.test(value)) {
|
|
15
|
+
throw new PerpsError(PerpsErrorCode.ValidationError, `'${String(value)}' does not match the decimal pattern.`);
|
|
16
|
+
}
|
|
17
|
+
return new Big(value);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Spell a `Big` as a canonical decimal string, with no exponent and no `-0`.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function bigToDecimalString(value) {
|
|
25
|
+
return value.eq(0) ? '0' : value.toFixed();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* {@link decimalStringToBig} as a `DivBig`, so a later `div` keeps 40 decimal
|
|
29
|
+
* places.
|
|
30
|
+
*
|
|
31
|
+
* @throws {PerpsError} `ValidationError` as {@link decimalStringToBig}.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export function decimalStringToDivBig(value) {
|
|
35
|
+
return new DivBig(decimalStringToBig(value));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=decimalStringToBig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimalStringToBig.js","sourceRoot":"","sources":["../../../src/decimal/decimalStringToBig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,GAAG,MAAM,QAAQ,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,UAAU,CAClB,cAAc,CAAC,eAAe,EAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,uCAAuC,CACzD,CAAA;IACH,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAU;IAC3C,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAA;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,OAAO,IAAI,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAA;AAC9C,CAAC"}
|
|
@@ -7,7 +7,10 @@ import type { DecimalString } from '@lifi/perps-types';
|
|
|
7
7
|
export interface FormatOptions {
|
|
8
8
|
/** Fixed number of decimal places. Defaults are per-formatter. */
|
|
9
9
|
decimals?: number;
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Rendered when the value is null, undefined, blank or a non-finite number.
|
|
12
|
+
* A string that is not a decimal is shown unchanged. Defaults to `'—'`.
|
|
13
|
+
*/
|
|
11
14
|
placeholder?: string;
|
|
12
15
|
/** BCP 47 locale controlling digit grouping and separators (e.g. `'en-US'`). */
|
|
13
16
|
locale?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/decimal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/decimal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAItD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,CAAA;AAI7C,KAAK,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;AA+ErE;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAgBR;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAgBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAgBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAgBR;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAwBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAqBR"}
|
|
@@ -1,66 +1,49 @@
|
|
|
1
|
+
import Big from 'big.js';
|
|
2
|
+
import { decimalStringToBig } from './decimalStringToBig.js';
|
|
1
3
|
const DEFAULT_PLACEHOLDER = '—';
|
|
2
4
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* Read a display input as a `Big`. `null` means the formatter renders the
|
|
6
|
+
* placeholder; a string that does not match the decimal pattern is returned
|
|
7
|
+
* unchanged for display.
|
|
6
8
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* when the value is null/undefined/blank or does not resolve to a finite
|
|
13
|
-
* number, so callers can render a placeholder instead of `$0.00` or `$NaN`.
|
|
14
|
-
*/
|
|
15
|
-
function toFiniteNumber(value) {
|
|
16
|
-
let n;
|
|
17
|
-
if (typeof value === 'string') {
|
|
18
|
-
const cleaned = value.replace(/[$,\s]/g, '');
|
|
19
|
-
if (!cleaned) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
n = Number(cleaned);
|
|
23
|
-
}
|
|
24
|
-
else if (typeof value === 'number') {
|
|
25
|
-
n = value;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
9
|
+
function toBig(value) {
|
|
10
|
+
if (typeof value === 'number') {
|
|
11
|
+
return Number.isFinite(value) ? new Big(value) : null;
|
|
12
|
+
}
|
|
13
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
28
14
|
return null;
|
|
29
15
|
}
|
|
30
|
-
|
|
16
|
+
try {
|
|
17
|
+
return decimalStringToBig(value);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
31
22
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* the guard digits are chopped: `99.999` at 2dp → `99.99`, `0.29` → `0.29`.
|
|
37
|
-
*/
|
|
38
|
-
function truncateAbs(abs, decimals) {
|
|
39
|
-
// `toFixed` emits exponent notation at >= 1e21; every double that large is an integer.
|
|
40
|
-
if (Number.isInteger(abs)) {
|
|
41
|
-
return abs;
|
|
42
|
-
}
|
|
43
|
-
const s = abs.toFixed(Math.min(decimals + FLOAT_GUARD_DIGITS, 100));
|
|
44
|
-
const dot = s.indexOf('.');
|
|
45
|
-
const cut = decimals === 0 ? dot : dot + 1 + decimals;
|
|
46
|
-
return Number(s.slice(0, cut));
|
|
23
|
+
function decimalSeparator(locale) {
|
|
24
|
+
return (new Intl.NumberFormat(locale)
|
|
25
|
+
.formatToParts(1.5)
|
|
26
|
+
.find((part) => part.type === 'decimal')?.value ?? '.');
|
|
47
27
|
}
|
|
48
28
|
/**
|
|
49
|
-
* Reduce `
|
|
29
|
+
* Reduce `value` to `decimals` places then split into a sign and the
|
|
50
30
|
* locale-formatted absolute body. The sign is derived from the reduced value
|
|
51
31
|
* so magnitudes that collapse to zero render without a spurious `-`/`+`.
|
|
52
32
|
* `signed` emits `+` for positives; `rounding` selects half-up or truncation.
|
|
53
33
|
*/
|
|
54
|
-
function signAndBody(
|
|
55
|
-
const reduced = rounding === 'floor'
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
34
|
+
function signAndBody(value, decimals, locale, grouping, rounding, signed) {
|
|
35
|
+
const reduced = value.round(decimals, rounding === 'floor' ? Big.roundDown : Big.roundHalfUp);
|
|
36
|
+
const sign = reduced.lt(0) ? '-' : signed && reduced.gt(0) ? '+' : '';
|
|
37
|
+
const [integerPart = '0', fractionPart] = reduced
|
|
38
|
+
.abs()
|
|
39
|
+
.toFixed(decimals)
|
|
40
|
+
.split('.');
|
|
41
|
+
const integerBody = grouping
|
|
42
|
+
? BigInt(integerPart).toLocaleString(locale)
|
|
43
|
+
: integerPart;
|
|
44
|
+
const body = fractionPart === undefined
|
|
45
|
+
? integerBody
|
|
46
|
+
: `${integerBody}${decimalSeparator(locale)}${fractionPart}`;
|
|
64
47
|
return { sign, body };
|
|
65
48
|
}
|
|
66
49
|
/**
|
|
@@ -68,13 +51,13 @@ function signAndBody(n, decimals, locale, grouping, rounding, signed) {
|
|
|
68
51
|
* `>=1` → 2, `>=0.1` → 4, `>=0.01` → 5, otherwise 6.
|
|
69
52
|
*/
|
|
70
53
|
function autoDecimals(abs) {
|
|
71
|
-
if (abs
|
|
54
|
+
if (abs.gte(1)) {
|
|
72
55
|
return 2;
|
|
73
56
|
}
|
|
74
|
-
if (abs
|
|
57
|
+
if (abs.gte('0.1')) {
|
|
75
58
|
return 4;
|
|
76
59
|
}
|
|
77
|
-
if (abs
|
|
60
|
+
if (abs.gte('0.01')) {
|
|
78
61
|
return 5;
|
|
79
62
|
}
|
|
80
63
|
return 6;
|
|
@@ -93,10 +76,13 @@ function autoDecimals(abs) {
|
|
|
93
76
|
*/
|
|
94
77
|
export function formatNumber(value, options = {}) {
|
|
95
78
|
const { decimals = 2, placeholder = DEFAULT_PLACEHOLDER, locale, rounding = 'halfUp', } = options;
|
|
96
|
-
const n =
|
|
79
|
+
const n = toBig(value);
|
|
97
80
|
if (n === null) {
|
|
98
81
|
return placeholder;
|
|
99
82
|
}
|
|
83
|
+
if (typeof n === 'string') {
|
|
84
|
+
return n;
|
|
85
|
+
}
|
|
100
86
|
const { sign, body } = signAndBody(n, decimals, locale, true, rounding, false);
|
|
101
87
|
return `${sign}${body}`;
|
|
102
88
|
}
|
|
@@ -110,10 +96,13 @@ export function formatNumber(value, options = {}) {
|
|
|
110
96
|
*/
|
|
111
97
|
export function formatUsd(value, options = {}) {
|
|
112
98
|
const { decimals = 2, placeholder = DEFAULT_PLACEHOLDER, locale, rounding = 'halfUp', } = options;
|
|
113
|
-
const n =
|
|
99
|
+
const n = toBig(value);
|
|
114
100
|
if (n === null) {
|
|
115
101
|
return placeholder;
|
|
116
102
|
}
|
|
103
|
+
if (typeof n === 'string') {
|
|
104
|
+
return n;
|
|
105
|
+
}
|
|
117
106
|
const { sign, body } = signAndBody(n, decimals, locale, true, rounding, false);
|
|
118
107
|
return `${sign}$${body}`;
|
|
119
108
|
}
|
|
@@ -128,10 +117,13 @@ export function formatUsd(value, options = {}) {
|
|
|
128
117
|
*/
|
|
129
118
|
export function formatSignedUsd(value, options = {}) {
|
|
130
119
|
const { decimals = 2, placeholder = DEFAULT_PLACEHOLDER, locale, rounding = 'halfUp', } = options;
|
|
131
|
-
const n =
|
|
120
|
+
const n = toBig(value);
|
|
132
121
|
if (n === null) {
|
|
133
122
|
return placeholder;
|
|
134
123
|
}
|
|
124
|
+
if (typeof n === 'string') {
|
|
125
|
+
return n;
|
|
126
|
+
}
|
|
135
127
|
const { sign, body } = signAndBody(n, decimals, locale, true, rounding, true);
|
|
136
128
|
return `${sign}$${body}`;
|
|
137
129
|
}
|
|
@@ -146,10 +138,13 @@ export function formatSignedUsd(value, options = {}) {
|
|
|
146
138
|
*/
|
|
147
139
|
export function formatSignedPercent(value, options = {}) {
|
|
148
140
|
const { decimals = 2, placeholder = DEFAULT_PLACEHOLDER, locale, rounding = 'halfUp', } = options;
|
|
149
|
-
const n =
|
|
141
|
+
const n = toBig(value);
|
|
150
142
|
if (n === null) {
|
|
151
143
|
return placeholder;
|
|
152
144
|
}
|
|
145
|
+
if (typeof n === 'string') {
|
|
146
|
+
return n;
|
|
147
|
+
}
|
|
153
148
|
const { sign, body } = signAndBody(n, decimals, locale, false, rounding, true);
|
|
154
149
|
return `${sign}${body}%`;
|
|
155
150
|
}
|
|
@@ -165,13 +160,16 @@ export function formatSignedPercent(value, options = {}) {
|
|
|
165
160
|
*/
|
|
166
161
|
export function formatPrice(value, options = {}) {
|
|
167
162
|
const { placeholder = DEFAULT_PLACEHOLDER, locale, rounding = 'halfUp', } = options;
|
|
168
|
-
const n =
|
|
163
|
+
const n = toBig(value);
|
|
169
164
|
if (n === null) {
|
|
170
165
|
return placeholder;
|
|
171
166
|
}
|
|
172
|
-
|
|
167
|
+
if (typeof n === 'string') {
|
|
168
|
+
return n;
|
|
169
|
+
}
|
|
170
|
+
const abs = n.abs();
|
|
173
171
|
const decimals = options.decimals ?? autoDecimals(abs);
|
|
174
|
-
const { sign, body } = signAndBody(n, decimals, locale, abs
|
|
172
|
+
const { sign, body } = signAndBody(n, decimals, locale, abs.gte(1000), rounding, false);
|
|
175
173
|
return `${sign}$${body}`;
|
|
176
174
|
}
|
|
177
175
|
/**
|
|
@@ -185,20 +183,23 @@ export function formatPrice(value, options = {}) {
|
|
|
185
183
|
*/
|
|
186
184
|
export function formatCompactUsd(value, options = {}) {
|
|
187
185
|
const { decimals = 2, placeholder = DEFAULT_PLACEHOLDER } = options;
|
|
188
|
-
const n =
|
|
186
|
+
const n = toBig(value);
|
|
189
187
|
if (n === null) {
|
|
190
188
|
return placeholder;
|
|
191
189
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
190
|
+
if (typeof n === 'string') {
|
|
191
|
+
return n;
|
|
192
|
+
}
|
|
193
|
+
const sign = n.lt(0) ? '-' : '';
|
|
194
|
+
const abs = n.abs();
|
|
195
|
+
if (abs.gte(1_000_000_000)) {
|
|
196
|
+
return `${sign}$${abs.div(1_000_000_000).toFixed(decimals)}B`;
|
|
196
197
|
}
|
|
197
|
-
if (abs
|
|
198
|
-
return `${sign}$${(
|
|
198
|
+
if (abs.gte(1_000_000)) {
|
|
199
|
+
return `${sign}$${abs.div(1_000_000).toFixed(decimals)}M`;
|
|
199
200
|
}
|
|
200
|
-
if (abs
|
|
201
|
-
return `${sign}$${(
|
|
201
|
+
if (abs.gte(1_000)) {
|
|
202
|
+
return `${sign}$${abs.div(1_000).toFixed(decimals)}K`;
|
|
202
203
|
}
|
|
203
204
|
return `${sign}$${abs.toFixed(decimals)}`;
|
|
204
205
|
}
|