[#535] Use 0.18.0's wipe() instead of obsolete nuke approach (#549)

- added alert view asking if nuke is triggered or canceled
- wipe of the keychain
- wipe publisher properly used
- functional wipe accessible through debug menu
This commit is contained in:
Lukas Korba 2023-02-27 22:43:38 +01:00 committed by GitHub
parent 148ca941f1
commit 75150da3a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 114 additions and 36 deletions

View File

@ -3517,8 +3517,8 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
requirement = {
branch = main;
kind = branch;
kind = revision;
revision = 3b2d972b2dd0c51e36d76e49fcf58273bf585c1b;
};
};
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {

View File

@ -338,8 +338,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/zcash/ZcashLightClientKit/",
"state" : {
"branch" : "main",
"revision" : "27b99013f7dda11caee0a261361c155490966e7f"
"revision" : "3b2d972b2dd0c51e36d76e49fcf58273bf585c1b"
}
}
],

View File

@ -18,24 +18,11 @@ extension DependencyValues {
}
enum SDKSynchronizerState: Equatable {
case unknown
case transactionsUpdated
case started
case progressUpdated
case statusWillUpdate
case synced
case started
case stopped
case disconnected
case syncing
case downloading
case validating
case scanning
case enhancing
case fetching
case minedTransaction
case foundTransactions
case failed
case connectionStateChanged
case synced
case unknown
}
enum SDKSynchronizerClientError: Error {
@ -54,6 +41,8 @@ protocol SDKSynchronizerClient {
func stop()
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?)
func statusSnapshot() -> SyncStatusSnapshot
func isSyncing() -> Bool
func isInitialized() -> Bool
func rewind(_ policy: RewindPolicy) async throws
@ -75,6 +64,8 @@ protocol SDKSynchronizerClient {
to recipientAddress: Recipient,
memo: Memo?
) -> EffectTask<Result<TransactionState, NSError>>
func wipe() -> AnyPublisher<Void, Error>?
}
extension SDKSynchronizerClient {

View File

@ -75,6 +75,14 @@ class LiveSDKSynchronizerClient: SDKSynchronizerClient {
func stop() {
synchronizer?.stop()
}
func isSyncing() -> Bool {
latestScannedSynchronizerState?.syncStatus.isSyncing ?? false
}
func isInitialized() -> Bool {
synchronizer != nil
}
func synchronizerStarted() {
stateChanged.send(.started)
@ -229,4 +237,8 @@ class LiveSDKSynchronizerClient: SDKSynchronizerClient {
}
}
}
func wipe() -> AnyPublisher<Void, Error>? {
synchronizer?.wipe()
}
}

View File

@ -33,6 +33,10 @@ class MockSDKSynchronizerClient: SDKSynchronizerClient {
func stop() { }
func isSyncing() -> Bool { false }
func isInitialized() -> Bool { false }
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?) { }
func statusSnapshot() -> SyncStatusSnapshot { .default }
@ -200,4 +204,6 @@ class MockSDKSynchronizerClient: SDKSynchronizerClient {
return EffectTask(value: Result.success(transactionState))
}
func wipe() -> AnyPublisher<Void, Error>? { nil }
}

View File

@ -32,6 +32,10 @@ class NoopSDKSynchronizer: SDKSynchronizerClient {
func stop() { }
func isSyncing() -> Bool { false }
func isInitialized() -> Bool { false }
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?) { }
func statusSnapshot() -> SyncStatusSnapshot { .default }
@ -70,6 +74,8 @@ class NoopSDKSynchronizer: SDKSynchronizerClient {
func updateStateChanged(_ newState: SDKSynchronizerState) {
stateChanged = CurrentValueSubject<SDKSynchronizerState, Never>(newState)
}
func wipe() -> AnyPublisher<Void, Error>? { nil }
}
class TestSDKSynchronizerClient: SDKSynchronizerClient {
@ -90,6 +96,10 @@ class TestSDKSynchronizerClient: SDKSynchronizerClient {
func stop() { }
func isSyncing() -> Bool { false }
func isInitialized() -> Bool { false }
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?) { }
func statusSnapshot() -> SyncStatusSnapshot { .default }
@ -235,4 +245,6 @@ class TestSDKSynchronizerClient: SDKSynchronizerClient {
func updateStateChanged(_ newState: SDKSynchronizerState) {
stateChanged = CurrentValueSubject<SDKSynchronizerState, Never>(newState)
}
func wipe() -> AnyPublisher<Void, Error>? { nil }
}

View File

@ -23,9 +23,10 @@ extension RootReducer {
case welcome
}
@BindingState var alert: AlertState<RootReducer.Action>?
var internalDestination: Destination = .welcome
var previousDestination: Destination?
var destination: Destination {
get { internalDestination }
set {
@ -39,6 +40,7 @@ extension RootReducer {
case deeplink(URL)
case deeplinkHome
case deeplinkSend(Zatoshi, String, String)
case dismissAlert
case updateDestination(RootReducer.DestinationState.Destination)
}
@ -112,7 +114,12 @@ extension RootReducer {
}
return EffectTask(value: .destination(.deeplink(url)))
case .home, .initialization, .onboarding, .phraseDisplay, .phraseValidation, .sandbox, .welcome, .debug:
case .destination(.dismissAlert):
state.destinationState.alert = nil
return .none
case .home, .initialization, .onboarding, .phraseDisplay, .phraseValidation,
.sandbox, .welcome, .binding, .nukeWalletFailed, .nukeWalletSucceeded, .debug:
return .none
}

View File

@ -21,6 +21,7 @@ extension RootReducer {
case initializeSDK
case initialSetups
case nukeWallet
case nukeWalletRequest
case respondToWalletInitializationState(InitializationState)
case walletConfigChanged(WalletConfig)
}
@ -125,10 +126,9 @@ extension RootReducer {
mnemonic: mnemonic,
zcashSDKEnvironment: zcashSDKEnvironment
)
try sdkSynchronizer.prepareWith(initializer: initializer, seedBytes: seedBytes)
try sdkSynchronizer.start()
return .none
} catch {
// TODO: [#221] error we need to handle (https://github.com/zcash/secant-ios-wallet/issues/221)
@ -199,14 +199,57 @@ extension RootReducer {
}
return .none
case .initialization(.nukeWallet):
walletStorage.nukeWallet()
do {
try databaseFiles.nukeDbFilesFor(zcashSDKEnvironment.network)
} catch {
// TODO: [#221] error we need to handle, issue #221 (https://github.com/zcash/secant-ios-wallet/issues/221)
}
case .initialization(.nukeWalletRequest):
state.destinationState.alert = AlertState(
title: TextState("Wipe of the wallet"),
message: TextState("Are you sure?"),
buttons: [
.destructive(
TextState("Yes"),
action: .send(.initialization(.nukeWallet))
),
.cancel(
TextState("No"),
action: .send(.destination(.dismissAlert))
)
]
)
return .none
case .initialization(.nukeWallet):
guard let wipePublisher = sdkSynchronizer.wipe() else {
return EffectTask(value: .nukeWalletFailed)
}
return wipePublisher
.catchToEffect()
.receive(on: mainQueue)
.replaceEmpty(with: .success(Void()))
.map { _ in return RootReducer.Action.nukeWalletSucceeded }
.replaceError(with: RootReducer.Action.nukeWalletFailed)
.eraseToEffect()
.cancellable(id: SynchronizerCancelId.self, cancelInFlight: true)
case .nukeWalletSucceeded:
walletStorage.nukeWallet()
state.onboardingState.destination = nil
state.onboardingState.index = 0
return .concatenate(
.cancel(id: SynchronizerCancelId.self),
EffectTask(value: .initialization(.checkWalletInitialization))
)
case .nukeWalletFailed:
// TODO: [#221] error we need to handle, issue #221 (https://github.com/zcash/secant-ios-wallet/issues/221)
let backDestination: EffectTask<RootReducer.Action>
if let previousDestination = state.destinationState.previousDestination {
backDestination = EffectTask(value: .destination(.updateDestination(previousDestination)))
} else {
backDestination = EffectTask(value: .destination(.updateDestination(state.destinationState.destination)))
}
return .concatenate(
.cancel(id: SynchronizerCancelId.self),
backDestination
)
case .welcome(.debugMenuStartup), .home(.debugMenuStartup):
return .concatenate(
@ -222,8 +265,8 @@ extension RootReducer {
case .onboarding(.createNewWallet):
return EffectTask(value: .initialization(.createNewWallet))
case .home, .destination, .onboarding, .phraseDisplay, .phraseValidation, .sandbox, .welcome:
case .home, .destination, .onboarding, .phraseDisplay, .phraseValidation, .sandbox, .welcome, .binding:
return .none
case .initialization(.configureCrashReporter):

View File

@ -6,6 +6,7 @@ typealias RootViewStore = ViewStore<RootReducer.State, RootReducer.Action>
struct RootReducer: ReducerProtocol {
enum CancelId {}
enum SynchronizerCancelId {}
struct State: Equatable {
var appInitializationState: InitializationState = .uninitialized
@ -20,10 +21,13 @@ struct RootReducer: ReducerProtocol {
var welcomeState: WelcomeReducer.State
}
enum Action: Equatable {
enum Action: Equatable, BindableAction {
case binding(BindingAction<RootReducer.State>)
case destination(DestinationAction)
case home(HomeReducer.Action)
case initialization(InitializationAction)
case nukeWalletFailed
case nukeWalletSucceeded
case onboarding(OnboardingFlowReducer.Action)
case phraseDisplay(RecoveryPhraseDisplayReducer.Action)
case phraseValidation(RecoveryPhraseValidationFlowReducer.Action)
@ -46,6 +50,8 @@ struct RootReducer: ReducerProtocol {
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
var body: some ReducerProtocol<State, Action> {
BindingReducer()
Scope(state: \.homeState, action: /Action.home) {
HomeReducer()
}
@ -144,6 +150,7 @@ extension RootReducer {
network: zcashSDKEnvironment.network,
spendParamsURL: try databaseFiles.spendParamsURLFor(network),
outputParamsURL: try databaseFiles.outputParamsURLFor(network),
saplingParamsSourceURL: SaplingParamsSourceURL.default,
viewingKeys: [viewingKey],
walletBirthday: birthday,
loggerProxy: OSLogger_(logLevel: .debug, category: LoggerConstants.sdkLogs)

View File

@ -126,7 +126,7 @@ private extension RootView {
}
Button("[Be careful] Nuke Wallet") {
viewStore.send(.initialization(.nukeWallet))
viewStore.send(.initialization(.nukeWalletRequest))
}
}
@ -154,6 +154,7 @@ private extension RootView {
}
}
}
.alert(self.store.scope(state: \.destinationState.alert), dismiss: .destination(.dismissAlert))
}
.navigationBarTitle("Startup")
}

View File

@ -17,7 +17,7 @@ class HomeTests: XCTestCase {
reducer: HomeReducer()
)
store.send(.synchronizerStateChanged(.downloading))
store.send(.synchronizerStateChanged(.progressUpdated))
store.receive(.updateSynchronizerStatus)
}