@fruitsjs/util
Version:
Useful utilities and tools for building Fruits Eco-Blockchain applications
214 lines (187 loc) • 5.94 kB
text/typescript
import BigNumber from 'bignumber.js';
import {CurrencyPlanckSymbol, CurrencySymbol} from './constants';
BigNumber.config({
EXPONENTIAL_AT: [-9, 20]
});
/**
* Enum to determine the representation format of [FruitsValue] string
* @module util
*/
export enum AmountFormat {
PLANCK,
FRUITS,
}
function assureValidValue(v: string): void {
if (!(v && /^-?\d*(\.\d+)?$/.test(v))) {
throw new Error(`Invalid value: ${v}`);
}
}
/**
* A Value Object to facilitate FRUITS and Planck conversions/calculations.
*
* Note: This class uses a big number representation (ES5 compatible) under the hood, so
* number limits and numeric calculations are much more precise than JS number type
*
* @module util
*/
export class Amount {
private _planck: BigNumber;
private constructor(planck: number | string) {
if (typeof planck === 'string') {
assureValidValue(planck);
}
this._planck = new BigNumber(planck);
}
public static CurrencySymbol(): string {
return CurrencySymbol;
}
public static Zero(): Amount {
return new Amount('0');
}
/**
* Creates a FRUITS Value object from Planck
* @param planck The value in Planck
*/
public static fromPlanck(planck: number | string): Amount {
return new Amount(planck);
}
/**
* Creates a Value object from FRUITS
* @param frts The value in FRUITS
*/
public static fromFrts(frts: number | string): Amount {
const b = new Amount('0');
b.setFrts(typeof frts === 'number' ? frts.toString(10) : frts);
return b;
}
/**
* Leaky value getter
* @return the underlying value in its big number representation (immutable)
*/
getRaw(): BigNumber {
return this._planck;
}
/**
* @return Gets Planck representation
*/
getPlanck(): string {
return this._planck.toString();
}
/**
* Sets value as Planck, i.e. overwrites current hold value
* @param p The planck value
*/
setPlanck(p: string): void {
assureValidValue(p);
this._planck = new BigNumber(p);
}
/**
* Gets FRUITS representation
* @return value in FRUITS
*/
getFrts(): string {
return this._planck.dividedBy(1E8).toString();
}
/**
* Sets value as FRUITS, i.e. overwrites current hold value
* @param b value in FRUITS
*/
setFrts(b: string): void {
assureValidValue(b);
this._planck = new BigNumber(b).multipliedBy(1E8);
}
/**
* Checks for equality
* @param amount The other value to be compared
* @return true if equal, otherwise false
*/
public equals(amount: Amount): boolean {
return this._planck.eq(amount._planck);
}
/**
* Checks for lesser or equality
* @param amount The other value to be compared
* @return true if less or equal, otherwise false
*/
public lessOrEqual(amount: Amount): boolean {
return this._planck.lte(amount._planck);
}
/**
* Checks for lesser value
* @param amount The other value to be compared
* @return true if less, otherwise false
*/
public less(amount: Amount): boolean {
return this._planck.lt(amount._planck);
}
/**
* Checks for greater or equality value
* @param amount The other value to be compared
* @return true if greater or equal, otherwise false
*/
public greaterOrEqual(amount: Amount): boolean {
return this._planck.gte(amount._planck);
}
/**
* Checks for greater value
* @param amount The other value to be compared
* @return true if greater, otherwise false
*/
public greater(amount: Amount): boolean {
return this._planck.gt(amount._planck);
}
/**
* Adds two values
* @param amount The other value to be added
* @return the _mutated_ FruitsValue object
*/
public add(amount: Amount): Amount {
this._planck = this._planck.plus(amount._planck);
return this;
}
/**
* Subtracts from value
* @param amount The other value to be subtracted
* @return the _mutated_ FruitsValue object
*/
public subtract(amount: Amount): Amount {
this._planck = this._planck.minus(amount._planck);
return this;
}
/**
* Multiplies with a _numeric_ value (not FruitsValue)
* @param value A numeric value to be multiplied with
* @return the _mutated_ FruitsValue object
*/
public multiply(value: number): Amount {
this._planck = this._planck.multipliedBy(value);
return this;
}
/**
* Divides by a _numeric_ value (not FruitsValue)
* @param value A numeric value to be divided by
* @return the _mutated_ FruitsValue object
*/
public divide(value: number): Amount {
if (value === 0) {
throw new Error('Division by zero');
}
this._planck = this._planck.div(value);
return this;
}
/**
* Gets a string representation in form `F 100` for FRUITS or `10000000000 frts` for Planck
* @param format The format
* @return The converted string accordingly the param in FRUITS or Planck
*/
public toString(format: AmountFormat = AmountFormat.FRUITS): string {
return format === AmountFormat.FRUITS ? `${CurrencySymbol} ${this.getFrts()}` : `${CurrencyPlanckSymbol} ${this._planck}`;
}
/**
* Clones/Copies the current FruitsValue to a new object
* @return new FruitsValue instance
*/
public clone(): Amount {
return Amount.fromPlanck(this.getPlanck());
}
}