-
Notifications
You must be signed in to change notification settings - Fork 59
/
amount-formatter.ts
98 lines (86 loc) · 3.14 KB
/
amount-formatter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import BigNumber from 'bignumber.js';
import { isBigNumber } from './bignumber';
import { ArgumentError } from './errors';
export enum AE_AMOUNT_FORMATS {
AE = 'ae',
MILI_AE = 'miliAE',
MICRO_AE = 'microAE',
NANO_AE = 'nanoAE',
PICO_AE = 'picoAE',
FEMTO_AE = 'femtoAE',
AETTOS = 'aettos',
}
/**
* DENOMINATION_MAGNITUDE
*/
const DENOMINATION_MAGNITUDE = {
[AE_AMOUNT_FORMATS.AE]: 0,
[AE_AMOUNT_FORMATS.MILI_AE]: -3,
[AE_AMOUNT_FORMATS.MICRO_AE]: -6,
[AE_AMOUNT_FORMATS.NANO_AE]: -9,
[AE_AMOUNT_FORMATS.PICO_AE]: -12,
[AE_AMOUNT_FORMATS.FEMTO_AE]: -15,
[AE_AMOUNT_FORMATS.AETTOS]: -18,
} as const;
/**
* Convert amount from one to other denomination
* @param value - amount to convert
* @param options - options
* @param options.denomination - denomination of amount, can be ['ae', 'aettos']
* @param options.targetDenomination - target denomination,
* can be ['ae', 'aettos']
*/
export const formatAmount = (
value: string | number | bigint | BigNumber,
{ denomination = AE_AMOUNT_FORMATS.AETTOS, targetDenomination = AE_AMOUNT_FORMATS.AETTOS }:
{ denomination?: AE_AMOUNT_FORMATS; targetDenomination?: AE_AMOUNT_FORMATS },
): string => {
if (!isBigNumber(value)) throw new ArgumentError('value', 'a number', value);
return new BigNumber(typeof value === 'bigint' ? value.toString() : value)
.shiftedBy(DENOMINATION_MAGNITUDE[denomination] - DENOMINATION_MAGNITUDE[targetDenomination])
.toFixed();
};
/**
* Convert amount to AE
* @param value - amount to convert
* @param options - options
* @param options.denomination - denomination of amount, can be ['ae', 'aettos']
*/
export const toAe = (
value: string | number | BigNumber,
{ denomination = AE_AMOUNT_FORMATS.AETTOS }: { denomination?: AE_AMOUNT_FORMATS } = {},
): string => formatAmount(value, { denomination, targetDenomination: AE_AMOUNT_FORMATS.AE });
/**
* Convert amount to aettos
* @param value - amount to convert
* @param options - options
* @param options.denomination - denomination of amount, can be ['ae', 'aettos']
*/
export const toAettos = (
value: string | number | BigNumber,
{ denomination = AE_AMOUNT_FORMATS.AE }: { denomination?: AE_AMOUNT_FORMATS } = {},
): string => formatAmount(value, { denomination });
interface Prefix {
name: string;
magnitude: number;
}
const prefixes: Prefix[] = [
{ name: 'exa', magnitude: 18 },
{ name: 'giga', magnitude: 9 },
{ name: '', magnitude: 0 },
{ name: 'pico', magnitude: -12 },
];
const getNearestPrefix = (exponent: number): Prefix => prefixes.reduce((p, n) => (
Math.abs(n.magnitude - exponent) < Math.abs(p.magnitude - exponent) ? n : p));
const getLowerBoundPrefix = (exponent: number): Prefix => prefixes
.find((p) => p.magnitude <= exponent) ?? prefixes[prefixes.length - 1];
export const prefixedAmount = (rawValue: string | number | BigNumber): string => {
const value: BigNumber = new BigNumber(rawValue);
const exp = value.e ?? 0;
const { name, magnitude } = (exp < 0 ? getNearestPrefix : getLowerBoundPrefix)(exp);
const v = value
.shiftedBy(-magnitude)
.precision(9 + Math.min(exp - magnitude, 0))
.toFixed();
return `${v}${name !== '' ? ' ' : ''}${name}`;
};