@ledgerhq/coin-module-framework 1.0.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.unimportedrc.json +0 -1
  2. package/CHANGELOG.md +12 -0
  3. package/lib/api/types.d.ts +6 -1
  4. package/lib/api/types.d.ts.map +1 -1
  5. package/lib/config.d.ts +3 -4
  6. package/lib/config.d.ts.map +1 -1
  7. package/lib/config.js +2 -2
  8. package/lib/config.js.map +1 -1
  9. package/lib/currencies/BigNumberToLocaleString.d.ts +7 -0
  10. package/lib/currencies/BigNumberToLocaleString.d.ts.map +1 -0
  11. package/lib/currencies/BigNumberToLocaleString.js +58 -0
  12. package/lib/currencies/BigNumberToLocaleString.js.map +1 -0
  13. package/lib/currencies/formatCurrencyUnit.d.ts +25 -1
  14. package/lib/currencies/formatCurrencyUnit.d.ts.map +1 -1
  15. package/lib/currencies/formatCurrencyUnit.js +130 -4
  16. package/lib/currencies/formatCurrencyUnit.js.map +1 -1
  17. package/lib/currencies/localeUtility.d.ts +8 -0
  18. package/lib/currencies/localeUtility.d.ts.map +1 -0
  19. package/lib/currencies/localeUtility.js +51 -0
  20. package/lib/currencies/localeUtility.js.map +1 -0
  21. package/lib/currencies/parseCurrencyUnit.d.ts +2 -1
  22. package/lib/currencies/parseCurrencyUnit.d.ts.map +1 -1
  23. package/lib/currencies/parseCurrencyUnit.js +9 -2
  24. package/lib/currencies/parseCurrencyUnit.js.map +1 -1
  25. package/lib-es/api/types.d.ts +6 -1
  26. package/lib-es/api/types.d.ts.map +1 -1
  27. package/lib-es/config.d.ts +3 -4
  28. package/lib-es/config.d.ts.map +1 -1
  29. package/lib-es/config.js +2 -2
  30. package/lib-es/config.js.map +1 -1
  31. package/lib-es/currencies/BigNumberToLocaleString.d.ts +7 -0
  32. package/lib-es/currencies/BigNumberToLocaleString.d.ts.map +1 -0
  33. package/lib-es/currencies/BigNumberToLocaleString.js +54 -0
  34. package/lib-es/currencies/BigNumberToLocaleString.js.map +1 -0
  35. package/lib-es/currencies/formatCurrencyUnit.d.ts +25 -1
  36. package/lib-es/currencies/formatCurrencyUnit.d.ts.map +1 -1
  37. package/lib-es/currencies/formatCurrencyUnit.js +127 -1
  38. package/lib-es/currencies/formatCurrencyUnit.js.map +1 -1
  39. package/lib-es/currencies/localeUtility.d.ts +8 -0
  40. package/lib-es/currencies/localeUtility.d.ts.map +1 -0
  41. package/lib-es/currencies/localeUtility.js +48 -0
  42. package/lib-es/currencies/localeUtility.js.map +1 -0
  43. package/lib-es/currencies/parseCurrencyUnit.d.ts +2 -1
  44. package/lib-es/currencies/parseCurrencyUnit.d.ts.map +1 -1
  45. package/lib-es/currencies/parseCurrencyUnit.js +8 -1
  46. package/lib-es/currencies/parseCurrencyUnit.js.map +1 -1
  47. package/package.json +5 -5
  48. package/src/api/types.ts +8 -1
  49. package/src/config.ts +4 -5
  50. package/src/currencies/BigNumberToLocaleString.test.ts +164 -0
  51. package/src/currencies/BigNumberToLocaleString.ts +70 -0
  52. package/src/currencies/formatCurrencyUnit.test.ts +215 -0
  53. package/src/currencies/formatCurrencyUnit.ts +200 -6
  54. package/src/currencies/localeUtility.test.ts +22 -0
  55. package/src/currencies/localeUtility.ts +59 -0
  56. package/src/currencies/parseCurrencyUnit.test.ts +26 -0
  57. package/src/currencies/parseCurrencyUnit.ts +10 -1
@@ -0,0 +1,70 @@
1
+ // Forked from @ledgerhq/live-currency-format/src/BigNumberToLocaleString.ts
2
+ import { BigNumber } from 'bignumber.js'
3
+ import { getSeparators } from './localeUtility'
4
+
5
+ export type SupportedOptions = {
6
+ minimumFractionDigits: number
7
+ maximumFractionDigits: number
8
+ useGrouping: boolean
9
+ }
10
+
11
+ const getFormatForLocale = (locale: string) => {
12
+ const { decimal, thousands } = getSeparators(locale)
13
+ const opts = {
14
+ decimalSeparator: '.',
15
+ groupSeparator: ',',
16
+ groupSize: 3,
17
+ secondaryGroupSize: 0,
18
+ fractionGroupSeparator: '\xA0', // non-breaking space
19
+ fractionGroupSize: 0,
20
+ }
21
+ if (typeof decimal === 'string') opts.decimalSeparator = decimal
22
+ if (typeof thousands === 'string') opts.groupSeparator = thousands
23
+ return opts
24
+ }
25
+
26
+ export const toLocaleString = (
27
+ n: BigNumber,
28
+ localeInput?: string,
29
+ options: Partial<SupportedOptions> = {}
30
+ ): string => {
31
+ let locale = localeInput
32
+ if (!locale) locale = 'en'
33
+ const minimumFractionDigits =
34
+ typeof options.minimumFractionDigits === 'number' ? options.minimumFractionDigits : 0
35
+ const maximumFractionDigits =
36
+ typeof options.maximumFractionDigits === 'number'
37
+ ? options.maximumFractionDigits
38
+ : Math.max(minimumFractionDigits, 3)
39
+ const useGrouping = 'useGrouping' in options ? options.useGrouping : true
40
+ const format = getFormatForLocale(locale)
41
+
42
+ if (!useGrouping) {
43
+ format.groupSeparator = ''
44
+ }
45
+
46
+ const BN = BigNumber.clone({
47
+ FORMAT: format,
48
+ })
49
+ const bn = new BN(n)
50
+ const maxDecimals = bn.toFormat(maximumFractionDigits, BigNumber.ROUND_FLOOR)
51
+
52
+ if (maximumFractionDigits !== minimumFractionDigits) {
53
+ const minDecimals = bn.toFormat(minimumFractionDigits, BigNumber.ROUND_FLOOR)
54
+ let i = maxDecimals.length
55
+
56
+ while (i > minDecimals.length) {
57
+ if (maxDecimals[i - 1] !== '0') {
58
+ if (maxDecimals[i - 1] === format.decimalSeparator) {
59
+ i--
60
+ }
61
+ break
62
+ }
63
+ i--
64
+ }
65
+
66
+ return maxDecimals.slice(0, i)
67
+ }
68
+
69
+ return maxDecimals
70
+ }
@@ -0,0 +1,215 @@
1
+ // Forked from @ledgerhq/live-currency-format/src/formatCurrencyUnit.test.ts
2
+ // Snapshot tests using @ledgerhq/cryptoassets removed (not available in this repo)
3
+ import { formatCurrencyUnit, formatCurrencyUnitFragment } from './formatCurrencyUnit'
4
+ import { BigNumber } from 'bignumber.js'
5
+ import type { Unit } from '../api/types'
6
+
7
+ describe('formatCurrencyUnit', () => {
8
+ describe('error handling', () => {
9
+ const unit: Unit = {
10
+ name: 'Test',
11
+ code: 'TST',
12
+ magnitude: 2,
13
+ showAllDigits: false,
14
+ prefixCode: false,
15
+ }
16
+
17
+ test('handles non-BigNumber', () => {
18
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
19
+ expect(formatCurrencyUnit(unit, null as unknown as BigNumber)).toBe('')
20
+ consoleSpy.mockRestore()
21
+ })
22
+
23
+ test('handles NaN', () => {
24
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
25
+ expect(formatCurrencyUnit(unit, new BigNumber(NaN))).toBe('')
26
+ consoleSpy.mockRestore()
27
+ })
28
+
29
+ test('handles Infinity', () => {
30
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
31
+ expect(formatCurrencyUnit(unit, new BigNumber(Infinity))).toBe('')
32
+ consoleSpy.mockRestore()
33
+ })
34
+ })
35
+
36
+ describe('formatCurrencyUnit options', () => {
37
+ const unit: Unit = {
38
+ name: 'Test',
39
+ code: 'USD',
40
+ magnitude: 2,
41
+ showAllDigits: false,
42
+ prefixCode: false,
43
+ }
44
+
45
+ test('prefixCode true', () => {
46
+ const prefixUnit: Unit = { ...unit, prefixCode: true }
47
+ expect(formatCurrencyUnit(prefixUnit, new BigNumber('12345'), { showCode: true })).toBe(
48
+ 'USD123.45'
49
+ )
50
+ })
51
+
52
+ test('prefixCode false', () => {
53
+ expect(formatCurrencyUnit(unit, new BigNumber('12345'), { showCode: true })).toBe(
54
+ '123.45\u00A0USD'
55
+ )
56
+ })
57
+
58
+ test('negative with prefixCode', () => {
59
+ const prefixUnit: Unit = { ...unit, prefixCode: true }
60
+ expect(formatCurrencyUnit(prefixUnit, new BigNumber('-12345'), { showCode: true })).toBe(
61
+ '-USD123.45'
62
+ )
63
+ })
64
+
65
+ test('negative with suffixCode', () => {
66
+ expect(formatCurrencyUnit(unit, new BigNumber('-12345'), { showCode: true })).toBe(
67
+ '-123.45\u00A0USD'
68
+ )
69
+ })
70
+
71
+ test('alwaysShowSign', () => {
72
+ expect(formatCurrencyUnit(unit, new BigNumber('12345'), { alwaysShowSign: true })).toBe(
73
+ '+123.45'
74
+ )
75
+ })
76
+
77
+ test('discreet mode', () => {
78
+ expect(formatCurrencyUnit(unit, new BigNumber('12345'), { discreet: true })).toBe('***')
79
+ })
80
+
81
+ test('joinFragmentsSeparator', () => {
82
+ const prefixUnit: Unit = { ...unit, prefixCode: true }
83
+ expect(
84
+ formatCurrencyUnit(prefixUnit, new BigNumber('12345'), {
85
+ showCode: true,
86
+ joinFragmentsSeparator: '-',
87
+ })
88
+ ).toBe('USD-123.45')
89
+ })
90
+
91
+ test('useGrouping false', () => {
92
+ expect(
93
+ formatCurrencyUnit(unit, new BigNumber('12345678'), { useGrouping: false })
94
+ ).not.toContain(',')
95
+ })
96
+
97
+ test('showAllDigits', () => {
98
+ const highMagUnit: Unit = { ...unit, magnitude: 4 }
99
+ expect(formatCurrencyUnit(highMagUnit, new BigNumber('12345'), { showAllDigits: true })).toBe(
100
+ '1.2345'
101
+ )
102
+ })
103
+
104
+ test('filters undefined options', () => {
105
+ expect(
106
+ formatCurrencyUnit(unit, new BigNumber('12345'), { showCode: undefined, locale: 'en-US' })
107
+ ).toBe('123.45')
108
+ })
109
+ })
110
+
111
+ describe('formatCurrencyUnitFragment', () => {
112
+ const unit: Unit = {
113
+ name: 'Test',
114
+ code: 'USD',
115
+ magnitude: 2,
116
+ showAllDigits: false,
117
+ prefixCode: false,
118
+ }
119
+
120
+ test('basic structure', () => {
121
+ const result = formatCurrencyUnitFragment(unit, new BigNumber('12345'))
122
+ expect(result.integerPart).toBe('123')
123
+ expect(result.decimalPart).toBe('45')
124
+ expect(result.decimalSeparator).toBe('.')
125
+ expect(result.currencyText).toBe('')
126
+ expect(result.currencyPosition).toBe('end')
127
+ })
128
+
129
+ test('negative with prefixCode false', () => {
130
+ const result = formatCurrencyUnitFragment(unit, new BigNumber('-12345'), { showCode: true })
131
+ expect(result.integerPart).toBe('-123')
132
+ expect(result.currencyText).toBe('USD')
133
+ })
134
+
135
+ test('negative with prefixCode true', () => {
136
+ const prefixUnit: Unit = { ...unit, prefixCode: true }
137
+ const result = formatCurrencyUnitFragment(prefixUnit, new BigNumber('-12345'), {
138
+ showCode: true,
139
+ })
140
+ expect(result.integerPart).toBe('123')
141
+ expect(result.currencyText).toBe('-USD')
142
+ })
143
+
144
+ test('negative with prefixCode true but no code', () => {
145
+ const prefixUnit: Unit = { ...unit, prefixCode: true }
146
+ const result = formatCurrencyUnitFragment(prefixUnit, new BigNumber('-12345'), {
147
+ showCode: false,
148
+ })
149
+ expect(result.integerPart).toBe('-123')
150
+ expect(result.currencyText).toBe('')
151
+ })
152
+
153
+ test('alwaysShowSign', () => {
154
+ const result = formatCurrencyUnitFragment(unit, new BigNumber('12345'), {
155
+ alwaysShowSign: true,
156
+ })
157
+ expect(result.integerPart).toBe('+123')
158
+ })
159
+
160
+ test('no decimals', () => {
161
+ const result = formatCurrencyUnitFragment(unit, new BigNumber('10000'))
162
+ expect(result.integerPart).toBe('100')
163
+ expect(result.decimalPart).toBe('')
164
+ })
165
+
166
+ test('french locale', () => {
167
+ const result = formatCurrencyUnitFragment(unit, new BigNumber('12345'), { locale: 'fr-FR' })
168
+ expect(result.decimalSeparator).toBe(',')
169
+ })
170
+
171
+ test('error handling', () => {
172
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
173
+ const result = formatCurrencyUnitFragment(unit, null as unknown as BigNumber)
174
+ expect(result.integerPart).toBe('')
175
+ expect(result.decimalPart).toBe('')
176
+ consoleSpy.mockRestore()
177
+ })
178
+
179
+ test('error handling with prefixCode true', () => {
180
+ const prefixUnit: Unit = { ...unit, prefixCode: true }
181
+ const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
182
+ const result = formatCurrencyUnitFragment(prefixUnit, new BigNumber(NaN))
183
+ expect(result.currencyPosition).toBe('start')
184
+ consoleSpy.mockRestore()
185
+ })
186
+ })
187
+
188
+ describe('coverage edge cases', () => {
189
+ test('disableRounding with subMagnitude', () => {
190
+ const unit: Unit = {
191
+ name: 'Test',
192
+ code: 'TST',
193
+ magnitude: 2,
194
+ showAllDigits: false,
195
+ prefixCode: false,
196
+ }
197
+ const value = new BigNumber('12345')
198
+ const result = formatCurrencyUnit(unit, value, { disableRounding: true, subMagnitude: 1 })
199
+ expect(result).toContain('123.45')
200
+ })
201
+
202
+ test('prefixCode true without code', () => {
203
+ const unit: Unit = {
204
+ name: 'Test',
205
+ code: 'USD',
206
+ magnitude: 2,
207
+ showAllDigits: false,
208
+ prefixCode: true,
209
+ }
210
+ const value = new BigNumber('12345')
211
+ const result = formatCurrencyUnit(unit, value, { showCode: false })
212
+ expect(result).toBe('123.45')
213
+ })
214
+ })
215
+ })
@@ -1,6 +1,200 @@
1
- export {
2
- formatCurrencyUnit,
3
- formatCurrencyUnitFragment,
4
- type formatCurrencyUnitOptions,
5
- type FormatterValue,
6
- } from '@ledgerhq/live-currency-format'
1
+ // Forked from @ledgerhq/live-currency-format/src/formatCurrencyUnit.ts
2
+ import { BigNumber } from 'bignumber.js'
3
+ import { getSeparators } from './localeUtility'
4
+ import { toLocaleString } from './BigNumberToLocaleString'
5
+ import type { Unit } from '../api/types'
6
+
7
+ const nonBreakableSpace = '\u00A0'
8
+ const defaultFormatOptions = {
9
+ locale: 'en-EN',
10
+ showCode: false,
11
+ alwaysShowSign: false,
12
+ showAllDigits: false,
13
+ disableRounding: false,
14
+ useGrouping: true,
15
+ subMagnitude: 0,
16
+ discreet: false,
17
+ joinFragmentsSeparator: '',
18
+ dynamicSignificantDigits: 6,
19
+ staticSignificantDigits: 8,
20
+ }
21
+
22
+ export type formatCurrencyUnitOptions = Partial<typeof defaultFormatOptions>
23
+
24
+ export type FormatterValue = {
25
+ integerPart: string
26
+ decimalPart: string
27
+ decimalSeparator: '.' | ','
28
+ currencyText: string
29
+ currencyPosition: 'start' | 'end'
30
+ }
31
+
32
+ type FormatState = {
33
+ value: string
34
+ sign: string | null
35
+ code: string | null
36
+ decimalSeparator: '.' | ','
37
+ currencyPosition: 'start' | 'end'
38
+ }
39
+
40
+ type ResolvedFormatOptions = typeof defaultFormatOptions & Unit
41
+
42
+ const buildFormatState = (
43
+ unit: Unit,
44
+ value: BigNumber,
45
+ _options?: formatCurrencyUnitOptions
46
+ ): FormatState => {
47
+ const emptyState = (): FormatState => ({
48
+ value: '',
49
+ sign: null,
50
+ code: null,
51
+ decimalSeparator: '.',
52
+ currencyPosition: unit.prefixCode ? 'start' : 'end',
53
+ })
54
+
55
+ if (!BigNumber.isBigNumber(value)) {
56
+ console.warn('formatCurrencyUnit called with value=', value)
57
+ return emptyState()
58
+ }
59
+
60
+ if (value.isNaN()) {
61
+ console.warn('formatCurrencyUnit called with NaN value!')
62
+ return emptyState()
63
+ }
64
+
65
+ if (!value.isFinite()) {
66
+ console.warn('formatCurrencyUnit called with infinite value=', value)
67
+ return emptyState()
68
+ }
69
+
70
+ const options: Record<string, unknown> = {}
71
+
72
+ if (_options) {
73
+ let k: keyof formatCurrencyUnitOptions
74
+ for (k in _options) {
75
+ const optionValue = _options[k]
76
+ if (optionValue !== undefined) {
77
+ options[k] = optionValue
78
+ }
79
+ }
80
+ }
81
+
82
+ const resolvedOptions: ResolvedFormatOptions = {
83
+ ...defaultFormatOptions,
84
+ ...unit,
85
+ ...options,
86
+ }
87
+ const {
88
+ showCode,
89
+ alwaysShowSign,
90
+ showAllDigits,
91
+ locale,
92
+ disableRounding,
93
+ useGrouping,
94
+ subMagnitude,
95
+ discreet,
96
+ dynamicSignificantDigits,
97
+ staticSignificantDigits,
98
+ } = resolvedOptions
99
+ const { magnitude, code } = unit
100
+ const floatValue = value.div(new BigNumber(10).pow(magnitude))
101
+ const floatValueAbs = floatValue.abs()
102
+ const minimumFractionDigits = showAllDigits ? magnitude : 0
103
+ const maximumFractionDigits = disableRounding
104
+ ? magnitude + subMagnitude
105
+ : Math.max(
106
+ minimumFractionDigits,
107
+ Math.max(
108
+ 0,
109
+ Math.min(
110
+ dynamicSignificantDigits - Math.ceil(Math.log(floatValueAbs.toNumber()) / Math.log(10)),
111
+ magnitude + subMagnitude,
112
+ staticSignificantDigits
113
+ )
114
+ )
115
+ )
116
+ const sign =
117
+ alwaysShowSign || floatValue.isNegative() ? (floatValue.isNegative() ? '-' : '+') : null
118
+ const formattedValue = discreet
119
+ ? '***'
120
+ : toLocaleString(floatValueAbs, locale, {
121
+ maximumFractionDigits,
122
+ minimumFractionDigits,
123
+ useGrouping,
124
+ })
125
+
126
+ const separators = getSeparators(locale)
127
+ const decimalSeparator = separators.decimal === ',' ? ',' : '.'
128
+ const currencyPosition = unit.prefixCode ? 'start' : 'end'
129
+ return {
130
+ value: formattedValue,
131
+ sign,
132
+ code: showCode ? code : null,
133
+ decimalSeparator,
134
+ currencyPosition,
135
+ }
136
+ }
137
+
138
+ export const formatCurrencyUnitFragment = (
139
+ unit: Unit,
140
+ value: BigNumber,
141
+ options?: formatCurrencyUnitOptions
142
+ ): FormatterValue => {
143
+ const {
144
+ value: formattedValue,
145
+ sign,
146
+ code,
147
+ decimalSeparator,
148
+ currencyPosition,
149
+ } = buildFormatState(unit, value, options)
150
+ const hasDecimals = formattedValue.indexOf(decimalSeparator) !== -1
151
+ const [integerPartRaw, decimalPartRaw] = hasDecimals
152
+ ? formattedValue.split(decimalSeparator)
153
+ : [formattedValue, '']
154
+
155
+ let integerPart = integerPartRaw
156
+ const decimalPart = decimalPartRaw || ''
157
+ let currencyText = code || ''
158
+
159
+ if (sign) {
160
+ if (currencyPosition === 'start' && currencyText) {
161
+ currencyText = `${sign}${currencyText}`
162
+ } else {
163
+ integerPart = `${sign}${integerPart}`
164
+ }
165
+ }
166
+
167
+ return {
168
+ integerPart,
169
+ decimalPart,
170
+ decimalSeparator,
171
+ currencyText,
172
+ currencyPosition,
173
+ }
174
+ }
175
+
176
+ export const formatCurrencyUnit = (
177
+ unit: Unit,
178
+ value: BigNumber,
179
+ options?: formatCurrencyUnitOptions
180
+ ): string => {
181
+ const joinFragmentsSeparator =
182
+ (options && options.joinFragmentsSeparator) || defaultFormatOptions.joinFragmentsSeparator
183
+ const { value: formattedValue, sign, code } = buildFormatState(unit, value, options)
184
+ const parts: string[] = []
185
+
186
+ if (unit.prefixCode) {
187
+ if (sign) parts.push(sign)
188
+ if (code) parts.push(code)
189
+ parts.push(formattedValue)
190
+ } else {
191
+ if (sign) parts.push(sign)
192
+ parts.push(formattedValue)
193
+ if (code) {
194
+ parts.push(nonBreakableSpace)
195
+ parts.push(code)
196
+ }
197
+ }
198
+
199
+ return parts.join(joinFragmentsSeparator)
200
+ }
@@ -0,0 +1,22 @@
1
+ // Forked from @ledgerhq/live-currency-format/src/localeUtility.test.ts
2
+ import { getSeparators } from './localeUtility'
3
+
4
+ describe('localeUtility', () => {
5
+ test('getSeparators with known locale in staticFallback', () => {
6
+ const result = getSeparators('en')
7
+ expect(result.decimal).toBe('.')
8
+ expect(result.thousands).toBe(',')
9
+ })
10
+
11
+ test('getSeparators with locale not in staticFallback', () => {
12
+ const result = getSeparators('it')
13
+ expect(result.decimal).toBeDefined()
14
+ expect(result.thousands).toBeDefined()
15
+ })
16
+
17
+ test('getFallback uses en when locale not in staticFallback', () => {
18
+ const result = getSeparators('de')
19
+ expect(result.decimal).toBeDefined()
20
+ expect(result.thousands).toBeDefined()
21
+ })
22
+ })
@@ -0,0 +1,59 @@
1
+ // Forked from @ledgerhq/live-currency-format/src/localeUtility.ts
2
+ const memoize = <T extends (arg: string) => ReturnType<T>>(fn: T): T => {
3
+ const cache: Record<string, ReturnType<T>> = {}
4
+ return ((arg: string) => {
5
+ if (!(arg in cache)) {
6
+ cache[arg] = fn(arg)
7
+ }
8
+ return cache[arg]
9
+ }) as T
10
+ }
11
+
12
+ const options = {
13
+ style: 'currency' as const,
14
+ currency: 'USD',
15
+ }
16
+ const localeNotAvailable = (1.2).toLocaleString('en', options) !== '$1.20'
17
+
18
+ const getFallback = (locale: string) =>
19
+ staticFallback[Object.prototype.hasOwnProperty.call(staticFallback, locale) ? locale : 'en']
20
+
21
+ const staticFallback: Record<string, string[]> = {
22
+ en: ['-$1.00', '10,000.2'],
23
+ es: ['-1,00 US$', '10.000,2'],
24
+ fr: ['-1,00 $US', '10 000,2'],
25
+ ja: ['-US$1.00', '10,000.2'],
26
+ ko: ['-US$1.00', '10,000.2'],
27
+ ru: ['-1,00 $', '10 000,2'],
28
+ zh: ['-US$1.00', '10,000.2'],
29
+ }
30
+
31
+ export const prefixFormat = ['sign', 'code', 'value'] as const
32
+ export const suffixFormat = ['sign', 'value', 'separator', 'code'] as const
33
+
34
+ export type GetSeparators = (locale: string) => {
35
+ decimal: string | null | undefined
36
+ thousands: string | null | undefined
37
+ }
38
+
39
+ export const getSeparators: GetSeparators = memoize((locale) => {
40
+ const res = localeNotAvailable ? getFallback(locale)[1] : (10000.2).toLocaleString(locale)
41
+ let decimal
42
+ let thousands
43
+
44
+ for (let i = 0; i < res.length; i++) {
45
+ const c = res[i]
46
+ if (/[0-9]/.test(c)) continue
47
+
48
+ if (!thousands) {
49
+ thousands = c
50
+ } else {
51
+ decimal = c
52
+ }
53
+ }
54
+
55
+ return {
56
+ decimal,
57
+ thousands,
58
+ }
59
+ })
@@ -0,0 +1,26 @@
1
+ // Forked from @ledgerhq/live-currency-format/src/parseCurrencyUnit.test.ts
2
+ import { BigNumber } from 'bignumber.js'
3
+ import type { Unit } from '../api/types'
4
+ import { parseCurrencyUnit } from './parseCurrencyUnit'
5
+
6
+ const unit: Unit = {
7
+ name: 'Test Unit',
8
+ code: 'TST',
9
+ magnitude: 2,
10
+ showAllDigits: false,
11
+ prefixCode: false,
12
+ }
13
+
14
+ describe('parseCurrencyUnit', () => {
15
+ test('parses dot decimals', () => {
16
+ expect(parseCurrencyUnit(unit, '1.23')).toEqual(new BigNumber(123))
17
+ })
18
+
19
+ test('parses comma decimals', () => {
20
+ expect(parseCurrencyUnit(unit, '1,23')).toEqual(new BigNumber(123))
21
+ })
22
+
23
+ test('returns zero on invalid input', () => {
24
+ expect(parseCurrencyUnit(unit, 'invalid')).toEqual(new BigNumber(0))
25
+ })
26
+ })
@@ -1 +1,10 @@
1
- export { parseCurrencyUnit } from '@ledgerhq/live-currency-format'
1
+ // Forked from @ledgerhq/live-currency-format/src/parseCurrencyUnit.ts
2
+ import type { Unit } from '../api/types'
3
+ import { BigNumber } from 'bignumber.js'
4
+
5
+ export const parseCurrencyUnit = (unit: Unit, valueString: string): BigNumber => {
6
+ const str = valueString.replace(/,/g, '.')
7
+ const value = new BigNumber(str)
8
+ if (value.isNaN()) return new BigNumber(0)
9
+ return value.times(new BigNumber(10).pow(unit.magnitude)).integerValue()
10
+ }