UNPKG

@alcorexchange/alcor-swap-sdk

Version:

## Installation ​​ **npm** ``` npm i @alcorexchange/alcor-swap-sdk ``` **yarn** ``` yarn add @alcorexchange/alcor-swap-sdk ``` ## Usage ### Import:

191 lines (167 loc) 5.79 kB
import JSBI from "jsbi"; import invariant from "tiny-invariant"; import toFormat from "toformat"; import _Decimal from "decimal.js-light"; import _Big, { RoundingMode } from "big.js"; import { BigintIsh, Rounding } from "../../internalConstants"; const Decimal = toFormat(_Decimal); const Big = toFormat(_Big); const toSignificantRounding = { [Rounding.ROUND_DOWN]: Decimal.ROUND_DOWN, [Rounding.ROUND_HALF_UP]: Decimal.ROUND_HALF_UP, [Rounding.ROUND_UP]: Decimal.ROUND_UP, }; // const toFixedRounding = { // [Rounding.ROUND_DOWN]: RoundingMode.RoundDown, // [Rounding.ROUND_HALF_UP]: RoundingMode.RoundHalfUp, // [Rounding.ROUND_UP]: RoundingMode.RoundUp // } const toFixedRounding = { [Rounding.ROUND_DOWN]: 0, [Rounding.ROUND_HALF_UP]: 1, [Rounding.ROUND_UP]: 3, }; export class Fraction { public readonly numerator: JSBI; public readonly denominator: JSBI; public constructor( numerator: BigintIsh, denominator: BigintIsh = JSBI.BigInt(1) ) { this.numerator = JSBI.BigInt(numerator); this.denominator = JSBI.BigInt(denominator); } private static tryParseFraction(fractionish: BigintIsh | Fraction): Fraction { if ( fractionish instanceof JSBI || typeof fractionish === "number" || typeof fractionish === "string" ) return new Fraction(fractionish); if ("numerator" in fractionish && "denominator" in fractionish) return fractionish; throw new Error("Could not parse fraction"); } // performs floor division public get quotient(): JSBI { return JSBI.divide(this.numerator, this.denominator); } // remainder after floor division public get remainder(): Fraction { return new Fraction( JSBI.remainder(this.numerator, this.denominator), this.denominator ); } public invert(): Fraction { return new Fraction(this.denominator, this.numerator); } public add(other: Fraction | BigintIsh): Fraction { const otherParsed = Fraction.tryParseFraction(other); if (JSBI.equal(this.denominator, otherParsed.denominator)) { return new Fraction( JSBI.add(this.numerator, otherParsed.numerator), this.denominator ); } return new Fraction( JSBI.add( JSBI.multiply(this.numerator, otherParsed.denominator), JSBI.multiply(otherParsed.numerator, this.denominator) ), JSBI.multiply(this.denominator, otherParsed.denominator) ); } public subtract(other: Fraction | BigintIsh): Fraction { const otherParsed = Fraction.tryParseFraction(other); if (JSBI.equal(this.denominator, otherParsed.denominator)) { return new Fraction( JSBI.subtract(this.numerator, otherParsed.numerator), this.denominator ); } return new Fraction( JSBI.subtract( JSBI.multiply(this.numerator, otherParsed.denominator), JSBI.multiply(otherParsed.numerator, this.denominator) ), JSBI.multiply(this.denominator, otherParsed.denominator) ); } public lessThan(other: Fraction | BigintIsh): boolean { const otherParsed = Fraction.tryParseFraction(other); return JSBI.lessThan( JSBI.multiply(this.numerator, otherParsed.denominator), JSBI.multiply(otherParsed.numerator, this.denominator) ); } public equalTo(other: Fraction | BigintIsh): boolean { const otherParsed = Fraction.tryParseFraction(other); return JSBI.equal( JSBI.multiply(this.numerator, otherParsed.denominator), JSBI.multiply(otherParsed.numerator, this.denominator) ); } public greaterThan(other: Fraction | BigintIsh): boolean { const otherParsed = Fraction.tryParseFraction(other); return JSBI.greaterThan( JSBI.multiply(this.numerator, otherParsed.denominator), JSBI.multiply(otherParsed.numerator, this.denominator) ); } public multiply(other: Fraction | BigintIsh): Fraction { const otherParsed = Fraction.tryParseFraction(other); return new Fraction( JSBI.multiply(this.numerator, otherParsed.numerator), JSBI.multiply(this.denominator, otherParsed.denominator) ); } public divide(other: Fraction | BigintIsh): Fraction { const otherParsed = Fraction.tryParseFraction(other); return new Fraction( JSBI.multiply(this.numerator, otherParsed.denominator), JSBI.multiply(this.denominator, otherParsed.numerator) ); } public toSignificant( significantDigits: number, format: object = { groupSeparator: "" }, rounding: Rounding = Rounding.ROUND_HALF_UP ): string { invariant( Number.isInteger(significantDigits), `${significantDigits} is not an integer.` ); invariant(significantDigits > 0, `${significantDigits} is not positive.`); Decimal.set({ precision: significantDigits + 1, rounding: toSignificantRounding[rounding], }); const quotient = new Decimal(this.numerator.toString()) .div(this.denominator.toString()) .toSignificantDigits(significantDigits); return quotient.toFormat(quotient.decimalPlaces(), format); } public toFixed( decimalPlaces: number, format: object = { groupSeparator: "" }, rounding: Rounding = Rounding.ROUND_HALF_UP ): string { invariant( Number.isInteger(decimalPlaces), `${decimalPlaces} is not an integer.` ); invariant(decimalPlaces >= 0, `${decimalPlaces} is negative.`); Big.DP = decimalPlaces; Big.RM = toFixedRounding[rounding]; return new Big(this.numerator.toString()) .div(this.denominator.toString()) .toFormat(decimalPlaces, format); } /** * Helper method for converting any super class back to a fraction */ public get asFraction(): Fraction { return new Fraction(this.numerator, this.denominator); } }