Skip to content

Commit 2520268

Browse files
authored
Merge pull request #107 from BANKEX/develop
improve formatter for edge cases of 1e-18 balances
2 parents 3d06c15 + 3dd774d commit 2520268

File tree

2 files changed

+67
-8
lines changed

2 files changed

+67
-8
lines changed

web3swift/Web3/Classes/Web3+Utils.swift

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ extension Web3.Utils {
142142
return mainPart
143143
}
144144

145-
public static func formatToEthereumUnits(_ bigNumber: BigInt, toUnits: Web3.Utils.Units = .eth, decimals: Int = 4) -> String? {
145+
public static func formatToEthereumUnits(_ bigNumber: BigInt, toUnits: Web3.Utils.Units = .eth, decimals: Int = 4, decimalSeparator: String = ".") -> String? {
146146
let magnitude = bigNumber.magnitude
147-
guard let formatted = formatToEthereumUnits(magnitude, toUnits: toUnits, decimals: decimals) else {return nil}
147+
guard let formatted = formatToEthereumUnits(magnitude, toUnits: toUnits, decimals: decimals, decimalSeparator: decimalSeparator) else {return nil}
148148
switch bigNumber.sign {
149149
case .plus:
150150
return formatted
@@ -153,19 +153,48 @@ extension Web3.Utils {
153153
}
154154
}
155155

156-
public static func formatToEthereumUnits(_ bigNumber: BigUInt, toUnits: Web3.Utils.Units = .eth, decimals: Int = 4) -> String? {
157-
let unitDecimals = toUnits.decimals
158-
var toDecimals = decimals
156+
public static func formatToPrecision(_ bigNumber: BigInt, numberDecimals: Int = 18, formattingDecimals: Int = 4, decimalSeparator: String = ".") -> String? {
157+
let magnitude = bigNumber.magnitude
158+
guard let formatted = formatToPrecision(magnitude, numberDecimals: numberDecimals, formattingDecimals: formattingDecimals, decimalSeparator: decimalSeparator) else {return nil}
159+
switch bigNumber.sign {
160+
case .plus:
161+
return formatted
162+
case .minus:
163+
return "-" + formatted
164+
}
165+
}
166+
167+
public static func formatToEthereumUnits(_ bigNumber: BigUInt, toUnits: Web3.Utils.Units = .eth, decimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? {
168+
return formatToPrecision(bigNumber, numberDecimals: toUnits.decimals, formattingDecimals: decimals, decimalSeparator: decimalSeparator, fallbackToScientific: fallbackToScientific);
169+
}
170+
171+
public static func formatToPrecision(_ bigNumber: BigUInt, numberDecimals: Int = 18, formattingDecimals: Int = 4, decimalSeparator: String = ".", fallbackToScientific: Bool = false) -> String? {
172+
let unitDecimals = numberDecimals
173+
var toDecimals = formattingDecimals
159174
if unitDecimals < toDecimals {
160175
toDecimals = unitDecimals
161176
}
162177
let divisor = BigUInt(10).power(unitDecimals)
163178
let (quotient, remainder) = bigNumber.quotientAndRemainder(dividingBy: divisor)
164-
let remainderPadded = String(remainder).leftPadding(toLength: unitDecimals, withPad: "0")[0..<toDecimals]
165-
if (decimals == 0) {
179+
let fullRemainder = String(remainder);
180+
let fullPaddedRemainder = fullRemainder.leftPadding(toLength: unitDecimals, withPad: "0")
181+
let remainderPadded = fullPaddedRemainder[0..<toDecimals]
182+
if remainderPadded == String(repeating: "0", count: toDecimals) && quotient == 0 {
183+
var firstDigit = 0
184+
for char in fullPaddedRemainder {
185+
if (char == "0") {
186+
firstDigit = firstDigit + 1;
187+
} else {
188+
firstDigit = firstDigit + 1;
189+
break
190+
}
191+
}
192+
return fullRemainder + "e-" + String(firstDigit)
193+
}
194+
if (toDecimals == 0) {
166195
return String(quotient)
167196
}
168-
return String(quotient) + "." + remainderPadded
197+
return String(quotient) + decimalSeparator + remainderPadded
169198
}
170199

171200
static public func personalECRecover(_ personalMessage: String, signature: String) -> EthereumAddress? {

web3swiftTests/web3swiftTests.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,36 @@ class web3swiftTests: XCTestCase {
22372237
XCTAssert(decoded!["_to"] as? EthereumAddress == EthereumAddress("0xcdd45864e794fe5e3e1b0045b77e62f4c43b8bd9"))
22382238
}
22392239

2240+
func testNumberFormattingUtil() {
2241+
let balance = BigInt("-1000000000000000000")!
2242+
let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",")
2243+
XCTAssert(formatted == "-1,0000")
2244+
}
2245+
2246+
func testNumberFormattingUtil2() {
2247+
let balance = BigInt("-1000000000000000")!
2248+
let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",")
2249+
XCTAssert(formatted == "-0,0010")
2250+
}
2251+
2252+
func testNumberFormattingUtil3() {
2253+
let balance = BigInt("-1000000000000")!
2254+
let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 4, decimalSeparator: ",")
2255+
XCTAssert(formatted == "-0,0000")
2256+
}
2257+
2258+
func testNumberFormattingUtil4() {
2259+
let balance = BigInt("-1000000000000")!
2260+
let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",")
2261+
XCTAssert(formatted == "-0,000001000")
2262+
}
2263+
2264+
func testNumberFormattingUtil5() {
2265+
let balance = BigInt("-1")!
2266+
let formatted = Web3.Utils.formatToPrecision(balance, numberDecimals: 18, formattingDecimals: 9, decimalSeparator: ",")
2267+
XCTAssert(formatted == "-1e-18")
2268+
}
2269+
22402270
func testPerformanceExample() {
22412271
// This is an example of a performance test case.
22422272
self.measure {

0 commit comments

Comments
 (0)