diff --git a/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift b/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift index 4e5de27fec7..06ae83c8bd3 100644 --- a/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift +++ b/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift @@ -335,8 +335,8 @@ extension Tab: BraveWalletProviderDelegate { let origin = getOrigin() // check if we receive account creation request without a wallet setup - let keyring = await keyringService.keyringInfo(BraveWallet.KeyringId.default) - if !keyring.isKeyringCreated { + let isWalletCreated = await keyringService.isWalletCreated() + if !isWalletCreated { // Wallet is not setup. User must onboard / setup wallet first. self.tabDelegate?.showWalletNotification(self, origin: origin) return @@ -579,13 +579,13 @@ extension Tab: BraveWalletSolanaEventsListener { } extension Tab: BraveWalletKeyringServiceObserver { - func keyringCreated(_ keyringId: BraveWallet.KeyringId) { + func walletCreated() { } func walletRestored() { } - func keyringReset() { + func walletReset() { reload() tabDelegate?.updateURLBarWalletButton() } diff --git a/Sources/BraveWallet/Crypto/Asset Details/AssetDetailView.swift b/Sources/BraveWallet/Crypto/Asset Details/AssetDetailView.swift index 0038f667b63..845877179a7 100644 --- a/Sources/BraveWallet/Crypto/Asset Details/AssetDetailView.swift +++ b/Sources/BraveWallet/Crypto/Asset Details/AssetDetailView.swift @@ -309,8 +309,8 @@ struct AssetDetailView: View { } ) ) - .onChange(of: keyringStore.defaultKeyring) { newValue in - if newValue.isLocked, isShowingAuroraBridgeAlert { + .onChange(of: keyringStore.isWalletLocked) { isLocked in + if isLocked, isShowingAuroraBridgeAlert { isShowingAuroraBridgeAlert = false } } diff --git a/Sources/BraveWallet/Crypto/CryptoView.swift b/Sources/BraveWallet/Crypto/CryptoView.swift index d6284c1ba58..0b3bef368ff 100644 --- a/Sources/BraveWallet/Crypto/CryptoView.swift +++ b/Sources/BraveWallet/Crypto/CryptoView.swift @@ -43,11 +43,10 @@ public struct CryptoView: View { } private var visibleScreen: VisibleScreen { - let keyring = keyringStore.defaultKeyring - if !keyring.isKeyringCreated || keyringStore.isOnboardingVisible { + if !keyringStore.isWalletCreated || keyringStore.isOnboardingVisible { return .onboarding } - if keyring.isLocked || keyringStore.isRestoreFromUnlockBiometricsPromptVisible { + if keyringStore.isWalletLocked || keyringStore.isRestoreFromUnlockBiometricsPromptVisible { return .unlock } return .crypto diff --git a/Sources/BraveWallet/Crypto/Portfolio/PortfolioHeaderView.swift b/Sources/BraveWallet/Crypto/Portfolio/PortfolioHeaderView.swift index 385e4235219..be723b5bf18 100644 --- a/Sources/BraveWallet/Crypto/Portfolio/PortfolioHeaderView.swift +++ b/Sources/BraveWallet/Crypto/Portfolio/PortfolioHeaderView.swift @@ -25,7 +25,7 @@ struct PortfolioHeaderView: View { @ObservedObject private var isShowingBalances = Preferences.Wallet.isShowingBalances private var isShowingBackupBanner: Bool { - !keyringStore.defaultKeyring.isBackedUp && !dismissedBackupBannerThisSession + !keyringStore.isWalletBackedUp && !dismissedBackupBannerThisSession } private var emptyBalanceData: [BalanceTimePrice] { diff --git a/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift b/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift index 3f63ced6c6b..f2054fcfcea 100644 --- a/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift @@ -331,13 +331,13 @@ class AccountActivityStore: ObservableObject, WalletObserverStore { } extension AccountActivityStore: BraveWalletKeyringServiceObserver { - func keyringCreated(_ keyringId: BraveWallet.KeyringId) { + func walletCreated() { } func walletRestored() { } - func keyringReset() { + func walletReset() { } func locked() { diff --git a/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift b/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift index 57596461680..f421910343e 100644 --- a/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift @@ -407,14 +407,14 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { } extension AssetDetailStore: BraveWalletKeyringServiceObserver { - func keyringReset() { + func walletReset() { } func accountsChanged() { update() } - func keyringCreated(_ keyringId: BraveWallet.KeyringId) { + func walletCreated() { } func walletRestored() { diff --git a/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift b/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift index ce071188b1f..55764db9d84 100644 --- a/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift @@ -214,12 +214,12 @@ public class CryptoStore: ObservableObject, WalletObserverStore { guard !isObserving else { return } self.keyringServiceObserver = KeyringServiceObserver( keyringService: keyringService, - _keyringReset: { [weak self] in + _walletReset: { [weak self] in WalletProviderPermissionRequestsManager.shared.cancelAllPendingRequests(for: [.eth, .sol]) WalletProviderAccountCreationRequestManager.shared.cancelAllPendingRequests(coins: [.eth, .sol]) self?.rejectAllPendingWebpageRequests() }, - _keyringCreated: { _ in + _walletCreated: { // 1. We don't need to rely on this observer method to migrate user visible assets // when user creates a new wallet, since in this case `CryptoStore` has not yet been initialized // 2. We don't need to rely on this observer method to migrate user visible assets diff --git a/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift b/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift index 3892de1abb4..eac0d70cd12 100644 --- a/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift @@ -114,15 +114,8 @@ enum PasswordStatus: Equatable { /// /// This wraps a KeyringService that you would obtain through BraveCore and makes it observable public class KeyringStore: ObservableObject, WalletObserverStore { - /// The defualt keyring information. By default this is an empty keyring which has no accounts. - @Published private(set) var defaultKeyring: BraveWallet.KeyringInfo = .init( - id: .default, - isKeyringCreated: false, - isLocked: true, - isBackedUp: false - ) - /// A boolean indciates front-end has or has not loaded Keyring from the core - @Published var isDefaultKeyringLoaded = false + /// A boolean indciates front-end has or has not loaded accounts from the core + @Published var isLoaded = false /// Whether or not the user should be viewing the onboarding flow to setup a keyring @Published private(set) var isOnboardingVisible: Bool = false /// Whether or not the last time the wallet was locked was due to the user manually locking it @@ -147,11 +140,12 @@ public class KeyringStore: ObservableObject, WalletObserverStore { setSelectedAccount(to: selectedAccount) } } - /// All available `KeyringInfo` for all supported coin type - @Published var allKeyrings: [BraveWallet.KeyringInfo] = [] - /// Indicates if default keyring has been created. This value used for display wallet related settings if default - /// keyring has been created - @Published var isDefaultKeyringCreated: Bool = false + /// Indicates if the wallet has been created. This value used for display wallet related settings if created. + @Published var isWalletCreated: Bool = false + /// Indicates if the wallet has been locked. + @Published var isWalletLocked: Bool = true + /// Indicates if the wallet has been backed up. + @Published var isWalletBackedUp: Bool = false /// All `AccountInfo` for all available keyrings @Published var allAccounts: [BraveWallet.AccountInfo] = [] @@ -192,13 +186,13 @@ public class KeyringStore: ObservableObject, WalletObserverStore { self.walletService = walletService self.rpcService = rpcService self.keychain = keychain - - self.setupObservers() - - updateKeyringInfo() - - self.keyringService.keyringInfo(BraveWallet.KeyringId.default) { [self] keyringInfo in - isOnboardingVisible = !keyringInfo.isKeyringCreated + + setupObservers() + updateInfo() + + Task { @MainActor in + let isWalletCreated = await keyringService.isWalletCreated() + self.isOnboardingVisible = !isWalletCreated if isKeychainPasswordStored && isOnboardingVisible { // If a user deletes the app and they had a stored user password in the past that keychain item // stays persisted. When we grab the keyring for the first time we should check to see if they have @@ -210,7 +204,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { cancellable = NotificationCenter.default .publisher(for: UIApplication.didBecomeActiveNotification, object: nil) .sink { [weak self] _ in - self?.updateKeyringInfo() + self?.updateInfo() } } @@ -218,27 +212,19 @@ public class KeyringStore: ObservableObject, WalletObserverStore { guard !isObserving else { return } self.keyringServiceObserver = KeyringServiceObserver( keyringService: keyringService, - _keyringReset: { [weak self] in + _walletReset: { [weak self] in self?.isOnboardingVisible = true - self?.updateKeyringInfo() + self?.updateInfo() }, - _keyringCreated: { [weak self] keyringId in + _walletCreated: { [weak self] in guard let self else { return } - if self.isOnboardingVisible, !self.isCreatingWallet, keyringId == BraveWallet.KeyringId.default { + if self.isOnboardingVisible, !self.isCreatingWallet { // Another window has created a wallet. We should dismiss onboarding on this // window and allow the other window to continue with it's onboarding flow. self.isOnboardingVisible = false } - Task { @MainActor in - let allAccounts = await self.keyringService.allAccounts() - let allAccountsForKeyring = allAccounts.accounts.filter { $0.keyringId == keyringId } - // if the new Keyring doesn't have a selected account, select the first account - if allAccounts.selectedAccount == nil, let newAccount = allAccountsForKeyring.first { - await self.keyringService.setSelectedAccount(newAccount.accountId) - } - self.updateKeyringInfo() - } + self.updateInfo() }, _walletRestored: { [weak self] in guard let self else { return } @@ -248,34 +234,34 @@ public class KeyringStore: ObservableObject, WalletObserverStore { self.isOnboardingVisible = false } - self.updateKeyringInfo() + self.updateInfo() }, _locked: { [weak self] in // Put this in the background since biometrics prompt will block the main queue DispatchQueue.main.async { - self?.updateKeyringInfo() + self?.updateInfo() } }, _unlocked: { [weak self] in - self?.updateKeyringInfo() + self?.updateInfo() }, _backedUp: { [weak self] in - self?.updateKeyringInfo() + self?.updateInfo() }, _accountsChanged: { [weak self] in - self?.updateKeyringInfo() + self?.updateInfo() }, _selectedWalletAccountChanged: { [weak self] _ in - self?.updateKeyringInfo() + self?.updateInfo() }, _selectedDappAccountChanged: { [weak self] _, _ in - self?.updateKeyringInfo() + self?.updateInfo() } ) self.rpcServiceObserver = JsonRpcServiceObserver( rpcService: rpcService, _chainChangedEvent: { [weak self] _, _, _ in - self?.updateKeyringInfo() + self?.updateInfo() } ) } @@ -285,7 +271,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { rpcServiceObserver = nil } - private func updateKeyringInfo() { + private func updateInfo() { if UIApplication.shared.applicationState != .active { // Changes made in the backgroud due to timers going off at launch don't // re-render things properly. @@ -295,21 +281,19 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } Task { @MainActor in // fetch all KeyringInfo for all coin types let allAccounts = await keyringService.allAccounts() - let allKeyrings = await keyringService.keyrings(for: WalletConstants.supportedCoinTypes()) - if let defaultKeyring = allKeyrings.first(where: { $0.id == BraveWallet.KeyringId.default }) { - self.defaultKeyring = defaultKeyring - self.isDefaultKeyringLoaded = true - self.isDefaultKeyringCreated = defaultKeyring.isKeyringCreated - // fallback case where user completed front-end onboarding, but has no keyring created/accounts. - if !defaultKeyring.isKeyringCreated && Preferences.Wallet.isOnboardingCompleted.value { - Preferences.Wallet.isOnboardingCompleted.reset() - } - } - self.allKeyrings = allKeyrings self.allAccounts = allAccounts.accounts if let selectedAccount = allAccounts.selectedAccount { self.selectedAccount = selectedAccount } + self.isWalletCreated = await keyringService.isWalletCreated() + // fallback case where user completed front-end onboarding, but has no keyring created/accounts. + // this can occur if we crash prior to saving, ex. brave-ios #8291 + if !isWalletCreated && Preferences.Wallet.isOnboardingCompleted.value { + Preferences.Wallet.isOnboardingCompleted.reset() + } + self.isWalletLocked = await keyringService.isLocked() + self.isWalletBackedUp = await keyringService.isWalletBackedUp() + self.isLoaded = true } } @@ -331,6 +315,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { self.isCreatingWallet = false self.isRestoringWallet = false self.isOnboardingVisible = false + updateInfo() } func notifyWalletBackupComplete() { @@ -340,10 +325,11 @@ public class KeyringStore: ObservableObject, WalletObserverStore { func lock() { lockedManually = true keyringService.lock() + isWalletLocked = true } func unlock(password: String, completion: @escaping (Bool) -> Void) { - if !defaultKeyring.isKeyringCreated { + if !isWalletCreated { completion(false) return } @@ -352,13 +338,14 @@ public class KeyringStore: ObservableObject, WalletObserverStore { if unlocked { // Reset this state for next unlock self?.lockedManually = false + self?.isWalletLocked = false } - self?.updateKeyringInfo() + self?.updateInfo() } } func validate(password: String, completion: @escaping (Bool) -> Void) { - if !defaultKeyring.isKeyringCreated { + if !isWalletCreated { completion(false) return } @@ -390,7 +377,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { func createWallet(password: String, completion: ((String) -> Void)? = nil) { isCreatingWallet = true keyringService.createWallet(password) { [weak self] mnemonic in - self?.updateKeyringInfo() + self?.updateInfo() if !mnemonic.isEmpty { self?.passwordToSaveInBiometric = password } @@ -424,7 +411,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { // Restoring from wallet means you already have your phrase backed up self.passwordToSaveInBiometric = password self.notifyWalletBackupComplete() - self.updateKeyringInfo() + self.updateInfo() self.resetKeychainStoredPassword() } for coin in WalletConstants.supportedCoinTypes(.dapps) { // only coin types support dapps have permission management @@ -453,7 +440,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { keyringId: BraveWallet.KeyringId.keyringId(for: coin, on: chainId), accountName: name ) { accountInfo in - self.updateKeyringInfo() + self.updateInfo() completion?(accountInfo != nil) } } @@ -472,7 +459,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } } else { keyringService.importAccount(name, privateKey: privateKey, coin: coin) { accountInfo in - self.updateKeyringInfo() + self.updateInfo() completion?(accountInfo) } } @@ -496,14 +483,14 @@ public class KeyringStore: ObservableObject, WalletObserverStore { ) { success in completion?(success) if success { - self.updateKeyringInfo() + self.updateInfo() } } } func renameAccount(_ account: BraveWallet.AccountInfo, name: String, completion: ((Bool) -> Void)? = nil) { let handler: (Bool) -> Void = { success in - self.updateKeyringInfo() + self.updateInfo() completion?(success) } keyringService.setAccountName(account.accountId, name: name, completion: handler) @@ -516,7 +503,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } func notifyUserInteraction() { - if defaultKeyring.isLocked { + if isWalletLocked { // Auto-lock isn't running until the keyring is unlocked return } diff --git a/Sources/BraveWallet/Crypto/Stores/UserAssetsStore.swift b/Sources/BraveWallet/Crypto/Stores/UserAssetsStore.swift index b0345dc4769..e9a1baded16 100644 --- a/Sources/BraveWallet/Crypto/Stores/UserAssetsStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/UserAssetsStore.swift @@ -109,7 +109,7 @@ public class UserAssetsStore: ObservableObject, WalletObserverStore { guard !isObserving else { return } self.keyringServiceObserver = KeyringServiceObserver( keyringService: keyringService, - _keyringCreated: { [weak self] _ in + _walletCreated: { [weak self] in self?.update() } ) diff --git a/Sources/BraveWallet/Crypto/Stores/WalletStore.swift b/Sources/BraveWallet/Crypto/Stores/WalletStore.swift index 4bb2aa0baea..511f9976a36 100644 --- a/Sources/BraveWallet/Crypto/Stores/WalletStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/WalletStore.swift @@ -111,17 +111,16 @@ public class WalletStore { solTxManagerProxy: BraveWalletSolanaTxManagerProxy, ipfsApi: IpfsAPI ) { - self.cancellable = self.keyringStore.$defaultKeyring - .map(\.isKeyringCreated) + self.cancellable = self.keyringStore.$isWalletCreated .removeDuplicates() - .sink { [weak self] isDefaultKeyringCreated in + .sink { [weak self] isWalletCreated in guard let self = self else { return } - if !isDefaultKeyringCreated, self.cryptoStore != nil { + if !isWalletCreated, self.cryptoStore != nil { // only tear down `CryptoStore` since we still need to listen // default keyring creation if user didn't dismiss the wallet after reset self.cryptoStore?.tearDown() self.cryptoStore = nil - } else if isDefaultKeyringCreated, self.cryptoStore == nil { + } else if isWalletCreated, self.cryptoStore == nil { self.cryptoStore = CryptoStore( keyringService: keyringService, rpcService: rpcService, diff --git a/Sources/BraveWallet/Crypto/UnlockWalletView.swift b/Sources/BraveWallet/Crypto/UnlockWalletView.swift index be4987d2f22..784e768d05f 100644 --- a/Sources/BraveWallet/Crypto/UnlockWalletView.swift +++ b/Sources/BraveWallet/Crypto/UnlockWalletView.swift @@ -122,7 +122,7 @@ struct UnlockWalletView: View { } .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [self] in - if !keyringStore.lockedManually && !attemptedBiometricsUnlock && keyringStore.defaultKeyring.isLocked && UIApplication.shared.isProtectedDataAvailable { + if !keyringStore.lockedManually && !attemptedBiometricsUnlock && keyringStore.isWalletLocked && UIApplication.shared.isProtectedDataAvailable { attemptedBiometricsUnlock = true fillPasswordFromKeychain() } diff --git a/Sources/BraveWallet/Crypto/WalletServiceObservers.swift b/Sources/BraveWallet/Crypto/WalletServiceObservers.swift index 1bd267c905a..b0279b71e27 100644 --- a/Sources/BraveWallet/Crypto/WalletServiceObservers.swift +++ b/Sources/BraveWallet/Crypto/WalletServiceObservers.swift @@ -7,8 +7,8 @@ import BraveCore class KeyringServiceObserver: BraveWalletKeyringServiceObserver { - var _keyringReset: (() -> Void)? - var _keyringCreated: ((_ keyringId: BraveWallet.KeyringId) -> Void)? + var _walletReset: (() -> Void)? + var _walletCreated: (() -> Void)? var _walletRestored: (() -> Void)? var _locked: (() -> Void)? var _unlocked: (() -> Void)? @@ -21,8 +21,8 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { init( keyringService: BraveWalletKeyringService, - _keyringReset: (() -> Void)? = nil, - _keyringCreated: ((BraveWallet.KeyringId) -> Void)? = nil, + _walletReset: (() -> Void)? = nil, + _walletCreated: (() -> Void)? = nil, _walletRestored: (() -> Void)? = nil, _locked: (() -> Void)? = nil, _unlocked: (() -> Void)? = nil, @@ -33,8 +33,8 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { _selectedDappAccountChanged: ((BraveWallet.CoinType, BraveWallet.AccountInfo?) -> Void)? = nil, _accountsAdded: (([BraveWallet.AccountInfo]) -> Void)? = nil ) { - self._keyringReset = _keyringReset - self._keyringCreated = _keyringCreated + self._walletReset = _walletReset + self._walletCreated = _walletCreated self._walletRestored = _walletRestored self._locked = _locked self._unlocked = _unlocked @@ -47,11 +47,11 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { keyringService.add(self) } - public func keyringReset() { - _keyringReset?() + func walletReset() { + _walletReset?() } - public func keyringCreated(_ keyringId: BraveWallet.KeyringId) { - _keyringCreated?(keyringId) + func walletCreated() { + _walletCreated?() } public func walletRestored() { _walletRestored?() diff --git a/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift b/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift index c71b925bd80..ea770f5a724 100644 --- a/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift +++ b/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift @@ -218,27 +218,6 @@ extension BraveWallet.CoinType { } } -extension BraveWallet.KeyringInfo { - var coin: BraveWallet.CoinType? { - switch self.id { - case .default: - return .eth - case .solana: - return .sol - case .filecoin, .filecoinTestnet: - return .fil - case .bitcoin84, .bitcoin84Testnet: - return .btc - case .zCashMainnet: - return nil - case .zCashTestnet: - return nil - @unknown default: - return nil - } - } -} - extension BraveWallet.TransactionInfo { var coin: BraveWallet.CoinType { if txDataUnion.solanaTxData != nil { diff --git a/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift b/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift index c061425538f..74dc2c8f6e6 100644 --- a/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift +++ b/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift @@ -9,61 +9,6 @@ import OrderedCollections extension BraveWalletKeyringService { - // Fetches all keyrings for all given coin types - func keyrings( - for coins: OrderedSet - ) async -> [BraveWallet.KeyringInfo] { - var allKeyrings: [BraveWallet.KeyringInfo] = [] - allKeyrings = await withTaskGroup( - of: BraveWallet.KeyringInfo.self, - returning: [BraveWallet.KeyringInfo].self, - body: { @MainActor group in - let keyringIds: [BraveWallet.KeyringId] = coins.flatMap(\.keyringIds) - for keyringId in keyringIds { - group.addTask { @MainActor in - await self.keyringInfo(keyringId) - } - } - return await group.reduce([BraveWallet.KeyringInfo](), { partialResult, prior in - return partialResult + [prior] - }) - .sorted(by: { lhs, rhs in - if lhs.coin == .fil && rhs.coin == .fil { - return lhs.id == BraveWallet.KeyringId.filecoin - } else { - return (lhs.coin ?? .eth).sortOrder < (rhs.coin ?? .eth).sortOrder - } - }) - } - ) - return allKeyrings - } - - // Fetches all keyrings for all given keyring IDs - func keyrings( - for keyringIds: [BraveWallet.KeyringId] - ) async -> [BraveWallet.KeyringInfo] { - var allKeyrings: [BraveWallet.KeyringInfo] = [] - allKeyrings = await withTaskGroup( - of: BraveWallet.KeyringInfo.self, - returning: [BraveWallet.KeyringInfo].self, - body: { @MainActor group in - for keyringId in keyringIds { - group.addTask { @MainActor in - await self.keyringInfo(keyringId) - } - } - return await group.reduce([BraveWallet.KeyringInfo](), { partialResult, prior in - return partialResult + [prior] - }) - .sorted(by: { lhs, rhs in - (lhs.coin ?? .eth).sortOrder < (rhs.coin ?? .eth).sortOrder - }) - } - ) - return allKeyrings - } - /// Check if any wallet account has been created given a coin type and a chain id @MainActor func isAccountAvailable(for coin: BraveWallet.CoinType, chainId: String) async -> Bool { // KeyringId must be checked with chainId for Filecoin, BTC (2 keyring types). diff --git a/Sources/BraveWallet/Panels/WalletPanelView.swift b/Sources/BraveWallet/Panels/WalletPanelView.swift index cca4d44dc7e..09707428bde 100644 --- a/Sources/BraveWallet/Panels/WalletPanelView.swift +++ b/Sources/BraveWallet/Panels/WalletPanelView.swift @@ -37,13 +37,12 @@ public struct WalletPanelContainerView: View { } private var visibleScreen: VisibleScreen { - let keyring = keyringStore.defaultKeyring - // check if we are still fetching the `defaultKeyring` - if !keyringStore.isDefaultKeyringLoaded { + // check if we are still fetching async info from core + if !keyringStore.isLoaded { return .loading } - // keyring fetched, check if user has created a wallet - if !keyring.isKeyringCreated || keyringStore.isOnboardingVisible { + // keyring fetched, check if user has setup a wallet + if !keyringStore.isWalletCreated || keyringStore.isOnboardingVisible { return .onboarding } // keyring fetched & wallet setup, but selected account not fetched @@ -51,7 +50,7 @@ public struct WalletPanelContainerView: View { return .loading } // keyring fetched & wallet setup, wallet is locked - if keyring.isLocked || keyringStore.isRestoreFromUnlockBiometricsPromptVisible { // wallet is locked + if keyringStore.isWalletLocked || keyringStore.isRestoreFromUnlockBiometricsPromptVisible { // wallet is locked return .unlock } return .panel @@ -147,7 +146,12 @@ public struct WalletPanelContainerView: View { } } .frame(idealWidth: 320, maxWidth: .infinity) - .onChange(of: keyringStore.defaultKeyring) { newValue in + .onChange(of: keyringStore.isWalletCreated) { newValue in + if visibleScreen != .panel, !keyringStore.lockedManually { + presentWalletWithContext?(.panelUnlockOrSetup) + } + } + .onChange(of: keyringStore.isWalletLocked) { newValue in if visibleScreen != .panel, !keyringStore.lockedManually { presentWalletWithContext?(.panelUnlockOrSetup) } diff --git a/Sources/BraveWallet/Preview Content/MockKeyringService.swift b/Sources/BraveWallet/Preview Content/MockKeyringService.swift index 669ce72c697..aaaaa774a83 100644 --- a/Sources/BraveWallet/Preview Content/MockKeyringService.swift +++ b/Sources/BraveWallet/Preview Content/MockKeyringService.swift @@ -11,14 +11,9 @@ import BraveCore /// /// - note: Do not use this directly, use ``CryptoKeyringStore.previewStore`` class MockKeyringService: BraveWalletKeyringService { - private var keyrings: [BraveWallet.KeyringInfo] = [ - .init( - id: BraveWallet.KeyringId.default, - isKeyringCreated: false, - isLocked: false, - isBackedUp: true - ) - ] + private var isWalletCreated = true + private var isLocked = false + private var isBackedUp = false private var allAccounts: [BraveWallet.AccountInfo] = [] private var privateKeys: [String: String] = [:] private var password = "" @@ -26,9 +21,6 @@ class MockKeyringService: BraveWalletKeyringService { private let mnemonic = "pass entire pelican lock repair desert entire cactus actress remain gossip rail" private var observers: NSHashTable = .weakObjects() private var selectedAccount: BraveWallet.AccountInfo? - private var defaultKeyring: BraveWallet.KeyringInfo { - return keyrings.first(where: { $0.id == BraveWallet.KeyringId.default }) ?? keyrings[0] - } func add(_ observer: BraveWalletKeyringServiceObserver) { observers.add(observer) @@ -90,40 +82,34 @@ class MockKeyringService: BraveWalletKeyringService { } func createWallet(_ password: String, completion: @escaping (String) -> Void) { - defaultKeyring.isKeyringCreated = true - defaultKeyring.isLocked = false + isLocked = false self.password = password - self.addAccount( + addAccount( .eth, keyringId: BraveWallet.KeyringId.default, accountName: "Account 1" ) { [self] accountInfo in selectedAccount = accountInfo observers.allObjects.forEach { - $0.keyringCreated(BraveWallet.KeyringId.default) + $0.walletCreated() } completion(mnemonic) } } - func keyringInfo(_ keyringId: BraveWallet.KeyringId, completion: @escaping (BraveWallet.KeyringInfo) -> Void) { - let keyringInfo = keyrings.first(where: { $0.id == keyringId }) ?? keyrings[0] - completion(keyringInfo.copy() as! BraveWallet.KeyringInfo) // swiftlint:disable:this force_cast - } - func isLocked(_ completion: @escaping (Bool) -> Void) { - completion(defaultKeyring.isLocked) + completion(isLocked) } func lock() { - defaultKeyring.isLocked = true + isLocked = true observers.allObjects.forEach { $0.locked() } } func isWalletBackedUp(_ completion: @escaping (Bool) -> Void) { - completion(defaultKeyring.isBackedUp) + completion(isBackedUp) } func mnemonic(forDefaultKeyring password: String, completion: @escaping (String) -> Void) { @@ -131,13 +117,13 @@ class MockKeyringService: BraveWalletKeyringService { } func unlock(_ password: String, completion: @escaping (Bool) -> Void) { - if !defaultKeyring.isKeyringCreated { + if !isWalletCreated { completion(false) return } let passwordsMatch = self.password == password if passwordsMatch { - defaultKeyring.isLocked = false + isLocked = false observers.allObjects.forEach { $0.unlocked() } @@ -146,7 +132,7 @@ class MockKeyringService: BraveWalletKeyringService { } func notifyWalletBackupComplete() { - defaultKeyring.isBackedUp = true + isBackedUp = true observers.allObjects.forEach { $0.backedUp() } @@ -359,6 +345,10 @@ class MockKeyringService: BraveWalletKeyringService { func allAccounts(_ completion: @escaping (BraveWallet.AllAccountsInfo) -> Void) { } + + func isWalletCreated(_ completion: @escaping (Bool) -> Void) { + completion(isWalletCreated) + } } extension BraveWallet.AccountInfo { @@ -419,36 +409,6 @@ extension BraveWallet.AccountInfo { ) } -extension BraveWallet.KeyringInfo { - static let mockDefaultKeyringInfo: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.default, - isKeyringCreated: true, - isLocked: false, - isBackedUp: false - ) - - static let mockSolanaKeyringInfo: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.solana, - isKeyringCreated: true, - isLocked: false, - isBackedUp: false - ) - - static let mockFilecoinKeyringInfo: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.filecoin, - isKeyringCreated: true, - isLocked: false, - isBackedUp: false - ) - - static let mockFilecoinTestnetKeyringInfo: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.filecoinTestnet, - isKeyringCreated: true, - isLocked: false, - isBackedUp: false - ) -} - extension BraveWallet.AllAccountsInfo { static let mock: BraveWallet.AllAccountsInfo = .init( accounts: [ diff --git a/Sources/BraveWallet/Settings/Web3SettingsView.swift b/Sources/BraveWallet/Settings/Web3SettingsView.swift index caf0ee7bf5d..5007e12ad4c 100644 --- a/Sources/BraveWallet/Settings/Web3SettingsView.swift +++ b/Sources/BraveWallet/Settings/Web3SettingsView.swift @@ -171,11 +171,11 @@ private struct WalletSettingsView: View { } var body: some View { - if keyringStore.isDefaultKeyringCreated { + if keyringStore.isWalletCreated { sections } else { // `KeyringStore` is optional in `Web3SettingsView`, but observed here. - // When wallet is reset, we need SwiftUI to be notified `isDefaultKeyringCreated` + // When wallet is reset, we need SwiftUI to be notified `isWalletCreated` // changed so we can hide Wallet specific sections EmptyView() } @@ -213,7 +213,7 @@ private struct WalletSettingsView: View { } .listRowBackground(Color(.secondaryBraveGroupedBackground)) } - if settingsStore.isBiometricsAvailable, keyringStore.defaultKeyring.isKeyringCreated { + if settingsStore.isBiometricsAvailable, keyringStore.isWalletCreated { Section( footer: Text(Strings.Wallet.settingsEnableBiometricsFooter) .foregroundColor(Color(.secondaryBraveLabel)) diff --git a/Sources/BraveWallet/WalletHostingViewController.swift b/Sources/BraveWallet/WalletHostingViewController.swift index 83a3ed298d6..03ca32bc04c 100644 --- a/Sources/BraveWallet/WalletHostingViewController.swift +++ b/Sources/BraveWallet/WalletHostingViewController.swift @@ -79,9 +79,8 @@ public class WalletHostingViewController: UIHostingController { rootView.appRatingRequestAction = { [unowned self] in self.delegate?.requestAppReview() } - cancellable = walletStore.keyringStore.$defaultKeyring + cancellable = walletStore.keyringStore.$isWalletLocked .dropFirst() // Drop initial value - .map(\.isLocked) .removeDuplicates() .dropFirst() // Drop first async fetch of keyring .sink { [weak self] isLocked in diff --git a/Sources/BraveWallet/WalletPanelHostingController.swift b/Sources/BraveWallet/WalletPanelHostingController.swift index 7b54a19658b..314dd56cdaf 100644 --- a/Sources/BraveWallet/WalletPanelHostingController.swift +++ b/Sources/BraveWallet/WalletPanelHostingController.swift @@ -61,9 +61,8 @@ public class WalletPanelHostingController: UIHostingController (BraveWallet.TestKeyringService, BraveWallet.TestJsonRpcService, BraveWallet.TestBraveWalletService, BraveWallet.TestBlockchainRegistry, BraveWallet.TestAssetRatioService, BraveWallet.TestTxService, BraveWallet.TestSolanaTxManagerProxy, IpfsAPI) { let keyringService = BraveWallet.TestKeyringService() keyringService._addObserver = { _ in } - keyringService._keyringInfo = { keyringInfo, completion in - switch keyringInfo { - case .default: - completion(.mockDefaultKeyringInfo) - case .solana: - completion(.mockSolanaKeyringInfo) - case .filecoin: - completion(.mockFilecoinKeyringInfo) - case .filecoinTestnet: - completion(.mockFilecoinTestnetKeyringInfo) - default: - completion(.mockDefaultKeyringInfo) - } - } keyringService._allAccounts = { $0(.mock) } diff --git a/Tests/BraveWalletTests/AssetDetailStoreTests.swift b/Tests/BraveWalletTests/AssetDetailStoreTests.swift index fe5861f2823..65531e42117 100644 --- a/Tests/BraveWalletTests/AssetDetailStoreTests.swift +++ b/Tests/BraveWalletTests/AssetDetailStoreTests.swift @@ -24,9 +24,6 @@ class AssetDetailStoreTests: XCTestCase { } let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { - $1(.mockDefaultKeyringInfo) - } keyringService._allAccounts = { completion in completion(.mock) } @@ -233,11 +230,7 @@ class AssetDetailStoreTests: XCTestCase { completion(true, [.init(date: Date(), price: "0.99")]) } - let keyring = BraveWallet.KeyringInfo.mockDefaultKeyringInfo let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { - $1(keyring) - } keyringService._allAccounts = { completion in completion(.mock) } diff --git a/Tests/BraveWalletTests/KeyringStoreTests.swift b/Tests/BraveWalletTests/KeyringStoreTests.swift index 6868f7accda..92a536b87cb 100644 --- a/Tests/BraveWalletTests/KeyringStoreTests.swift +++ b/Tests/BraveWalletTests/KeyringStoreTests.swift @@ -18,20 +18,6 @@ class KeyringStoreTests: XCTestCase { let currentSelectedAccount: BraveWallet.AccountInfo = .mockEthAccount let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { keyringId, completion in - switch keyringId { - case BraveWallet.KeyringId.default: - completion(.mockDefaultKeyringInfo) - case BraveWallet.KeyringId.solana: - completion(.mockSolanaKeyringInfo) - case BraveWallet.KeyringId.filecoin: - completion(.mockFilecoinKeyringInfo) - case BraveWallet.KeyringId.filecoinTestnet: - completion(.mockFilecoinTestnetKeyringInfo) - default: - completion(.init()) - } - } keyringService._addObserver = { _ in } keyringService._isLocked = { $0(false) } keyringService._allAccounts = { completion in @@ -43,6 +29,8 @@ class KeyringStoreTests: XCTestCase { )) } keyringService._setSelectedAccount = { $1(true) } + keyringService._isWalletBackedUp = { $0(true) } + keyringService._isWalletCreated = { $0(true) } let rpcService = BraveWallet.TestJsonRpcService() rpcService._addObserver = { _ in } @@ -59,34 +47,6 @@ class KeyringStoreTests: XCTestCase { return (keyringService, rpcService, walletService) } - func testAllKeyrings() { - let (keyringService, rpcService, walletService) = setupServices() - - let store = KeyringStore( - keyringService: keyringService, - walletService: walletService, - rpcService: rpcService - ) - - let expectedKeyrings = [BraveWallet.KeyringInfo.mockDefaultKeyringInfo, BraveWallet.KeyringInfo.mockSolanaKeyringInfo, BraveWallet.KeyringInfo.mockFilecoinKeyringInfo, BraveWallet.KeyringInfo.mockFilecoinTestnetKeyringInfo] - - let allTokensExpectation = expectation(description: "allKeyrings") - store.$allKeyrings - .dropFirst() - .sink { allKeyrings in - defer { allTokensExpectation.fulfill() } - XCTAssertEqual(allKeyrings.count, 4) - for keyring in allKeyrings { - XCTAssertTrue(expectedKeyrings.contains(where: { $0.id == keyring.id })) - } - } - .store(in: &cancellables) - - waitForExpectations(timeout: 1) { error in - XCTAssertNil(error) - } - } - func testInitialSelectedAccount() { let (keyringService, rpcService, walletService) = setupServices() diff --git a/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift b/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift index 4a8e5bc325d..32848e0e4f3 100644 --- a/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift +++ b/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift @@ -24,15 +24,6 @@ import Preferences let currentChainId = currentNetwork.chainId let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { keyringId, completion in - let keyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.default, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true - ) - completion(keyring) - } keyringService._addObserver = { _ in } keyringService._isLocked = { $0(false) } keyringService._allAccounts = { completion in @@ -214,15 +205,6 @@ import Preferences .eth: [.mockEthAccount] ] - keyringService._keyringInfo = { keyringId, completion in - let keyring: BraveWallet.KeyringInfo = .init( - id: keyringId, - isKeyringCreated: true, - isLocked: false, - isBackedUp: false - ) - completion(keyring) - } keyringService._addObserver = { _ in } keyringService._isLocked = { $0(false) } keyringService._allAccounts = { completion in diff --git a/Tests/BraveWalletTests/NetworkStoreTests.swift b/Tests/BraveWalletTests/NetworkStoreTests.swift index 425269de906..dfc3550b976 100644 --- a/Tests/BraveWalletTests/NetworkStoreTests.swift +++ b/Tests/BraveWalletTests/NetworkStoreTests.swift @@ -30,15 +30,6 @@ import Preferences ] let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { keyringId, completion in - let keyring: BraveWallet.KeyringInfo = .init( - id: keyringId, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true - ) - completion(keyring) - } keyringService._addObserver = { _ in } keyringService._isLocked = { $0(false) } keyringService._allAccounts = { completion in diff --git a/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift b/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift index 6472fbd57a8..3f74a30a475 100644 --- a/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift +++ b/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift @@ -138,32 +138,6 @@ import Preferences price: mockFILPrice, assetTimeframeChange: "-57.23") let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { keyringId, completion in - switch keyringId { - case .default: - let keyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.default, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true - ) - completion(keyring) - case .solana: - let keyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.solana, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true - ) - completion(keyring) - case .filecoin: - completion(.mockFilecoinKeyringInfo) - case .filecoinTestnet: - completion(.mockFilecoinTestnetKeyringInfo) - default: - completion(.mockDefaultKeyringInfo) - } - } keyringService._allAccounts = { $0(.init( accounts: [ diff --git a/Tests/BraveWalletTests/SettingsStoreTests.swift b/Tests/BraveWalletTests/SettingsStoreTests.swift index b5f8883b1c9..f2728350e3c 100644 --- a/Tests/BraveWalletTests/SettingsStoreTests.swift +++ b/Tests/BraveWalletTests/SettingsStoreTests.swift @@ -19,15 +19,6 @@ class SettingsStoreTests: XCTestCase { let mockUserAssets: [BraveWallet.BlockchainToken] = [.previewToken.copy(asVisibleAsset: true)] let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { _, completion in - let keyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.default, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true - ) - completion(keyring) - } keyringService._addObserver = { _ in } keyringService._isLocked = { $0(false) } keyringService._setAutoLockMinutes = { _, _ in } diff --git a/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift b/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift index 30e23693f63..442f6526a20 100644 --- a/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift +++ b/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift @@ -109,15 +109,6 @@ import Preferences completion(setDataForUnapprovedTransactionSuccess) } let keyringService = BraveWallet.TestKeyringService() - keyringService._keyringInfo = { id, completion in - let keyring: BraveWallet.KeyringInfo = .init( - id: id, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true - ) - completion(keyring) - } keyringService._allAccounts = { $0(.init( accounts: accountInfos, diff --git a/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift b/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift index 598f0f27683..7c249dacbce 100644 --- a/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift +++ b/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift @@ -51,20 +51,6 @@ class TransactionsActivityStoreTests: XCTestCase { func testUpdate() { let keyringService = BraveWallet.TestKeyringService() keyringService._addObserver = { _ in } - keyringService._keyringInfo = { keyringId, completion in - switch keyringId { - case .default: - completion(.mockDefaultKeyringInfo) - case .solana: - completion(.mockSolanaKeyringInfo) - case .filecoin: - completion(.mockFilecoinKeyringInfo) - case .filecoinTestnet: - completion(.mockFilecoinTestnetKeyringInfo) - default: - completion(.mockDefaultKeyringInfo) - } - } keyringService._allAccounts = { $0(.mock) } diff --git a/package-lock.json b/package-lock.json index 232e3f88660..2a0e39dbe47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MPL-2.0", "dependencies": { "@mozilla/readability": "^0.4.2", - "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.61.32/brave-core-ios-1.61.32.tgz", + "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.61.39/brave-core-ios-1.61.39.tgz", "leo": "github:brave/leo#7f2dfddb70aff1501ef5a2f3c640a8c74a7343ee", "leo-sf-symbols": "github:brave/leo-sf-symbols#d6056328b8d6ef06e68996ff02a22e06f52590c3", "page-metadata-parser": "^1.1.3", @@ -493,9 +493,9 @@ } }, "node_modules/brave-core-ios": { - "version": "1.61.32", - "resolved": "https://github.com/brave/brave-browser/releases/download/v1.61.32/brave-core-ios-1.61.32.tgz", - "integrity": "sha512-kki2F0hFA0xuZ3bZsP1gNGMJTXv7IiGRP+Rr7x3C5oqHw/qKznSY4OPKoKkvcCzs1XCG6gk1N50mhxS/OJYi8g==", + "version": "1.61.39", + "resolved": "https://github.com/brave/brave-browser/releases/download/v1.61.39/brave-core-ios-1.61.39.tgz", + "integrity": "sha512-8BjoLtSDCZhveL5Vaqw4zOwiiYT69JgkW+exEG/SoyrJo1/ImQSnuW6LGy5EZHxhfp8PyEfB1rbJWEc2CFGLGQ==", "license": "ISC" }, "node_modules/browserslist": { @@ -3171,8 +3171,8 @@ } }, "brave-core-ios": { - "version": "https://github.com/brave/brave-browser/releases/download/v1.61.32/brave-core-ios-1.61.32.tgz", - "integrity": "sha512-kki2F0hFA0xuZ3bZsP1gNGMJTXv7IiGRP+Rr7x3C5oqHw/qKznSY4OPKoKkvcCzs1XCG6gk1N50mhxS/OJYi8g==" + "version": "https://github.com/brave/brave-browser/releases/download/v1.61.39/brave-core-ios-1.61.39.tgz", + "integrity": "sha512-8BjoLtSDCZhveL5Vaqw4zOwiiYT69JgkW+exEG/SoyrJo1/ImQSnuW6LGy5EZHxhfp8PyEfB1rbJWEc2CFGLGQ==" }, "browserslist": { "version": "4.17.1", diff --git a/package.json b/package.json index 0a3b45b7ad3..79cc071da8c 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "license": "MPL-2.0", "dependencies": { "@mozilla/readability": "^0.4.2", - "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.61.32/brave-core-ios-1.61.32.tgz", + "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.61.39/brave-core-ios-1.61.39.tgz", "leo": "github:brave/leo#7f2dfddb70aff1501ef5a2f3c640a8c74a7343ee", "leo-sf-symbols": "github:brave/leo-sf-symbols#d6056328b8d6ef06e68996ff02a22e06f52590c3", "page-metadata-parser": "^1.1.3",