Skip to content

Commit

Permalink
Add BalanceStatus for insufficient wordings (trustwallet#400)
Browse files Browse the repository at this point in the history
* Add BalanceStatus for insufficient texts

* add protected logic (set gasSufficient = false)

* Remove private _L(), use switch instead of if-else

* Add BalanceStatusTests
  • Loading branch information
hewigovens authored and vikmeup committed Feb 25, 2018
1 parent 1fcc92a commit 31f94aa
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 24 deletions.
8 changes: 8 additions & 0 deletions Trust.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,8 @@
A2B7ECAA2038122200828E7D /* ExportPrivateKeyCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2B7ECA92038122200828E7D /* ExportPrivateKeyCoordinator.swift */; };
A2B7ECAC2038FFBC00828E7D /* ExportPrivateKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2B7ECAB2038FFBC00828E7D /* ExportPrivateKeyViewModel.swift */; };
A2B7ECAE2039001300828E7D /* ExportPrivateKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2B7ECAD2039001300828E7D /* ExportPrivateKeyViewController.swift */; };
BB03A86D20416AF600649DA0 /* BalanceStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB03A86C20416AF600649DA0 /* BalanceStatus.swift */; };
BB03A8712042B01300649DA0 /* BalanceStatusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB03A8702042B01300649DA0 /* BalanceStatusTests.swift */; };
BB1CC266203BA4440042E56C /* SendMaxAmountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1CC265203BA4440042E56C /* SendMaxAmountTest.swift */; };
BB1CC27A203D061B0042E56C /* TrustDocumentPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1CC279203D061B0042E56C /* TrustDocumentPickerViewController.swift */; };
BB5D6A9E20232EE8000FC5AB /* CurrencyRate+Fee.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5D6A9D20232EE8000FC5AB /* CurrencyRate+Fee.swift */; };
Expand Down Expand Up @@ -760,6 +762,8 @@
A3B747245A27436E621E7E41 /* Pods-TrustUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TrustUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-TrustUITests/Pods-TrustUITests.release.xcconfig"; sourceTree = "<group>"; };
A48A17FC2CC895AF2BB871D0 /* Pods_TrustTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TrustTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B13A87D3BA5167741E5D0801 /* Pods-Trust.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Trust.release.xcconfig"; path = "Pods/Target Support Files/Pods-Trust/Pods-Trust.release.xcconfig"; sourceTree = "<group>"; };
BB03A86C20416AF600649DA0 /* BalanceStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceStatus.swift; sourceTree = "<group>"; };
BB03A8702042B01300649DA0 /* BalanceStatusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceStatusTests.swift; sourceTree = "<group>"; };
BB1CC265203BA4440042E56C /* SendMaxAmountTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMaxAmountTest.swift; sourceTree = "<group>"; };
BB1CC279203D061B0042E56C /* TrustDocumentPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustDocumentPickerViewController.swift; sourceTree = "<group>"; };
BB5D6A9D20232EE8000FC5AB /* CurrencyRate+Fee.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CurrencyRate+Fee.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1609,6 +1613,7 @@
29FF6D6A2011D2AF00A3011C /* InCoordinatorError.swift */,
29C70C702016C7780072E454 /* SentTransaction.swift */,
BB5D6A9D20232EE8000FC5AB /* CurrencyRate+Fee.swift */,
BB03A86C20416AF600649DA0 /* BalanceStatus.swift */,
);
path = Types;
sourceTree = "<group>";
Expand Down Expand Up @@ -1652,6 +1657,7 @@
children = (
29BDF19C1FEE50E90023A45F /* GasPriceConfigurationTests.swift */,
29BDF19E1FEE51650023A45F /* GasLimitConfigurationTests.swift */,
BB03A8702042B01300649DA0 /* BalanceStatusTests.swift */,
);
path = Types;
sourceTree = "<group>";
Expand Down Expand Up @@ -2875,6 +2881,7 @@
291A1B651F974E8600ADEC80 /* WalletEntryPoint.swift in Sources */,
2959960E1FAB05C200DB66A8 /* TransactionsEmptyView.swift in Sources */,
29BB94931F6FC380009B09CC /* BalanceViewModel.swift in Sources */,
BB03A86D20416AF600649DA0 /* BalanceStatus.swift in Sources */,
775DF436203DFF2D009CD082 /* OpenseaClient.swift in Sources */,
29D03F1D1F712183006E548C /* Button.swift in Sources */,
291794FF1F95F5CE00539A30 /* Web3Request.swift in Sources */,
Expand Down Expand Up @@ -2942,6 +2949,7 @@
29F114FA1FA817A800114A29 /* RequestCoordinatorTests.swift in Sources */,
2977CAE01F7DEEB0009682A0 /* FakeEtherKeystore.swift in Sources */,
29DBF2A51F9EB75E00327C60 /* BackupCoordinatorTests.swift in Sources */,
BB03A8712042B01300649DA0 /* BalanceStatusTests.swift in Sources */,
29E14FD51F7F470C00185568 /* TransactionsStorageTests.swift in Sources */,
61C359E22002AC9D0097B04D /* TransactionSigningTests.swift in Sources */,
299B5E381FCBCDF70051361C /* RequestViewModelTests.swift in Sources */,
Expand Down
4 changes: 3 additions & 1 deletion Trust/Localization/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
"send.error.emptyClipBoard" = "Empty ClipBoard";
"send.error.invalidAddress" = "Invalid Address";
"send.error.wrongInput" = "Wrong Input";
"send.error.insufficientFund" = "Insufficient Fund";
"send.error.insufficientEther" = "Insufficient ethers";
"send.error.insufficientGas" = "Insufficient ethers for gas fee";
"send.error.insufficientToken" = "Insufficient token";
"send.max.button.title" = "Max";
"send.paste.button.title" = "Paste";
"send.recipientAddress.textField.placeholder" = "Recipient Address";
Expand Down
33 changes: 24 additions & 9 deletions Trust/Transfer/Controllers/TransactionConfigurator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,23 +187,38 @@ class TransactionConfigurator {
self.configuration = configuration
}

func isValidBalance() -> Bool {
func balanceValidStatus() -> BalanceStatus {
var etherSufficient = true
var gasSufficient = true
var tokenSufficient = true

guard let balance = session.balance else {
return true
return .ether(etherSufficient: etherSufficient, gasSufficient: gasSufficient)
}
let transaction = previewTransaction()
var totalGasValue = transaction.gasPrice * transaction.gasLimit
let totalGasValue = transaction.gasPrice * transaction.gasLimit

//We check if it is ETH or token operation.
switch transaction.transferType {
case .ether:
totalGasValue += transaction.value
return totalGasValue < balance.value
if transaction.value > balance.value {
etherSufficient = false
gasSufficient = false
} else {
if totalGasValue + transaction.value > balance.value {
gasSufficient = false
}
}
return .ether(etherSufficient: etherSufficient, gasSufficient: gasSufficient)
case .token(let token):
let tokenValue = transaction.value
let isEnoughOfEther = totalGasValue < balance.value
let isEnoughOfTokens = tokenValue < token.valueBigInt
return isEnoughOfTokens && isEnoughOfEther
if totalGasValue > balance.value {
etherSufficient = false
gasSufficient = false
}
if transaction.value > token.valueBigInt {
tokenSufficient = false
}
return .token(tokenSufficient: tokenSufficient, gasSufficient: gasSufficient)
}
}
}
74 changes: 74 additions & 0 deletions Trust/Transfer/Types/BalanceStatus.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright SIX DAY LLC. All rights reserved.

import Foundation

enum BalanceStatus {
case ether(etherSufficient: Bool, gasSufficient: Bool)
case token(tokenSufficient: Bool, gasSufficient: Bool)
}

extension BalanceStatus {

enum Key {
case insufficientEther
case insufficientGas
case insufficientToken
case correct

var string: String {
switch self {
case .insufficientEther:
return "send.error.insufficientEther"
case .insufficientGas:
return "send.error.insufficientGas"
case .insufficientToken:
return "send.error.insufficientToken"
case .correct:
return ""
}
}
}

var sufficient: Bool {
switch self {
case .ether(let etherSufficient, let gasSufficient):
return etherSufficient && gasSufficient
case .token(let tokenSufficient, let gasSufficient):
return tokenSufficient && gasSufficient
}
}

var insufficientTextKey: Key {
switch self {
case .ether(let etherSufficient, let gasSufficient):
if !etherSufficient {
return .insufficientEther
}
if !gasSufficient {
return .insufficientGas
}
case .token(let tokenSufficient, let gasSufficient):
if !tokenSufficient {
return .insufficientToken
}
if !gasSufficient {
return .insufficientGas
}
}
return .correct
}

var insufficientText: String {
let key = insufficientTextKey
switch key {
case .insufficientEther:
return NSLocalizedString(key.string, value: "Insufficient ethers", comment: "")
case .insufficientGas:
return NSLocalizedString(key.string, value: "Insufficient ethers for gas fee", comment: "")
case .insufficientToken:
return NSLocalizedString(key.string, value: "Insufficient tokens", comment: "")
case .correct:
return ""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ class ConfirmPaymentViewController: UIViewController {
}

private func updateSubmitButton() {
submitButton.isEnabled = configurator.isValidBalance()
let text = configurator.isValidBalance() ? viewModel.actionButtonText : viewModel.insufficientFundText
let status = configurator.balanceValidStatus()
submitButton.isEnabled = status.sufficient
let text = status.sufficient ? viewModel.actionButtonText : status.insufficientText
submitButton.setTitle(text, for: .normal)
}

Expand Down
4 changes: 0 additions & 4 deletions Trust/Transfer/ViewModels/ConfirmPaymentViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ struct ConfirmPaymentViewModel {
}
}

var insufficientFundText: String {
return NSLocalizedString("send.error.insufficientFund", value: "Insufficient Fund", comment: "")
}

var backgroundColor: UIColor {
return .white
}
Expand Down
45 changes: 37 additions & 8 deletions TrustTests/Transfer/Controllers/TransactionConfiguratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,51 @@ class TransactionConfiguratorTests: XCTestCase {

func testBalanceValidationWithNoBalance() {
let emptyBalance = TransactionConfigurator(session: .make(), account: .make(), transaction: .make(gasLimit: BigInt(90000), gasPrice: .none))
XCTAssertEqual(true, emptyBalance.isValidBalance())
let status = emptyBalance.balanceValidStatus()
XCTAssertEqual(true, status.sufficient)
XCTAssertEqual(.correct, status.insufficientTextKey)
}

func testBalanceValidationWithETHTransaction() {
func testBalanceValidationWithEthTransaction() {
let ethBalance = TransactionConfigurator(session: .makeWithEthBalance(amount: "10000000000000000000"), account: .make(), transaction: .make(gasLimit: BigInt(90000), gasPrice: .none))
XCTAssertEqual(true, ethBalance.isValidBalance())
let status = ethBalance.balanceValidStatus()
XCTAssertEqual(true, status.sufficient)
XCTAssertEqual(.correct, status.insufficientTextKey)
}

func testBalanceValidationWithInsufficientEthTransaction() {
let ethBalance = TransactionConfigurator(session: .makeWithEthBalance(amount: "900000"), account: .make(), transaction: .make(value: BigInt(1000000), gasLimit: BigInt(90000), gasPrice: .none))
let status = ethBalance.balanceValidStatus()
XCTAssertEqual(false, status.sufficient)
XCTAssertEqual(.insufficientEther, status.insufficientTextKey)
}

func testBalanceValidationWithInsufficientGasTransaction() {
let ethBalance = TransactionConfigurator(session: .makeWithEthBalance(amount: "100000000000000"), account: .make(), transaction: .make(gasLimit: BigInt(100000000000000), gasPrice: BigInt(21000000000)))
let status = ethBalance.balanceValidStatus()
XCTAssertEqual(false, status.sufficient)
XCTAssertEqual(.insufficientGas, status.insufficientTextKey)
}

func testBalanceValidationWithTokensTransaction() {
let ethBalanceForTokens = TransactionConfigurator(session: .makeWithEthBalance(amount: "10000000000000000000"), account: .make(), transaction: .makeToken(gasLimit: BigInt(90000), gasPrice: .none))
XCTAssertEqual(true, ethBalanceForTokens.isValidBalance())
let ethBalanceForTokens = TransactionConfigurator(session: .makeWithEthBalance(amount: "10000000000000000000"), account: .make(), transaction: .makeToken(gasLimit: BigInt(90000), gasPrice: BigInt(21000000000)))
let status = ethBalanceForTokens.balanceValidStatus()
XCTAssertEqual(true, status.sufficient)
XCTAssertEqual(.correct, status.insufficientTextKey)
}

func testBalanceValidationForNotEnoughtTokensTransaction() {
let ethBalanceForTokensNotEnought = TransactionConfigurator(session: .makeWithEthBalance(amount: "1000000"), account: .make(), transaction: .makeNotEnoughtToken(gasLimit: BigInt(90000), gasPrice: .none))
XCTAssertEqual(false, ethBalanceForTokensNotEnought.isValidBalance())
func testBalanceValidationWithInsufficientTokensTransaction() {
let ethBalanceForTokensNotEnough = TransactionConfigurator(session: .makeWithEthBalance(amount: "1000000"), account: .make(), transaction: .makeNotEnoughtToken(gasLimit: BigInt(90000), gasPrice: .none))
let status = ethBalanceForTokensNotEnough.balanceValidStatus()
XCTAssertEqual(false, status.sufficient)
XCTAssertEqual(.insufficientToken, status.insufficientTextKey)
}

func testBalanceValidationForTokensWithInsufficientGasTransaction() {
let emptyBalance = TransactionConfigurator(session: .makeWithEthBalance(amount: "1"), account: .make(), transaction: .makeToken(gasLimit: BigInt(90000), gasPrice: BigInt(21000000000)))
let status = emptyBalance.balanceValidStatus()
XCTAssertEqual(false, status.sufficient)
XCTAssertEqual(.insufficientGas, status.insufficientTextKey)
}

func testValueToSent() {
Expand Down
51 changes: 51 additions & 0 deletions TrustTests/Transfer/Types/BalanceStatusTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright SIX DAY LLC. All rights reserved.

import XCTest
@testable import Trust

class BalanceStatusTests: XCTestCase {

func testSufficientEth() {
let status: BalanceStatus = .ether(etherSufficient: true, gasSufficient: true)
XCTAssertTrue(status.sufficient)
XCTAssertEqual(.correct, status.insufficientTextKey)
}

func testInsufficientGasForEth() {
let status: BalanceStatus = .ether(etherSufficient: true, gasSufficient: false)
XCTAssertFalse(status.sufficient)
XCTAssertEqual(.insufficientGas, status.insufficientTextKey)
}

func testInsufficientEth() {
let status: BalanceStatus = .ether(etherSufficient: false, gasSufficient: true)
XCTAssertFalse(status.sufficient)
XCTAssertEqual(.insufficientEther, status.insufficientTextKey)

let status2: BalanceStatus = .ether(etherSufficient: false, gasSufficient: false)
XCTAssertFalse(status2.sufficient)
XCTAssertEqual(.insufficientEther, status2.insufficientTextKey)
}

func testSufficientTokens() {
let status: BalanceStatus = .token(tokenSufficient: true, gasSufficient: true)
XCTAssertTrue(status.sufficient)
XCTAssertEqual(.correct, status.insufficientTextKey)
}

func testInsufficientGasForTokens() {
let status: BalanceStatus = .token(tokenSufficient: true, gasSufficient: false)
XCTAssertFalse(status.sufficient)
XCTAssertEqual(.insufficientGas, status.insufficientTextKey)
}

func testInsufficientTokens() {
let status: BalanceStatus = .token(tokenSufficient: false, gasSufficient: true)
XCTAssertFalse(status.sufficient)
XCTAssertEqual(.insufficientToken, status.insufficientTextKey)

let status2: BalanceStatus = .token(tokenSufficient: false, gasSufficient: false)
XCTAssertFalse(status2.sufficient)
XCTAssertEqual(.insufficientToken, status2.insufficientTextKey)
}
}

0 comments on commit 31f94aa

Please sign in to comment.