From 05f37989129fc48b8532afc168ab231de42dab2d Mon Sep 17 00:00:00 2001 From: Semen Loktionov Date: Mon, 30 Oct 2023 12:10:22 +0200 Subject: [PATCH 1/2] fix BN.parseFrom raw value with exponential notation --- CHANGELOG.md | 7 ++- packages/fetcher/package.json | 2 +- packages/jac/package.json | 2 +- packages/reactivity/package.json | 2 +- packages/tools/package.json | 2 +- packages/tools/src/bn/bn.test.ts | 83 ++++++++++++++++++++++++++++++++ packages/tools/src/bn/parsers.ts | 21 +++++++- packages/tools/src/const/bn.ts | 2 +- packages/w3p/package.json | 2 +- 9 files changed, 114 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b70f6de..9eb87b36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [1.0.0-rc.8] - 2023-10-30 +### Fixed +- `@distributedlab/tools` - `BN.fromRaw` parsing string value with the exponential notation + ## [1.0.0-rc.7] - 2023-09-25 ### Added - `@distributedlab/w3p` - WalletConnect EVM provider @@ -336,7 +340,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [old repo]: https://github.com/distributed-lab/web-kit-old -[Unreleased]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.7...HEAD +[Unreleased]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.8...HEAD +[1.0.0-rc.8]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.7...1.0.0-rc.8 [1.0.0-rc.7]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.6...1.0.0-rc.7 [1.0.0-rc.6]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.5...1.0.0-rc.6 [1.0.0-rc.5]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.4...1.0.0-rc.5 diff --git a/packages/fetcher/package.json b/packages/fetcher/package.json index b98101b1..896b630b 100644 --- a/packages/fetcher/package.json +++ b/packages/fetcher/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/fetcher", - "version": "1.0.0-rc.7", + "version": "1.0.0-rc.8", "description": "Fetch API wrapper with the extended functionality and simple interface", "repository": { "type": "git", diff --git a/packages/jac/package.json b/packages/jac/package.json index f5b5b306..ef70bded 100644 --- a/packages/jac/package.json +++ b/packages/jac/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/jac", - "version": "1.0.0-rc.7", + "version": "1.0.0-rc.8", "description": "A library for constructing JSON-API compliant requests and responses", "repository": { "type": "git", diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index e7b76c06..f3d8b0b5 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/reactivity", - "version": "1.0.0-rc.7", + "version": "1.0.0-rc.8", "description": "Implementation of the reactivity connections to propagate changes between objects", "repository": { "type": "git", diff --git a/packages/tools/package.json b/packages/tools/package.json index 0994c0e6..227d646b 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/tools", - "version": "1.0.0-rc.7", + "version": "1.0.0-rc.8", "description": "Collection of common utility functions and classes", "repository": { "type": "git", diff --git a/packages/tools/src/bn/bn.test.ts b/packages/tools/src/bn/bn.test.ts index f5442be0..dfdbdaad 100644 --- a/packages/tools/src/bn/bn.test.ts +++ b/packages/tools/src/bn/bn.test.ts @@ -234,6 +234,89 @@ describe('performs BN unit test', () => { expect(bn.raw).toBe(100000000000000000000000000n) }) }) + + describe('if value with exponential notation', () => { + describe('without fraction part', () => { + test('with positive exponent', () => { + const bn = BN.fromRaw('1e+2', 6) + expect(bn.value).toBe('100000000') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(10000000000000000000000000000n) + }) + + test('with negative exponent which equals value length', () => { + const bn = BN.fromRaw('33e-2', 6) + expect(bn.value).toBe('330000') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(33000000000000000000000000n) + }) + + test('with negative exponent which more than value length', () => { + const bn = BN.fromRaw('22e-10', 18) + expect(bn.value).toBe('2200000000') + expect(bn.decimals).toBe(18) + expect(bn.raw).toBe(220000000000000000n) + }) + + test('with negative exponent which more than value length [2]', () => { + const bn = BN.fromRaw('22e-10', 6) + expect(bn.value).toBe('0') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(220000000000000000n) + }) + + test('with negative exponent which more than BN precision', () => { + const bn = BN.fromRaw(`22e-${BN.precision + 4}`, 6) + expect(bn.value).toBe('0') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(0n) + }) + }) + + describe('with fraction part', () => { + test('with positive exponent', () => { + const bn = BN.fromRaw('3.5e+4', 6) + expect(bn.value).toBe('35000000000') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(3500000000000000000000000000000n) + }) + + test('with positive exponent and whole is zero', () => { + const bn = BN.fromRaw('0.1e+5', 6) + expect(bn.value).toBe('10000000000') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(1000000000000000000000000000000n) + }) + + test('with negative exponent which equals value length', () => { + const bn = BN.fromRaw('0.33e-3', 6) + expect(bn.value).toBe('330') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(33000000000000000000000n) + }) + + test('with negative exponent which more than value length', () => { + const bn = BN.fromRaw('1.34e-10', 18) + expect(bn.value).toBe('134000000') + expect(bn.decimals).toBe(18) + expect(bn.raw).toBe(13400000000000000n) + }) + + test('with negative exponent which equals BN precision', () => { + const bn = BN.fromRaw(`1.3e-${BN.precision}`, 6) + expect(bn.value).toBe('0') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(1n) + }) + + test('with negative exponent which more than BN precision', () => { + const bn = BN.fromRaw(`2.2e-${BN.precision + 4}`, 6) + expect(bn.value).toBe('0') + expect(bn.decimals).toBe(6) + expect(bn.raw).toBe(0n) + }) + }) + }) }) }) diff --git a/packages/tools/src/bn/parsers.ts b/packages/tools/src/bn/parsers.ts index e53df0e7..1fa1f9ce 100644 --- a/packages/tools/src/bn/parsers.ts +++ b/packages/tools/src/bn/parsers.ts @@ -21,10 +21,27 @@ export const parseNumberString = (_value: string): string => { const isFractionalZero = !fractional || fractional.match(/^(0+)$/) const isWholeZero = whole === '0' || whole.replaceAll('0', '') === '' + const exponential = match[4] + const exponentialSign = exponential?.slice(1, 2) + const exponentialDecimals = Number(exponential?.slice(2)) + if (isWholeZero && isFractionalZero) return '0' - if (!fractional) return whole.padEnd(whole.length + BN.precision, '0') - return (isWholeZero ? '' : whole) + fractional.padEnd(BN.precision, '0') + let result = whole.padEnd(whole.length + BN.precision, '0') + + if (!fractional) return fromExp(result, exponentialSign, exponentialDecimals) + + result = (isWholeZero ? '' : whole) + fractional.padEnd(BN.precision, '0') + + return fromExp(result, exponentialSign, exponentialDecimals) +} + +const fromExp = (value: string, sign?: string, decimals?: number) => { + if (!sign || !decimals) return value + if (sign === '+') return value.padEnd(value.length + decimals, '0') + if (decimals > value.length) return '0' + + return value.slice(0, value.length - decimals) } export const parseConfig = (config: BnConfigLike): BnConfig => { diff --git a/packages/tools/src/const/bn.ts b/packages/tools/src/const/bn.ts index 23b74a15..1e69f7a6 100644 --- a/packages/tools/src/const/bn.ts +++ b/packages/tools/src/const/bn.ts @@ -1,3 +1,3 @@ export const DEFAULT_BN_PRECISION = 26 -export const NUMBER_REGEX = /^(-?)(\d+)(\.\d+)?$/ +export const NUMBER_REGEX = /^(-?)(\d+)(\.\d+)?([eE][-+]?\d+)?$/ export const HEX_REGEX = /^0x[0-9a-f]+$/i diff --git a/packages/w3p/package.json b/packages/w3p/package.json index b04720a6..f05bfa47 100644 --- a/packages/w3p/package.json +++ b/packages/w3p/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/w3p", - "version": "1.0.0-rc.7", + "version": "1.0.0-rc.8", "description": "Wrapper for Web3 Providers", "repository": { "type": "git", From 7cfefad74ee5cddffe542a18c9bb0bfe65d38068 Mon Sep 17 00:00:00 2001 From: Semen Loktionov Date: Tue, 7 Nov 2023 11:49:57 +0200 Subject: [PATCH 2/2] upd changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb87b36..9ef1c743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -## [1.0.0-rc.8] - 2023-10-30 +## [1.0.0-rc.8] - 2023-11-07 ### Fixed - `@distributedlab/tools` - `BN.fromRaw` parsing string value with the exponential notation