From bb8877894bbdb5fe42e6bf95c521c5e18603be28 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 4 Jun 2019 09:43:11 +0200 Subject: [PATCH] Cater for negative values in number formats (#415) * Cater for negative values in number formats * Handle edge-case where -text is provided --- CHANGELOG.md | 6 ++++ lerna.json | 2 +- packages/chainspec/package.json | 4 +-- packages/db/package.json | 6 ++-- packages/keyring/package.json | 6 ++-- packages/trie-codec/package.json | 4 +-- packages/trie-db/package.json | 16 ++++----- packages/trie-hash/package.json | 6 ++-- packages/util-crypto/package.json | 4 +-- packages/util-rlp/package.json | 4 +-- packages/util/package.json | 2 +- .../util/src/format/formatBalance.spec.ts | 14 ++++++++ packages/util/src/format/formatBalance.ts | 12 +++++-- .../util/src/format/formatDecimal.spec.ts | 8 +++++ packages/util/src/format/formatDecimal.ts | 9 +++-- packages/util/src/format/formatNumber.spec.ts | 35 +++++++++++++++++++ 16 files changed, 107 insertions(+), 31 deletions(-) create mode 100644 packages/util/src/format/formatNumber.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b355a79a0..d2101b37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.92.1 + +- Only allow integer input values into formatBalance +- Allow formatBalance, formatDecimal & formatNumber to cater for negative numbers +- Add 'Bob//stash' to testing keyring + # 0.91.1 - ed25519/sr25519 sign & verify functions can now take the message input as Uint8Array/string/hex and verify allows for the signature/publicKey to be specified as Uint8Array/hex diff --git a/lerna.json b/lerna.json index 83fbf0313..0af4a70e1 100644 --- a/lerna.json +++ b/lerna.json @@ -9,5 +9,5 @@ "packages": [ "packages/*" ], - "version": "0.92.0-beta.3" + "version": "0.92.0" } diff --git a/packages/chainspec/package.json b/packages/chainspec/package.json index b39b6e749..978bae3fd 100644 --- a/packages/chainspec/package.json +++ b/packages/chainspec/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/chainspec", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "Contains chain specifications for known chains", "main": "index.js", "keywords": [ @@ -26,6 +26,6 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/chainspec#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/util": "^0.92.0-beta.3" + "@polkadot/util": "^0.92.0" } } diff --git a/packages/db/package.json b/packages/db/package.json index 4aca894cc..08c1c0903 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/db", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "Implementation of a basic sync in-memory and on-disk databases with overlays", "main": "index.js", "keywords": [ @@ -26,8 +26,8 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/db#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/trie-hash": "^0.92.0-beta.3", - "@polkadot/util": "^0.92.0-beta.3", + "@polkadot/trie-hash": "^0.92.0", + "@polkadot/util": "^0.92.0", "lru_map": "^0.3.3" } } diff --git a/packages/keyring/package.json b/packages/keyring/package.json index f48310089..78dd662d9 100644 --- a/packages/keyring/package.json +++ b/packages/keyring/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/keyring", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "Keyring management", "main": "index.js", "publishConfig": { @@ -28,8 +28,8 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/keyring#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/util": "^0.92.0-beta.3", - "@polkadot/util-crypto": "^0.92.0-beta.3", + "@polkadot/util": "^0.92.0", + "@polkadot/util-crypto": "^0.92.0", "@types/bs58": "^4.0.0", "bs58": "^4.0.1" } diff --git a/packages/trie-codec/package.json b/packages/trie-codec/package.json index 28fc99d3b..06b8bc46e 100644 --- a/packages/trie-codec/package.json +++ b/packages/trie-codec/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/trie-codec", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "This is an implementation of the codec for Substrate Trie", "main": "index.js", "keywords": [ @@ -26,6 +26,6 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/trie-codec#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/util": "^0.92.0-beta.3" + "@polkadot/util": "^0.92.0" } } diff --git a/packages/trie-db/package.json b/packages/trie-db/package.json index 7c257f11f..c25c66f9e 100644 --- a/packages/trie-db/package.json +++ b/packages/trie-db/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/trie-db", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "This is an implementation of the modified merkle patricia tree as specified in Ethereum's yellow paper, adapted for Polkadot", "main": "index.js", "keywords": [ @@ -26,15 +26,15 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/trie-db#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/db": "^0.92.0-beta.3", - "@polkadot/trie-codec": "^0.92.0-beta.3", - "@polkadot/trie-hash": "^0.92.0-beta.3", - "@polkadot/util": "^0.92.0-beta.3", - "@polkadot/util-crypto": "^0.92.0-beta.3" + "@polkadot/db": "^0.92.0", + "@polkadot/trie-codec": "^0.92.0", + "@polkadot/trie-hash": "^0.92.0", + "@polkadot/util": "^0.92.0", + "@polkadot/util-crypto": "^0.92.0" }, "devDependencies": { - "@polkadot/chainspec": "^0.92.0-beta.3", - "@polkadot/util-rlp": "^0.92.0-beta.3", + "@polkadot/chainspec": "^0.92.0", + "@polkadot/util-rlp": "^0.92.0", "ethereumjs-testing": "1.0.4" } } diff --git a/packages/trie-hash/package.json b/packages/trie-hash/package.json index a423aa48d..747155608 100644 --- a/packages/trie-hash/package.json +++ b/packages/trie-hash/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/trie-hash", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "Generates trie roots from key-value pairs", "main": "index.js", "keywords": [ @@ -26,9 +26,9 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/trie-hash#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/util": "^0.92.0-beta.3" + "@polkadot/util": "^0.92.0" }, "devDependencies": { - "@polkadot/chainspec": "^0.92.0-beta.3" + "@polkadot/chainspec": "^0.92.0" } } diff --git a/packages/util-crypto/package.json b/packages/util-crypto/package.json index bf86fc429..4bd202bb1 100644 --- a/packages/util-crypto/package.json +++ b/packages/util-crypto/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/util-crypto", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "A collection of useful crypto utilities for @polkadot", "main": "index.js", "keywords": [ @@ -26,7 +26,7 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-crypto#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/util": "^0.92.0-beta.3", + "@polkadot/util": "^0.92.0", "@polkadot/wasm-crypto": "^0.11.1", "@types/bip39": "^2.4.2", "@types/pbkdf2": "^3.0.0", diff --git a/packages/util-rlp/package.json b/packages/util-rlp/package.json index 9478eb69c..5aff59ca8 100644 --- a/packages/util-rlp/package.json +++ b/packages/util-rlp/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/util-rlp", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "RLP encoding and decoding", "main": "index.js", "keywords": [ @@ -28,7 +28,7 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-rlp#readme", "dependencies": { "@babel/runtime": "^7.4.5", - "@polkadot/util": "^0.92.0-beta.3" + "@polkadot/util": "^0.92.0" }, "devDependencies": { "ethereumjs-testing": "1.0.4" diff --git a/packages/util/package.json b/packages/util/package.json index 2ab5abe22..2981849b4 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/util", - "version": "0.92.0-beta.3", + "version": "0.92.0", "description": "A collection of useful utilities for @polkadot", "main": "index.js", "keywords": [ diff --git a/packages/util/src/format/formatBalance.spec.ts b/packages/util/src/format/formatBalance.spec.ts index e5da0c4e7..b4f496635 100644 --- a/packages/util/src/format/formatBalance.spec.ts +++ b/packages/util/src/format/formatBalance.spec.ts @@ -68,6 +68,20 @@ describe('formatBalance', () => { ).toEqual('123.456 Unit'); }); + it('formats -123,456,789,000 (decimals=15)', () => { + expect( + formatBalance(new BN('-123456789000'), true, 15) + ).toEqual('-123.456ยต Unit'); + }); + + describe('calcSi', () => { + it('exposes calcSi on formatBalance', () => { + expect( + formatBalance.calcSi('12345').value + ).toEqual('k'); + }); + }); + describe('findSi', () => { it('finds the SI value', () => { expect( diff --git a/packages/util/src/format/formatBalance.ts b/packages/util/src/format/formatBalance.ts index ad0613d13..f25864bb6 100644 --- a/packages/util/src/format/formatBalance.ts +++ b/packages/util/src/format/formatBalance.ts @@ -31,12 +31,20 @@ let defaultUnit = DEFAULT_UNIT; // Formats a string/number with . notation function _formatBalance (input?: number | string | BN, withSi: boolean = true, decimals: number = defaultDecimals): string { - const text = (input || '').toString(); + let text = (input || '').toString(); if (text.length === 0 || text === '0') { return '0'; } + // strip the negative sign so we can work with clean groupings, re-add this in the + // end when we return the result (from here on we work with positive numbers) + const isNegative = text[0] === '-'; + + if (isNegative) { + text = text.substr(1); + } + assert(/^\d+$/.test(text), `Non-integer input value '${text}' supplied to balanceFormat`); // NOTE We start at midpoint (8) minus 1 - this means that values display as @@ -54,7 +62,7 @@ function _formatBalance (input?: number | string | BN, withSi: boolean = true, d ) : ''; - return `${formatDecimal(prefix || '0')}.${postfix}${units}`; + return `${isNegative ? '-' : ''}${formatDecimal(prefix || '0')}.${postfix}${units}`; } const formatBalance = _formatBalance as BalanceFormatter; diff --git a/packages/util/src/format/formatDecimal.spec.ts b/packages/util/src/format/formatDecimal.spec.ts index 49cbb207c..9ac7e437b 100644 --- a/packages/util/src/format/formatDecimal.spec.ts +++ b/packages/util/src/format/formatDecimal.spec.ts @@ -16,4 +16,12 @@ describe('formatDecimal', () => { it('returns input for non-decimal', () => { expect(formatDecimal('test')).toEqual('test'); }); + + it('returns non-sensical negative text', () => { + expect(formatDecimal('-test')).toEqual('-test'); + }); + + it('formats negative numbers', () => { + expect(formatDecimal('-123456')).toEqual('-123,456'); + }); }); diff --git a/packages/util/src/format/formatDecimal.ts b/packages/util/src/format/formatDecimal.ts index 097c21462..a36817247 100644 --- a/packages/util/src/format/formatDecimal.ts +++ b/packages/util/src/format/formatDecimal.ts @@ -5,9 +5,14 @@ const NUMBER_REGEX = new RegExp('(\\d+?)(?=(\\d{3})+(?!\\d)|$)', 'g'); export default function formatDecimal (value: string): string { - const matched = value.match(NUMBER_REGEX); + // We can do this by adjusting the regx, however for the sake of clarity + // we rather strip and re-add the negative sign in the output + const isNegative = value[0] === '-'; + const matched = isNegative + ? value.substr(1).match(NUMBER_REGEX) + : value.match(NUMBER_REGEX); return matched - ? matched.join(',') + ? `${isNegative ? '-' : ''}${matched.join(',')}` : value; } diff --git a/packages/util/src/format/formatNumber.spec.ts b/packages/util/src/format/formatNumber.spec.ts new file mode 100644 index 000000000..775f1b2e7 --- /dev/null +++ b/packages/util/src/format/formatNumber.spec.ts @@ -0,0 +1,35 @@ +// Copyright 2017-2019 @polkadot/util authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Compact } from './types'; + +import BN from 'bn.js'; + +import formatNumber from './formatNumber'; + +describe('formatNumber', () => { + it('formats empty', () => { + expect( + formatNumber() + ).toEqual('0'); + }); + + it('formats negative numbers', () => { + expect( + formatNumber(-123456) + ).toEqual('-123,456'); + }); + + it('formats BN numbers', () => { + expect( + formatNumber(new BN(12345)) + ).toEqual('12,345'); + }); + + it('formats Compact', () => { + expect( + formatNumber({ toBn: () => new BN(12345) } as Compact) + ).toEqual('12,345'); + }); +});