sushi 6.7.0 → 6.7.1
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/_cjs/generic/currency/price.js +23 -2
- package/_cjs/generic/currency/price.js.map +1 -1
- package/_cjs/generic/math/fraction.js +70 -3
- package/_cjs/generic/math/fraction.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/generic/currency/price.js +29 -2
- package/_esm/generic/currency/price.js.map +1 -1
- package/_esm/generic/math/fraction.js +70 -3
- package/_esm/generic/math/fraction.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/generic/currency/price.d.ts +9 -2
- package/_types/generic/currency/price.d.ts.map +1 -1
- package/_types/generic/math/fraction.d.ts +3 -1
- package/_types/generic/math/fraction.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/generic/currency/price.test-d.ts +59 -0
- package/generic/currency/price.test.ts +132 -0
- package/generic/currency/price.ts +41 -3
- package/generic/math/fraction.test.ts +97 -0
- package/generic/math/fraction.ts +106 -3
- package/package.json +1 -1
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Price = void 0;
|
|
4
|
-
const number_js_1 = require("../format/number.js");
|
|
5
4
|
const fraction_js_1 = require("../math/fraction.js");
|
|
6
5
|
const amount_js_1 = require("./amount.js");
|
|
7
6
|
class Price extends fraction_js_1.Fraction {
|
|
7
|
+
static fromHuman(base, quote, value) {
|
|
8
|
+
if (!value.match(/^\d*\.?\d+$/)) {
|
|
9
|
+
throw new Error(`Invalid price: ${value}`);
|
|
10
|
+
}
|
|
11
|
+
const [whole = '', fraction = ''] = value.split('.');
|
|
12
|
+
const decimalScale = 10n ** BigInt(fraction.length);
|
|
13
|
+
const valueWithoutDecimals = BigInt(`${whole}${fraction}`);
|
|
14
|
+
return new Price({
|
|
15
|
+
base,
|
|
16
|
+
quote,
|
|
17
|
+
numerator: valueWithoutDecimals * 10n ** BigInt(quote.decimals),
|
|
18
|
+
denominator: decimalScale * 10n ** BigInt(base.decimals),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
static tryFromHuman(base, quote, value) {
|
|
22
|
+
try {
|
|
23
|
+
return Price.fromHuman(base, quote, value);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
8
29
|
constructor(args) {
|
|
9
30
|
if ('baseAmount' in args && 'quoteAmount' in args) {
|
|
10
31
|
const { baseAmount, quoteAmount } = args;
|
|
@@ -39,7 +60,7 @@ class Price extends fraction_js_1.Fraction {
|
|
|
39
60
|
return super.mul(this.scalar).toNumber();
|
|
40
61
|
}
|
|
41
62
|
toString(args) {
|
|
42
|
-
return
|
|
63
|
+
return super.mul(this.scalar).toString(args);
|
|
43
64
|
}
|
|
44
65
|
toSignificant(significantDigits = 5) {
|
|
45
66
|
return this.toString({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"price.js","sourceRoot":"","sources":["../../../generic/currency/price.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"price.js","sourceRoot":"","sources":["../../../generic/currency/price.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Fraction = void 0;
|
|
7
7
|
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
|
|
8
|
-
const number_js_1 = require("../format/number.js");
|
|
9
8
|
class Fraction {
|
|
10
9
|
constructor(arg) {
|
|
11
10
|
if (typeof arg === 'number') {
|
|
@@ -129,11 +128,79 @@ class Fraction {
|
|
|
129
128
|
toNumber() {
|
|
130
129
|
return Number(this.numerator) / Number(this.denominator);
|
|
131
130
|
}
|
|
131
|
+
formatDecimal(decimalPlaces, { round, trim }) {
|
|
132
|
+
(0, tiny_invariant_1.default)(Number.isSafeInteger(decimalPlaces), 'Decimal places must be a safe integer');
|
|
133
|
+
(0, tiny_invariant_1.default)(this.denominator !== 0n, 'Cannot format a fraction by zero');
|
|
134
|
+
const negative = this.numerator < 0n !== this.denominator < 0n;
|
|
135
|
+
const numerator = this.numerator < 0n ? -this.numerator : this.numerator;
|
|
136
|
+
const denominator = this.denominator < 0n ? -this.denominator : this.denominator;
|
|
137
|
+
const scale = 10n ** BigInt(Math.abs(decimalPlaces));
|
|
138
|
+
const scaledDenominator = decimalPlaces >= 0 ? denominator : denominator * scale;
|
|
139
|
+
const scaledNumerator = decimalPlaces >= 0 ? numerator * scale : numerator;
|
|
140
|
+
let scaledValue = scaledNumerator / scaledDenominator;
|
|
141
|
+
const remainder = scaledNumerator % scaledDenominator;
|
|
142
|
+
if (round && remainder * 2n >= scaledDenominator) {
|
|
143
|
+
scaledValue += 1n;
|
|
144
|
+
}
|
|
145
|
+
let integerPart;
|
|
146
|
+
let decimalPart = '';
|
|
147
|
+
if (decimalPlaces > 0) {
|
|
148
|
+
const value = scaledValue.toString().padStart(decimalPlaces + 1, '0');
|
|
149
|
+
integerPart = value.slice(0, -decimalPlaces);
|
|
150
|
+
decimalPart = value.slice(-decimalPlaces);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
integerPart = (scaledValue * scale).toString();
|
|
154
|
+
}
|
|
155
|
+
if (trim) {
|
|
156
|
+
decimalPart = decimalPart.replace(/0+$/, '');
|
|
157
|
+
}
|
|
158
|
+
return `${negative ? '-' : ''}${integerPart}${decimalPart ? `.${decimalPart}` : ''}`;
|
|
159
|
+
}
|
|
160
|
+
getDecimalExponent() {
|
|
161
|
+
const numerator = this.numerator < 0n ? -this.numerator : this.numerator;
|
|
162
|
+
const denominator = this.denominator < 0n ? -this.denominator : this.denominator;
|
|
163
|
+
(0, tiny_invariant_1.default)(numerator !== 0n, 'Cannot get the decimal exponent of zero');
|
|
164
|
+
(0, tiny_invariant_1.default)(denominator !== 0n, 'Cannot format a fraction by zero');
|
|
165
|
+
let exponent = numerator.toString().length - denominator.toString().length;
|
|
166
|
+
if ((exponent >= 0 && numerator < denominator * 10n ** BigInt(exponent)) ||
|
|
167
|
+
(exponent < 0 && numerator * 10n ** BigInt(-exponent) < denominator)) {
|
|
168
|
+
exponent -= 1;
|
|
169
|
+
}
|
|
170
|
+
return exponent;
|
|
171
|
+
}
|
|
132
172
|
toString(args) {
|
|
133
|
-
|
|
173
|
+
if ('fixed' in args) {
|
|
174
|
+
(0, tiny_invariant_1.default)(Number.isSafeInteger(args.fixed) && args.fixed >= 0, 'Fixed digits must be a non-negative safe integer');
|
|
175
|
+
}
|
|
176
|
+
else if ('maxFixed' in args) {
|
|
177
|
+
(0, tiny_invariant_1.default)(Number.isSafeInteger(args.maxFixed) && args.maxFixed >= 0, 'Maximum fixed digits must be a non-negative safe integer');
|
|
178
|
+
}
|
|
179
|
+
else if ('significant' in args) {
|
|
180
|
+
(0, tiny_invariant_1.default)(Number.isSafeInteger(args.significant) && args.significant > 0, 'Significant digits must be a positive safe integer');
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
throw new Error('Invalid arguments for Fraction.toString');
|
|
184
|
+
}
|
|
185
|
+
if (this.denominator === 0n) {
|
|
186
|
+
return this.toNumber().toString();
|
|
187
|
+
}
|
|
188
|
+
if ('fixed' in args) {
|
|
189
|
+
return this.formatDecimal(args.fixed, { round: true, trim: false });
|
|
190
|
+
}
|
|
191
|
+
if ('maxFixed' in args) {
|
|
192
|
+
return this.formatDecimal(args.maxFixed, { round: false, trim: true });
|
|
193
|
+
}
|
|
194
|
+
if ('significant' in args) {
|
|
195
|
+
if (this.numerator === 0n)
|
|
196
|
+
return '0';
|
|
197
|
+
const decimalPlaces = args.significant - this.getDecimalExponent() - 1;
|
|
198
|
+
return this.formatDecimal(decimalPlaces, { round: true, trim: true });
|
|
199
|
+
}
|
|
200
|
+
throw new Error('Invalid arguments for Fraction.toString');
|
|
134
201
|
}
|
|
135
202
|
toSignificant(significantDigits) {
|
|
136
|
-
return this.
|
|
203
|
+
return this.toString({ significant: significantDigits });
|
|
137
204
|
}
|
|
138
205
|
toJSON() {
|
|
139
206
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fraction.js","sourceRoot":"","sources":["../../../generic/math/fraction.ts"],"names":[],"mappings":";;;;;;AAAA,oEAAsC;
|
|
1
|
+
{"version":3,"file":"fraction.js","sourceRoot":"","sources":["../../../generic/math/fraction.ts"],"names":[],"mappings":"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"}
|
package/_cjs/version.js
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import { numberToFixed } from '../format/number.js';
|
|
2
1
|
import { Fraction } from '../math/fraction.js';
|
|
3
2
|
import { Amount } from './amount.js';
|
|
4
3
|
export class Price extends Fraction {
|
|
4
|
+
/**
|
|
5
|
+
* Creates a Price from a human-readable quote-per-base value, e.g. "1.5".
|
|
6
|
+
*/
|
|
7
|
+
static fromHuman(base, quote, value) {
|
|
8
|
+
if (!value.match(/^\d*\.?\d+$/)) {
|
|
9
|
+
throw new Error(`Invalid price: ${value}`);
|
|
10
|
+
}
|
|
11
|
+
const [whole = '', fraction = ''] = value.split('.');
|
|
12
|
+
const decimalScale = 10n ** BigInt(fraction.length);
|
|
13
|
+
const valueWithoutDecimals = BigInt(`${whole}${fraction}`);
|
|
14
|
+
return new Price({
|
|
15
|
+
base,
|
|
16
|
+
quote,
|
|
17
|
+
numerator: valueWithoutDecimals * 10n ** BigInt(quote.decimals),
|
|
18
|
+
denominator: decimalScale * 10n ** BigInt(base.decimals),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Tries to create a Price from a human-readable quote-per-base value.
|
|
23
|
+
*/
|
|
24
|
+
static tryFromHuman(base, quote, value) {
|
|
25
|
+
try {
|
|
26
|
+
return Price.fromHuman(base, quote, value);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
5
32
|
constructor(args) {
|
|
6
33
|
if ('baseAmount' in args && 'quoteAmount' in args) {
|
|
7
34
|
const { baseAmount, quoteAmount } = args;
|
|
@@ -41,7 +68,7 @@ export class Price extends Fraction {
|
|
|
41
68
|
return super.mul(this.scalar).toNumber();
|
|
42
69
|
}
|
|
43
70
|
toString(args) {
|
|
44
|
-
return
|
|
71
|
+
return super.mul(this.scalar).toString(args);
|
|
45
72
|
}
|
|
46
73
|
toSignificant(significantDigits = 5) {
|
|
47
74
|
return this.toString({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"price.js","sourceRoot":"","sources":["../../../generic/currency/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"price.js","sourceRoot":"","sources":["../../../generic/currency/price.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import invariant from 'tiny-invariant';
|
|
2
|
-
import { numberToFixed } from '../format/number.js';
|
|
3
2
|
export class Fraction {
|
|
4
3
|
constructor(arg) {
|
|
5
4
|
if (typeof arg === 'number') {
|
|
@@ -123,11 +122,79 @@ export class Fraction {
|
|
|
123
122
|
toNumber() {
|
|
124
123
|
return Number(this.numerator) / Number(this.denominator);
|
|
125
124
|
}
|
|
125
|
+
formatDecimal(decimalPlaces, { round, trim }) {
|
|
126
|
+
invariant(Number.isSafeInteger(decimalPlaces), 'Decimal places must be a safe integer');
|
|
127
|
+
invariant(this.denominator !== 0n, 'Cannot format a fraction by zero');
|
|
128
|
+
const negative = this.numerator < 0n !== this.denominator < 0n;
|
|
129
|
+
const numerator = this.numerator < 0n ? -this.numerator : this.numerator;
|
|
130
|
+
const denominator = this.denominator < 0n ? -this.denominator : this.denominator;
|
|
131
|
+
const scale = 10n ** BigInt(Math.abs(decimalPlaces));
|
|
132
|
+
const scaledDenominator = decimalPlaces >= 0 ? denominator : denominator * scale;
|
|
133
|
+
const scaledNumerator = decimalPlaces >= 0 ? numerator * scale : numerator;
|
|
134
|
+
let scaledValue = scaledNumerator / scaledDenominator;
|
|
135
|
+
const remainder = scaledNumerator % scaledDenominator;
|
|
136
|
+
if (round && remainder * 2n >= scaledDenominator) {
|
|
137
|
+
scaledValue += 1n;
|
|
138
|
+
}
|
|
139
|
+
let integerPart;
|
|
140
|
+
let decimalPart = '';
|
|
141
|
+
if (decimalPlaces > 0) {
|
|
142
|
+
const value = scaledValue.toString().padStart(decimalPlaces + 1, '0');
|
|
143
|
+
integerPart = value.slice(0, -decimalPlaces);
|
|
144
|
+
decimalPart = value.slice(-decimalPlaces);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
integerPart = (scaledValue * scale).toString();
|
|
148
|
+
}
|
|
149
|
+
if (trim) {
|
|
150
|
+
decimalPart = decimalPart.replace(/0+$/, '');
|
|
151
|
+
}
|
|
152
|
+
return `${negative ? '-' : ''}${integerPart}${decimalPart ? `.${decimalPart}` : ''}`;
|
|
153
|
+
}
|
|
154
|
+
getDecimalExponent() {
|
|
155
|
+
const numerator = this.numerator < 0n ? -this.numerator : this.numerator;
|
|
156
|
+
const denominator = this.denominator < 0n ? -this.denominator : this.denominator;
|
|
157
|
+
invariant(numerator !== 0n, 'Cannot get the decimal exponent of zero');
|
|
158
|
+
invariant(denominator !== 0n, 'Cannot format a fraction by zero');
|
|
159
|
+
let exponent = numerator.toString().length - denominator.toString().length;
|
|
160
|
+
if ((exponent >= 0 && numerator < denominator * 10n ** BigInt(exponent)) ||
|
|
161
|
+
(exponent < 0 && numerator * 10n ** BigInt(-exponent) < denominator)) {
|
|
162
|
+
exponent -= 1;
|
|
163
|
+
}
|
|
164
|
+
return exponent;
|
|
165
|
+
}
|
|
126
166
|
toString(args) {
|
|
127
|
-
|
|
167
|
+
if ('fixed' in args) {
|
|
168
|
+
invariant(Number.isSafeInteger(args.fixed) && args.fixed >= 0, 'Fixed digits must be a non-negative safe integer');
|
|
169
|
+
}
|
|
170
|
+
else if ('maxFixed' in args) {
|
|
171
|
+
invariant(Number.isSafeInteger(args.maxFixed) && args.maxFixed >= 0, 'Maximum fixed digits must be a non-negative safe integer');
|
|
172
|
+
}
|
|
173
|
+
else if ('significant' in args) {
|
|
174
|
+
invariant(Number.isSafeInteger(args.significant) && args.significant > 0, 'Significant digits must be a positive safe integer');
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
throw new Error('Invalid arguments for Fraction.toString');
|
|
178
|
+
}
|
|
179
|
+
if (this.denominator === 0n) {
|
|
180
|
+
return this.toNumber().toString();
|
|
181
|
+
}
|
|
182
|
+
if ('fixed' in args) {
|
|
183
|
+
return this.formatDecimal(args.fixed, { round: true, trim: false });
|
|
184
|
+
}
|
|
185
|
+
if ('maxFixed' in args) {
|
|
186
|
+
return this.formatDecimal(args.maxFixed, { round: false, trim: true });
|
|
187
|
+
}
|
|
188
|
+
if ('significant' in args) {
|
|
189
|
+
if (this.numerator === 0n)
|
|
190
|
+
return '0';
|
|
191
|
+
const decimalPlaces = args.significant - this.getDecimalExponent() - 1;
|
|
192
|
+
return this.formatDecimal(decimalPlaces, { round: true, trim: true });
|
|
193
|
+
}
|
|
194
|
+
throw new Error('Invalid arguments for Fraction.toString');
|
|
128
195
|
}
|
|
129
196
|
toSignificant(significantDigits) {
|
|
130
|
-
return this.
|
|
197
|
+
return this.toString({ significant: significantDigits });
|
|
131
198
|
}
|
|
132
199
|
toJSON() {
|
|
133
200
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fraction.js","sourceRoot":"","sources":["../../../generic/math/fraction.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"fraction.js","sourceRoot":"","sources":["../../../generic/math/fraction.ts"],"names":[],"mappings":"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"}
|
package/_esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '6.7.
|
|
1
|
+
export const version = '6.7.1';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { numberToFixed } from '../format/number.js';
|
|
2
1
|
import { Fraction } from '../math/fraction.js';
|
|
3
2
|
import type { BigintIsh } from '../types/bigintish.js';
|
|
4
3
|
import { Amount } from './amount.js';
|
|
@@ -6,6 +5,14 @@ import type { Currency } from './currency.js';
|
|
|
6
5
|
export declare class Price<TBase extends Currency, TQuote extends Currency> extends Fraction {
|
|
7
6
|
readonly base: TBase;
|
|
8
7
|
readonly quote: TQuote;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a Price from a human-readable quote-per-base value, e.g. "1.5".
|
|
10
|
+
*/
|
|
11
|
+
static fromHuman<TBase extends Currency, TQuote extends Currency>(base: TBase, quote: TQuote, value: string): Price<TBase, TQuote>;
|
|
12
|
+
/**
|
|
13
|
+
* Tries to create a Price from a human-readable quote-per-base value.
|
|
14
|
+
*/
|
|
15
|
+
static tryFromHuman<TBase extends Currency, TQuote extends Currency>(base: TBase, quote: TQuote, value: string): Price<TBase, TQuote> | undefined;
|
|
9
16
|
constructor(args: {
|
|
10
17
|
base: TBase;
|
|
11
18
|
quote: TQuote;
|
|
@@ -24,7 +31,7 @@ export declare class Price<TBase extends Currency, TQuote extends Currency> exte
|
|
|
24
31
|
getQuote(baseAmount: Amount<TBase>): Amount<TQuote>;
|
|
25
32
|
invert(): Price<TQuote, TBase>;
|
|
26
33
|
toNumber(): number;
|
|
27
|
-
toString(args: Parameters<
|
|
34
|
+
toString(args: Parameters<Fraction['toString']>[0]): string;
|
|
28
35
|
toSignificant(significantDigits?: number): string;
|
|
29
36
|
}
|
|
30
37
|
//# sourceMappingURL=price.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../../generic/currency/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../../generic/currency/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C,qBAAa,KAAK,CAChB,KAAK,SAAS,QAAQ,EACtB,MAAM,SAAS,QAAQ,CACvB,SAAQ,QAAQ;IAChB,SAAgB,IAAI,EAAE,KAAK,CAAA;IAC3B,SAAgB,KAAK,EAAE,MAAM,CAAA;IAE7B;;OAEG;WACW,SAAS,CAAC,KAAK,SAAS,QAAQ,EAAE,MAAM,SAAS,QAAQ,EACrE,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC;IAiBvB;;OAEG;WACW,YAAY,CAAC,KAAK,SAAS,QAAQ,EAAE,MAAM,SAAS,QAAQ,EACxE,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS;gBASjC,IAAI,EACA;QACE,IAAI,EAAE,KAAK,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,SAAS,CAAA;QACpB,WAAW,CAAC,EAAE,SAAS,CAAA;KACxB,GACD;QAAE,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;KAAE;IAgBhE,IAAI,MAAM,IAAI,QAAQ,CAKrB;IAED;;;;OAIG;IACI,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IAK1C,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC;IAS9B,QAAQ,IAAI,MAAM;IAIlB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM;IAI3D,aAAa,CAAC,iBAAiB,SAAI,GAAG,MAAM;CAK7D"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { numberToFixed } from '../format/number.js';
|
|
1
|
+
import type { numberToFixed } from '../format/number.js';
|
|
2
2
|
import type { BigintIsh } from '../types/bigintish.js';
|
|
3
3
|
export declare class Fraction {
|
|
4
4
|
readonly numerator: bigint;
|
|
@@ -22,6 +22,8 @@ export declare class Fraction {
|
|
|
22
22
|
gt(other: Fraction | BigintIsh): boolean;
|
|
23
23
|
neq(other: Fraction | BigintIsh): boolean;
|
|
24
24
|
toNumber(): number;
|
|
25
|
+
private formatDecimal;
|
|
26
|
+
private getDecimalExponent;
|
|
25
27
|
toString(args: Parameters<typeof numberToFixed>[1]): string;
|
|
26
28
|
toSignificant(significantDigits: number): string;
|
|
27
29
|
toJSON(): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fraction.d.ts","sourceRoot":"","sources":["../../../generic/math/fraction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"fraction.d.ts","sourceRoot":"","sources":["../../../generic/math/fraction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEtD,qBAAa,QAAQ;IACnB,SAAgB,SAAS,EAAE,MAAM,CAAA;IACjC,SAAgB,WAAW,EAAE,MAAM,CAAA;gBAGjC,GAAG,EAAE;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,WAAW,CAAC,EAAE,SAAS,CAAA;KAAE,GAAG,MAAM;IAgBjE,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,SAAS,IAAI,MAAM,CAE7B;IAEM,MAAM,IAAI,QAAQ;IAYlB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ;IAgB1C,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ;IAgB1C,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ;IAc1C,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ;IAcjD,OAAO,CAAC,OAAO;IAiCR,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAIxC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAIzC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAIxC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAIzC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAIxC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAIzC,QAAQ,IAAI,MAAM;IAIzB,OAAO,CAAC,aAAa;IA6CrB,OAAO,CAAC,kBAAkB;IAoBnB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM;IA0C3D,aAAa,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM;IAIhD,MAAM;;;;IAOb;;OAEG;IACH,IAAW,UAAU,IAAI,QAAQ,CAKhC;CACF"}
|
package/_types/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "6.7.
|
|
1
|
+
export declare const version = "6.7.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import { describe, expectTypeOf } from 'vitest'
|
|
3
|
+
import { Price } from './price.js'
|
|
4
|
+
import { Token } from './token.js'
|
|
5
|
+
|
|
6
|
+
class BaseToken extends Token {
|
|
7
|
+
public override toJSON() {
|
|
8
|
+
return {} as any
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public override wrap() {
|
|
12
|
+
return this
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class QuoteToken extends Token {
|
|
17
|
+
public override toJSON() {
|
|
18
|
+
return {} as any
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public override wrap() {
|
|
22
|
+
return this
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const base = new BaseToken({
|
|
27
|
+
chainId: 1,
|
|
28
|
+
address: '0x1234567890abcdef1234567890abcdef12345678',
|
|
29
|
+
symbol: 'BASE',
|
|
30
|
+
name: 'Base',
|
|
31
|
+
decimals: 18,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const quote = new QuoteToken({
|
|
35
|
+
chainId: 1,
|
|
36
|
+
address: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
37
|
+
symbol: 'QUOTE',
|
|
38
|
+
name: 'Quote',
|
|
39
|
+
decimals: 6,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('generic/currency/price.ts types', () => {
|
|
43
|
+
it('preserves concrete base and quote currency types', () => {
|
|
44
|
+
const price = Price.fromHuman(base, quote, '1.25')
|
|
45
|
+
|
|
46
|
+
expectTypeOf(price).toEqualTypeOf<Price<BaseToken, QuoteToken>>()
|
|
47
|
+
expectTypeOf(price.base).toEqualTypeOf<BaseToken>()
|
|
48
|
+
expectTypeOf(price.quote).toEqualTypeOf<QuoteToken>()
|
|
49
|
+
expectTypeOf(price.invert()).toEqualTypeOf<Price<QuoteToken, BaseToken>>()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('preserves types when trying to create a price', () => {
|
|
53
|
+
const price = Price.tryFromHuman(base, quote, '1.25')
|
|
54
|
+
|
|
55
|
+
expectTypeOf(price).toEqualTypeOf<
|
|
56
|
+
Price<BaseToken, QuoteToken> | undefined
|
|
57
|
+
>()
|
|
58
|
+
})
|
|
59
|
+
})
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { Price } from './price.js'
|
|
3
|
+
import { Token } from './token.js'
|
|
4
|
+
|
|
5
|
+
class TestToken extends Token {
|
|
6
|
+
public override toJSON() {
|
|
7
|
+
return {} as any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public override wrap() {
|
|
11
|
+
return this
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const wbtc = new TestToken({
|
|
16
|
+
decimals: 8,
|
|
17
|
+
symbol: 'WBTC',
|
|
18
|
+
name: 'Wrapped Bitcoin',
|
|
19
|
+
chainId: 1,
|
|
20
|
+
address: '0x1234567890abcdef1234567890abcdef12345678',
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const usdc = new TestToken({
|
|
24
|
+
decimals: 6,
|
|
25
|
+
symbol: 'USDC',
|
|
26
|
+
name: 'USD Coin',
|
|
27
|
+
chainId: 1,
|
|
28
|
+
address: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('Price', () => {
|
|
32
|
+
describe('fromHuman', () => {
|
|
33
|
+
it('creates a price for currencies with different decimals', () => {
|
|
34
|
+
const price = Price.fromHuman(wbtc, usdc, '1.25')
|
|
35
|
+
|
|
36
|
+
expect(price.base).toBe(wbtc)
|
|
37
|
+
expect(price.quote).toBe(usdc)
|
|
38
|
+
expect(price.toNumber()).toBe(1.25)
|
|
39
|
+
expect(price.numerator).toBe(125000000n)
|
|
40
|
+
expect(price.denominator).toBe(10000000000n)
|
|
41
|
+
expect(price.invert().toNumber()).toBe(0.8)
|
|
42
|
+
expect(price.invert().toString({ maxFixed: 18 })).toBe('0.8')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('accepts a decimal without a leading zero', () => {
|
|
46
|
+
expect(Price.fromHuman(wbtc, usdc, '.5').toNumber()).toBe(0.5)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('accepts zero', () => {
|
|
50
|
+
const price = Price.fromHuman(wbtc, usdc, '0')
|
|
51
|
+
|
|
52
|
+
expect(price.toNumber()).toBe(0)
|
|
53
|
+
expect(price.numerator).toBe(0n)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('preserves more than 18 fractional digits', () => {
|
|
57
|
+
const price = Price.fromHuman(wbtc, usdc, '0.0000000000000000001')
|
|
58
|
+
|
|
59
|
+
expect(price.numerator).toBe(1000000n)
|
|
60
|
+
expect(price.denominator).toBe(1000000000000000000000000000n)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it.each([
|
|
64
|
+
'',
|
|
65
|
+
'-1',
|
|
66
|
+
'1e6',
|
|
67
|
+
'Infinity',
|
|
68
|
+
])('rejects invalid input %j', (value) => {
|
|
69
|
+
expect(() => Price.fromHuman(wbtc, usdc, value)).toThrow(
|
|
70
|
+
`Invalid price: ${value}`,
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('tryFromHuman', () => {
|
|
76
|
+
it('returns a price for valid input', () => {
|
|
77
|
+
expect(Price.tryFromHuman(wbtc, usdc, '1.25')?.toNumber()).toBe(1.25)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it.each([
|
|
81
|
+
'',
|
|
82
|
+
'-1',
|
|
83
|
+
'1e6',
|
|
84
|
+
'Infinity',
|
|
85
|
+
])('returns undefined for invalid input %j', (value) => {
|
|
86
|
+
expect(Price.tryFromHuman(wbtc, usdc, value)).toBeUndefined()
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
describe('string formatting', () => {
|
|
91
|
+
it('formats very small prices without scientific notation', () => {
|
|
92
|
+
const price = Price.fromHuman(wbtc, usdc, '0.000000000001')
|
|
93
|
+
|
|
94
|
+
expect(price.toString({ maxFixed: 18 })).toBe('0.000000000001')
|
|
95
|
+
expect(price.toString({ significant: 6 })).toBe('0.000000000001')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('truncates repeating prices to maxFixed decimal places', () => {
|
|
99
|
+
const price = new Price({
|
|
100
|
+
base: wbtc,
|
|
101
|
+
quote: wbtc,
|
|
102
|
+
numerator: 1n,
|
|
103
|
+
denominator: 3n,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
expect(price.toString({ maxFixed: 18 })).toBe('0.333333333333333333')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('preserves prices beyond Number.MAX_SAFE_INTEGER', () => {
|
|
110
|
+
const price = new Price({
|
|
111
|
+
base: wbtc,
|
|
112
|
+
quote: wbtc,
|
|
113
|
+
numerator: 9007199254740993n,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
expect(price.toString({ maxFixed: 18 })).toBe('9007199254740993')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('supports fixed, maxFixed, and significant formatting', () => {
|
|
120
|
+
const price = new Price({
|
|
121
|
+
base: wbtc,
|
|
122
|
+
quote: wbtc,
|
|
123
|
+
numerator: 1n,
|
|
124
|
+
denominator: 8n,
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
expect(price.toString({ fixed: 3 })).toBe('0.125')
|
|
128
|
+
expect(price.toString({ maxFixed: 2 })).toBe('0.12')
|
|
129
|
+
expect(price.toString({ significant: 2 })).toBe('0.13')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
})
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { numberToFixed } from '../format/number.js'
|
|
2
1
|
import { Fraction } from '../math/fraction.js'
|
|
3
2
|
import type { BigintIsh } from '../types/bigintish.js'
|
|
4
3
|
import { Amount } from './amount.js'
|
|
@@ -11,6 +10,45 @@ export class Price<
|
|
|
11
10
|
public readonly base: TBase
|
|
12
11
|
public readonly quote: TQuote
|
|
13
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Price from a human-readable quote-per-base value, e.g. "1.5".
|
|
15
|
+
*/
|
|
16
|
+
public static fromHuman<TBase extends Currency, TQuote extends Currency>(
|
|
17
|
+
base: TBase,
|
|
18
|
+
quote: TQuote,
|
|
19
|
+
value: string,
|
|
20
|
+
): Price<TBase, TQuote> {
|
|
21
|
+
if (!value.match(/^\d*\.?\d+$/)) {
|
|
22
|
+
throw new Error(`Invalid price: ${value}`)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const [whole = '', fraction = ''] = value.split('.')
|
|
26
|
+
const decimalScale = 10n ** BigInt(fraction.length)
|
|
27
|
+
const valueWithoutDecimals = BigInt(`${whole}${fraction}`)
|
|
28
|
+
|
|
29
|
+
return new Price({
|
|
30
|
+
base,
|
|
31
|
+
quote,
|
|
32
|
+
numerator: valueWithoutDecimals * 10n ** BigInt(quote.decimals),
|
|
33
|
+
denominator: decimalScale * 10n ** BigInt(base.decimals),
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Tries to create a Price from a human-readable quote-per-base value.
|
|
39
|
+
*/
|
|
40
|
+
public static tryFromHuman<TBase extends Currency, TQuote extends Currency>(
|
|
41
|
+
base: TBase,
|
|
42
|
+
quote: TQuote,
|
|
43
|
+
value: string,
|
|
44
|
+
): Price<TBase, TQuote> | undefined {
|
|
45
|
+
try {
|
|
46
|
+
return Price.fromHuman(base, quote, value)
|
|
47
|
+
} catch {
|
|
48
|
+
return undefined
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
14
52
|
constructor(
|
|
15
53
|
args:
|
|
16
54
|
| {
|
|
@@ -65,8 +103,8 @@ export class Price<
|
|
|
65
103
|
return super.mul(this.scalar).toNumber()
|
|
66
104
|
}
|
|
67
105
|
|
|
68
|
-
public override toString(args: Parameters<
|
|
69
|
-
return
|
|
106
|
+
public override toString(args: Parameters<Fraction['toString']>[0]): string {
|
|
107
|
+
return super.mul(this.scalar).toString(args)
|
|
70
108
|
}
|
|
71
109
|
|
|
72
110
|
public override toSignificant(significantDigits = 5): string {
|
|
@@ -188,6 +188,103 @@ describe('Fraction', () => {
|
|
|
188
188
|
})
|
|
189
189
|
})
|
|
190
190
|
|
|
191
|
+
describe('string formatting', () => {
|
|
192
|
+
it('formats terminating fractions without floating-point artifacts', () => {
|
|
193
|
+
const fraction = new Fraction({ numerator: 4n, denominator: 5n })
|
|
194
|
+
|
|
195
|
+
expect(fraction.toString({ maxFixed: 18 })).toBe('0.8')
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('truncates repeating fractions to maxFixed decimal places', () => {
|
|
199
|
+
const fraction = new Fraction({ numerator: 1n, denominator: 3n })
|
|
200
|
+
|
|
201
|
+
expect(fraction.toString({ maxFixed: 18 })).toBe('0.333333333333333333')
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('preserves very small fractions in ordinary decimal notation', () => {
|
|
205
|
+
const fraction = new Fraction({
|
|
206
|
+
numerator: 1n,
|
|
207
|
+
denominator: 10n ** 12n,
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
expect(fraction.toString({ maxFixed: 18 })).toBe('0.000000000001')
|
|
211
|
+
expect(fraction.toSignificant(6)).toBe('0.000000000001')
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
it('preserves integers beyond Number.MAX_SAFE_INTEGER', () => {
|
|
215
|
+
const fraction = new Fraction({
|
|
216
|
+
numerator: 9007199254740993n,
|
|
217
|
+
denominator: 1n,
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
expect(fraction.toString({ maxFixed: 18 })).toBe('9007199254740993')
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
it('rounds and pads fixed decimal places', () => {
|
|
224
|
+
expect(
|
|
225
|
+
new Fraction({ numerator: 1n, denominator: 8n }).toString({
|
|
226
|
+
fixed: 2,
|
|
227
|
+
}),
|
|
228
|
+
).toBe('0.13')
|
|
229
|
+
expect(
|
|
230
|
+
new Fraction({ numerator: 1n, denominator: 2n }).toString({
|
|
231
|
+
fixed: 3,
|
|
232
|
+
}),
|
|
233
|
+
).toBe('0.500')
|
|
234
|
+
expect(
|
|
235
|
+
new Fraction({ numerator: 199995n, denominator: 1000n }).toString({
|
|
236
|
+
fixed: 2,
|
|
237
|
+
}),
|
|
238
|
+
).toBe('200.00')
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('rounds to significant digits without scientific notation', () => {
|
|
242
|
+
expect(
|
|
243
|
+
new Fraction({ numerator: 1n, denominator: 3n }).toString({
|
|
244
|
+
significant: 6,
|
|
245
|
+
}),
|
|
246
|
+
).toBe('0.333333')
|
|
247
|
+
expect(
|
|
248
|
+
new Fraction({
|
|
249
|
+
numerator: 123456789123n,
|
|
250
|
+
denominator: 100n,
|
|
251
|
+
}).toString({ significant: 4 }),
|
|
252
|
+
).toBe('1235000000')
|
|
253
|
+
expect(
|
|
254
|
+
new Fraction({ numerator: 9999n, denominator: 10n }).toString({
|
|
255
|
+
significant: 3,
|
|
256
|
+
}),
|
|
257
|
+
).toBe('1000')
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('formats negative fractions', () => {
|
|
261
|
+
const fraction = new Fraction({ numerator: -1n, denominator: 8n })
|
|
262
|
+
|
|
263
|
+
expect(fraction.toString({ fixed: 2 })).toBe('-0.13')
|
|
264
|
+
expect(fraction.toString({ maxFixed: 2 })).toBe('-0.12')
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('formats zero-denominator fractions as non-finite numbers', () => {
|
|
268
|
+
const infinity = new Fraction({ numerator: 1n, denominator: 2n }).div(
|
|
269
|
+
new Fraction({ numerator: 0n }),
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
expect(infinity.toString({ fixed: 2 })).toBe('Infinity')
|
|
273
|
+
expect(infinity.toString({ maxFixed: 2 })).toBe('Infinity')
|
|
274
|
+
expect(infinity.toString({ significant: 2 })).toBe('Infinity')
|
|
275
|
+
expect(
|
|
276
|
+
new Fraction({ numerator: -1n, denominator: 0n }).toString({
|
|
277
|
+
maxFixed: 2,
|
|
278
|
+
}),
|
|
279
|
+
).toBe('-Infinity')
|
|
280
|
+
expect(
|
|
281
|
+
new Fraction({ numerator: 0n, denominator: 0n }).toString({
|
|
282
|
+
maxFixed: 2,
|
|
283
|
+
}),
|
|
284
|
+
).toBe('NaN')
|
|
285
|
+
})
|
|
286
|
+
})
|
|
287
|
+
|
|
191
288
|
describe('serialization', () => {
|
|
192
289
|
it('should serialize to JSON correctly', () => {
|
|
193
290
|
const fraction = new Fraction({ numerator: 3, denominator: 4 })
|
package/generic/math/fraction.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import invariant from 'tiny-invariant'
|
|
2
|
-
import { numberToFixed } from '../format/number.js'
|
|
2
|
+
import type { numberToFixed } from '../format/number.js'
|
|
3
3
|
import type { BigintIsh } from '../types/bigintish.js'
|
|
4
4
|
|
|
5
5
|
export class Fraction {
|
|
@@ -164,12 +164,115 @@ export class Fraction {
|
|
|
164
164
|
return Number(this.numerator) / Number(this.denominator)
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
private formatDecimal(
|
|
168
|
+
decimalPlaces: number,
|
|
169
|
+
{ round, trim }: { round: boolean; trim: boolean },
|
|
170
|
+
): string {
|
|
171
|
+
invariant(
|
|
172
|
+
Number.isSafeInteger(decimalPlaces),
|
|
173
|
+
'Decimal places must be a safe integer',
|
|
174
|
+
)
|
|
175
|
+
invariant(this.denominator !== 0n, 'Cannot format a fraction by zero')
|
|
176
|
+
|
|
177
|
+
const negative = this.numerator < 0n !== this.denominator < 0n
|
|
178
|
+
const numerator = this.numerator < 0n ? -this.numerator : this.numerator
|
|
179
|
+
const denominator =
|
|
180
|
+
this.denominator < 0n ? -this.denominator : this.denominator
|
|
181
|
+
|
|
182
|
+
const scale = 10n ** BigInt(Math.abs(decimalPlaces))
|
|
183
|
+
const scaledDenominator =
|
|
184
|
+
decimalPlaces >= 0 ? denominator : denominator * scale
|
|
185
|
+
const scaledNumerator = decimalPlaces >= 0 ? numerator * scale : numerator
|
|
186
|
+
|
|
187
|
+
let scaledValue = scaledNumerator / scaledDenominator
|
|
188
|
+
const remainder = scaledNumerator % scaledDenominator
|
|
189
|
+
if (round && remainder * 2n >= scaledDenominator) {
|
|
190
|
+
scaledValue += 1n
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let integerPart: string
|
|
194
|
+
let decimalPart = ''
|
|
195
|
+
if (decimalPlaces > 0) {
|
|
196
|
+
const value = scaledValue.toString().padStart(decimalPlaces + 1, '0')
|
|
197
|
+
integerPart = value.slice(0, -decimalPlaces)
|
|
198
|
+
decimalPart = value.slice(-decimalPlaces)
|
|
199
|
+
} else {
|
|
200
|
+
integerPart = (scaledValue * scale).toString()
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (trim) {
|
|
204
|
+
decimalPart = decimalPart.replace(/0+$/, '')
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return `${negative ? '-' : ''}${integerPart}${
|
|
208
|
+
decimalPart ? `.${decimalPart}` : ''
|
|
209
|
+
}`
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private getDecimalExponent(): number {
|
|
213
|
+
const numerator = this.numerator < 0n ? -this.numerator : this.numerator
|
|
214
|
+
const denominator =
|
|
215
|
+
this.denominator < 0n ? -this.denominator : this.denominator
|
|
216
|
+
|
|
217
|
+
invariant(numerator !== 0n, 'Cannot get the decimal exponent of zero')
|
|
218
|
+
invariant(denominator !== 0n, 'Cannot format a fraction by zero')
|
|
219
|
+
|
|
220
|
+
let exponent = numerator.toString().length - denominator.toString().length
|
|
221
|
+
|
|
222
|
+
if (
|
|
223
|
+
(exponent >= 0 && numerator < denominator * 10n ** BigInt(exponent)) ||
|
|
224
|
+
(exponent < 0 && numerator * 10n ** BigInt(-exponent) < denominator)
|
|
225
|
+
) {
|
|
226
|
+
exponent -= 1
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return exponent
|
|
230
|
+
}
|
|
231
|
+
|
|
167
232
|
public toString(args: Parameters<typeof numberToFixed>[1]): string {
|
|
168
|
-
|
|
233
|
+
if ('fixed' in args) {
|
|
234
|
+
invariant(
|
|
235
|
+
Number.isSafeInteger(args.fixed) && args.fixed >= 0,
|
|
236
|
+
'Fixed digits must be a non-negative safe integer',
|
|
237
|
+
)
|
|
238
|
+
} else if ('maxFixed' in args) {
|
|
239
|
+
invariant(
|
|
240
|
+
Number.isSafeInteger(args.maxFixed) && args.maxFixed >= 0,
|
|
241
|
+
'Maximum fixed digits must be a non-negative safe integer',
|
|
242
|
+
)
|
|
243
|
+
} else if ('significant' in args) {
|
|
244
|
+
invariant(
|
|
245
|
+
Number.isSafeInteger(args.significant) && args.significant > 0,
|
|
246
|
+
'Significant digits must be a positive safe integer',
|
|
247
|
+
)
|
|
248
|
+
} else {
|
|
249
|
+
throw new Error('Invalid arguments for Fraction.toString')
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (this.denominator === 0n) {
|
|
253
|
+
return this.toNumber().toString()
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if ('fixed' in args) {
|
|
257
|
+
return this.formatDecimal(args.fixed, { round: true, trim: false })
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if ('maxFixed' in args) {
|
|
261
|
+
return this.formatDecimal(args.maxFixed, { round: false, trim: true })
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if ('significant' in args) {
|
|
265
|
+
if (this.numerator === 0n) return '0'
|
|
266
|
+
|
|
267
|
+
const decimalPlaces = args.significant - this.getDecimalExponent() - 1
|
|
268
|
+
return this.formatDecimal(decimalPlaces, { round: true, trim: true })
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
throw new Error('Invalid arguments for Fraction.toString')
|
|
169
272
|
}
|
|
170
273
|
|
|
171
274
|
public toSignificant(significantDigits: number): string {
|
|
172
|
-
return this.
|
|
275
|
+
return this.toString({ significant: significantDigits })
|
|
173
276
|
}
|
|
174
277
|
|
|
175
278
|
public toJSON() {
|