-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aaa430d
commit 1c9e72c
Showing
7 changed files
with
251 additions
and
41 deletions.
There are no files selected for viewing
46 changes: 25 additions & 21 deletions
46
...allet-mobile/src/features/Send/useCases/ListAmountsToSend/EditAmount/EditAmountScreen.tsx
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
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
119 changes: 119 additions & 0 deletions
119
packages/common/src/numbers/parse-input-to-bigint.test.ts
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,119 @@ | ||
import BigNumber from 'bignumber.js' | ||
|
||
import {parseInputToBigInt} from './parse-input-to-bigint' | ||
|
||
describe('parse-input-to-bigint', () => { | ||
it('parseInputToBigInt', () => { | ||
const english = { | ||
prefix: '', | ||
decimalSeparator: '.', | ||
groupSeparator: ',', | ||
groupSize: 3, | ||
secondaryGroupSize: 0, | ||
fractionGroupSize: 0, | ||
fractionGroupSeparator: ' ', | ||
suffix: '', | ||
} | ||
|
||
const italian = { | ||
...english, | ||
decimalSeparator: ',', | ||
groupSeparator: ' ', | ||
} | ||
|
||
BigNumber.config({ | ||
FORMAT: italian, | ||
}) | ||
|
||
expect( | ||
parseInputToBigInt({input: '', decimalPlaces: 3, format: italian}), | ||
).toEqual(['', 0n]) | ||
expect( | ||
parseInputToBigInt({input: ',', decimalPlaces: 3, format: italian}), | ||
).toEqual(['0,', 0n]) | ||
expect( | ||
parseInputToBigInt({input: '1', decimalPlaces: 3, format: italian}), | ||
).toEqual(['1', 1000n]) | ||
expect( | ||
parseInputToBigInt({input: '123,55', decimalPlaces: 3, format: italian}), | ||
).toEqual(['123,55', 123550n]) | ||
expect( | ||
parseInputToBigInt({ | ||
input: '1234,6666', | ||
decimalPlaces: 3, | ||
format: italian, | ||
}), | ||
).toEqual(['1 234,666', 1234666n]) | ||
expect( | ||
parseInputToBigInt({input: '55,', decimalPlaces: 3, format: italian}), | ||
).toEqual(['55,', 55000n]) | ||
expect( | ||
parseInputToBigInt({input: '55,0', decimalPlaces: 3, format: italian}), | ||
).toEqual(['55,0', 55000n]) | ||
expect( | ||
parseInputToBigInt({input: '55,10', decimalPlaces: 3, format: italian}), | ||
).toEqual(['55,10', 55100n]) | ||
expect( | ||
parseInputToBigInt({ | ||
input: 'ab1.5c,6.5', | ||
decimalPlaces: 3, | ||
format: italian, | ||
}), | ||
).toEqual(['15,65', 15650n]) | ||
|
||
BigNumber.config({FORMAT: english}) | ||
|
||
expect( | ||
parseInputToBigInt({input: '', decimalPlaces: 3, format: english}), | ||
).toEqual(['', 0n]) | ||
expect( | ||
parseInputToBigInt({input: '1', decimalPlaces: 3, format: english}), | ||
).toEqual(['1', 1000n]) | ||
expect( | ||
parseInputToBigInt({input: '123.55', decimalPlaces: 3, format: english}), | ||
).toEqual(['123.55', 123550n]) | ||
expect( | ||
parseInputToBigInt({ | ||
input: '1234.6666', | ||
decimalPlaces: 3, | ||
format: english, | ||
}), | ||
).toEqual(['1,234.666', 1234666n]) | ||
expect( | ||
parseInputToBigInt({input: '55.', decimalPlaces: 3, format: english}), | ||
).toEqual(['55.', 55000n]) | ||
expect( | ||
parseInputToBigInt({input: '55.0', decimalPlaces: 3, format: english}), | ||
).toEqual(['55.0', 55000n]) | ||
expect( | ||
parseInputToBigInt({input: '55.10', decimalPlaces: 3, format: english}), | ||
).toEqual(['55.10', 55100n]) | ||
expect( | ||
parseInputToBigInt({ | ||
input: 'ab1.5c,6.5', | ||
decimalPlaces: 3, | ||
format: english, | ||
}), | ||
).toEqual(['1.56', 1560n]) | ||
|
||
expect( | ||
parseInputToBigInt({ | ||
input: '1.23456', | ||
decimalPlaces: 0, | ||
format: english, | ||
precision: 3, | ||
}), | ||
).toEqual(['1.234', 1n]) | ||
expect( | ||
parseInputToBigInt({ | ||
input: '1.23456', | ||
decimalPlaces: 2, | ||
format: english, | ||
precision: 3, | ||
}), | ||
// how? simple, precision of 3 keep 1.234, 2 decimals drop the 4, toFixed 0 | ||
// 123 with 2 decimals = 1.23 | ||
// so be mindfull when using precision and decimalPlaces together | ||
).toEqual(['1.234', 123n]) | ||
}) | ||
}) |
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,85 @@ | ||
import {Numbers} from '@yoroi/types' | ||
import BigNumber from 'bignumber.js' | ||
|
||
/** | ||
* Parses a localized numeric input into a formatted string and a corresponding | ||
* BigInt representation, adjusting for specified decimal places and precision | ||
* Don't use this to parse non-inputs, use toBigInt instead | ||
* @note It will append 0 if starting with a decimal separator | ||
* | ||
* @param options - The options for parsing the input | ||
* @param options.input - The input string to be parsed | ||
* @param options.decimalPlaces - The number of decimal places to consider | ||
* @param options.format - The locale format for numbers | ||
* @param [options.precision] - The precision for rounding the number (optional, defaults to decimalPlaces) | ||
* | ||
* @returns {[string, bigint]} - A tuple containing the formatted string and BigInt value | ||
* | ||
* @example | ||
* parseInputToBigInt({input: '', decimalPlaces: 3, format: italian}) // => ['', 0n] | ||
* parseInputToBigInt({input: '1', decimalPlaces: 3, format: italian}) // => ['1', 1000n] | ||
* parseInputToBigInt({input: '123,55', decimalPlaces: 3, format: italian}) // => ['123,55', 123550n] | ||
*/ | ||
export function parseInputToBigInt({ | ||
input, | ||
decimalPlaces, | ||
format, | ||
precision = decimalPlaces, | ||
}: { | ||
input: string | ||
decimalPlaces: number | ||
format: Numbers.Locale | ||
precision?: number | ||
}): [string, bigint] { | ||
const {decimalSeparator} = format | ||
const invalidCharsRegex = new RegExp(`[^0-9${decimalSeparator}]`, 'g') | ||
const sanitizedInput = | ||
input === '' ? '' : input.replace(invalidCharsRegex, '') | ||
|
||
if (sanitizedInput === '') return ['', 0n] | ||
if (sanitizedInput.startsWith(decimalSeparator)) | ||
return [`0${decimalSeparator}`, 0n] | ||
|
||
const parts = sanitizedInput.split(decimalSeparator) | ||
let formattedValue = sanitizedInput | ||
let numericalValue = sanitizedInput | ||
|
||
if (parts.length <= 1) { | ||
const quantity = BigInt( | ||
new BigNumber(numericalValue.replace(decimalSeparator, '.')) | ||
.decimalPlaces(precision) | ||
.shiftedBy(decimalPlaces) | ||
.toFixed(0, BigNumber.ROUND_DOWN), | ||
) | ||
return [ | ||
new BigNumber(formattedValue.replace(decimalSeparator, '.')).toFormat(), | ||
quantity, | ||
] | ||
} | ||
|
||
const [integerPart, decimalPart] = parts | ||
formattedValue = `${integerPart}${decimalSeparator}${decimalPart?.slice( | ||
0, | ||
precision, | ||
)}1` | ||
numericalValue = `${integerPart}${decimalSeparator}${decimalPart?.slice( | ||
0, | ||
precision, | ||
)}` | ||
|
||
const formattedNumber = new BigNumber( | ||
formattedValue.replace(decimalSeparator, '.'), | ||
).toFormat() | ||
|
||
// Remove the temporary character used for formatting purposes | ||
const textOutput = formattedNumber.slice(0, -1) | ||
|
||
const quantity = BigInt( | ||
new BigNumber(numericalValue.replace(decimalSeparator, '.')) | ||
.decimalPlaces(precision) | ||
.shiftedBy(decimalPlaces) | ||
.toFixed(0, BigNumber.ROUND_DOWN), | ||
) | ||
|
||
return [textOutput, quantity] | ||
} |
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