From 2e3aa602e0af34c02f4d2466f9183a59368884ca Mon Sep 17 00:00:00 2001 From: Slava Fomin II Date: Thu, 2 Jun 2022 17:15:20 +0300 Subject: [PATCH 1/4] Added failed test for small numbers Signed-off-by: Slava Fomin II --- .gitignore | 1 + src/tests/test.index.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 3260b1f..c9ffb7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Don't check auto-generated stuff into git +.idea node_modules coverage lib diff --git a/src/tests/test.index.js b/src/tests/test.index.js index 0397aa1..c613b51 100644 --- a/src/tests/test.index.js +++ b/src/tests/test.index.js @@ -75,6 +75,10 @@ describe('toWei', () => { assert.throws(() => { units.toWei(1, 'wei1'); }, Error); }); + + it('should return the correct value for small numbers', () => { + assert.equal(units.toWei(1e-7, 'gwei').toString(10), '100'); + }); }); describe('numberToString', () => { From 9fe113aed986af25f337e6a178ce0a071c529212 Mon Sep 17 00:00:00 2001 From: Slava Fomin II Date: Thu, 2 Jun 2022 17:50:38 +0300 Subject: [PATCH 2/4] Fixed small numbers parsing Signed-off-by: Slava Fomin II --- src/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 55b62fe..aaeadb3 100644 --- a/src/index.js +++ b/src/index.js @@ -69,7 +69,8 @@ function numberToString(arg) { } return arg; } else if (typeof arg === 'number') { - return String(arg); + const fixedString = arg.toFixed(20); // 20 is the max safe value according to the standard + return fixedString.replace(/(\.0+|0+)$/g, ''); // trimming of extra zeroes from the end } else if (typeof arg === 'object' && arg.toString && (arg.toTwos || arg.dividedToIntegerBy)) { if (arg.toPrecision) { return String(arg.toPrecision()); From 419a7f4c56763d9bfbe83e2788d4e0b3a2bd8b52 Mon Sep 17 00:00:00 2001 From: Slava Fomin II Date: Thu, 2 Jun 2022 18:01:11 +0300 Subject: [PATCH 3/4] Simplified regex for number trimming Signed-off-by: Slava Fomin II --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index aaeadb3..11d2905 100644 --- a/src/index.js +++ b/src/index.js @@ -70,7 +70,7 @@ function numberToString(arg) { return arg; } else if (typeof arg === 'number') { const fixedString = arg.toFixed(20); // 20 is the max safe value according to the standard - return fixedString.replace(/(\.0+|0+)$/g, ''); // trimming of extra zeroes from the end + return fixedString.replace(/(\.?0+)$/g, ''); // trimming of extra zeroes from the end } else if (typeof arg === 'object' && arg.toString && (arg.toTwos || arg.dividedToIntegerBy)) { if (arg.toPrecision) { return String(arg.toPrecision()); From 6aa169291a5199220489f0289041bb2b40890998 Mon Sep 17 00:00:00 2001 From: Slava Fomin II Date: Thu, 2 Jun 2022 19:27:04 +0300 Subject: [PATCH 4/4] Updated number parsing to use Intl for more reliable results Signed-off-by: Slava Fomin II --- src/index.js | 11 +++++++++-- src/tests/test.index.js | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 11d2905..c4f3d90 100644 --- a/src/index.js +++ b/src/index.js @@ -69,8 +69,15 @@ function numberToString(arg) { } return arg; } else if (typeof arg === 'number') { - const fixedString = arg.toFixed(20); // 20 is the max safe value according to the standard - return fixedString.replace(/(\.?0+)$/g, ''); // trimming of extra zeroes from the end + if (arg === -0) { + return '0'; + } + // Using Intl to reliably convert number to string, + // toString/toFixed will give incorrect results for some numbers + return arg.toLocaleString('en', { + maximumFractionDigits: 20, + useGrouping: false, + }); } else if (typeof arg === 'object' && arg.toString && (arg.toTwos || arg.dividedToIntegerBy)) { if (arg.toPrecision) { return String(arg.toPrecision()); diff --git a/src/tests/test.index.js b/src/tests/test.index.js index c613b51..89ca66e 100644 --- a/src/tests/test.index.js +++ b/src/tests/test.index.js @@ -74,6 +74,8 @@ describe('toWei', () => { assert.equal(units.toWei(1, 'milli').toString(10), units.toWei(1000, 'micro').toString(10)); assert.throws(() => { units.toWei(1, 'wei1'); }, Error); + + assert.equal(units.toWei(0.1, 'gwei').toString(10), '100000000'); }); it('should return the correct value for small numbers', () => {