diff --git a/Trust.xcodeproj/project.pbxproj b/Trust.xcodeproj/project.pbxproj index 645dd589c3..36b3cc67ba 100644 --- a/Trust.xcodeproj/project.pbxproj +++ b/Trust.xcodeproj/project.pbxproj @@ -250,6 +250,8 @@ 61FC5ECF1FCFBAE500CCB12A /* EtherNumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FC5ECE1FCFBAE500CCB12A /* EtherNumberFormatter.swift */; }; 61FC5ED11FCFBDEB00CCB12A /* EtherNumberFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FC5ED01FCFBDEB00CCB12A /* EtherNumberFormatterTests.swift */; }; 664D11A12007D59F0041A0B0 /* EstimateGasRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664D11A02007D59F0041A0B0 /* EstimateGasRequest.swift */; }; + 71684E5521105E4200D8FD4B /* AuthenticateEnterPasscodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71684E5421105E4200D8FD4B /* AuthenticateEnterPasscodeViewModel.swift */; }; + 71684E5721105F3E00D8FD4B /* EnterPasscodeViewModelInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71684E5621105F3E00D8FD4B /* EnterPasscodeViewModelInterface.swift */; }; 71A433702113860900985ADC /* ConfirmPaymentDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A4336F2113860900985ADC /* ConfirmPaymentDetailsViewModelTests.swift */; }; 7301BA9220A3117000E1AFE5 /* AutoLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7301BA9120A3117000E1AFE5 /* AutoLock.swift */; }; 7301BA9620AB1E5600E1AFE5 /* CookiesStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7301BA9520AB1E5600E1AFE5 /* CookiesStore.swift */; }; @@ -746,6 +748,8 @@ 61FC5ED01FCFBDEB00CCB12A /* EtherNumberFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EtherNumberFormatterTests.swift; sourceTree = ""; }; 646C8C822C986358D7388602 /* Pods_Trust.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Trust.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 664D11A02007D59F0041A0B0 /* EstimateGasRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EstimateGasRequest.swift; sourceTree = ""; }; + 71684E5421105E4200D8FD4B /* AuthenticateEnterPasscodeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticateEnterPasscodeViewModel.swift; sourceTree = ""; }; + 71684E5621105F3E00D8FD4B /* EnterPasscodeViewModelInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterPasscodeViewModelInterface.swift; sourceTree = ""; }; 71A4336F2113860900985ADC /* ConfirmPaymentDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmPaymentDetailsViewModelTests.swift; sourceTree = ""; }; 7301BA9120A3117000E1AFE5 /* AutoLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoLock.swift; sourceTree = ""; }; 7301BA9520AB1E5600E1AFE5 /* CookiesStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookiesStore.swift; sourceTree = ""; }; @@ -2102,8 +2106,8 @@ 73ACEEF720163B4E003DD71D /* Coordinators */ = { isa = PBXGroup; children = ( - 73ACEF0420163F46003DD71D /* LockEnterPasscodeCoordinator.swift */, 73C41C74201B65AD00243C6C /* LockCreatePasscodeCoordinator.swift */, + 73ACEF0420163F46003DD71D /* LockEnterPasscodeCoordinator.swift */, 772C6DBA210A842200FCE4F1 /* AuthenticateUserCoordinator.swift */, ); path = Coordinators; @@ -2123,8 +2127,10 @@ isa = PBXGroup; children = ( 73ACEF0020163ED4003DD71D /* LockViewModel.swift */, - 73C41C70201B46AD00243C6C /* LockEnterPasscodeViewModel.swift */, 73C41C72201B5EFF00243C6C /* LockCreatePasscodeViewModel.swift */, + 73C41C70201B46AD00243C6C /* LockEnterPasscodeViewModel.swift */, + 71684E5421105E4200D8FD4B /* AuthenticateEnterPasscodeViewModel.swift */, + 71684E5621105F3E00D8FD4B /* EnterPasscodeViewModelInterface.swift */, ); path = ViewModels; sourceTree = ""; @@ -2922,6 +2928,7 @@ 29E14FDB1F7F4F3D00185568 /* Transaction.swift in Sources */, 7712437A20FD97730097296E /* WalletAccountViewModel.swift in Sources */, BBF4F9B72029D0B3009E04C0 /* GasViewModel.swift in Sources */, + 71684E5721105F3E00D8FD4B /* EnterPasscodeViewModelInterface.swift in Sources */, 73C41C75201B65AD00243C6C /* LockCreatePasscodeCoordinator.swift in Sources */, 7301BA9220A3117000E1AFE5 /* AutoLock.swift in Sources */, 296106C81F7646590006164B /* TokensViewModel.swift in Sources */, @@ -3017,6 +3024,7 @@ 90DDF48520518AE50016E6D4 /* BookmarkViewModel.swift in Sources */, BBB61E122050993A00428BBD /* BrowserErrorView.swift in Sources */, 29C80D4B1FB51C460037B1E0 /* Decimal.swift in Sources */, + 71684E5521105E4200D8FD4B /* AuthenticateEnterPasscodeViewModel.swift in Sources */, 297800521F71FDCF003185C1 /* FormAppearance.swift in Sources */, 77B3BF3C201908ED00EEC15A /* ConfirmCoordinator.swift in Sources */, 7704837020FFD2F700837735 /* TransactionsViewController.swift in Sources */, diff --git a/Trust/Localization/en.lproj/Localizable.strings b/Trust/Localization/en.lproj/Localizable.strings index 93999458b6..aedb100bd8 100644 --- a/Trust/Localization/en.lproj/Localizable.strings +++ b/Trust/Localization/en.lproj/Localizable.strings @@ -59,6 +59,7 @@ "settings.feedback.email.title" = "Trust Feedback"; "settings.navigation.title" = "Settings"; "settings.network.button.title" = "Network"; +"settings.lockTransactions.label.title" = "Authenticate Transactions"; "settings.openSourceDevelopment.label.title" = "Open Source Development"; "settings.privacyPolicy.button.title" = "Privacy Policy"; "settings.pushNotifications.button.title" = "Push Notifications"; @@ -142,6 +143,7 @@ "lock.enter.passcode.view.model.incorrect.passcode" = "Incorrect passcode. You have %li attempts left."; "lock.enter.passcode.view.model.initial" = "Enter your passcode."; "lock.enter.passcode.view.model.touch.id" = "Logging in with Touch ID"; +"lock.authenticate.enter.passcode.view.model.touch.id" = "Authenticating with Touch ID"; "lock.enter.passcode.view.model.try.after.one.minute" = "Try after 1 minute."; "Name" = "Name"; "send.action.copy.transaction.title" = "Copy Transaction ID"; diff --git a/Trust/Lock/Coordinators/AuthenticateUserCoordinator.swift b/Trust/Lock/Coordinators/AuthenticateUserCoordinator.swift index 39d3b7e4ff..fe5570de7a 100644 --- a/Trust/Lock/Coordinators/AuthenticateUserCoordinator.swift +++ b/Trust/Lock/Coordinators/AuthenticateUserCoordinator.swift @@ -5,8 +5,9 @@ import Foundation final class AuthenticateUserCoordinator: Coordinator { var coordinators: [Coordinator] = [] + private var waitForUnlockResult: UnlockResult? let navigationController: NavigationController - private let model: LockEnterPasscodeViewModel + private let model: AuthenticateEnterPasscodeViewModel private let lock: LockInterface private lazy var lockEnterPasscodeViewController: LockEnterPasscodeViewController = { return LockEnterPasscodeViewController(model: model) @@ -14,24 +15,29 @@ final class AuthenticateUserCoordinator: Coordinator { init( navigationController: NavigationController, - model: LockEnterPasscodeViewModel = LockEnterPasscodeViewModel(), + model: AuthenticateEnterPasscodeViewModel = AuthenticateEnterPasscodeViewModel(), lock: LockInterface = Lock() ) { self.navigationController = navigationController self.model = model self.lock = lock - lockEnterPasscodeViewController.unlockWithResult = { [weak self] (state, bioUnlock) in - if state { + lockEnterPasscodeViewController.unlockWithResult = { [weak self] (success, bioUnlock) in + self?.waitForUnlockResult?(success, bioUnlock) + if success { self?.stop() } } } - func start() { + func start(unlockResult: UnlockResult? = nil) { guard lock.shouldShowProtection() else { return } navigationController.present(lockEnterPasscodeViewController, animated: true) + + if let unlockResult = unlockResult { + lockEnterPasscodeViewController.unlockWithResult = unlockResult + } } func showAuthentication() { diff --git a/Trust/Lock/Coordinators/LockEnterPasscodeCoordinator.swift b/Trust/Lock/Coordinators/LockEnterPasscodeCoordinator.swift index e4531b3872..f1a2b91aba 100644 --- a/Trust/Lock/Coordinators/LockEnterPasscodeCoordinator.swift +++ b/Trust/Lock/Coordinators/LockEnterPasscodeCoordinator.swift @@ -14,8 +14,8 @@ final class LockEnterPasscodeCoordinator: Coordinator { self.window.windowLevel = UIWindowLevelStatusBar + 1.0 self.model = model self.lock = lock - lockEnterPasscodeViewController.unlockWithResult = { [weak self] (state, bioUnlock) in - if state { + lockEnterPasscodeViewController.unlockWithResult = { [weak self] (success, bioUnlock) in + if success { self?.stop() } } @@ -27,6 +27,7 @@ final class LockEnterPasscodeCoordinator: Coordinator { window.rootViewController = lockEnterPasscodeViewController window.makeKeyAndVisible() } + //This method should be refactored!!! func showAuthentication() { guard window.isKeyWindow, lock.isPasscodeSet() else { diff --git a/Trust/Lock/Lock.swift b/Trust/Lock/Lock.swift index 82120f68ad..7ef007d08d 100644 --- a/Trust/Lock/Lock.swift +++ b/Trust/Lock/Lock.swift @@ -7,6 +7,7 @@ import KeychainSwift protocol LockInterface { func isPasscodeSet() -> Bool func shouldShowProtection() -> Bool + func shouldAuthorizeTransactions() -> Bool } final class Lock: LockInterface { @@ -20,12 +21,17 @@ final class Lock: LockInterface { private let maxAttemptTime = "maxAttemptTime" private let autoLockType = "autoLockType" private let autoLockTime = "autoLockTime" + private let authorizeTransactions = "authorizeTransactions" private let keychain = KeychainSwift(keyPrefix: Constants.keychainKeyPrefix) func shouldShowProtection() -> Bool { return isPasscodeSet() && autoLockTriggered() } + func shouldAuthorizeTransactions() -> Bool { + return isPasscodeSet() && authorizeTransactionsValue() + } + func isPasscodeSet() -> Bool { return currentPasscode() != nil } @@ -34,6 +40,14 @@ final class Lock: LockInterface { return SAMKeychain.password(forService: Keys.service, account: Keys.account) } + func authorizeTransactionsValue() -> Bool { + if let value = keychain.getBool(authorizeTransactions) { + return value + } + setShouldAuthorizeTransactions(enabled: false) + return false + } + func isPasscodeValid(passcode: String) -> Bool { return passcode == currentPasscode() } @@ -67,6 +81,10 @@ final class Lock: LockInterface { SAMKeychain.setPassword(passcode, forService: Keys.service, account: Keys.account) } + func setShouldAuthorizeTransactions(enabled: Bool) { + keychain.set(enabled, forKey: authorizeTransactions) + } + func deletePasscode() { SAMKeychain.deletePassword(forService: Keys.service, account: Keys.account) resetPasscodeAttemptHistory() diff --git a/Trust/Lock/ViewControllers/LockEnterPasscodeViewController.swift b/Trust/Lock/ViewControllers/LockEnterPasscodeViewController.swift index 1583fe39fa..afd37e50a2 100644 --- a/Trust/Lock/ViewControllers/LockEnterPasscodeViewController.swift +++ b/Trust/Lock/ViewControllers/LockEnterPasscodeViewController.swift @@ -3,11 +3,13 @@ import UIKit import LocalAuthentication +typealias UnlockResult = ((_ success: Bool, _ bioUnlock: Bool) -> Void) + final class LockEnterPasscodeViewController: LockPasscodeViewController { - private lazy var lockEnterPasscodeViewModel: LockEnterPasscodeViewModel = { - return self.model as! LockEnterPasscodeViewModel + private lazy var lockEnterPasscodeViewModel: EnterPasscodeViewModelInterface = { + return self.model as! EnterPasscodeViewModelInterface }() - var unlockWithResult: ((_ success: Bool, _ bioUnlock: Bool) -> Void)? + var unlockWithResult: UnlockResult? private var context: LAContext! override func viewDidLoad() { super.viewDidLoad() diff --git a/Trust/Lock/ViewModels/AuthenticateEnterPasscodeViewModel.swift b/Trust/Lock/ViewModels/AuthenticateEnterPasscodeViewModel.swift new file mode 100644 index 0000000000..0d8f666394 --- /dev/null +++ b/Trust/Lock/ViewModels/AuthenticateEnterPasscodeViewModel.swift @@ -0,0 +1,9 @@ +// Copyright DApps Platform Inc. All rights reserved. + +import Foundation + +final class AuthenticateEnterPasscodeViewModel: LockViewModel, EnterPasscodeViewModelInterface { + var loginReason: String { + return R.string.localizable.lockAuthenticateEnterPasscodeViewModelTouchId() + } +} diff --git a/Trust/Lock/ViewModels/EnterPasscodeViewModelInterface.swift b/Trust/Lock/ViewModels/EnterPasscodeViewModelInterface.swift new file mode 100644 index 0000000000..68bd2a6181 --- /dev/null +++ b/Trust/Lock/ViewModels/EnterPasscodeViewModelInterface.swift @@ -0,0 +1,16 @@ +// Copyright DApps Platform Inc. All rights reserved. + +import Foundation + +protocol EnterPasscodeViewModelInterface: class { + var loginReason: String { get } +} + +extension EnterPasscodeViewModelInterface { + var initialLabelText: String { + return R.string.localizable.lockEnterPasscodeViewModelInitial() + } + var tryAfterOneMinute: String { + return R.string.localizable.lockEnterPasscodeViewModelTryAfterOneMinute() + } +} diff --git a/Trust/Lock/ViewModels/LockCreatePasscodeViewModel.swift b/Trust/Lock/ViewModels/LockCreatePasscodeViewModel.swift index 956e343062..e2a5fa7f0d 100644 --- a/Trust/Lock/ViewModels/LockCreatePasscodeViewModel.swift +++ b/Trust/Lock/ViewModels/LockCreatePasscodeViewModel.swift @@ -3,7 +3,7 @@ import UIKit final class LockCreatePasscodeViewModel: LockViewModel { - let title = NSLocalizedString("lock.create.passcode.view.model.title", value: "Set Passcode", comment: "") - let initialLabelText = NSLocalizedString("lock.create.passcode.view.model.initial", value: "Enter a new passcode", comment: "") - let confirmLabelText = NSLocalizedString("lock.create.passcode.view.model.confirm", value: "Please re-enter your passcode", comment: "") + let title = R.string.localizable.lockCreatePasscodeViewModelTitle() + let initialLabelText = R.string.localizable.lockCreatePasscodeViewModelInitial() + let confirmLabelText = R.string.localizable.lockCreatePasscodeViewModelConfirm() } diff --git a/Trust/Lock/ViewModels/LockEnterPasscodeViewModel.swift b/Trust/Lock/ViewModels/LockEnterPasscodeViewModel.swift index 6f12ceb5d5..431302a9d6 100644 --- a/Trust/Lock/ViewModels/LockEnterPasscodeViewModel.swift +++ b/Trust/Lock/ViewModels/LockEnterPasscodeViewModel.swift @@ -2,8 +2,8 @@ import UIKit -final class LockEnterPasscodeViewModel: LockViewModel { - let initialLabelText = NSLocalizedString("lock.enter.passcode.view.model.initial", value: "Enter your passcode.", comment: "") - let tryAfterOneMinute = NSLocalizedString("lock.enter.passcode.view.model.try.after.one.minute", value: "Try after 1 minute.", comment: "") - let loginReason = NSLocalizedString("lock.enter.passcode.view.model.touch.id", value: "Logging in with Touch ID", comment: "") +final class LockEnterPasscodeViewModel: LockViewModel, EnterPasscodeViewModelInterface { + var loginReason: String { + return R.string.localizable.lockEnterPasscodeViewModelTouchId() + } } diff --git a/Trust/Settings/ViewControllers/SettingsViewController.swift b/Trust/Settings/ViewControllers/SettingsViewController.swift index 3629c73452..1a611792ca 100644 --- a/Trust/Settings/ViewControllers/SettingsViewController.swift +++ b/Trust/Settings/ViewControllers/SettingsViewController.swift @@ -16,6 +16,7 @@ final class SettingsViewController: FormViewController, Coordinator { static let currencyPopularKey = "0" static let currencyAllKey = "1" static let passcodeRow = "PasscodeRow" + static let passcodeTransactionLockRow = "PasscodeTransactionLockRow" } private var config = Config() @@ -28,6 +29,10 @@ final class SettingsViewController: FormViewController, Coordinator { return lock.isPasscodeSet() } + var passcodeRow: SwitchRow? { + return form.rowBy(tag: Values.passcodeRow) as? SwitchRow + } + lazy var viewModel: SettingsViewModel = { return SettingsViewModel(isDebug: isDebug) }() @@ -44,8 +49,8 @@ final class SettingsViewController: FormViewController, Coordinator { $0.displayValueFor = { value in return value?.displayName } - $0.hidden = Condition.function([Values.passcodeRow], { form in - return !((form.rowBy(tag: Values.passcodeRow) as? SwitchRow)?.value ?? false) + $0.hidden = Condition.function([Values.passcodeRow], { [weak self] _ in + return !(self?.passcodeRow?.value ?? false) }) }.onChange { [weak self] row in let autoLockType = row.value ?? AutoLock.immediate @@ -58,6 +63,23 @@ final class SettingsViewController: FormViewController, Coordinator { } }() + lazy var passcodeTransactionLockRow: SwitchRow = { + return SwitchRow(Values.passcodeTransactionLockRow) { [weak self] in + $0.title = self?.viewModel.verifyTransactionsWithPasscodeTitle + $0.value = self?.lock.shouldAuthorizeTransactions() + $0.hidden = Condition.function([Values.passcodeRow], { [weak self] _ in + return !(self?.passcodeRow?.value ?? false) + }) + }.onChange { [unowned self] row in + if let value = row.value { + self.lock.setShouldAuthorizeTransactions(enabled: value) + row.updateCell() + } + }.cellSetup { cell, _ in + cell.imageView?.image = R.image.settings_colorful_security() + } + }() + let session: WalletSession let keystore: Keystore @@ -91,11 +113,14 @@ final class SettingsViewController: FormViewController, Coordinator { } else { self.lock.deletePasscode() self.updateAutoLockRow(with: AutoLock.immediate) + self.updatePasscodeTransactionLockRow(enabled: false) } }.cellSetup { cell, _ in cell.imageView?.image = R.image.settings_colorful_security() } + <<< passcodeTransactionLockRow + <<< autoLockRow <<< AppFormAppearance.button { [weak self] row in @@ -306,6 +331,12 @@ final class SettingsViewController: FormViewController, Coordinator { self.autoLockRow.reload() } + private func updatePasscodeTransactionLockRow(enabled: Bool) { + lock.setShouldAuthorizeTransactions(enabled: enabled) + passcodeTransactionLockRow.value = enabled + passcodeTransactionLockRow.reload() + } + func run(action: SettingsAction) { delegate?.didAction(action: action, in: self) } diff --git a/Trust/Settings/ViewModels/SettingsViewModel.swift b/Trust/Settings/ViewModels/SettingsViewModel.swift index a08ee969a6..28cbc3d44a 100644 --- a/Trust/Settings/ViewModels/SettingsViewModel.swift +++ b/Trust/Settings/ViewModels/SettingsViewModel.swift @@ -48,6 +48,10 @@ struct SettingsViewModel { } } + var verifyTransactionsWithPasscodeTitle: String { + return R.string.localizable.settingsLockTransactionsLabelTitle() + } + var networkTitle: String { return NSLocalizedString("settings.network.button.title", value: "Network", comment: "") } diff --git a/Trust/Transfer/Coordinators/ConfirmCoordinator.swift b/Trust/Transfer/Coordinators/ConfirmCoordinator.swift index 89d6771a24..572b3804cf 100644 --- a/Trust/Transfer/Coordinators/ConfirmCoordinator.swift +++ b/Trust/Transfer/Coordinators/ConfirmCoordinator.swift @@ -27,6 +27,10 @@ final class ConfirmCoordinator: RootCoordinator { return controller } + private lazy var authenticateUserCoordinator: AuthenticateUserCoordinator = { + return AuthenticateUserCoordinator(navigationController: navigationController) + }() + private lazy var controller: ConfirmPaymentViewController = { return ConfirmPaymentViewController( session: session, @@ -55,7 +59,8 @@ final class ConfirmCoordinator: RootCoordinator { self.type = type self.server = server - controller.didCompleted = { [weak self] result in + controller.delegate = self + controller.didComplete = { [weak self] result in guard let `self` = self else { return } switch result { case .success(let data): @@ -76,3 +81,19 @@ final class ConfirmCoordinator: RootCoordinator { delegate?.didCancel(in: self) } } + +extension ConfirmCoordinator: ConfirmPaymentAuthenticationDelegate { + func confirmPaymentControllerNeedsAuthentication(_ controller: ConfirmPaymentViewController) { + let needsPasscodeCheck = Lock().shouldAuthorizeTransactions() + if needsPasscodeCheck { + authenticateUserCoordinator.start { [weak self] (success, _) in + if success { + self?.controller.sendTransaction() + self?.authenticateUserCoordinator.stop() + } + } + } else { + self.controller.sendTransaction() + } + } +} diff --git a/Trust/Transfer/ViewControllers/ConfirmPaymentViewController.swift b/Trust/Transfer/ViewControllers/ConfirmPaymentViewController.swift index 53a90ba6ba..0d680eee7d 100644 --- a/Trust/Transfer/ViewControllers/ConfirmPaymentViewController.swift +++ b/Trust/Transfer/ViewControllers/ConfirmPaymentViewController.swift @@ -16,10 +16,15 @@ enum ConfirmResult { case sentTransaction(SentTransaction) } +protocol ConfirmPaymentAuthenticationDelegate: class { + func confirmPaymentControllerNeedsAuthentication(_ controller: ConfirmPaymentViewController) +} + class ConfirmPaymentViewController: UIViewController { private let keystore: Keystore let session: WalletSession + public weak var delegate: ConfirmPaymentAuthenticationDelegate? lazy var sendTransactionCoordinator = { return SendTransactionCoordinator(session: self.session, keystore: keystore, confirmType: confirmType, server: server) }() @@ -37,7 +42,7 @@ class ConfirmPaymentViewController: UIViewController { var configurator: TransactionConfigurator let confirmType: ConfirmType let server: RPCServer - var didCompleted: ((Result) -> Void)? + var didComplete: ((Result) -> Void)? lazy var stackView: UIStackView = { let stackView = UIStackView() @@ -207,12 +212,15 @@ class ConfirmPaymentViewController: UIViewController { } @objc func send() { - self.displayLoading() + delegate?.confirmPaymentControllerNeedsAuthentication(self) + } - let transaction = configurator.signTransaction + public func sendTransaction() { + self.displayLoading() + let transaction = self.configurator.signTransaction self.sendTransactionCoordinator.send(transaction: transaction) { [weak self] result in guard let `self` = self else { return } - self.didCompleted?(result) + self.didComplete?(result) self.hideLoading() } } diff --git a/TrustTests/Factories/FakeLockProtocol.swift b/TrustTests/Factories/FakeLockProtocol.swift index 37b1e5112d..b9c5fcf3fb 100644 --- a/TrustTests/Factories/FakeLockProtocol.swift +++ b/TrustTests/Factories/FakeLockProtocol.swift @@ -7,6 +7,7 @@ class FakeLockProtocol: LockInterface { var passcodeSet = true var showProtection = true + var authorizeTransactions = true func isPasscodeSet() -> Bool { return passcodeSet @@ -15,4 +16,12 @@ class FakeLockProtocol: LockInterface { func shouldShowProtection() -> Bool { return isPasscodeSet() && showProtection } + + func authorizeTransactionsValue() -> Bool { + return authorizeTransactions + } + + func shouldAuthorizeTransactions() -> Bool { + return isPasscodeSet() && authorizeTransactionsValue() + } }