export type BCHUnits = ['sats', 'bits', 'mBCH', 'BCH']; /** * Satoshis Primitive * * @example * * ```ts * // Import our primitives * import { Satoshis } from '@xocash/primitives'; * * // Create an amount from BCH. * const sats = Satoshis.fromBCH(0.54321); * * // Output as a satoshi number. * console.log(satoshis.toSats()); * * // Output as a satoshis bigint. * console.log(satoshis.toBigInt()); * ``` */ export class Satoshis { protected readonly satoshis: bigint; /** * Construct a new instance of Satoshis. * * This is the same as using fromSatoshis(). * * @param satoshis {number} The satoshi amount. */ protected constructor(satoshis: bigint | number) { // Set the satoshi amount. this.satoshis = BigInt(satoshis); } /** * Instantiates from a Satoshi Amount. * * @param satoshis {number} The Satoshi amount. * * @returns {Satoshis} New instance of Satoshis. */ public static fromSats(satoshis: bigint | number): Satoshis { return new this(satoshis); } /** * Instantiates from a Satoshi Amount. * * @param satoshis {number} The Satoshi amount. * * @deprecated Use fromSats() instead. * * @returns {Satoshis} New instance of Satoshis. */ public static fromSatoshis(satoshis: bigint | number): Satoshis { return new this(satoshis); } /** * Instantiates from a Bits Amount (100 satoshis = 1 bit). * * @param bits {number} The Bits amount. * * @returns {Satoshis} New instance of Satoshis. */ public static fromBits(bits: number): Satoshis { const satoshis = Satoshis.roundToDigits(bits * 100, 0); return new this(satoshis); } /** * Instantiates from a mBCH Amount (100,000 satoshis = 1 mBCH). * * @param mBCH {number} The mBCH amount. * * @returns {Satoshis} New instance of Satoshis. */ public static fromMBCH(mBCH: number): Satoshis { const satoshis = Satoshis.roundToDigits(mBCH * 100_000, 0); return new this(satoshis); } /** * Instantiates from a BCH Amount (100,000,000 satoshis = 1 BCH). * * @param bch {number} The BCH amount. * * @returns {Satoshis} New instance of Satoshis. */ public static fromBCH(bch: number): Satoshis { const satoshis = Satoshis.roundToDigits(bch * 100_000_000, 0); return new this(satoshis); } /** * Creates an instance from serialized data. * * @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted. * * @param bytes - Serialized Primitive Data * * @returns A new instance of this primitive. */ public static fromRaw(sats: bigint) { return new this(sats); } /** * Rounds a number to the given number of digits. * * @param numberToRound {number} The number to round. * @param digits {number} The number of digits to round to. * * @returns {Number} The rounded number. */ protected static roundToDigits( numberToRound: number, digits: number, ): number { // Set the options of the Number Format object. const options: Intl.NumberFormatOptions = { style: 'decimal', minimumFractionDigits: digits, maximumFractionDigits: digits, useGrouping: false, numberingSystem: 'latn', }; // Create an instance of number format using above options. // NOTE: We force the locale to en-GB so that the number is formatted correctly (e.g. with a decimal, not a comma). const numberFormat = new Intl.NumberFormat('en-GB', options); // Format the number. const formattedAmount = numberFormat.format(numberToRound); // Return the formatted number. return Number(formattedAmount); } /** * Converts the amount to Satoshis (as a BigInt). * * @returns {bigint} The satoshi amount. */ public toBigInt(): bigint { return this.satoshis; } /** * Converts the amount to Satoshis. * * @returns {number} The satoshi amount. */ public toSats(): number { return Number(this.satoshis); } /** * Converts the amount to Satoshis. * * @deprecated Use toSats() instead. * * @returns {number} The satoshi amount. */ public toSatoshis(): number { return Number(this.satoshis); } /** * Converts the amount to Bits (100 satoshis = 1 bit). * * @returns {number} The bit amount. */ public toBits(): number { return Satoshis.roundToDigits(Number(this.satoshis) / 100, 2); } /** * Converts the amount to mBCH (100,000 satoshis = 1 mBCH). * * @returns {number} The mBCH amount. */ public toMBCH(): number { return Satoshis.roundToDigits(Number(this.satoshis) / 100_000, 5); } /** * Converts the amount to BCH (100,000,000 satoshis = 1 BCH). * * @returns {number} The BCH amount. */ public toBCH(): number { return Satoshis.roundToDigits(Number(this.satoshis) / 100_000_000, 8); } /** * Converts this primitive to a serializable raw object representation. * * @returns Serialzied primitive data. */ toRaw() { return this.satoshis; } }