From b753efbc5f01c56261c38d6d6f0f8ef8cc921eef Mon Sep 17 00:00:00 2001 From: Lukas Korba Date: Tue, 24 May 2022 07:30:16 +0200 Subject: [PATCH] [285] Advanced Routing: setting a route may vary depending on the originating context (#325) - context based routing in Home Screen - mnemonic refactor - backup phrase display from the profile screen --- secant/Features/App/AppStore.swift | 45 ++++++++------ secant/Features/Home/HomeStore.swift | 20 +++++-- .../ImportWallet/ImportWalletStore.swift | 8 +-- .../OnboardingFlow/OnboardingFlowStore.swift | 8 +-- secant/Features/Profile/ProfileStore.swift | 59 +++++++++++++++++-- secant/Features/Profile/ProfileView.swift | 20 ++++++- secant/Features/Sandbox/SandboxStore.swift | 4 +- secant/Features/Sandbox/SandboxView.swift | 2 +- secant/Features/SendFlow/SendFlowStore.swift | 6 +- secant/Features/SendFlow/SendFlowView.swift | 2 +- .../AppReducerTests/AppReducerTests.swift | 8 +-- secantTests/SendTests/SendTests.swift | 22 +++---- 12 files changed, 142 insertions(+), 62 deletions(-) diff --git a/secant/Features/App/AppStore.swift b/secant/Features/App/AppStore.swift index a49bd54..8104054 100644 --- a/secant/Features/App/AppStore.swift +++ b/secant/Features/App/AppStore.swift @@ -23,10 +23,19 @@ struct AppState: Equatable { var onboardingState: OnboardingFlowState var phraseValidationState: RecoveryPhraseValidationFlowState var phraseDisplayState: RecoveryPhraseDisplayState - var route: Route = .welcome + var prevRoute: Route? + var internalRoute: Route = .welcome var sandboxState: SandboxState var storedWallet: StoredWallet? var welcomeState: WelcomeState + + var route: Route { + get { internalRoute } + set { + prevRoute = internalRoute + internalRoute = newValue + } + } } // MARK: - Action @@ -53,7 +62,7 @@ enum AppAction: Equatable { struct AppEnvironment { let SDKSynchronizer: WrappedSDKSynchronizer let databaseFiles: WrappedDatabaseFiles - let mnemonicSeedPhraseProvider: WrappedMnemonic + let mnemonic: WrappedMnemonic let scheduler: AnySchedulerOf let walletStorage: WrappedWalletStorage let derivationTool: WrappedDerivationTool @@ -64,7 +73,7 @@ extension AppEnvironment { static let live = AppEnvironment( SDKSynchronizer: LiveWrappedSDKSynchronizer(), databaseFiles: .live(), - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, scheduler: DispatchQueue.main.eraseToAnyScheduler(), walletStorage: .live(), derivationTool: .live(), @@ -74,7 +83,7 @@ extension AppEnvironment { static let mock = AppEnvironment( SDKSynchronizer: LiveWrappedSDKSynchronizer(), databaseFiles: .live(), - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: DispatchQueue.main.eraseToAnyScheduler(), walletStorage: .live(), derivationTool: .live(derivationTool: DerivationTool(networkType: .mainnet)), @@ -152,7 +161,7 @@ extension AppReducer { return .none } - try environment.mnemonicSeedPhraseProvider.isValid(storedWallet.seedPhrase) + try environment.mnemonic.isValid(storedWallet.seedPhrase) let birthday = state.storedWallet?.birthday ?? environment.zcashSDKEnvironment.defaultBirthday @@ -180,7 +189,7 @@ extension AppReducer { if !storedWallet.hasUserPassedPhraseBackupTest { do { - let phraseWords = try environment.mnemonicSeedPhraseProvider.asWords(storedWallet.seedPhrase) + let phraseWords = try environment.mnemonic.asWords(storedWallet.seedPhrase) let recoveryPhrase = RecoveryPhrase(words: phraseWords) state.phraseDisplayState.phrase = recoveryPhrase @@ -201,14 +210,14 @@ extension AppReducer { case .createNewWallet: do { // get the random english mnemonic - let randomPhrase = try environment.mnemonicSeedPhraseProvider.randomMnemonic() + let randomPhrase = try environment.mnemonic.randomMnemonic() let birthday = try environment.zcashSDKEnvironment.lightWalletService.latestBlockHeight() // store the wallet to the keychain try environment.walletStorage.importWallet(randomPhrase, birthday, .english, false) // start the backup phrase validation test - let randomPhraseWords = try environment.mnemonicSeedPhraseProvider.asWords(randomPhrase) + let randomPhraseWords = try environment.mnemonic.asWords(randomPhrase) let recoveryPhrase = RecoveryPhrase(words: randomPhraseWords) state.phraseDisplayState.phrase = recoveryPhrase state.phraseValidationState = RecoveryPhraseValidationFlowState.random(phrase: recoveryPhrase) @@ -258,7 +267,7 @@ extension AppReducer { } } - private static let routeReducer = AppReducer { state, action, environment in + private static let routeReducer = AppReducer { state, action, _ in switch action { case let .updateRoute(route): state.route = route @@ -277,14 +286,14 @@ extension AppReducer { state.route = .phraseDisplay case .phraseDisplay(.finishedPressed): - // TODO: Advanced Routing: setting a route may vary depending on the originating context #285 - // see https://github.com/zcash/secant-ios-wallet/issues/285 - if let storedWallet = try? environment.walletStorage.exportWallet(), - storedWallet.hasUserPassedPhraseBackupTest { - state.route = .home - } else { + // user is still supposed to do the backup phrase validation test + if state.prevRoute == .welcome || state.prevRoute == .onboarding { state.route = .phraseValidation } + // user wanted to see the backup phrase once again (at validation finished screen) + if state.prevRoute == .phraseValidation { + state.route = .home + } /// Default is meaningful here because there's `appReducer` handling actions and this reducer is handling only routes. We don't here plenty of unused cases. default: @@ -299,7 +308,7 @@ extension AppReducer { action: /AppAction.home, environment: { environment in HomeEnvironment( - mnemonicSeedPhraseProvider: environment.mnemonicSeedPhraseProvider, + mnemonic: environment.mnemonic, scheduler: environment.scheduler, walletStorage: environment.walletStorage, derivationTool: environment.derivationTool, @@ -313,7 +322,7 @@ extension AppReducer { action: /AppAction.onboarding, environment: { environment in OnboardingFlowEnvironment( - mnemonicSeedPhraseProvider: environment.mnemonicSeedPhraseProvider, + mnemonic: environment.mnemonic, walletStorage: environment.walletStorage, zcashSDKEnvironment: environment.zcashSDKEnvironment ) @@ -391,7 +400,7 @@ extension AppReducer { with environment: AppEnvironment ) throws -> Initializer { do { - let seedBytes = try environment.mnemonicSeedPhraseProvider.toSeed(seedPhrase) + let seedBytes = try environment.mnemonic.toSeed(seedPhrase) let viewingKeys = try environment.derivationTool.deriveUnifiedViewingKeysFromSeed(seedBytes, 1) let network = environment.zcashSDKEnvironment.network diff --git a/secant/Features/Home/HomeStore.swift b/secant/Features/Home/HomeStore.swift index 2167552..2f4e127 100644 --- a/secant/Features/Home/HomeStore.swift +++ b/secant/Features/Home/HomeStore.swift @@ -51,7 +51,7 @@ enum HomeAction: Equatable { // MARK: Environment struct HomeEnvironment { - let mnemonicSeedPhraseProvider: WrappedMnemonic + let mnemonic: WrappedMnemonic let scheduler: AnySchedulerOf let walletStorage: WrappedWalletStorage let derivationTool: WrappedDerivationTool @@ -67,7 +67,8 @@ extension HomeReducer { [ homeReducer, historyReducer, - sendReducer + sendReducer, + profileReducer ] ) .debug() @@ -168,7 +169,7 @@ extension HomeReducer { action: /HomeAction.send, environment: { environment in SendFlowEnvironment( - mnemonicSeedPhraseProvider: environment.mnemonicSeedPhraseProvider, + mnemonic: environment.mnemonic, scheduler: environment.scheduler, walletStorage: environment.walletStorage, derivationTool: environment.derivationTool, @@ -176,6 +177,17 @@ extension HomeReducer { ) } ) + + private static let profileReducer: HomeReducer = ProfileReducer.default.pullback( + state: \HomeState.profileState, + action: /HomeAction.profile, + environment: { environment in + ProfileEnvironment( + mnemonic: environment.mnemonic, + walletStorage: environment.walletStorage + ) + } + ) } // MARK: - Store @@ -261,7 +273,7 @@ extension HomeStore { initialState: .placeholder, reducer: .default.debug(), environment: HomeEnvironment( - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, scheduler: DispatchQueue.main.eraseToAnyScheduler(), walletStorage: .live(), derivationTool: .live(), diff --git a/secant/Features/ImportWallet/ImportWalletStore.swift b/secant/Features/ImportWallet/ImportWalletStore.swift index e844994..2187de8 100644 --- a/secant/Features/ImportWallet/ImportWalletStore.swift +++ b/secant/Features/ImportWallet/ImportWalletStore.swift @@ -33,20 +33,20 @@ enum ImportWalletAction: Equatable, BindableAction { // MARK: - Environment struct ImportWalletEnvironment { - let mnemonicSeedPhraseProvider: WrappedMnemonic + let mnemonic: WrappedMnemonic let walletStorage: WrappedWalletStorage let zcashSDKEnvironment: ZCashSDKEnvironment } extension ImportWalletEnvironment { static let live = ImportWalletEnvironment( - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, walletStorage: .live(), zcashSDKEnvironment: .mainnet ) static let demo = ImportWalletEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, walletStorage: .live(), zcashSDKEnvironment: .testnet ) @@ -67,7 +67,7 @@ extension ImportWalletReducer { case .importRecoveryPhrase: do { // validate the seed - try environment.mnemonicSeedPhraseProvider.isValid(state.importedSeedPhrase) + try environment.mnemonic.isValid(state.importedSeedPhrase) // store it to the keychain let birthday = environment.zcashSDKEnvironment.defaultBirthday diff --git a/secant/Features/OnboardingFlow/OnboardingFlowStore.swift b/secant/Features/OnboardingFlow/OnboardingFlowStore.swift index 0392bf7..8ca5927 100644 --- a/secant/Features/OnboardingFlow/OnboardingFlowStore.swift +++ b/secant/Features/OnboardingFlow/OnboardingFlowStore.swift @@ -99,20 +99,20 @@ enum OnboardingFlowAction: Equatable { // MARK: - Environment struct OnboardingFlowEnvironment { - let mnemonicSeedPhraseProvider: WrappedMnemonic + let mnemonic: WrappedMnemonic let walletStorage: WrappedWalletStorage let zcashSDKEnvironment: ZCashSDKEnvironment } extension OnboardingFlowEnvironment { static let live = OnboardingFlowEnvironment( - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, walletStorage: .live(), zcashSDKEnvironment: .mainnet ) static let demo = OnboardingFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, walletStorage: .live(), zcashSDKEnvironment: .testnet ) @@ -173,7 +173,7 @@ extension OnboardingFlowReducer { action: /OnboardingFlowAction.importWallet, environment: { environment in ImportWalletEnvironment( - mnemonicSeedPhraseProvider: environment.mnemonicSeedPhraseProvider, + mnemonic: environment.mnemonic, walletStorage: environment.walletStorage, zcashSDKEnvironment: environment.zcashSDKEnvironment ) diff --git a/secant/Features/Profile/ProfileStore.swift b/secant/Features/Profile/ProfileStore.swift index 066f3d1..75be0a9 100644 --- a/secant/Features/Profile/ProfileStore.swift +++ b/secant/Features/Profile/ProfileStore.swift @@ -9,33 +9,72 @@ typealias ProfileViewStore = ViewStore struct ProfileState: Equatable { enum Route { + case phraseDisplay case settings case walletInfo } - var walletInfoState: WalletInfoState - var settingsState: SettingsState + var phraseDisplayState: RecoveryPhraseDisplayState var route: Route? + var settingsState: SettingsState + var walletInfoState: WalletInfoState } // MARK: - Action enum ProfileAction: Equatable { + case phraseDisplay(RecoveryPhraseDisplayAction) case updateRoute(ProfileState.Route?) } // MARK: - Environment -struct ProfileEnvironment { } +struct ProfileEnvironment { + let mnemonic: WrappedMnemonic + let walletStorage: WrappedWalletStorage +} + +extension ProfileEnvironment { + static let live = ProfileEnvironment( + mnemonic: .live, + walletStorage: .live() + ) + + static let mock = ProfileEnvironment( + mnemonic: .mock, + walletStorage: .live() + ) +} // MARK: - Reducer extension ProfileReducer { - static let `default` = ProfileReducer { state, action, _ in + static let `default` = ProfileReducer { state, action, environment in switch action { + case .updateRoute(.phraseDisplay): + do { + let storedWallet = try environment.walletStorage.exportWallet() + let phraseWords = try environment.mnemonic.asWords(storedWallet.seedPhrase) + + let recoveryPhrase = RecoveryPhrase(words: phraseWords) + state.phraseDisplayState.phrase = recoveryPhrase + state.route = .phraseDisplay + } catch { + // TODO: - merge with issue 201 (https://github.com/zcash/secant-ios-wallet/issues/201) and its Error States + return .none + } + return .none + case let .updateRoute(route): state.route = route return .none + + case .phraseDisplay(.finishedPressed): + state.route = nil + return .none + + case .phraseDisplay: + return .none } } } @@ -63,6 +102,13 @@ extension ProfileViewStore { embed: { $0 ? .settings : nil } ) } + + var bindingForPhraseDisplay: Binding { + self.routeBinding.map( + extract: { $0 == .phraseDisplay }, + embed: { $0 ? .phraseDisplay : nil } + ) + } } // MARK: Placeholders @@ -70,9 +116,10 @@ extension ProfileViewStore { extension ProfileState { static var placeholder: Self { .init( - walletInfoState: .init(), + phraseDisplayState: .init(), + route: nil, settingsState: .init(), - route: nil + walletInfoState: .init() ) } } diff --git a/secant/Features/Profile/ProfileView.swift b/secant/Features/Profile/ProfileView.swift index 4dfc86f..983aaea 100644 --- a/secant/Features/Profile/ProfileView.swift +++ b/secant/Features/Profile/ProfileView.swift @@ -15,6 +15,19 @@ struct ProfileView: View { } ) + Text("Show me backup phrase") + .navigationLink( + isActive: viewStore.bindingForPhraseDisplay, + destination: { + RecoveryPhraseDisplayView( + store: store.scope( + state: \.phraseDisplayState, + action: ProfileAction.phraseDisplay + ) + ) + } + ) + Text("Go To Settings") .navigationLink( isActive: viewStore.bindingForSettings, @@ -36,11 +49,12 @@ struct ProfileView_Previews: PreviewProvider { ProfileView( store: .init( initialState: .init( - walletInfoState: .init(), - settingsState: .init() + phraseDisplayState: .init(), + settingsState: .init(), + walletInfoState: .init() ), reducer: .default, - environment: .init() + environment: .live ) ) } diff --git a/secant/Features/Sandbox/SandboxStore.swift b/secant/Features/Sandbox/SandboxStore.swift index 42b3750..dd4bb30 100644 --- a/secant/Features/Sandbox/SandboxStore.swift +++ b/secant/Features/Sandbox/SandboxStore.swift @@ -60,9 +60,7 @@ extension SandboxReducer { .pullback( state: \.profileState, action: /SandboxAction.profile, - environment: { _ in - return ProfileEnvironment() - } + environment: { _ in ProfileEnvironment.live } ) .run(&state, action, ()) case .reset: diff --git a/secant/Features/Sandbox/SandboxView.swift b/secant/Features/Sandbox/SandboxView.swift index 605fa39..ce4a729 100644 --- a/secant/Features/Sandbox/SandboxView.swift +++ b/secant/Features/Sandbox/SandboxView.swift @@ -32,7 +32,7 @@ struct SandboxView: View { ) .debug(), environment: SendFlowEnvironment( - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, scheduler: DispatchQueue.main.eraseToAnyScheduler(), walletStorage: .live(), derivationTool: .live(), diff --git a/secant/Features/SendFlow/SendFlowStore.swift b/secant/Features/SendFlow/SendFlowStore.swift index e13a734..0aaeca3 100644 --- a/secant/Features/SendFlow/SendFlowStore.swift +++ b/secant/Features/SendFlow/SendFlowStore.swift @@ -76,7 +76,7 @@ enum SendFlowAction: Equatable { // MARK: - Environment struct SendFlowEnvironment { - let mnemonicSeedPhraseProvider: WrappedMnemonic + let mnemonic: WrappedMnemonic let scheduler: AnySchedulerOf let walletStorage: WrappedWalletStorage let derivationTool: WrappedDerivationTool @@ -124,7 +124,7 @@ extension SendFlowReducer { do { let storedWallet = try environment.walletStorage.exportWallet() - let seedBytes = try environment.mnemonicSeedPhraseProvider.toSeed(storedWallet.seedPhrase) + let seedBytes = try environment.mnemonic.toSeed(storedWallet.seedPhrase) guard let spendingKey = try environment.derivationTool.deriveSpendingKeys(seedBytes, 1).first else { return Effect(value: .updateRoute(.failure)) } @@ -309,7 +309,7 @@ extension SendFlowStore { ), reducer: .default, environment: SendFlowEnvironment( - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, scheduler: DispatchQueue.main.eraseToAnyScheduler(), walletStorage: .live(), derivationTool: .live(), diff --git a/secant/Features/SendFlow/SendFlowView.swift b/secant/Features/SendFlow/SendFlowView.swift index 2f739dc..263079a 100644 --- a/secant/Features/SendFlow/SendFlowView.swift +++ b/secant/Features/SendFlow/SendFlowView.swift @@ -41,7 +41,7 @@ struct SendFLowView_Previews: PreviewProvider { ), reducer: .default, environment: SendFlowEnvironment( - mnemonicSeedPhraseProvider: .live, + mnemonic: .live, scheduler: DispatchQueue.main.eraseToAnyScheduler(), walletStorage: .live(), derivationTool: .live(), diff --git a/secantTests/AppReducerTests/AppReducerTests.swift b/secantTests/AppReducerTests/AppReducerTests.swift index 838b779..13d26d8 100644 --- a/secantTests/AppReducerTests/AppReducerTests.swift +++ b/secantTests/AppReducerTests/AppReducerTests.swift @@ -15,7 +15,7 @@ class AppReducerTests: XCTestCase { let testEnvironment = AppEnvironment( SDKSynchronizer: TestWrappedSDKSynchronizer(), databaseFiles: .throwing, - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .throwing, derivationTool: .live(), @@ -26,7 +26,7 @@ class AppReducerTests: XCTestCase { let uninitializedEnvironment = AppEnvironment( SDKSynchronizer: TestWrappedSDKSynchronizer(), databaseFiles: .throwing, - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: DispatchQueue.test.eraseToAnyScheduler(), walletStorage: .throwing, derivationTool: .live(), @@ -48,7 +48,7 @@ class AppReducerTests: XCTestCase { let keysMissingEnvironment = AppEnvironment( SDKSynchronizer: TestWrappedSDKSynchronizer(), databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)), - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: Self.testScheduler.eraseToAnyScheduler(), walletStorage: .throwing, derivationTool: .live(), @@ -70,7 +70,7 @@ class AppReducerTests: XCTestCase { let keysMissingEnvironment = AppEnvironment( SDKSynchronizer: TestWrappedSDKSynchronizer(), databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)), - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: Self.testScheduler.eraseToAnyScheduler(), walletStorage: .throwing, derivationTool: .live(), diff --git a/secantTests/SendTests/SendTests.swift b/secantTests/SendTests/SendTests.swift index cbcfe6b..9e8b4ff 100644 --- a/secantTests/SendTests/SendTests.swift +++ b/secantTests/SendTests/SendTests.swift @@ -32,7 +32,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: storage), derivationTool: .live(), @@ -88,7 +88,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: storage), derivationTool: .live(), @@ -127,7 +127,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -169,7 +169,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -191,7 +191,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -235,7 +235,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -273,7 +273,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -321,7 +321,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -366,7 +366,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -411,7 +411,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(), @@ -456,7 +456,7 @@ class SendTests: XCTestCase { let testScheduler = DispatchQueue.test let testEnvironment = SendFlowEnvironment( - mnemonicSeedPhraseProvider: .mock, + mnemonic: .mock, scheduler: testScheduler.eraseToAnyScheduler(), walletStorage: .live(walletStorage: WalletStorage(secItem: .live)), derivationTool: .live(),