diff --git a/package.json b/package.json index 58a63ba..89eaa01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lay2/pw-core", - "version": "0.3.20-beta.2", + "version": "0.3.20-beta.3", "description": "the javascript sdk of pw-sdk", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -109,4 +109,4 @@ "**/*.spec.js" ] } -} +} \ No newline at end of file diff --git a/src/models/amount.spec.ts b/src/models/amount.spec.ts index 25420e7..c766bf4 100644 --- a/src/models/amount.spec.ts +++ b/src/models/amount.spec.ts @@ -3,6 +3,7 @@ import PWCore, { ChainID } from '../core'; import { DummyCollector } from '../collectors/dummy-collector'; import { Amount, AmountUnit } from '.'; import { DummyProvider } from '../providers/dummy-provider'; +import JSBI from 'jsbi'; test.before(async () => { await new PWCore('https://aggron.ckb.dev').init( @@ -127,4 +128,17 @@ test('to hex string', (t) => { t.is(shannonFull.toHexString(), '0xe94c0e8734'); }); -test.todo('random decimal test'); +// tests for random decimals + +const d0 = new Amount('10', 0); +const d1 = new Amount('1', 1); +const d2 = new Amount('0.1', 2); +const p = new Amount('0.00361', AmountUnit.ckb); + +test.only('to BigInt', (t) => { + t.is(d0.toBigInt().toString(), JSBI.BigInt(10).toString()); + t.is(d1.toBigInt().toString(), JSBI.BigInt(10).toString()); + t.is(d2.toBigInt().toString(), JSBI.BigInt(10).toString()); + t.is(p.toString(), '0.00361'); + t.is(p.toString(AmountUnit.shannon), '361000'); +}); diff --git a/src/models/amount.ts b/src/models/amount.ts index a00a57b..8496b7b 100644 --- a/src/models/amount.ts +++ b/src/models/amount.ts @@ -2,10 +2,9 @@ import JSBI from 'jsbi'; import { toBigUInt128LE, readBigUInt128LE, - rationalNumberToBnString, bnStringToRationalNumber, + rationalNumberToBnString, } from '../utils'; -import { HexStringToBigInt } from 'ckb-js-toolkit'; export enum AmountUnit { shannon, @@ -36,7 +35,7 @@ export class Amount { mul(val: Amount): Amount { const res = JSBI.divide( JSBI.multiply(this.toBigInt(), val.toBigInt()), - JSBI.BigInt(10 ** (val.decimal + this.decimal)) + JSBI.BigInt(10 ** (val.decimals + this.decimals)) ).toString(); return new Amount(res, AmountUnit.shannon); } @@ -62,52 +61,33 @@ export class Amount { } private amount: string; - private decimal: number; - - constructor(amount: string, unit?: AmountUnit); - constructor(amount: string, decimal: number = 8) { - if (Number.isNaN(amount)) { - throw new Error(`Amount ${amount} is not a valid number`); - } - amount = `${amount}`; + private decimals: number; - if (!Number.isInteger(decimal) || decimal < 0) { - throw new Error(`Decimal ${decimal} must be a natural number`); + constructor(amount: string, decimals: number | AmountUnit = AmountUnit.ckb) { + if (!Number.isInteger(decimals) || decimals < 0) { + throw new Error(`decimals ${decimals} must be a natural number`); } - this.decimal = decimal; + this.decimals = decimals; - if (amount.startsWith('0x')) { - amount = HexStringToBigInt(amount).toString(); - } - - if (decimal === AmountUnit.shannon) { - try { - amount = amount.match(/^0*(\d*)$/)[1]; - if (amount === '') { - amount = '0'; - } - } catch (e) { - throw new Error(`Amount ${amount} is invalid`); - } + if (Number.isNaN(amount)) { + throw new Error(`amount ${amount} must be a valid number`); } - this.amount = amount; - this.decimal = decimal; + this.amount = rationalNumberToBnString(amount, decimals); } + toString( - decimal = AmountUnit.ckb as number, + decimals: number | AmountUnit = AmountUnit.ckb, options?: FormatOptions ): string { return bnStringToRationalNumber( this.toBigInt().toString(), - decimal, + decimals, options ); } - toBigInt(decimal?: number) { - return JSBI.BigInt( - rationalNumberToBnString(this.amount, decimal || this.decimal) - ); + toBigInt() { + return JSBI.BigInt(this.amount); } toHexString() { diff --git a/src/models/sudt.ts b/src/models/sudt.ts index 53dd13b..243ed54 100644 --- a/src/models/sudt.ts +++ b/src/models/sudt.ts @@ -3,7 +3,7 @@ import PWCore from '../core'; export interface SudtInfo { symbol: string; - decimal: number; + decimals: number; name: string; } export class SUDT { diff --git a/src/utils.ts b/src/utils.ts index 29b8597..076bc95 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -16,11 +16,11 @@ export const ckbToShannon = (ckbAmount: string): string => export const bnStringToRationalNumber = ( bn: string, - decimal: number, + decimals: number, options: FormatOptions ) => { - if (!Number.isInteger(decimal) || decimal < 0) { - throw new Error("value of 'decimal' must be a positive integer"); + if (!Number.isInteger(decimals) || decimals < 0) { + throw new Error("value of 'decimals' must be a natural integer"); } const n = new Decimal(bn); @@ -30,8 +30,8 @@ export const bnStringToRationalNumber = ( let int = bn; let dec = ''; - if (decimal > 0) { - const intLen = bn.length - decimal; + if (decimals > 0) { + const intLen = bn.length - decimals; int = intLen > 0 ? bn.substr(0, intLen) : '0'; dec = intLen > 0 ? bn.slice(intLen) : `${'0'.repeat(-intLen)}${bn}`; dec = new Decimal(`0.${dec}`).toFixed().slice(2); @@ -41,11 +41,12 @@ export const bnStringToRationalNumber = ( if (options.fixed) { if ( !Number.isInteger(options.fixed) || - options.fixed < 1 || - options.fixed > decimal + options.fixed < 1 + // || options.fixed > decimals ) { throw new Error( - `value of \'fixed\' must be a positive integer and not bigger than decimal value ${decimal}` + // `value of \'fixed\' must be a positive integer and not bigger than decimals value ${decimals}` + `value of \'fixed\' must be a positive integer` ); } const res = new Decimal(`0.${dec}`).toFixed(options.fixed).split('.'); @@ -53,8 +54,8 @@ export const bnStringToRationalNumber = ( if (res[0] === '1') { int = JSBI.add(JSBI.BigInt(int), JSBI.BigInt(1)).toString(); } - } else if (options.pad && dec.length < decimal) { - dec = `${dec}${'0'.repeat(decimal - dec.length)}`; + } else if (options.pad && dec.length < decimals) { + dec = `${dec}${'0'.repeat(decimals - dec.length)}`; } if (options.commify) { int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ','); @@ -75,20 +76,24 @@ export const bnStringToRationalNumber = ( return int; }; -export const rationalNumberToBnString = (rational: string, decimal: number) => { - if (!Number.isInteger(decimal) || decimal < 0) { - throw new Error("value of 'decimal' must be a positive integer"); +export const rationalNumberToBnString = ( + rational: string, + decimals: number +) => { + if (!Number.isInteger(decimals) || decimals < 0) { + throw new Error("value of 'decimals' must be a natural integer"); } - if (decimal === 0) return rational; + if (decimals === 0) return rational; + if (rational === '0x') rational = '0'; const r = new Decimal(rational); - if (r.dp() > decimal) { + if (r.dp() > decimals) { throw new Error( - `Decimal ${decimal} is smaller than the digits number of ${rational}` + `decimals ${decimals} is smaller than the digits number of ${rational}` ); } - return `${rational.split('.').join('')}${'0'.repeat(decimal - r.dp())}`; + return `${rational.split('.').join('')}${'0'.repeat(decimals - r.dp())}`; }; // from @lumos/helper