-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: user friendly Weight scale (#544)
- Loading branch information
Showing
7 changed files
with
220 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,17 @@ | ||
// Copyright 2022-2024 @paritytech/contracts-ui authors & contributors | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
import { Balance } from 'types'; | ||
|
||
type FormattingOptions = { | ||
decimals: number; | ||
symbol: string | undefined; | ||
fractionDigits: number; | ||
}; | ||
import { Balance } from '@polkadot/types/interfaces'; | ||
import type { FormattingOptions } from './formatUInt'; | ||
import { formatUInt } from './formatUInt'; | ||
|
||
const DEFAULT_OPTIONS: FormattingOptions = { | ||
decimals: 12, | ||
fractionDigits: 2, | ||
symbol: undefined, | ||
digitGrouping: true, | ||
}; | ||
|
||
export const formatBalance = (balance: Balance, partialOptions?: Partial<FormattingOptions>) => { | ||
const options: FormattingOptions = { ...DEFAULT_OPTIONS, ...partialOptions }; | ||
|
||
if (options.decimals < 0) throw new Error('Decimals must be positive'); | ||
if (options.fractionDigits < 0) throw new Error('Fraction digits must be positive'); | ||
if (options.decimals < options.fractionDigits) | ||
throw new Error('Decimals must be greater than fraction digits'); | ||
|
||
const balanceString = balance.toString(); | ||
const integerDigits = balanceString.split(''); | ||
const fractionDigits = integerDigits.splice(-options.decimals); | ||
|
||
const fractionalPart = fractionDigits.join('').padStart(options.decimals, '0'); | ||
const integerPart = integerDigits.length ? integerDigits.join('') : '0'; | ||
|
||
return ( | ||
Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(BigInt(integerPart)) + | ||
'.' + | ||
fractionalPart.toString().slice(0, options.fractionDigits).padEnd(options.fractionDigits, '0') + | ||
(options.symbol ? ` ${options.symbol}` : '') | ||
); | ||
return formatUInt(balance, { ...DEFAULT_OPTIONS, ...partialOptions }); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright 2022-2024 @paritytech/contracts-ui authors & contributors | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
import type { Compact, UInt } from '@polkadot/types-codec'; | ||
|
||
export type FormattingOptions = { | ||
decimals: number; | ||
symbol: string | undefined; | ||
fractionDigits: number; | ||
digitGrouping: boolean; | ||
}; | ||
|
||
export const formatUInt = (value: UInt | Compact<UInt>, options: FormattingOptions) => { | ||
if (options.decimals < 0) throw new Error('Decimals must be positive'); | ||
if (options.fractionDigits < 0) throw new Error('Fraction digits must be positive'); | ||
if (options.decimals < options.fractionDigits) | ||
throw new Error('Decimals must be greater than fraction digits'); | ||
|
||
const valueString = value.toString(); | ||
const integerDigits = valueString.split(''); | ||
|
||
let fractionalPart = ''.padStart(options.decimals, '0'); | ||
if (options.decimals !== 0) { | ||
const fractionDigits = integerDigits.splice(-options.decimals); | ||
fractionalPart = fractionDigits.join('').padStart(options.decimals, '0'); | ||
} | ||
|
||
let integerPart = integerDigits.length ? integerDigits.join('') : '0'; | ||
|
||
if (options.digitGrouping) { | ||
integerPart = Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format( | ||
BigInt(integerPart), | ||
); | ||
} | ||
|
||
if (options.fractionDigits === 0) { | ||
return integerPart + (options.symbol ? ` ${options.symbol}` : ''); | ||
} else { | ||
return ( | ||
integerPart + | ||
'.' + | ||
fractionalPart.slice(0, options.fractionDigits) + | ||
(options.symbol ? ` ${options.symbol}` : '') | ||
); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright 2022-2024 @paritytech/contracts-ui authors & contributors | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
import { TypeRegistry } from '@polkadot/types'; | ||
import { beforeAll, describe, expect, it } from 'vitest'; | ||
import { formatProofSize, formatRefTime } from './formatWeight'; | ||
|
||
describe('formatProofSize', () => { | ||
let registry: TypeRegistry; | ||
|
||
beforeAll(() => { | ||
registry = new TypeRegistry(); | ||
}); | ||
|
||
it('should format edge cases correctly', () => { | ||
[ | ||
{ value: 0n, expected: '0.00 MB' }, | ||
{ value: 1_000_000n, expected: '1.00 MB' }, | ||
// u64::MAX value | ||
{ | ||
value: 18_446_744_073_709_551_615n, | ||
expected: '18446744073709.55 MB', | ||
}, | ||
].forEach(({ value, expected }) => { | ||
const proofSize = registry.createType('Compact<u64>', value); | ||
expect(formatProofSize(proofSize, 'MB')).toBe(expected); | ||
}); | ||
}); | ||
|
||
it('should format edge cases correctly', () => { | ||
[ | ||
{ value: 0n, expected: '0 bytes' }, | ||
{ value: 1_000_000n, expected: '1000000 bytes' }, | ||
// u64::MAX value | ||
{ | ||
value: 18_446_744_073_709_551_615n, | ||
expected: '18446744073709551615 bytes', | ||
}, | ||
].forEach(({ value, expected }) => { | ||
const proofSize = registry.createType('Compact<u64>', value); | ||
expect(formatProofSize(proofSize, 'bytes')).toBe(expected); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('formatRefTime', () => { | ||
let registry: TypeRegistry; | ||
|
||
beforeAll(() => { | ||
registry = new TypeRegistry(); | ||
}); | ||
|
||
it('should format edge cases correctly', () => { | ||
[ | ||
{ value: 0n, expected: '0.00 ms' }, | ||
{ value: 123n, expected: '0.00 ms' }, | ||
{ value: 123_000_000n, expected: '0.12 ms' }, | ||
{ value: 1_000_000_000n, expected: '1.00 ms' }, | ||
// u64::MAX value | ||
{ | ||
value: 18_446_744_073_709_551_615n, | ||
expected: '18446744073.70 ms', | ||
}, | ||
].forEach(({ value, expected }) => { | ||
const refTime = registry.createType('Compact<u64>', value); | ||
expect(formatRefTime(refTime, 'ms')).toBe(expected); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright 2022-2024 @paritytech/contracts-ui authors & contributors | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
import { WeightV2 } from '@polkadot/types/interfaces'; | ||
import { formatUInt } from './formatUInt'; | ||
|
||
/** | ||
* Formats given Reference Time value from expected picoseconds to milliseconds. | ||
* @param refTime | ||
* @returns formatted refTime in milliseconds, with 2 decimal places | ||
*/ | ||
export function formatRefTime(refTime: WeightV2['refTime'], unit: 'ms' | 'ps' = 'ps'): string { | ||
switch (unit) { | ||
case 'ps': | ||
return formatUInt(refTime, { | ||
decimals: 0, | ||
digitGrouping: false, | ||
fractionDigits: 0, | ||
symbol: unit, | ||
}); | ||
case 'ms': | ||
return formatUInt(refTime, { | ||
decimals: 9, | ||
digitGrouping: false, | ||
fractionDigits: 2, | ||
symbol: unit, | ||
}); | ||
default: | ||
throw new Error('Unsupported unit'); | ||
} | ||
} | ||
|
||
/** | ||
* Formats given Proof Size value from expected bytes to megabytes. | ||
* @param refTime | ||
* @returns formatted refTime in megabytes, with 2 decimal places | ||
*/ | ||
export function formatProofSize( | ||
proofSize: WeightV2['proofSize'], | ||
unit: 'MB' | 'bytes' | 'kb' = 'bytes', | ||
): string { | ||
switch (unit) { | ||
case 'bytes': | ||
return formatUInt(proofSize, { | ||
decimals: 0, | ||
digitGrouping: false, | ||
fractionDigits: 0, | ||
symbol: unit, | ||
}); | ||
case 'kb': | ||
return formatUInt(proofSize, { | ||
decimals: 3, | ||
digitGrouping: false, | ||
fractionDigits: 2, | ||
symbol: unit, | ||
}); | ||
case 'MB': | ||
return formatUInt(proofSize, { | ||
decimals: 6, | ||
digitGrouping: false, | ||
fractionDigits: 2, | ||
symbol: unit, | ||
}); | ||
default: | ||
throw new Error('Unsupported unit'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters