diff --git a/near-java-api-common/src/main/java/com/syntifi/near/api/common/helper/Formats.java b/near-java-api-common/src/main/java/com/syntifi/near/api/common/helper/Formats.java index 77fba1b6..bb7f71d3 100644 --- a/near-java-api-common/src/main/java/com/syntifi/near/api/common/helper/Formats.java +++ b/near-java-api-common/src/main/java/com/syntifi/near/api/common/helper/Formats.java @@ -22,11 +22,22 @@ public class Formats { /** * Number of indivisible units in one NEAR. Derived from {@link #NEAR_NOMINATION_EXP}. */ - public static BigInteger NEAR_NOMINATION = new BigInteger("10", 10).pow(NEAR_NOMINATION_EXP); + public static BigInteger NEAR_NOMINATION = BigInteger.valueOf(10).pow(NEAR_NOMINATION_EXP); + + /** + * Pre-calculate offsets used for rounding to different number of digits + */ + static BigInteger[] ROUNDING_OFFSETS = new BigInteger[NEAR_NOMINATION_EXP]; + static { + BigInteger ten = BigInteger.valueOf(10); + for (BigInteger i = BigInteger.ZERO, offset = BigInteger.valueOf(5); + i.compareTo(BigInteger.valueOf(NEAR_NOMINATION_EXP)) < 0; + i = i.add(BigInteger.ONE), offset = offset.multiply(ten)) { + ROUNDING_OFFSETS[(int) i.longValue()] = offset; + } + } /** - * TODO: WIP IF NEEDED - *
* Convert account balance value from internal indivisible units to NEAR. 1 NEAR is defined by {@link #NEAR_NOMINATION}.
* Effectively this divides given amount by {@link #NEAR_NOMINATION}.
*
@@ -34,19 +45,20 @@ public class Formats {
* @param fracDigits number of fractional digits to preserve in formatted string. Balance is rounded to match given number of digits.
* @return Value in Ⓝ
*/
- public static String formatNearAmount(String balance, int fracDigits) {
- final BigInteger balanceBN = new BigInteger(balance, 10);
+ public static String formatNearAmount(String balance, Integer fracDigits) {
+ if (fracDigits == null) fracDigits = NEAR_NOMINATION_EXP;
+ BigInteger balanceBN = new BigInteger(balance, 10);
if (fracDigits != NEAR_NOMINATION_EXP) {
// Adjust balance for rounding at given number of digits
final int roundingExp = NEAR_NOMINATION_EXP - fracDigits - 1;
if (roundingExp > 0) {
- //balanceBN.iadd(ROUNDING_OFFSETS[roundingExp]);
+ balanceBN = balanceBN.add(ROUNDING_OFFSETS[roundingExp]);
}
}
balance = balanceBN.toString();
- final String wholeStr = balance != null ? balance.substring(0, balance.length() - NEAR_NOMINATION_EXP) : "0";
- final String fractionStr = balance != null ? padStart(balance.substring(balance.length() - NEAR_NOMINATION_EXP), NEAR_NOMINATION_EXP, '0').substring(0, fracDigits) : "0";
+ final String wholeStr = balance != null && balance.length() - NEAR_NOMINATION_EXP > 0 ? balance.substring(0, balance.length() - NEAR_NOMINATION_EXP) : "0";
+ final String fractionStr = balance != null ? padStart(balance.substring(Math.max(balance.length() - NEAR_NOMINATION_EXP, 0)), NEAR_NOMINATION_EXP, '0').substring(0, fracDigits) : "0";
return trimTrailingZeroes(formatWithCommas(wholeStr) + "." + fractionStr);
}
@@ -73,6 +85,14 @@ public static String parseNearAmount(String amount) {
return trimLeadingZeroes(toTrim);
}
+ /**
+ * Pads an input string from its start with a char until it reaches a max length
+ *
+ * @param input the input string
+ * @param maxLength the max length to reach
+ * @param fillChar the char to fill
+ * @return the padded string
+ */
public static String padStart(String input, int maxLength, char fillChar) {
StringBuilder sb = new StringBuilder();
sb.append(input);
@@ -82,6 +102,14 @@ public static String padStart(String input, int maxLength, char fillChar) {
return sb.toString();
}
+ /**
+ * Pads an input string from its end with a char until it reaches a max length
+ *
+ * @param input the input string
+ * @param maxLength the max length to reach
+ * @param fillChar the char to fill
+ * @return the padded string
+ */
public static String padEnd(String input, int maxLength, char fillChar) {
StringBuilder sb = new StringBuilder();
sb.append(input);
@@ -134,9 +162,10 @@ public static String trimLeadingZeroes(String value) {
public static String formatWithCommas(String value) {
final String patternString = "(-?\\d+)(\\d{3})";
Pattern pattern = Pattern.compile(patternString);
- final Matcher matcher = pattern.matcher(value);
+ Matcher matcher = pattern.matcher(value);
while (matcher.find()) {
- value = value.replaceAll(value, matcher.group(1) + "," + matcher.group(2));
+ value = value.replace(matcher.group(0), matcher.group(1) + "," + matcher.group(2));
+ matcher = pattern.matcher(value);
}
return value;
}
diff --git a/near-java-api-common/src/test/java/com/syntifi/near/api/common/helper/FormatsTest.java b/near-java-api-common/src/test/java/com/syntifi/near/api/common/helper/FormatsTest.java
index 90c16ecb..4a960824 100644
--- a/near-java-api-common/src/test/java/com/syntifi/near/api/common/helper/FormatsTest.java
+++ b/near-java-api-common/src/test/java/com/syntifi/near/api/common/helper/FormatsTest.java
@@ -7,6 +7,7 @@
import java.util.Arrays;
import java.util.List;
+import static com.syntifi.near.api.common.helper.Formats.formatNearAmount;
import static com.syntifi.near.api.common.helper.Formats.parseNearAmount;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -14,6 +15,29 @@ public class FormatsTest {
private static final Logger LOGGER = LoggerFactory.getLogger(FormatsTest.class);
+ private static final List