[#1024] KeysMissing when restored to a new iPhone
- validation flow done for the 2 out of 3 flows - 1. when the restore path is selected and the seed doesn't match the DB - 2. when create new wallet is selected - (missing) 3. seed is validated (waiting on API) [#1024] KeysMissing when restored to a new iPhone - preparations for SDK 2.1.0 [#1024] KeysMissing when restored to a new iPhone - Seed validation API used and integrated - There's an error in rust that must be resolved first [#1024] KeysMissing when restored to a new iPhone - rebased [#1024] KeysMissing when restored to a new iPhone - updated to use latest SDK's isSeedRelevantToAnyDerivedAccount [#1024] KeysMissing when restored to a new iPhone - unstable SDK branch test [#1024] KeysMissing when restored to a new iPhone - version bump [#1024] KeysMissing when restored to a new iPhone - bugfix - packae redirected to ECCs repo [#1024] KeysMissing when restored to a new iPhone - tests fixed
This commit is contained in:
parent
2e51a9d839
commit
3e6afc69a8
|
@ -9,6 +9,8 @@ directly impact users rather than highlighting other crucial architectural updat
|
|||
### Added
|
||||
- Proposal API integrated with error handling for multi-transaction Proposals.
|
||||
- Privacy info manifest.
|
||||
- Orchard support.
|
||||
- Seed validation for case when Zashi is migrated to another device.
|
||||
|
||||
### Fixed
|
||||
- White area above the keyboard has been removed.
|
||||
|
|
|
@ -68,7 +68,7 @@ let package = Package(
|
|||
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.1.0"),
|
||||
.package(url: "https://github.com/pointfreeco/swift-url-routing", from: "0.6.0"),
|
||||
.package(url: "https://github.com/zcash-hackworks/MnemonicSwift", from: "2.2.4"),
|
||||
.package(url: "https://github.com/zcash/ZcashLightClientKit", from: "2.0.11"),
|
||||
.package(url: "https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk", from: "2.1.0"),
|
||||
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: "10.17.0")
|
||||
],
|
||||
targets: [
|
||||
|
@ -80,7 +80,7 @@ let package = Package(
|
|||
"UIComponents",
|
||||
"Utils",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/AddressDetails"
|
||||
),
|
||||
|
@ -116,7 +116,7 @@ let package = Package(
|
|||
"WalletStorage",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/BalanceBreakdown"
|
||||
),
|
||||
|
@ -126,7 +126,7 @@ let package = Package(
|
|||
"Generated",
|
||||
"Utils",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/BalanceFormatter"
|
||||
),
|
||||
|
@ -151,7 +151,7 @@ let package = Package(
|
|||
"FileManager",
|
||||
"Utils",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/DatabaseFiles"
|
||||
),
|
||||
|
@ -168,7 +168,7 @@ let package = Package(
|
|||
"DerivationTool",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "URLRouting", package: "swift-url-routing"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/Deeplink"
|
||||
),
|
||||
|
@ -177,7 +177,7 @@ let package = Package(
|
|||
dependencies: [
|
||||
"Utils",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/DerivationTool"
|
||||
),
|
||||
|
@ -195,7 +195,7 @@ let package = Package(
|
|||
"LogsHandler",
|
||||
"Utils",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/ExportLogs"
|
||||
),
|
||||
|
@ -235,7 +235,7 @@ let package = Package(
|
|||
"TransactionList",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/Home"
|
||||
),
|
||||
|
@ -249,7 +249,7 @@ let package = Package(
|
|||
"WalletStorage",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/ImportWallet"
|
||||
),
|
||||
|
@ -303,7 +303,7 @@ let package = Package(
|
|||
"SecurityWarning",
|
||||
"UIComponents",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/OnboardingFlow"
|
||||
),
|
||||
|
@ -352,7 +352,7 @@ let package = Package(
|
|||
"Utils",
|
||||
"WalletStorage",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/RecoveryPhraseDisplay"
|
||||
),
|
||||
|
@ -401,7 +401,7 @@ let package = Package(
|
|||
"Welcome",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/Root"
|
||||
),
|
||||
|
@ -413,7 +413,7 @@ let package = Package(
|
|||
"SendFlow",
|
||||
"TransactionList",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/Sandbox"
|
||||
),
|
||||
|
@ -427,7 +427,7 @@ let package = Package(
|
|||
"Utils",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/Scan"
|
||||
),
|
||||
|
@ -438,7 +438,7 @@ let package = Package(
|
|||
"Models",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/SDKSynchronizer"
|
||||
),
|
||||
|
@ -483,7 +483,7 @@ let package = Package(
|
|||
"WalletStorage",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/SendFlow"
|
||||
),
|
||||
|
@ -496,7 +496,7 @@ let package = Package(
|
|||
"UserDefaults",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/ServerSetup"
|
||||
),
|
||||
|
@ -515,7 +515,7 @@ let package = Package(
|
|||
"SupportDataGenerator",
|
||||
"UIComponents",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/Settings"
|
||||
),
|
||||
|
@ -560,7 +560,7 @@ let package = Package(
|
|||
"Settings",
|
||||
"UIComponents",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/Tabs"
|
||||
),
|
||||
|
@ -576,7 +576,7 @@ let package = Package(
|
|||
"Utils",
|
||||
"ZcashSDKEnvironment",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Features/TransactionList"
|
||||
),
|
||||
|
@ -587,6 +587,7 @@ let package = Package(
|
|||
"DerivationTool",
|
||||
"Generated",
|
||||
"NumberFormatter",
|
||||
"SupportDataGenerator",
|
||||
"Utils",
|
||||
"ZcashSDKEnvironment"
|
||||
],
|
||||
|
@ -597,7 +598,7 @@ let package = Package(
|
|||
dependencies: [
|
||||
"DerivationTool",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/URIParser"
|
||||
),
|
||||
|
@ -619,7 +620,7 @@ let package = Package(
|
|||
.target(
|
||||
name: "Utils",
|
||||
dependencies: [
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit"),
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk"),
|
||||
.product(name: "CasePaths", package: "swift-case-paths"),
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture")
|
||||
],
|
||||
|
@ -642,7 +643,7 @@ let package = Package(
|
|||
"MnemonicClient",
|
||||
"Models",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit")
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk")
|
||||
],
|
||||
path: "Sources/Dependencies/WalletStorage"
|
||||
),
|
||||
|
@ -660,7 +661,7 @@ let package = Package(
|
|||
name: "ZcashSDKEnvironment",
|
||||
dependencies: [
|
||||
"UserDefaults",
|
||||
.product(name: "ZcashLightClientKit", package: "ZcashLightClientKit"),
|
||||
.product(name: "ZcashLightClientKit", package: "zcash-swift-wallet-sdk"),
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture")
|
||||
],
|
||||
path: "Sources/Dependencies/ZcashSDKEnvironment"
|
||||
|
|
|
@ -28,24 +28,24 @@ public struct SDKSynchronizerClient {
|
|||
public let stateStream: () -> AnyPublisher<SynchronizerState, Never>
|
||||
public let eventStream: () -> AnyPublisher<SynchronizerEvent, Never>
|
||||
public let latestState: () -> SynchronizerState
|
||||
|
||||
|
||||
public let prepareWith: ([UInt8], BlockHeight, WalletInitMode) async throws -> Void
|
||||
public let start: (_ retry: Bool) async throws -> Void
|
||||
public let stop: () -> Void
|
||||
public let isSyncing: () -> Bool
|
||||
public let isInitialized: () -> Bool
|
||||
|
||||
|
||||
public let rewind: (RewindPolicy) -> AnyPublisher<Void, Error>
|
||||
|
||||
|
||||
public var getAllTransactions: () async throws -> [TransactionState]
|
||||
|
||||
|
||||
public let getUnifiedAddress: (_ account: Int) async throws -> UnifiedAddress?
|
||||
public let getTransparentAddress: (_ account: Int) async throws -> TransparentAddress?
|
||||
public let getSaplingAddress: (_ accountIndex: Int) async throws -> SaplingAddress?
|
||||
|
||||
|
||||
public var sendTransaction: (UnifiedSpendingKey, Zatoshi, Recipient, Memo?) async throws -> TransactionState
|
||||
public let shieldFunds: (UnifiedSpendingKey, Memo, Zatoshi) async throws -> TransactionState
|
||||
|
||||
|
||||
public var wipe: () -> AnyPublisher<Void, Error>?
|
||||
|
||||
public var switchToEndpoint: (LightWalletEndpoint) async throws -> Void
|
||||
|
@ -54,4 +54,6 @@ public struct SDKSynchronizerClient {
|
|||
public var proposeTransfer: (Int, Recipient, Zatoshi, Memo?) async throws -> Proposal
|
||||
public var createProposedTransactions: (Proposal, UnifiedSpendingKey) async throws -> CreateProposedTransactionsResult
|
||||
public var proposeShielding: (Int, Zatoshi, Memo, TransparentAddress?) async throws -> Proposal?
|
||||
|
||||
public var isSeedRelevantToAnyDerivedAccount: ([UInt8]) async throws -> Bool
|
||||
}
|
||||
|
|
|
@ -173,6 +173,9 @@ extension SDKSynchronizerClient: DependencyKey {
|
|||
memo: memo,
|
||||
transparentReceiver: transparentReceiver
|
||||
)
|
||||
},
|
||||
isSeedRelevantToAnyDerivedAccount: { seed in
|
||||
try await synchronizer.isSeedRelevantToAnyDerivedAccount(seed: seed)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ extension SDKSynchronizerClient: TestDependencyKey {
|
|||
switchToEndpoint: XCTUnimplemented("\(Self.self).switchToEndpoint"),
|
||||
proposeTransfer: XCTUnimplemented("\(Self.self).proposeTransfer", placeholder: .testOnlyFakeProposal(totalFee: 0)),
|
||||
createProposedTransactions: XCTUnimplemented("\(Self.self).createProposedTransactions", placeholder: .success),
|
||||
proposeShielding: XCTUnimplemented("\(Self.self).proposeShielding", placeholder: nil)
|
||||
proposeShielding: XCTUnimplemented("\(Self.self).proposeShielding", placeholder: nil),
|
||||
isSeedRelevantToAnyDerivedAccount: XCTUnimplemented("\(Self.self).isSeedRelevantToAnyDerivedAccount")
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -58,7 +59,8 @@ extension SDKSynchronizerClient {
|
|||
switchToEndpoint: { _ in },
|
||||
proposeTransfer: { _, _, _, _ in .testOnlyFakeProposal(totalFee: 0) },
|
||||
createProposedTransactions: { _, _ in .success },
|
||||
proposeShielding: { _, _, _, _ in nil }
|
||||
proposeShielding: { _, _, _, _ in nil },
|
||||
isSeedRelevantToAnyDerivedAccount: { _ in false }
|
||||
)
|
||||
|
||||
public static let mock = Self.mocked()
|
||||
|
@ -179,12 +181,13 @@ extension SDKSynchronizerClient {
|
|||
},
|
||||
wipe: @escaping () -> AnyPublisher<Void, Error>? = { Fail(error: "Error").eraseToAnyPublisher() },
|
||||
switchToEndpoint: @escaping (LightWalletEndpoint) async throws -> Void = { _ in },
|
||||
proposeTransfer:
|
||||
proposeTransfer:
|
||||
@escaping (Int, Recipient, Zatoshi, Memo?) async throws -> Proposal = { _, _, _, _ in .testOnlyFakeProposal(totalFee: 0) },
|
||||
createProposedTransactions:
|
||||
@escaping (Proposal, UnifiedSpendingKey) async throws -> CreateProposedTransactionsResult = { _, _ in .success },
|
||||
proposeShielding:
|
||||
@escaping (Int, Zatoshi, Memo, TransparentAddress?) async throws -> Proposal? = { _, _, _, _ in nil }
|
||||
@escaping (Int, Zatoshi, Memo, TransparentAddress?) async throws -> Proposal? = { _, _, _, _ in nil },
|
||||
isSeedRelevantToAnyDerivedAccount: @escaping ([UInt8]) async throws -> Bool = { _ in false }
|
||||
) -> SDKSynchronizerClient {
|
||||
SDKSynchronizerClient(
|
||||
stateStream: stateStream,
|
||||
|
@ -206,7 +209,8 @@ extension SDKSynchronizerClient {
|
|||
switchToEndpoint: switchToEndpoint,
|
||||
proposeTransfer: proposeTransfer,
|
||||
createProposedTransactions: createProposedTransactions,
|
||||
proposeShielding: proposeShielding
|
||||
proposeShielding: proposeShielding,
|
||||
isSeedRelevantToAnyDerivedAccount: isSeedRelevantToAnyDerivedAccount
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,11 +210,12 @@ public struct BalanceBreakdownReducer: Reducer {
|
|||
|
||||
case .synchronizerStateChanged(let latestState):
|
||||
let accountBalance = latestState.data.accountBalance?.data
|
||||
state.shieldedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero
|
||||
state.totalBalance = accountBalance?.saplingBalance.total() ?? .zero
|
||||
|
||||
state.shieldedBalance = (accountBalance?.saplingBalance.spendableValue ?? .zero) + (accountBalance?.orchardBalance.spendableValue ?? .zero)
|
||||
state.totalBalance = (accountBalance?.saplingBalance.total() ?? .zero) + (accountBalance?.orchardBalance.total() ?? .zero)
|
||||
state.transparentBalance = accountBalance?.unshielded ?? .zero
|
||||
state.changePending = accountBalance?.saplingBalance.changePendingConfirmation ?? .zero
|
||||
state.pendingTransactions = accountBalance?.saplingBalance.valuePendingSpendability ?? .zero
|
||||
state.changePending = (accountBalance?.saplingBalance.changePendingConfirmation ?? .zero) + (accountBalance?.orchardBalance.changePendingConfirmation ?? .zero)
|
||||
state.pendingTransactions = (accountBalance?.saplingBalance.valuePendingSpendability ?? .zero) + (accountBalance?.orchardBalance.valuePendingSpendability ?? .zero)
|
||||
return .none
|
||||
|
||||
case .syncProgress:
|
||||
|
|
|
@ -70,6 +70,7 @@ public struct BalanceBreakdownView: View {
|
|||
)
|
||||
)
|
||||
.padding(.top, viewStore.isRestoringWallet ? 0 : 40)
|
||||
.padding(.bottom, 25)
|
||||
.navigationLinkEmpty(
|
||||
isActive: viewStore.bindingForPartialProposalError,
|
||||
destination: {
|
||||
|
|
|
@ -196,8 +196,9 @@ public struct HomeReducer: Reducer {
|
|||
|
||||
state.synchronizerStatusSnapshot = snapshot
|
||||
let accountBalance = latestState.data.accountBalance?.data
|
||||
state.shieldedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero
|
||||
state.totalBalance = accountBalance?.saplingBalance.total() ?? .zero
|
||||
|
||||
state.shieldedBalance = (accountBalance?.saplingBalance.spendableValue ?? .zero) + (accountBalance?.orchardBalance.spendableValue ?? .zero)
|
||||
state.totalBalance = (accountBalance?.saplingBalance.total() ?? .zero) + (accountBalance?.orchardBalance.total() ?? .zero)
|
||||
|
||||
switch snapshot.syncStatus {
|
||||
case .error(let error):
|
||||
|
|
|
@ -72,10 +72,11 @@ public struct ImportWalletReducer: Reducer {
|
|||
public enum Action: Equatable {
|
||||
case alert(PresentationAction<Action>)
|
||||
case birthdayInputChanged(RedactableString)
|
||||
case restoreWallet
|
||||
case importPrivateOrViewingKey
|
||||
case initializeSDK
|
||||
case nextPressed
|
||||
case onAppear
|
||||
case restoreWallet
|
||||
case seedPhraseInputChanged(RedactableString)
|
||||
case successfullyRecovered
|
||||
case updateDestination(ImportWalletReducer.State.Destination?)
|
||||
|
@ -130,6 +131,9 @@ public struct ImportWalletReducer: Reducer {
|
|||
case .alert:
|
||||
return .none
|
||||
|
||||
case .nextPressed:
|
||||
return .none
|
||||
|
||||
case .restoreWallet:
|
||||
do {
|
||||
// validate the seed
|
||||
|
|
|
@ -97,7 +97,7 @@ public struct ImportWalletView: View {
|
|||
}
|
||||
|
||||
Button(L10n.General.next.uppercased()) {
|
||||
viewStore.send(.updateDestination(.birthday))
|
||||
viewStore.send(.nextPressed)
|
||||
}
|
||||
.zcashStyle()
|
||||
.frame(width: 236)
|
||||
|
|
|
@ -28,6 +28,8 @@ extension RootReducer {
|
|||
case nukeWallet
|
||||
case nukeWalletRequest
|
||||
case respondToWalletInitializationState(InitializationState)
|
||||
case restoreExistingWallet
|
||||
case seedValidationResult(Bool)
|
||||
case synchronizerStartFailed(ZcashError)
|
||||
case registerForSynchronizersUpdate
|
||||
case retryStart
|
||||
|
@ -39,6 +41,7 @@ extension RootReducer {
|
|||
Reduce { state, action in
|
||||
switch action {
|
||||
case .initialization(.appDelegate(.didFinishLaunching)):
|
||||
//walletStorage.nukeWallet()
|
||||
state.appStartState = .didFinishLaunching
|
||||
// TODO: [#704], trigger the review request logic when approved by the team,
|
||||
// https://github.com/Electric-Coin-Company/zashi-ios/issues/704
|
||||
|
@ -58,7 +61,7 @@ extension RootReducer {
|
|||
} else {
|
||||
return .send(.initialization(.retryStart))
|
||||
}
|
||||
|
||||
|
||||
case .initialization(.appDelegate(.didEnterBackground)):
|
||||
sdkSynchronizer.stop()
|
||||
state.bgTask?.setTaskCompleted(success: false)
|
||||
|
@ -86,14 +89,14 @@ extension RootReducer {
|
|||
await send(.initialization(.retryStart))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case .synchronizerStateChanged(let latestState):
|
||||
let snapshot = SyncStatusSnapshot.snapshotFor(state: latestState.data.syncStatus)
|
||||
|
||||
|
||||
guard state.bgTask != nil else {
|
||||
return .send(.initialization(.checkRestoreWalletFlag(snapshot.syncStatus)))
|
||||
}
|
||||
|
||||
|
||||
var finishBGTask = false
|
||||
var successOfBGTask = false
|
||||
|
||||
|
@ -106,16 +109,16 @@ extension RootReducer {
|
|||
finishBGTask = true
|
||||
default: break
|
||||
}
|
||||
|
||||
|
||||
if finishBGTask {
|
||||
LoggerProxy.event("BGTask setTaskCompleted(success: \(successOfBGTask)) from TCA")
|
||||
state.bgTask?.setTaskCompleted(success: successOfBGTask)
|
||||
state.bgTask = nil
|
||||
return .cancel(id: CancelStateId)
|
||||
}
|
||||
|
||||
|
||||
return .send(.initialization(.checkRestoreWalletFlag(snapshot.syncStatus)))
|
||||
|
||||
|
||||
case .initialization(.checkRestoreWalletFlag(let syncStatus)):
|
||||
if state.isRestoringWallet && syncStatus == .upToDate {
|
||||
state.isRestoringWallet = false
|
||||
|
@ -125,10 +128,10 @@ extension RootReducer {
|
|||
} else {
|
||||
return .none
|
||||
}
|
||||
|
||||
|
||||
case .initialization(.synchronizerStartFailed):
|
||||
return .none
|
||||
|
||||
|
||||
case .initialization(.retryStart):
|
||||
// Try the start only if the synchronizer has been already prepared
|
||||
guard sdkSynchronizer.latestState().syncStatus.isPrepared else {
|
||||
|
@ -172,7 +175,7 @@ extension RootReducer {
|
|||
} else {
|
||||
return Effect.send(.initialization(.walletConfigChanged(walletConfig)))
|
||||
}
|
||||
|
||||
|
||||
case .initialization(.walletConfigChanged(let walletConfig)):
|
||||
return .concatenate(
|
||||
Effect.send(.updateStateAfterConfigUpdate(walletConfig)),
|
||||
|
@ -193,7 +196,7 @@ extension RootReducer {
|
|||
zcashNetwork: zcashSDKEnvironment.network
|
||||
)
|
||||
return Effect.send(.initialization(.respondToWalletInitializationState(walletState)))
|
||||
|
||||
|
||||
/// Respond to all possible states of the wallet and initiate appropriate side effects including errors handling
|
||||
case .initialization(.respondToWalletInitializationState(let walletState)):
|
||||
switch walletState {
|
||||
|
@ -203,11 +206,7 @@ extension RootReducer {
|
|||
return .none
|
||||
case .keysMissing:
|
||||
state.appInitializationState = .keysMissing
|
||||
// TODO: [#1024] This is the case when this wallet migrated to another device
|
||||
// https://github.com/Electric-Coin-Company/zashi-ios/issues/1024
|
||||
// Temporary alert view until #1024 is implemented
|
||||
state.alert = AlertState.tmpMigrationToBeDeveloped()
|
||||
return .none
|
||||
return .send(.destination(.updateDestination(.onboarding)))
|
||||
case .initialized, .filesMissing:
|
||||
if walletState == .filesMissing {
|
||||
state.appInitializationState = .filesMissing
|
||||
|
@ -235,14 +234,13 @@ extension RootReducer {
|
|||
}
|
||||
.cancellable(id: CancelId, cancelInFlight: true)
|
||||
}
|
||||
|
||||
|
||||
/// Stored wallet is present, database files may or may not be present, trying to initialize app state variables and environments.
|
||||
/// When initialization succeeds user is taken to the home screen.
|
||||
case .initialization(.initializeSDK(let walletMode)):
|
||||
do {
|
||||
let storedWallet = try walletStorage.exportWallet()
|
||||
let birthday = storedWallet.birthday?.value() ?? zcashSDKEnvironment.latestCheckpoint
|
||||
|
||||
try mnemonic.isValid(storedWallet.seedPhrase.value())
|
||||
let seedBytes = try mnemonic.toSeed(storedWallet.seedPhrase.value())
|
||||
|
||||
|
@ -250,7 +248,7 @@ extension RootReducer {
|
|||
do {
|
||||
try await sdkSynchronizer.prepareWith(seedBytes, birthday, walletMode)
|
||||
try await sdkSynchronizer.start(false)
|
||||
|
||||
|
||||
let uAddress = try? await sdkSynchronizer.getUnifiedAddress(0)
|
||||
await send(.initialization(.initializationSuccessfullyDone(uAddress)))
|
||||
} catch {
|
||||
|
@ -260,16 +258,16 @@ extension RootReducer {
|
|||
} catch {
|
||||
return Effect.send(.initialization(.initializationFailed(error.toZcashError())))
|
||||
}
|
||||
|
||||
|
||||
case .initialization(.initializationSuccessfullyDone(let uAddress)):
|
||||
state.tabsState.addressDetailsState.uAddress = uAddress
|
||||
return .send(.initialization(.registerForSynchronizersUpdate))
|
||||
|
||||
|
||||
case .initialization(.checkBackupPhraseValidation):
|
||||
do {
|
||||
let storedWallet = try walletStorage.exportWallet()
|
||||
var landingDestination = RootReducer.DestinationState.Destination.tabs
|
||||
|
||||
|
||||
if !storedWallet.hasUserPassedPhraseBackupTest {
|
||||
let phraseWords = mnemonic.asWords(storedWallet.seedPhrase.value())
|
||||
|
||||
|
@ -297,7 +295,7 @@ extension RootReducer {
|
|||
case .initialization(.nukeWalletRequest):
|
||||
state.alert = AlertState.wipeRequest()
|
||||
return .none
|
||||
|
||||
|
||||
case .initialization(.nukeWallet):
|
||||
guard let wipePublisher = sdkSynchronizer.wipe() else {
|
||||
return Effect.send(.nukeWalletFailed)
|
||||
|
@ -312,17 +310,40 @@ extension RootReducer {
|
|||
.cancellable(id: SynchronizerCancelId, cancelInFlight: true)
|
||||
|
||||
case .nukeWalletSucceeded:
|
||||
state = .initial
|
||||
if state.appInitializationState != .keysMissing {
|
||||
state = .initial
|
||||
}
|
||||
state.splashAppeared = true
|
||||
walletStorage.nukeWallet()
|
||||
try? readTransactionsStorage.nukeWallet()
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
.run { send in
|
||||
await userStoredPreferences.removeAll()
|
||||
},
|
||||
Effect.send(.initialization(.checkWalletInitialization))
|
||||
)
|
||||
|
||||
if state.appInitializationState == .keysMissing && state.onboardingState.destination == .importExistingWallet {
|
||||
state.appInitializationState = .uninitialized
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
.run { send in
|
||||
await userStoredPreferences.removeAll()
|
||||
},
|
||||
Effect.send(.onboarding(.importWallet(.updateDestination(.birthday))))
|
||||
)
|
||||
} else if state.appInitializationState == .keysMissing && state.onboardingState.destination == .createNewWallet {
|
||||
state.appInitializationState = .uninitialized
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
.run { send in
|
||||
await userStoredPreferences.removeAll()
|
||||
},
|
||||
Effect.send(.onboarding(.securityWarning(.createNewWallet)))
|
||||
)
|
||||
} else {
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
.run { send in
|
||||
await userStoredPreferences.removeAll()
|
||||
},
|
||||
Effect.send(.initialization(.checkWalletInitialization))
|
||||
)
|
||||
}
|
||||
|
||||
case .nukeWalletFailed:
|
||||
let backDestination: Effect<RootReducer.Action>
|
||||
|
@ -332,10 +353,15 @@ extension RootReducer {
|
|||
backDestination = Effect.send(.destination(.updateDestination(state.destinationState.destination)))
|
||||
}
|
||||
state.alert = AlertState.wipeFailed()
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
backDestination
|
||||
)
|
||||
|
||||
if state.appInitializationState == .keysMissing {
|
||||
return .cancel(id: SynchronizerCancelId)
|
||||
} else {
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
backDestination
|
||||
)
|
||||
}
|
||||
|
||||
case .phraseDisplay(.finishedPressed):
|
||||
do {
|
||||
|
@ -352,6 +378,38 @@ extension RootReducer {
|
|||
Effect.send(.destination(.updateDestination(.startup)))
|
||||
)
|
||||
|
||||
case .onboarding(.securityWarning(.confirmTapped)):
|
||||
if state.appInitializationState == .keysMissing {
|
||||
state.alert = AlertState.existingWallet()
|
||||
return .none
|
||||
} else {
|
||||
return .send(.onboarding(.securityWarning(.createNewWallet)))
|
||||
}
|
||||
|
||||
case .initialization(.restoreExistingWallet):
|
||||
return .run { send in
|
||||
await send(.onboarding(.updateDestination(nil)))
|
||||
try await mainQueue.sleep(for: .seconds(1))
|
||||
await send(.onboarding(.importExistingWallet))
|
||||
}
|
||||
|
||||
case .onboarding(.importWallet(.nextPressed)):
|
||||
if state.appInitializationState == .keysMissing {
|
||||
let seedPhrase = state.onboardingState.importWalletState.importedSeedPhrase.data
|
||||
return .run { send in
|
||||
do {
|
||||
let seedBytes = try mnemonic.toSeed(seedPhrase)
|
||||
let result = try await sdkSynchronizer.isSeedRelevantToAnyDerivedAccount(seedBytes)
|
||||
await send(.initialization(.seedValidationResult(result)))
|
||||
} catch {
|
||||
await send(.initialization(.seedValidationResult(false)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.onboardingState.importWalletState.destination = .birthday
|
||||
return .none
|
||||
}
|
||||
|
||||
case .onboarding(.importWallet(.successfullyRecovered)):
|
||||
state.alert = AlertState.successfullyRecovered()
|
||||
return Effect.send(.destination(.updateDestination(.tabs)))
|
||||
|
@ -365,6 +423,14 @@ extension RootReducer {
|
|||
}
|
||||
)
|
||||
|
||||
case .initialization(.seedValidationResult(let validSeed)):
|
||||
if validSeed {
|
||||
return .send(.onboarding(.importWallet(.restoreWallet)))
|
||||
} else {
|
||||
state.alert = AlertState.differentSeed()
|
||||
}
|
||||
return .none
|
||||
|
||||
case .initialization(.configureCrashReporter):
|
||||
crashReporter.configure(
|
||||
!userStoredPreferences.isUserOptedOutOfCrashReporting()
|
||||
|
|
|
@ -297,11 +297,33 @@ extension AlertState where Action == RootReducer.Action {
|
|||
}
|
||||
}
|
||||
|
||||
public static func tmpMigrationToBeDeveloped() -> AlertState {
|
||||
public static func differentSeed() -> AlertState {
|
||||
AlertState {
|
||||
TextState("Automatic migration to be developed soon")
|
||||
TextState("Warning")
|
||||
} actions: {
|
||||
ButtonState(role: .cancel, action: .alert(.dismiss)) {
|
||||
TextState("Try Again")
|
||||
}
|
||||
ButtonState(role: .destructive, action: .initialization(.nukeWallet)) {
|
||||
TextState("Continue")
|
||||
}
|
||||
} message: {
|
||||
TextState("This copy of Zashi has been migrated from another device. Your funds are safe provided that you have the seed phrase. This issue will be addressed soon; until then, delete Zashi and reinstall it, providing the seed phrase to restore your wallet.")
|
||||
TextState("This recovery phrase doesn't match the Zashi database backup saved on this device. If you proceed, you will lose access to this database backup and if you try to restore later, some information may be lost.")
|
||||
}
|
||||
}
|
||||
|
||||
public static func existingWallet() -> AlertState {
|
||||
AlertState {
|
||||
TextState("Warning")
|
||||
} actions: {
|
||||
ButtonState(role: .cancel, action: .initialization(.restoreExistingWallet)) {
|
||||
TextState("Restore")
|
||||
}
|
||||
ButtonState(role: .destructive, action: .initialization(.nukeWallet)) {
|
||||
TextState("Continue")
|
||||
}
|
||||
} message: {
|
||||
TextState("We identified a Zashi database backup on this device. If you create a new wallet, you will lose access to this database backup and if you try to restore later, some information may be lost.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public struct SecurityWarning {
|
|||
case alert(PresentationAction<Action>)
|
||||
case binding(BindingAction<SecurityWarning.State>)
|
||||
case confirmTapped
|
||||
case createNewWallet
|
||||
case newWalletCreated
|
||||
case onAppear
|
||||
case recoveryPhraseDisplay(RecoveryPhraseDisplay.Action)
|
||||
|
@ -85,6 +86,9 @@ public struct SecurityWarning {
|
|||
return .none
|
||||
|
||||
case .confirmTapped:
|
||||
return .none
|
||||
|
||||
case .createNewWallet:
|
||||
do {
|
||||
// get the random english mnemonic
|
||||
let newRandomPhrase = try mnemonic.randomMnemonic()
|
||||
|
|
|
@ -320,8 +320,10 @@ public struct SendFlowReducer: Reducer {
|
|||
return .none
|
||||
|
||||
case .synchronizerStateChanged(let latestState):
|
||||
state.spendableBalance = latestState.data.accountBalance?.data?.saplingBalance.spendableValue ?? .zero
|
||||
state.totalBalance = latestState.data.accountBalance?.data?.saplingBalance.total() ?? .zero
|
||||
let latestAccountBalance = latestState.data.accountBalance?.data
|
||||
|
||||
state.spendableBalance = (latestAccountBalance?.saplingBalance.spendableValue ?? .zero) + (latestAccountBalance?.orchardBalance.spendableValue ?? .zero)
|
||||
state.totalBalance = (latestAccountBalance?.saplingBalance.total() ?? .zero) + (latestAccountBalance?.orchardBalance.total() ?? .zero)
|
||||
state.transactionAmountInputState.maxValue = state.spendableBalance.amount.redacted
|
||||
return .none
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import Foundation
|
||||
import ZcashLightClientKit
|
||||
import Generated
|
||||
import Utils
|
||||
|
||||
public struct SyncStatusSnapshot: Equatable {
|
||||
public let message: String
|
||||
|
@ -27,7 +28,7 @@ public struct SyncStatusSnapshot: Equatable {
|
|||
return SyncStatusSnapshot(state, L10n.Sync.Message.unprepared)
|
||||
|
||||
case .error(let error):
|
||||
return SyncStatusSnapshot(state, L10n.Sync.Message.error(error.toZcashError().message))
|
||||
return SyncStatusSnapshot(state, L10n.Sync.Message.error(error.toZcashError().detailedMessage))
|
||||
|
||||
case .stopped:
|
||||
return SyncStatusSnapshot(state, L10n.Sync.Message.stopped)
|
||||
|
|
|
@ -1204,7 +1204,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = RLPRR8CPQG;
|
||||
|
@ -1234,7 +1234,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = RLPRR8CPQG;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -1539,7 +1539,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = RLPRR8CPQG;
|
||||
|
@ -1552,7 +1552,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.1;
|
||||
OTHER_SWIFT_FLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.secant-mainnet";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1569,7 +1569,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = RLPRR8CPQG;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -1581,7 +1581,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.1;
|
||||
OTHER_SWIFT_FLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.secant-mainnet";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1684,7 +1684,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = RLPRR8CPQG;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -1759,7 +1759,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = RLPRR8CPQG;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -1771,7 +1771,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.1;
|
||||
OTHER_SWIFT_FLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.secant-mainnet";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
|
@ -374,17 +374,17 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
||||
"state" : {
|
||||
"revision" : "7c801be1f445402a433b32835a50d832e8a50437",
|
||||
"version" : "0.6.0"
|
||||
"revision" : "c7e5158edf5e62af15492d30237163b78af35ce9",
|
||||
"version" : "0.7.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "zcashlightclientkit",
|
||||
"identity" : "zcash-swift-wallet-sdk",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
||||
"location" : "https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk",
|
||||
"state" : {
|
||||
"revision" : "6c9b7a91d6b9ec4f3b8cb699a558eac1178ba837",
|
||||
"version" : "2.0.11"
|
||||
"revision" : "8909f237225676be70dfeaa103b77139481dfd86",
|
||||
"version" : "2.1.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -203,7 +203,11 @@ class AppInitializationTests: XCTestCase {
|
|||
|
||||
await store.receive(.initialization(.respondToWalletInitializationState(.keysMissing))) { state in
|
||||
state.appInitializationState = .keysMissing
|
||||
state.alert = AlertState.tmpMigrationToBeDeveloped()
|
||||
}
|
||||
|
||||
await store.receive(.destination(.updateDestination(.onboarding))) { state in
|
||||
state.destinationState.internalDestination = .onboarding
|
||||
state.destinationState.previousDestination = .welcome
|
||||
}
|
||||
|
||||
await store.finish()
|
||||
|
|
|
@ -133,7 +133,11 @@ class RootTests: XCTestCase {
|
|||
|
||||
await store.send(.initialization(.respondToWalletInitializationState(.keysMissing))) { state in
|
||||
state.appInitializationState = .keysMissing
|
||||
state.alert = AlertState.tmpMigrationToBeDeveloped()
|
||||
}
|
||||
|
||||
await store.receive(.destination(.updateDestination(.onboarding))) { state in
|
||||
state.destinationState.internalDestination = .onboarding
|
||||
state.destinationState.previousDestination = .welcome
|
||||
}
|
||||
|
||||
await store.finish()
|
||||
|
|
Loading…
Reference in New Issue