@okxweb3/coin-base
Version:
A base package for @ok/coin-*
138 lines • 5.28 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Decimal = void 0;
const bn_js_1 = __importDefault(require("bn.js"));
const maxFractionalDigits = 100;
class Decimal {
static fromUserInput(input, fractionalDigits) {
Decimal.verifyFractionalDigits(fractionalDigits);
const badCharacter = input.match(/[^0-9.]/);
if (badCharacter) {
throw new Error(`Invalid character at position ${badCharacter.index + 1}`);
}
let whole;
let fractional;
if (input.search(/\./) === -1) {
whole = input;
fractional = '';
}
else {
const parts = input.split('.');
switch (parts.length) {
case 0:
case 1:
throw new Error('Fewer than two elements in split result. This must not happen here.');
case 2:
if (!parts[1])
throw new Error('Fractional part missing');
whole = parts[0];
fractional = parts[1].replace(/0+$/, '');
break;
default:
throw new Error('More than one separator found');
}
}
if (fractional.length > fractionalDigits) {
throw new Error('Got more fractional digits than supported');
}
const quantity = `${whole}${fractional.padEnd(fractionalDigits, '0')}`;
return new Decimal(quantity, fractionalDigits);
}
static fromAtomics(atomics, fractionalDigits) {
Decimal.verifyFractionalDigits(fractionalDigits);
return new Decimal(atomics, fractionalDigits);
}
static zero(fractionalDigits) {
Decimal.verifyFractionalDigits(fractionalDigits);
return new Decimal('0', fractionalDigits);
}
static one(fractionalDigits) {
Decimal.verifyFractionalDigits(fractionalDigits);
return new Decimal('1' + '0'.repeat(fractionalDigits), fractionalDigits);
}
static verifyFractionalDigits(fractionalDigits) {
if (!Number.isInteger(fractionalDigits))
throw new Error('Fractional digits is not an integer');
if (fractionalDigits < 0)
throw new Error('Fractional digits must not be negative');
if (fractionalDigits > maxFractionalDigits) {
throw new Error(`Fractional digits must not exceed ${maxFractionalDigits}`);
}
}
static compare(a, b) {
if (a.fractionalDigits !== b.fractionalDigits)
throw new Error('Fractional digits do not match');
return a.data.atomics.cmp(new bn_js_1.default(b.atomics));
}
get atomics() {
return this.data.atomics.toString();
}
get fractionalDigits() {
return this.data.fractionalDigits;
}
constructor(atomics, fractionalDigits) {
this.data = {
atomics: new bn_js_1.default(atomics),
fractionalDigits: fractionalDigits,
};
}
toString() {
const factor = new bn_js_1.default(10).pow(new bn_js_1.default(this.data.fractionalDigits));
const whole = this.data.atomics.div(factor);
const fractional = this.data.atomics.mod(factor);
if (fractional.isZero()) {
return whole.toString();
}
else {
const fullFractionalPart = fractional
.toString()
.padStart(this.data.fractionalDigits, '0');
const trimmedFractionalPart = fullFractionalPart.replace(/0+$/, '');
return `${whole.toString()}.${trimmedFractionalPart}`;
}
}
toFloatApproximation() {
const out = Number(this.toString());
if (Number.isNaN(out))
throw new Error('Conversion to number failed');
return out;
}
plus(b) {
if (this.fractionalDigits !== b.fractionalDigits)
throw new Error('Fractional digits do not match');
const sum = this.data.atomics.add(new bn_js_1.default(b.atomics));
return new Decimal(sum.toString(), this.fractionalDigits);
}
minus(b) {
if (this.fractionalDigits !== b.fractionalDigits)
throw new Error('Fractional digits do not match');
const difference = this.data.atomics.sub(new bn_js_1.default(b.atomics));
if (difference.ltn(0))
throw new Error('Difference must not be negative');
return new Decimal(difference.toString(), this.fractionalDigits);
}
multiply(b) {
const product = this.data.atomics.mul(new bn_js_1.default(b.toString()));
return new Decimal(product.toString(), this.fractionalDigits);
}
equals(b) {
return Decimal.compare(this, b) === 0;
}
isLessThan(b) {
return Decimal.compare(this, b) < 0;
}
isLessThanOrEqual(b) {
return Decimal.compare(this, b) <= 0;
}
isGreaterThan(b) {
return Decimal.compare(this, b) > 0;
}
isGreaterThanOrEqual(b) {
return Decimal.compare(this, b) >= 0;
}
}
exports.Decimal = Decimal;
//# sourceMappingURL=decimal.js.map