secant-ios-wallet/modules/Sources/Features/SecurityWarning/SecurityWarningStore.swift

133 lines
4.3 KiB
Swift

//
// SecurityWarningStore.swift
// secant-testnet
//
// Created by Lukáš Korba on 04.10.2023.
//
import Foundation
import ComposableArchitecture
import AppVersion
import RecoveryPhraseDisplay
import MnemonicClient
import WalletStorage
import ZcashSDKEnvironment
import ZcashLightClientKit
import Models
import Generated
import Utils
import SwiftUI
@Reducer
public struct SecurityWarning {
@ObservableState
public struct State: Equatable {
@Presents public var alert: AlertState<Action>?
public var appBuild = ""
public var appVersion = ""
/// This flag holds information whether a user acknowledged the consent or not. `false` by default.
public var isAcknowledged: Bool = false
/// This boolean is a TCA view binding, `false` by default = recovery phrase view is not presented, `true` = presented.
public var recoveryPhraseDisplayViewBinding: Bool = false
public var recoveryPhraseDisplayState: RecoveryPhraseDisplay.State
public init(
appBuild: String = "",
appVersion: String = "",
recoveryPhraseDisplayViewBinding: Bool = false,
recoveryPhraseDisplayState: RecoveryPhraseDisplay.State
) {
self.appBuild = appBuild
self.appVersion = appVersion
self.recoveryPhraseDisplayViewBinding = recoveryPhraseDisplayViewBinding
self.recoveryPhraseDisplayState = recoveryPhraseDisplayState
}
}
public enum Action: BindableAction, Equatable {
case alert(PresentationAction<Action>)
case binding(BindingAction<SecurityWarning.State>)
case confirmTapped
case createNewWallet
case newWalletCreated
case onAppear
case recoveryPhraseDisplay(RecoveryPhraseDisplay.Action)
}
@Dependency(\.appVersion) var appVersion
@Dependency(\.mnemonic) var mnemonic
@Dependency(\.walletStorage) var walletStorage
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
public init() { }
public var body: some Reducer<State, Action> {
BindingReducer()
Scope(state: \.recoveryPhraseDisplayState, action: /Action.recoveryPhraseDisplay) {
RecoveryPhraseDisplay()
}
Reduce { state, action in
switch action {
case .onAppear:
state.appBuild = appVersion.appBuild()
state.appVersion = appVersion.appVersion()
return .none
case .alert(.presented(let action)):
return Effect.send(action)
case .alert(.dismiss):
state.alert = nil
return .none
case .binding:
return .none
case .confirmTapped:
return .none
case .createNewWallet:
do {
// get the random english mnemonic
let newRandomPhrase = try mnemonic.randomMnemonic()
let birthday = zcashSDKEnvironment.latestCheckpoint
// store the wallet to the keychain
try walletStorage.importWallet(newRandomPhrase, birthday, .english, false)
state.recoveryPhraseDisplayViewBinding = true
return Effect.send(.newWalletCreated)
} catch {
state.alert = AlertState.cantCreateNewWallet(error.toZcashError())
}
return .none
case .newWalletCreated:
return .none
case .recoveryPhraseDisplay(.finishedPressed):
state.recoveryPhraseDisplayViewBinding = false
return .none
case .recoveryPhraseDisplay:
return .none
}
}
}
}
// MARK: Alerts
extension AlertState where Action == SecurityWarning.Action {
public static func cantCreateNewWallet(_ error: ZcashError) -> AlertState {
AlertState {
TextState(L10n.Root.Initialization.Alert.Failed.title)
} message: {
TextState(L10n.Root.Initialization.Alert.CantCreateNewWallet.message(error.detailedMessage))
}
}
}