diff --git a/RadixWallet/EngineKit/RETDecimal+Extensions.swift b/RadixWallet/EngineKit/RETDecimal+Extensions.swift index 6da7dd74f8..f759690235 100644 --- a/RadixWallet/EngineKit/RETDecimal+Extensions.swift +++ b/RadixWallet/EngineKit/RETDecimal+Extensions.swift @@ -246,7 +246,23 @@ extension RETDecimal { let integerCount = UInt(Swift.max(digits.count - RETDecimal.scale, 1)) if integerCount > totalPlaces { let scale = RETDecimal(exponent: integerCount - totalPlaces) - return (self / scale).rounded(decimalPlaces: 0) * scale + let base = self / scale + let decimalPlaces: UInt = 0 + let base_rounded = base.rounded(decimalPlaces: decimalPlaces) + + do { + return try base_rounded.mul(other: scale) + } catch { + // we overflowed which will happen if we are using RETDecimal.max() + // instead of using `base.rounded(decimalPlaces: 0)` which uses + // rounding mode `toNearestMidpointAwayFromZero` we will use + // `toZero` to avoid overflow. + let safeBase = try! base.round( + decimalPlaces: Int32(decimalPlaces), + roundingMode: .toZero + ) + return safeBase * scale + } } else { // The remaining digits are decimals and we keep up to totalPlaces of them let decimalsToKeep = totalPlaces - integerCount diff --git a/RadixWalletTests/EngineKitTests/DecimalTests.swift b/RadixWalletTests/EngineKitTests/DecimalTests.swift index 310d0575d9..5a12380875 100644 --- a/RadixWalletTests/EngineKitTests/DecimalTests.swift +++ b/RadixWalletTests/EngineKitTests/DecimalTests.swift @@ -274,15 +274,17 @@ final class DecimalTests: TestCase { } func test_format_decimal() throws { - func doTest(_ decimalString: String, expected: String, line: UInt = #line) throws { + func doTest(_ decimal: RETDecimal, expected: String, line: UInt = #line) throws { let locale = Locale(identifier: "en_US_POSIX") - let decimal = try RETDecimal(value: decimalString) let actual = decimal.formatted(locale: locale, totalPlaces: 8, useGroupingSeparator: false) XCTAssertEqual(actual, expected, line: line) } + func doTest(_ decimalString: String, expected: String, line: UInt = #line) throws { + try doTest(RETDecimal(value: decimalString), expected: expected, line: line) + } + try doTest(RETDecimal.max(), expected: "3.138e39") try doTest("0.009999999999999", expected: "0.01") - try doTest("12341234", expected: "12.341234 M") try doTest("1234123.4", expected: "1.2341234 M") try doTest("123456.34", expected: "123456.34")