From 319803e5b7a4f14680adce80fcd5cc7a610c650f Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Thu, 20 Jun 2019 11:13:07 +0200 Subject: [PATCH] catching AmountError in SufficientFundsValidator, catch crash bug --- .../Validators/AmountFromText.swift | 10 +-------- .../Validators/SufficientFundsValidator.swift | 7 ++++--- .../OutputFormatting/AmountFormatter.swift | 10 +++++---- .../1_Main/1_Main/0_Main/MainViewModel.swift | 2 +- .../PrepareTransactionViewModel.swift | 21 ++++++++++++------- .../B_Receive/Receive/ReceiveViewModel.swift | 17 --------------- 6 files changed, 26 insertions(+), 41 deletions(-) diff --git a/Source/Application/InputValidators/Validators/AmountFromText.swift b/Source/Application/InputValidators/Validators/AmountFromText.swift index 288f51f0..ecc1eed2 100644 --- a/Source/Application/InputValidators/Validators/AmountFromText.swift +++ b/Source/Application/InputValidators/Validators/AmountFromText.swift @@ -44,6 +44,7 @@ extension AmountFromText { extension AmountFromText { + // swiftlint:disable:next function_body_length init(string amountString: String, unit: Zesame.Unit) throws { let correctSeparator = Locale.current.decimalSeparatorForSure let wrongSeparator = correctSeparator == "." ? "," : "." @@ -70,13 +71,4 @@ extension AmountFromText { } } } - - var display: String { - switch self { - case .amount(let amount, let unit): - return AmountFormatter().format(amount: amount, in: unit) - case .string(let string): - return string - } - } } diff --git a/Source/Application/InputValidators/Validators/SufficientFundsValidator.swift b/Source/Application/InputValidators/Validators/SufficientFundsValidator.swift index 3d2d754f..76172f85 100644 --- a/Source/Application/InputValidators/Validators/SufficientFundsValidator.swift +++ b/Source/Application/InputValidators/Validators/SufficientFundsValidator.swift @@ -46,9 +46,10 @@ struct SufficientFundsValidator: InputValidator { return self.error(Error.insufficientFunds) } } catch let error as AmountError { - return .invalid(.error(.amountError(error))) - } catch { - incorrectImplementation("AmountError should cover all errors") + return self.error(Error.amountError(error)) + } catch let otherError { + let zilAmountError: AmountError = .init(error: otherError) + return self.error(Error.amountError(zilAmountError)) } return .valid(amount) diff --git a/Source/Application/OutputFormatting/AmountFormatter.swift b/Source/Application/OutputFormatting/AmountFormatter.swift index be4cbde3..671be2f6 100644 --- a/Source/Application/OutputFormatting/AmountFormatter.swift +++ b/Source/Application/OutputFormatting/AmountFormatter.swift @@ -37,8 +37,8 @@ extension Zesame.Unit { } struct AmountFormatter { - func format(amount: Amount, in unit: Zesame.Unit, minFractionDigits: Int? = nil, showUnit: Bool = false) -> String where Amount: ExpressibleByAmount { - let amountString = amount.formatted(unit: unit, minFractionDigits: minFractionDigits) + func format(amount: Amount, in unit: Zesame.Unit, formatThousands: Bool, minFractionDigits: Int? = nil, showUnit: Bool = false) -> String where Amount: ExpressibleByAmount { + let amountString = amount.formatted(unit: unit, formatThousands: formatThousands, minFractionDigits: minFractionDigits) guard showUnit else { return amountString } @@ -51,9 +51,11 @@ struct AmountFormatter { } extension ExpressibleByAmount { - func formatted(unit targetUnit: Zesame.Unit, minFractionDigits: Int? = nil) -> String { + func formatted(unit targetUnit: Zesame.Unit, formatThousands: Bool = false, minFractionDigits: Int? = nil) -> String { let string = asString(in: targetUnit, roundingIfNeeded: .down, roundingNumberOfDigits: AmountFormatter.maxNumberOfDecimalDigits, minFractionDigits: minFractionDigits) - + guard formatThousands else { + return string + } let decimalSeparator = Locale.current.decimalSeparatorForSure let components = string.components(separatedBy: decimalSeparator) if components.count == 2 { diff --git a/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift b/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift index c8429b6a..373c53bc 100644 --- a/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/0_Main/MainViewModel.swift @@ -106,7 +106,7 @@ final class MainViewModel: BaseViewModel< return Output( isFetchingBalance: activityIndicator.asDriver(), - balance: latestBalanceOrZero.map { formatter.format(amount: $0, in: .zil) }, + balance: latestBalanceOrZero.map { formatter.format(amount: $0, in: .zil, formatThousands: true) }, refreshControlLastUpdatedTitle: refreshControlLastUpdatedTitle ) } diff --git a/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift b/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift index 51604f6f..2e10442b 100644 --- a/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/A_Send/1_PrepareTransaction/0_PrepareTransaction/PrepareTransactionViewModel.swift @@ -81,7 +81,7 @@ final class PrepareTransactionViewModel: BaseViewModel< let nonce = latestBalanceAndNonce.map { $0.nonce }.startWith(0) let _startingBalance: ZilAmount = transactionUseCase.cachedBalance ?? 0 - let balance: Driver = latestBalanceAndNonce.map { $0.balance }.startWith(_startingBalance) + let balance: Driver = latestBalanceAndNonce.map { $0.balance }.startWith(_startingBalance) // MARK: - VALIDATION -> VALUE let validator = InputValidator() @@ -196,21 +196,28 @@ final class PrepareTransactionViewModel: BaseViewModel< // MARK: FORMATTING let formatter = AmountFormatter() - let balanceFormatted = balance.map { formatter.format(amount: $0, in: .zil, showUnit: true) } + let balanceFormatted = balance.map { formatter.format(amount: $0, in: .zil, formatThousands: true, showUnit: true) } // It is deliberate that we do NOT auto checksum the address here. We would like to be able to inform the user that // she might have pasted an unchecksummed address. let recipientFormatted = recipient.filterNil().map { $0.asString } let amountFormatted: Driver = amountBoundByBalance.filterNil() - .map { formatter.format(amount: $0, in: .zil) } - .ifEmpty(switchTo: amountWithoutSufficientFundsCheckValidationValue.map { $0.value?.display }) + .map { formatter.format(amount: $0, in: .zil, formatThousands: false) } + .ifEmpty(switchTo: amountWithoutSufficientFundsCheckValidationValue.map { + guard let value = $0.value else { return nil } + switch value { + case .string(let string): return string + case .amount(let amount, _): + return formatter.format(amount: amount, in: .zil, formatThousands: false) + } + }) let isSendButtonEnabled = payment.map { $0 != nil } - let gasPricePlaceholder = Driver.just(GasPrice.min).map { €.Field.gasPrice(formatter.format(amount: $0, in: .li, showUnit: true)) } + let gasPricePlaceholder = Driver.just(GasPrice.min).map { €.Field.gasPrice(formatter.format(amount: $0, in: .li, formatThousands: true, showUnit: true)) } - let gasPriceFormatted = gasPrice.filterNil().map { formatter.format(amount: $0, in: .li) } + let gasPriceFormatted = gasPrice.filterNil().map { formatter.format(amount: $0, in: .li, formatThousands: true) } let balanceWasUpdatedAt = fetchTrigger.map { [unowned self] in self.transactionUseCase.balanceUpdatedAt @@ -251,7 +258,7 @@ final class PrepareTransactionViewModel: BaseViewModel< return Observable.just(gasPrice) .map { try Payment.estimatedTotalTransactionFee(gasPrice: $0) } .asDriverOnErrorReturnEmpty() - .map { formatter.format(amount: $0, in: .zil, showUnit: true) } + .map { formatter.format(amount: $0, in: .zil, formatThousands: true, showUnit: true) } .map { €.Label.costOfTransactionInZil($0) } } ) diff --git a/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift b/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift index 5220c747..679087ef 100644 --- a/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift +++ b/Source/Scenes/1_Main/1_Main/B_Receive/Receive/ReceiveViewModel.swift @@ -99,25 +99,9 @@ final class ReceiveViewModel: BaseViewModel< .drive() ] -// let amountFormatted: Driver = amountValidationValue.map { $0.value?.display } -// /* ugly fix to fix bug where if you've entered an incorrect decimal separator then the text -// never is formatted using the thousands formatting again. -// */ -// .ifNil(switchTo: -// input.fromView.amountToReceive.map { -// if let zilAmount = try? ZilAmount(trimming: $0) { -// let formattedFallback = AmountFormatter().format(amount: zilAmount, in: .zil) -// return formattedFallback -// } else { -// return $0 -// } -// } -// ) - return Output( receivingAddress: receivingAddress, amountPlaceholder: Driver.just(€.Field.requestAmount(Unit.zil.name)), -// amount: amountFormatted, amountValidation: amountValidation, qrImage: qrImage ) @@ -137,7 +121,6 @@ extension ReceiveViewModel { struct Output { let receivingAddress: Driver let amountPlaceholder: Driver -// let amount: Driver let amountValidation: Driver let qrImage: Driver }