dev
dart 80 lines 2.47 KB
Raw
1 /// Parses the string [value] as a fixed-point decimal literal and returns its
2 /// [BigInt] value.
3 ///
4 /// The number of fractional digits is determined by [decimals].
5 ///
6 /// Returns `null` if the input [value] is not a valid fixed-point literal
7 /// (e.g., non-numeric characters, too many fractional digits).
8 ///
9 /// Like [parseFixed], except that this function returns `null` for invalid inputs
10 /// instead of throwing.
11 BigInt? tryParseFixed(String value, int decimals) {
12 try {
13 return parseFixed(value, decimals);
14 } on FormatException catch (_) {
15 return null;
16 }
17 }
18
19 /// Parses the string [value] as a fixed-point decimal literal and returns its
20 /// [BigInt] value.
21 ///
22 /// The number of fractional digits is determined by [decimals].
23 ///
24 /// Throws a [FormatException] if the input [value] is not a valid fixed-point literal
25 /// (e.g., non-numeric characters, too many fractional digits).
26 ///
27 /// Rather than throwing and immediately catching the [FormatException],
28 /// instead use [tryParseFixed] to handle a potential parsing error.
29 BigInt parseFixed(String value, int decimals) {
30 final multiplier = getMultiplier(decimals);
31
32 /// handle weird cases where users enter spaces and currency after the amount
33 /// This should be handled from UI field to prevent non numerical values
34 /// but will be in the refactoring
35 if (value.contains(" ")) {
36 value = value.split(" ").first;
37 }
38
39 final negative = value.startsWith("-");
40 if (negative) {
41 value = value.substring(1);
42 }
43
44 if (value == ".") {
45 throw FormatException("missing value, value, $value");
46 }
47
48 if (value.startsWith(".")) {
49 value = "0$value";
50 }
51
52 final comps = value.split(".");
53 if (comps.length > 2) {
54 throw FormatException("too many decimal points, value, $value");
55 }
56
57 final whole = comps.isNotEmpty ? comps[0] : "0";
58 final fraction = (comps.length == 2 ? comps[1] : "").padRight(decimals, "0");
59
60 if (fraction.length > multiplier.length - 1) {
61 throw FormatException(
62 "fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed",
63 );
64 }
65
66 final wholeValue = BigInt.parse(whole);
67 final fractionValue = fraction.isEmpty ? BigInt.zero : BigInt.parse(fraction);
68 final multiplierValue = BigInt.parse(multiplier);
69
70 var wei = (wholeValue * multiplierValue) + fractionValue;
71
72 if (negative) {
73 wei *= BigInt.from(-1);
74 }
75
76 return wei;
77 }
78
79 // Returns a string "1" followed by decimal "0"s
80 String getMultiplier(int decimals) => "1".padRight(decimals + 1, "0");