diff --git a/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift b/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift index b5a90212527..92185985365 100644 --- a/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift +++ b/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift @@ -110,8 +110,10 @@ class BraveRewardsViewController: UIViewController, PopoverContentComponent { observer.fetchedPanelPublisher = { [weak self] publisher, tabId in guard let self = self else { return } - if tabId == self.tab.rewardsId { - self.publisher = publisher + DispatchQueue.main.async { + if tabId == self.tab.rewardsId { + self.publisher = publisher + } } } } diff --git a/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift b/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift index dc014bdd827..4e5de27fec7 100644 --- a/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift +++ b/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController+Wallet.swift @@ -582,7 +582,7 @@ extension Tab: BraveWalletKeyringServiceObserver { func keyringCreated(_ keyringId: BraveWallet.KeyringId) { } - func keyringRestored(_ keyringId: BraveWallet.KeyringId) { + func walletRestored() { } func keyringReset() { diff --git a/Sources/BraveWallet/Crypto/Accounts/Activity/AccountActivityView.swift b/Sources/BraveWallet/Crypto/Accounts/Activity/AccountActivityView.swift index 6b69feb9a92..1cd5f303eae 100644 --- a/Sources/BraveWallet/Crypto/Accounts/Activity/AccountActivityView.swift +++ b/Sources/BraveWallet/Crypto/Accounts/Activity/AccountActivityView.swift @@ -164,8 +164,7 @@ struct AccountActivityView: View { } } ) - .onReceive(keyringStore.$allKeyrings) { allKeyrings in - let allAccounts = allKeyrings.flatMap(\.accountInfos) + .onReceive(keyringStore.$allAccounts) { allAccounts in if !allAccounts.contains(where: { $0.address == accountInfo.address }) { // Account was deleted detailsPresentation = nil diff --git a/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift b/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift index 212125d50b1..fa152b5d355 100644 --- a/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift +++ b/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift @@ -348,12 +348,13 @@ struct AddAccountView: View { } private func defaultAccountName(for coin: BraveWallet.CoinType, chainId: String, isPrimary: Bool) -> String { - let keyringId = BraveWallet.KeyringId.keyringId(for: coin, on: chainId) - let keyringInfo = keyringStore.allKeyrings.first { $0.id == keyringId } + let accountsForCoin = keyringStore.allAccounts.filter { $0.coin == coin } if isPrimary { - return String.localizedStringWithFormat(coin.defaultAccountName, (keyringInfo?.accountInfos.filter(\.isPrimary).count ?? 0) + 1) + let numberOfPrimaryAccountsForCoin = accountsForCoin.filter(\.isPrimary).count + return String.localizedStringWithFormat(coin.defaultAccountName, numberOfPrimaryAccountsForCoin + 1) } else { - return String.localizedStringWithFormat(coin.defaultSecondaryAccountName, (keyringInfo?.accountInfos.filter(\.isImported).count ?? 0) + 1) + let numberOfImportedAccounts = accountsForCoin.filter(\.isImported).count + return String.localizedStringWithFormat(coin.defaultSecondaryAccountName, numberOfImportedAccounts + 1) } } } diff --git a/Sources/BraveWallet/Crypto/Accounts/Details/AccountDetailsView.swift b/Sources/BraveWallet/Crypto/Accounts/Details/AccountDetailsView.swift index b8bdf607789..966d5fc6ae5 100644 --- a/Sources/BraveWallet/Crypto/Accounts/Details/AccountDetailsView.swift +++ b/Sources/BraveWallet/Crypto/Accounts/Details/AccountDetailsView.swift @@ -185,7 +185,7 @@ struct AccountDetailsView_Previews: PreviewProvider { static var previews: some View { AccountDetailsView( keyringStore: .previewStoreWithWalletCreated, - account: KeyringStore.previewStoreWithWalletCreated.defaultKeyring.accountInfos.first!, + account: KeyringStore.previewStoreWithWalletCreated.allAccounts.first!, editMode: false ) .previewColorSchemes() diff --git a/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift b/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift index 357e403dc48..2316205145c 100644 --- a/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift @@ -172,7 +172,6 @@ class AccountActivityStore: ObservableObject, WalletObserverStore { self.userAssets = updatedUserAssets self.userNFTs = updatedUserNFTs - let keyringForAccount = await keyringService.keyringInfo(account.keyringId) typealias TokenNetworkAccounts = (token: BraveWallet.BlockchainToken, network: BraveWallet.NetworkInfo, accounts: [BraveWallet.AccountInfo]) let allTokenNetworkAccounts = allUserAssets.flatMap { networkAssets in networkAssets.tokens.map { token in @@ -253,9 +252,10 @@ class AccountActivityStore: ObservableObject, WalletObserverStore { $0[$1.token.assetRatioId.lowercased()] = Double($1.price) }) + let allAccountsForCoin = await keyringService.allAccounts().accounts.filter { $0.coin == account.coin } self.transactionSummaries = await fetchTransactionSummarys( networksForAccountCoin: networksForAccountCoin, - accountInfos: keyringForAccount.accountInfos, + accountInfos: allAccountsForCoin, userAssets: userAssets.map(\.token), allTokens: allTokens, assetRatios: assetRatios @@ -327,3 +327,103 @@ class AccountActivityStore: ObservableObject, WalletObserverStore { } #endif } + +extension AccountActivityStore: BraveWalletKeyringServiceObserver { + func keyringCreated(_ keyringId: BraveWallet.KeyringId) { + } + + func walletRestored() { + } + + func keyringReset() { + } + + func locked() { + } + + func unlocked() { + } + + func backedUp() { + } + + func accountsChanged() { + } + + func autoLockMinutesChanged() { + } + + func selectedWalletAccountChanged(_ account: BraveWallet.AccountInfo) { + guard observeAccountUpdates else { return } + self.account = account + update() + } + + func selectedDappAccountChanged(_ coin: BraveWallet.CoinType, account: BraveWallet.AccountInfo?) { + guard observeAccountUpdates, let account else { return } + self.account = account + update() + } + + func accountsAdded(_ addedAccounts: [BraveWallet.AccountInfo]) { + } +} + +extension AccountActivityStore: BraveWalletJsonRpcServiceObserver { + func chainChangedEvent(_ chainId: String, coin: BraveWallet.CoinType, origin: URLOrigin?) { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + // Handle small gap between chain changing and txController having the correct chain Id + self.update() + } + } + func onAddEthereumChainRequestCompleted(_ chainId: String, error: String) { + } + func onIsEip1559Changed(_ chainId: String, isEip1559: Bool) { + } +} + +extension AccountActivityStore: BraveWalletTxServiceObserver { + func onNewUnapprovedTx(_ txInfo: BraveWallet.TransactionInfo) { + update() + } + func onTransactionStatusChanged(_ txInfo: BraveWallet.TransactionInfo) { + update() + } + func onUnapprovedTxUpdated(_ txInfo: BraveWallet.TransactionInfo) { + } + func onTxServiceReset() { + } +} + +extension AccountActivityStore: BraveWalletBraveWalletServiceObserver { + public func onActiveOriginChanged(_ originInfo: BraveWallet.OriginInfo) { + } + + public func onDefaultWalletChanged(_ wallet: BraveWallet.DefaultWallet) { + } + + public func onDefaultBaseCurrencyChanged(_ currency: String) { + currencyCode = currency + } + + public func onDefaultBaseCryptocurrencyChanged(_ cryptocurrency: String) { + } + + public func onNetworkListChanged() { + } + + func onDefaultEthereumWalletChanged(_ wallet: BraveWallet.DefaultWallet) { + } + + func onDefaultSolanaWalletChanged(_ wallet: BraveWallet.DefaultWallet) { + } + + public func onDiscoverAssetsStarted() { + } + + func onDiscoverAssetsCompleted(_ discoveredAssets: [BraveWallet.BlockchainToken]) { + } + + func onResetWallet() { + } +} diff --git a/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift b/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift index b043d3de902..57596461680 100644 --- a/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift @@ -191,9 +191,8 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { self.isSwapSupported = await swapService.isSwapSupported(token.chainId) // fetch accounts - let keyringId = BraveWallet.KeyringId.keyringId(for: token.coin, on: token.chainId) - let keyring = await keyringService.keyringInfo(keyringId) - var updatedAccounts = keyring.accountInfos.map { + let allAccountsForTokenCoin = await keyringService.allAccounts().accounts.filter { $0.coin == token.coin } + var updatedAccounts = allAccountsForTokenCoin.map { AccountAssetViewModel(account: $0, decimalBalance: 0.0, balance: "", fiatBalance: "") } @@ -220,9 +219,13 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { } } - self.accounts = await fetchAccountBalances(updatedAccounts, keyring: keyring, network: network) + self.accounts = await fetchAccountBalances(updatedAccounts, network: network) let assetRatios = [token.assetRatioId.lowercased(): assetPriceValue] - self.transactionSummaries = await fetchTransactionSummarys(keyring: keyring, network: network, assetRatios: assetRatios) + self.transactionSummaries = await fetchTransactionSummarys( + accounts: allAccountsForTokenCoin, + network: network, + assetRatios: assetRatios + ) case .coinMarket(let coinMarket): // comes from Market tab self.price = self.currencyFormatter.string(from: NSNumber(value: coinMarket.currentPrice)) ?? "" @@ -277,7 +280,6 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { @MainActor private func fetchAccountBalances( _ accountAssetViewModels: [AccountAssetViewModel], - keyring: BraveWallet.KeyringInfo, network: BraveWallet.NetworkInfo ) async -> [AccountAssetViewModel] { guard case let .blockchainToken(token) = assetDetailType @@ -311,7 +313,7 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { } @MainActor private func fetchTransactionSummarys( - keyring: BraveWallet.KeyringInfo, + accounts: [BraveWallet.AccountInfo], network: BraveWallet.NetworkInfo, assetRatios: [String: Double] ) async -> [TransactionSummary] { @@ -320,7 +322,7 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens } let allTokens = await blockchainRegistry.allTokens(network.chainId, coin: network.coin) let allTransactions = await withTaskGroup(of: [BraveWallet.TransactionInfo].self) { @MainActor group -> [BraveWallet.TransactionInfo] in - for account in keyring.accountInfos { + for account in accounts { group.addTask { @MainActor in await self.txService.allTransactionInfo( network.coin, @@ -370,7 +372,7 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { TransactionParser.transactionSummary( from: transaction, network: network, - accountInfos: keyring.accountInfos, + accountInfos: accounts, userAssets: userAssets, allTokens: allTokens, assetRatios: assetRatios, @@ -403,3 +405,84 @@ class AssetDetailStore: ObservableObject, WalletObserverStore { } } } + +extension AssetDetailStore: BraveWalletKeyringServiceObserver { + func keyringReset() { + } + + func accountsChanged() { + update() + } + + func keyringCreated(_ keyringId: BraveWallet.KeyringId) { + } + + func walletRestored() { + } + + func locked() { + } + + func unlocked() { + } + + func backedUp() { + } + + func autoLockMinutesChanged() { + } + + func selectedWalletAccountChanged(_ account: BraveWallet.AccountInfo) { + } + + func selectedDappAccountChanged(_ coin: BraveWallet.CoinType, account: BraveWallet.AccountInfo?) { + } + + func accountsAdded(_ addedAccounts: [BraveWallet.AccountInfo]) { + } +} + +extension AssetDetailStore: BraveWalletTxServiceObserver { + func onNewUnapprovedTx(_ txInfo: BraveWallet.TransactionInfo) { + } + func onUnapprovedTxUpdated(_ txInfo: BraveWallet.TransactionInfo) { + } + func onTransactionStatusChanged(_ txInfo: BraveWallet.TransactionInfo) { + update() + } + func onTxServiceReset() { + } +} + +extension AssetDetailStore: BraveWalletBraveWalletServiceObserver { + public func onActiveOriginChanged(_ originInfo: BraveWallet.OriginInfo) { + } + + public func onDefaultWalletChanged(_ wallet: BraveWallet.DefaultWallet) { + } + + public func onDefaultBaseCurrencyChanged(_ currency: String) { + currencyCode = currency + } + + public func onDefaultBaseCryptocurrencyChanged(_ cryptocurrency: String) { + } + + public func onNetworkListChanged() { + } + + func onDefaultEthereumWalletChanged(_ wallet: BraveWallet.DefaultWallet) { + } + + func onDefaultSolanaWalletChanged(_ wallet: BraveWallet.DefaultWallet) { + } + + func onDiscoverAssetsStarted() { + } + + func onDiscoverAssetsCompleted(_ discoveredAssets: [BraveWallet.BlockchainToken]) { + } + + func onResetWallet() { + } +} diff --git a/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift b/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift index e9bdffaeaea..ce071188b1f 100644 --- a/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/CryptoStore.swift @@ -15,6 +15,7 @@ enum PendingRequest: Equatable { case switchChain(BraveWallet.SwitchChainRequest) case addSuggestedToken(BraveWallet.AddSuggestTokenRequest) case signMessage([BraveWallet.SignMessageRequest]) + case signMessageError([BraveWallet.SignMessageError]) case getEncryptionPublicKey(BraveWallet.GetEncryptionPublicKeyRequest) case decrypt(BraveWallet.DecryptRequest) case signTransaction([BraveWallet.SignTransactionRequest]) @@ -34,6 +35,8 @@ extension PendingRequest: Identifiable { return "addSuggestedToken-\(tokenRequest.token.id)" case let .signMessage(signRequests): return "signMessage-\(signRequests.map(\.id))" + case let .signMessageError(signMessageErrorRequests): + return "signMessageError-\(signMessageErrorRequests.map(\.id))" case let .getEncryptionPublicKey(request): return "getEncryptionPublicKey-\(request.accountId.uniqueKey)-\(request.requestId)" case let .decrypt(request): @@ -51,6 +54,7 @@ enum WebpageRequestResponse: Equatable { case addNetwork(approved: Bool, chainId: String) case addSuggestedToken(approved: Bool, token: BraveWallet.BlockchainToken) case signMessage(approved: Bool, id: Int32) + case signMessageError(errorId: String) case getEncryptionPublicKey(approved: Bool, requestId: String) case decrypt(approved: Bool, requestId: String) case signTransaction(approved: Bool, id: Int32) @@ -222,7 +226,7 @@ public class CryptoStore: ObservableObject, WalletObserverStore { // when user creates or imports a new account with a new keyring since any new // supported coin type / keyring will be migrated inside `CryptoStore`'s init() }, - _keyringRestored: { [weak self] _ in + _walletRestored: { [weak self] in // This observer method will only get called when user restore a wallet // from the lock screen // We will need to @@ -580,13 +584,13 @@ public class CryptoStore: ObservableObject, WalletObserverStore { @MainActor func fetchPendingTransactions() async -> [BraveWallet.TransactionInfo] { - let allKeyrings = await keyringService.keyrings(for: WalletConstants.supportedCoinTypes()) + let allAccounts = await keyringService.allAccounts().accounts var allNetworksForCoin: [BraveWallet.CoinType: [BraveWallet.NetworkInfo]] = [:] for coin in WalletConstants.supportedCoinTypes() { let allNetworks = await rpcService.allNetworks(coin) allNetworksForCoin[coin] = allNetworks } - return await txService.pendingTransactions(networksForCoin: allNetworksForCoin, for: allKeyrings) + return await txService.pendingTransactions(networksForCoin: allNetworksForCoin, for: allAccounts) } @MainActor @@ -597,6 +601,8 @@ public class CryptoStore: ObservableObject, WalletObserverStore { return .signTransaction(signTransactionRequests) } else if case let signAllTransactionsRequests = await walletService.pendingSignAllTransactionsRequests(), !signAllTransactionsRequests.isEmpty { return .signAllTransactions(signAllTransactionsRequests) + } else if case let signMessageErrors = await walletService.pendingSignMessageErrors(), !signMessageErrors.isEmpty { + return .signMessageError(signMessageErrors) } else if case let signMessageRequests = await walletService.pendingSignMessageRequests(), !signMessageRequests.isEmpty { return .signMessage(signMessageRequests) } else if let switchRequest = await rpcService.pendingSwitchChainRequests().first { @@ -665,6 +671,8 @@ public class CryptoStore: ObservableObject, WalletObserverStore { walletService.notifyAddSuggestTokenRequestsProcessed(approved, contractAddresses: [token.contractAddress]) case let .signMessage(approved, id): walletService.notifySignMessageRequestProcessed(approved, id: id, signature: nil, error: nil) + case let .signMessageError(errorId): + walletService.notifySignMessageErrorProcessed(errorId) case let .getEncryptionPublicKey(approved, requestId): walletService.notifyGetPublicKeyRequestProcessed(requestId, approved: approved) case let .decrypt(approved, requestId): diff --git a/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift b/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift index 315b650ab23..3892de1abb4 100644 --- a/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift @@ -119,8 +119,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { id: .default, isKeyringCreated: false, isLocked: true, - isBackedUp: false, - accountInfos: [] + isBackedUp: false ) /// A boolean indciates front-end has or has not loaded Keyring from the core @Published var isDefaultKeyringLoaded = false @@ -154,9 +153,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { /// keyring has been created @Published var isDefaultKeyringCreated: Bool = false /// All `AccountInfo` for all available keyrings - var allAccounts: [BraveWallet.AccountInfo] { - allKeyrings.flatMap(\.accountInfos) - } + @Published var allAccounts: [BraveWallet.AccountInfo] = [] /// A list of default account with all support coin types @Published var defaultAccounts: [BraveWallet.AccountInfo] = [] @@ -234,18 +231,18 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } Task { @MainActor in - let newKeyring = await self.keyringService.keyringInfo(keyringId) - let selectedAccount = await self.keyringService.allAccounts().selectedAccount + 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 selectedAccount == nil, let newAccount = newKeyring.accountInfos.first { + if allAccounts.selectedAccount == nil, let newAccount = allAccountsForKeyring.first { await self.keyringService.setSelectedAccount(newAccount.accountId) } self.updateKeyringInfo() } }, - _keyringRestored: { [weak self] keyringId in + _walletRestored: { [weak self] in guard let self else { return } - if self.isOnboardingVisible && !self.isRestoringWallet, keyringId == BraveWallet.KeyringId.default { + if self.isOnboardingVisible && !self.isRestoringWallet { // Another window has restored a wallet. We should dismiss onboarding on this // window and allow the other window to continue with it's onboarding flow. self.isOnboardingVisible = false @@ -297,8 +294,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { return } Task { @MainActor in // fetch all KeyringInfo for all coin types - let selectedAccount = await keyringService.allAccounts().selectedAccount - let selectedAccountAddress = selectedAccount?.address + 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 @@ -310,16 +306,10 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } } self.allKeyrings = allKeyrings - if let selectedAccountKeyring = allKeyrings.first(where: { $0.id == selectedAccount?.keyringId }) { - if self.selectedAccount.address != selectedAccountAddress { - if let selectedAccount = selectedAccountKeyring.accountInfos.first(where: { $0.address == selectedAccountAddress }) { - self.selectedAccount = selectedAccount - } else if let firstAccount = selectedAccountKeyring.accountInfos.first { - // try and correct invalid state (no selected account for this coin type) - self.selectedAccount = firstAccount - } // else selected account address does not exist in keyring (should not occur...) - } // else `self.selectedAccount` is already the currently selected account - } // else keyring for selected coin is unavailable (should not occur...) + self.allAccounts = allAccounts.accounts + if let selectedAccount = allAccounts.selectedAccount { + self.selectedAccount = selectedAccount + } } } diff --git a/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift b/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift index e543375a6ae..4a9d8c05604 100644 --- a/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift @@ -183,9 +183,9 @@ public class NetworkStore: ObservableObject, WalletObserverStore { _ network: BraveWallet.NetworkInfo, isForOrigin: Bool ) async -> SetSelectedChainError? { - let keyringId = BraveWallet.KeyringId.keyringId(for: network.coin, on: network.chainId) - let keyringInfo = await keyringService.keyringInfo(keyringId) - if keyringInfo.accountInfos.isEmpty { + let allAccounts = await keyringService.allAccounts() + let allAccountsForNetworkCoin = allAccounts.accounts.filter { $0.coin == network.coin } + if allAccountsForNetworkCoin.isEmpty { // Need to prompt user to create new account via alert return .selectedChainHasNoAccounts } else { @@ -195,7 +195,7 @@ public class NetworkStore: ObservableObject, WalletObserverStore { self.defaultSelectedChainId = network.chainId } - let currentlySelectedCoin = await keyringService.allAccounts().selectedAccount?.coin ?? .eth + let currentlySelectedCoin = allAccounts.selectedAccount?.coin ?? .eth let rpcServiceNetwork = await rpcService.network(currentlySelectedCoin, origin: isForOrigin ? origin : nil) guard rpcServiceNetwork.chainId != network.chainId else { if !isForOrigin { // `isSwapSupported` is for the `defaultSelectedChain` diff --git a/Sources/BraveWallet/Crypto/Stores/SelectAccountTokenStore.swift b/Sources/BraveWallet/Crypto/Stores/SelectAccountTokenStore.swift index dc5d8e434ae..b376c31b8dd 100644 --- a/Sources/BraveWallet/Crypto/Stores/SelectAccountTokenStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/SelectAccountTokenStore.swift @@ -173,7 +173,7 @@ class SelectAccountTokenStore: ObservableObject, WalletObserverStore { } @MainActor func update() async { - let allKeyrings = await keyringService.keyrings(for: WalletConstants.supportedCoinTypes()) + let allAccounts = await keyringService.allAccounts() let allNetworks = await rpcService.allNetworksForSupportedCoins() self.allNetworks = allNetworks // setup network filters if not currently setup @@ -184,27 +184,26 @@ class SelectAccountTokenStore: ObservableObject, WalletObserverStore { } let allVisibleUserAssets = assetManager.getAllUserAssetsInNetworkAssetsByVisibility(networks: allNetworks, visible: true).flatMap { $0.tokens } guard !Task.isCancelled else { return } - self.accountSections = allKeyrings.flatMap { keyring in - let tokensForCoin = allVisibleUserAssets.filter { $0.coin == keyring.coin } - return keyring.accountInfos.map { account in - let tokenBalances = tokensForCoin.compactMap { token in - let tokenNetwork = allNetworks.first(where: { $0.chainId == token.chainId }) ?? .init() - if tokenNetwork.supportedKeyrings.contains(keyring.id.rawValue as NSNumber) { - return AccountSection.TokenBalance( - token: token, - network: allNetworks.first(where: { $0.chainId == token.chainId }) ?? .init(), - balance: cachedBalance(for: token, in: account), - price: cachedPrice(for: token, in: account), - nftMetadata: cachedMetadata(for: token) - ) - } - return nil + let tokensGroupedByCoinType = Dictionary(grouping: allVisibleUserAssets, by: \.coin) + self.accountSections = allAccounts.accounts.map { account in + let tokensForAccountCoin = tokensGroupedByCoinType[account.coin] ?? [] + let tokenBalances = tokensForAccountCoin.compactMap { token in + let tokenNetwork = allNetworks.first(where: { $0.chainId == token.chainId }) ?? .init() + if tokenNetwork.supportedKeyrings.contains(account.keyringId.rawValue as NSNumber) { + return AccountSection.TokenBalance( + token: token, + network: allNetworks.first(where: { $0.chainId == token.chainId }) ?? .init(), + balance: cachedBalance(for: token, in: account), + price: cachedPrice(for: token, in: account), + nftMetadata: cachedMetadata(for: token) + ) } - return AccountSection( - account: account, - tokenBalances: tokenBalances - ) + return nil } + return AccountSection( + account: account, + tokenBalances: tokenBalances + ) } updateAccountBalances() diff --git a/Sources/BraveWallet/Crypto/Stores/SendTokenStore.swift b/Sources/BraveWallet/Crypto/Stores/SendTokenStore.swift index 3ddb3d33123..97e67fca1f6 100644 --- a/Sources/BraveWallet/Crypto/Stores/SendTokenStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/SendTokenStore.swift @@ -337,7 +337,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { ) { let eip1559Data = BraveWallet.TxData1559(baseData: baseData, chainId: chainId, maxPriorityFeePerGas: "", maxFeePerGas: "", gasEstimation: nil) let txDataUnion = BraveWallet.TxDataUnion(ethTxData1559: eip1559Data) - self.txService.addUnapprovedTransaction(txDataUnion, from: accountId, origin: nil, groupId: nil) { success, txMetaId, errorMessage in + self.txService.addUnapprovedTransaction(txDataUnion, from: accountId) { success, txMetaId, errorMessage in completion(success, errorMessage) } } @@ -573,7 +573,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { } } else { let txDataUnion = BraveWallet.TxDataUnion(ethTxData: baseData) - self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId, origin: nil, groupId: nil) { success, txMetaId, errorMessage in + self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId) { success, txMetaId, errorMessage in self.isMakingTx = false completion(success, errorMessage) } @@ -586,7 +586,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { } let baseData = BraveWallet.TxData(nonce: "", gasPrice: "", gasLimit: "", to: token.contractAddress, value: "0x0", data: data, signOnly: false, signedTransaction: nil) let txDataUnion = BraveWallet.TxDataUnion(ethTxData: baseData) - self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId, origin: nil, groupId: nil) { success, txMetaId, errorMessage in + self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId) { success, txMetaId, errorMessage in self.isMakingTx = false completion(success, errorMessage) } @@ -605,7 +605,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { } } else { let txDataUnion = BraveWallet.TxDataUnion(ethTxData: baseData) - self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId, origin: nil, groupId: nil) { success, txMetaId, errorMessage in + self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId) { success, txMetaId, errorMessage in self.isMakingTx = false completion(success, errorMessage) } @@ -641,7 +641,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { return } let txDataUnion = BraveWallet.TxDataUnion(solanaTxData: solanaTxData) - self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId, origin: nil, groupId: nil) { success, txMetaId, errMsg in + self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId) { success, txMetaId, errMsg in completion(success, errMsg) } } @@ -658,7 +658,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { return } let txDataUnion = BraveWallet.TxDataUnion(solanaTxData: solanaTxData) - self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId, origin: nil, groupId: nil) { success, txMetaId, errorMessage in + self.txService.addUnapprovedTransaction(txDataUnion, from: fromAccountId) { success, txMetaId, errorMessage in completion(success, errorMessage) } } @@ -688,7 +688,7 @@ public class SendTokenStore: ObservableObject, WalletObserverStore { to: sendAddress, value: weiString ) - self.txService.addUnapprovedTransaction(BraveWallet.TxDataUnion(filTxData: filTxData), from: fromAccountId, origin: nil, groupId: nil) { success, txMetaId, errorMessage in + self.txService.addUnapprovedTransaction(BraveWallet.TxDataUnion(filTxData: filTxData), from: fromAccountId) { success, txMetaId, errorMessage in self.isMakingTx = false completion(success, errorMessage) } diff --git a/Sources/BraveWallet/Crypto/Stores/SwapTokenStore.swift b/Sources/BraveWallet/Crypto/Stores/SwapTokenStore.swift index 688bfe991e0..a8c0d4a43b0 100644 --- a/Sources/BraveWallet/Crypto/Stores/SwapTokenStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/SwapTokenStore.swift @@ -407,7 +407,7 @@ public class SwapTokenStore: ObservableObject, WalletObserverStore { signedTransaction: nil ) let txDataUnion = BraveWallet.TxDataUnion(ethTxData: baseData) - let (success, _, _) = await txService.addUnapprovedTransaction(txDataUnion, from: accountInfo.accountId, origin: nil, groupId: nil) + let (success, _, _) = await txService.addUnapprovedTransaction(txDataUnion, from: accountInfo.accountId) if !success { self.state = .error(Strings.Wallet.unknownError) self.clearAllAmount() @@ -529,7 +529,7 @@ public class SwapTokenStore: ObservableObject, WalletObserverStore { return success } else { let txDataUnion = BraveWallet.TxDataUnion(ethTxData: baseData) - let (success, _, _) = await txService.addUnapprovedTransaction(txDataUnion, from: accountInfo.accountId, origin: nil, groupId: nil) + let (success, _, _) = await txService.addUnapprovedTransaction(txDataUnion, from: accountInfo.accountId) if !success { self.state = .error(Strings.Wallet.unknownError) self.clearAllAmount() @@ -559,7 +559,7 @@ public class SwapTokenStore: ObservableObject, WalletObserverStore { } let eip1559Data = BraveWallet.TxData1559(baseData: baseData, chainId: chainId, maxPriorityFeePerGas: maxPriorityFeePerGas, maxFeePerGas: maxFeePerGas, gasEstimation: gasEstimation) let txDataUnion = BraveWallet.TxDataUnion(ethTxData1559: eip1559Data) - let (success, _, _) = await txService.addUnapprovedTransaction(txDataUnion, from: account.accountId, origin: nil, groupId: nil) + let (success, _, _) = await txService.addUnapprovedTransaction(txDataUnion, from: account.accountId) if !success { self.state = .error(Strings.Wallet.unknownError) self.clearAllAmount() @@ -770,15 +770,6 @@ public class SwapTokenStore: ObservableObject, WalletObserverStore { self.state = .error(Strings.Wallet.unknownError) return false } - /* Group transactions no longer used in core. - let serializedTransactions = [ - swapTransactions.setupTransaction, - swapTransactions.swapTransaction, - swapTransactions.cleanupTransaction - ].filter { !$0.isEmpty } - let hasParts = serializedTransactions.count > 1 - let groupId: String? = hasParts ? UUID().uuidString : nil - */ let (solTxData, status, _) = await solTxManagerProxy.makeTxData( fromBase64EncodedTransaction: swapTransactions.swapTransaction, txType: .solanaSwap, @@ -794,9 +785,7 @@ public class SwapTokenStore: ObservableObject, WalletObserverStore { } let (success, _, _) = await txService.addUnapprovedTransaction( .init(solanaTxData: solTxData), - from: accountInfo.accountId, - origin: nil, - groupId: nil + from: accountInfo.accountId ) return success } diff --git a/Sources/BraveWallet/Crypto/Stores/TransactionConfirmationStore.swift b/Sources/BraveWallet/Crypto/Stores/TransactionConfirmationStore.swift index 00035fff68c..237952277b7 100644 --- a/Sources/BraveWallet/Crypto/Stores/TransactionConfirmationStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/TransactionConfirmationStore.swift @@ -293,8 +293,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore clearTrasactionInfoBeforeUpdate() let coin = transaction.coin - let keyringId = BraveWallet.KeyringId.keyringId(for: transaction.coin, on: transaction.chainId) - let keyring = await keyringService.keyringInfo(keyringId) + let allAccountsForCoin = await keyringService.allAccounts().accounts.filter { $0.coin == coin } if !allNetworks.contains(where: { $0.chainId == transaction.chainId }) { allNetworks = await rpcService.allNetworksForSupportedCoins() } @@ -316,7 +315,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore guard let parsedTransaction = transaction.parsedTransaction( network: network, - accountInfos: keyring.accountInfos, + accountInfos: allAccountsForCoin, userAssets: userAssets, allTokens: allTokens, assetRatios: assetRatios, @@ -328,7 +327,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore activeParsedTransaction = parsedTransaction await fetchActiveTransactionDetails( - keyring: keyring, + accounts: allAccountsForCoin, network: network, allTokens: allTokens, shouldFetchCurrentAllowance: shouldFetchCurrentAllowance, @@ -458,7 +457,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore } @MainActor func fetchActiveTransactionDetails( - keyring: BraveWallet.KeyringInfo, + accounts: [BraveWallet.AccountInfo], network: BraveWallet.NetworkInfo, allTokens: [BraveWallet.BlockchainToken], shouldFetchCurrentAllowance: Bool, @@ -493,7 +492,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore isBalanceSufficient = false } } else if shouldFetchGasTokenBalance { - if let account = keyring.accountInfos.first(where: { $0.address == activeParsedTransaction.fromAddress }) { + if let account = accounts.first(where: { $0.address == activeParsedTransaction.fromAddress }) { await fetchGasTokenBalance(token: network.nativeToken, account: account, network: network) } } @@ -522,7 +521,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore isBalanceSufficient = false } } else if shouldFetchGasTokenBalance { - if let account = keyring.accountInfos.first(where: { $0.address == activeParsedTransaction.fromAddress }) { + if let account = accounts.first(where: { $0.address == activeParsedTransaction.fromAddress }) { await fetchGasTokenBalance(token: network.nativeToken, account: account, network: network) } } @@ -555,7 +554,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore isBalanceSufficient = false } } else if shouldFetchGasTokenBalance { - if let account = keyring.accountInfos.first(where: { $0.address == activeParsedTransaction.fromAddress }) { + if let account = accounts.first(where: { $0.address == activeParsedTransaction.fromAddress }) { await fetchGasTokenBalance(token: network.nativeToken, account: account, network: network) } } @@ -580,7 +579,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore isBalanceSufficient = false } } else if shouldFetchGasTokenBalance { - if let account = keyring.accountInfos.first(where: { $0.address == activeParsedTransaction.fromAddress }) { + if let account = accounts.first(where: { $0.address == activeParsedTransaction.fromAddress }) { await fetchGasTokenBalance(token: network.nativeToken, account: account, network: network) } } @@ -608,7 +607,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore isBalanceSufficient = false } } else if shouldFetchGasTokenBalance { - if let account = keyring.accountInfos.first(where: { $0.address == activeParsedTransaction.fromAddress }) { + if let account = accounts.first(where: { $0.address == activeParsedTransaction.fromAddress }) { await fetchGasTokenBalance(token: network.nativeToken, account: account, network: network) } } @@ -636,7 +635,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore isBalanceSufficient = false } } else if shouldFetchGasTokenBalance { - if let account = keyring.accountInfos.first(where: { $0.address == activeParsedTransaction.fromAddress }) { + if let account = accounts.first(where: { $0.address == activeParsedTransaction.fromAddress }) { await fetchGasTokenBalance(token: network.nativeToken, account: account, network: network) } } @@ -666,13 +665,13 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore } @MainActor private func fetchAllTransactions() async -> [BraveWallet.TransactionInfo] { - let allKeyrings = await keyringService.keyrings(for: WalletConstants.supportedCoinTypes()) + let allAccounts = await keyringService.allAccounts().accounts var allNetworksForCoin: [BraveWallet.CoinType: [BraveWallet.NetworkInfo]] = [:] for coin in WalletConstants.supportedCoinTypes() { let allNetworks = await rpcService.allNetworks(coin) allNetworksForCoin[coin] = allNetworks } - return await txService.pendingTransactions(networksForCoin: allNetworksForCoin, for: allKeyrings) + return await txService.pendingTransactions(networksForCoin: allNetworksForCoin, for: allAccounts) .sorted(by: { $0.createdTime > $1.createdTime }) } diff --git a/Sources/BraveWallet/Crypto/Stores/TransactionDetailsStore.swift b/Sources/BraveWallet/Crypto/Stores/TransactionDetailsStore.swift index 35836ecd6a9..6f20590a199 100644 --- a/Sources/BraveWallet/Crypto/Stores/TransactionDetailsStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/TransactionDetailsStore.swift @@ -77,8 +77,6 @@ class TransactionDetailsStore: ObservableObject, WalletObserverStore { return } self.network = network - let keringId = BraveWallet.KeyringId.keyringId(for: coin, on: transaction.chainId) - let keyring = await keyringService.keyringInfo(keringId) var allTokens: [BraveWallet.BlockchainToken] = await blockchainRegistry.allTokens(network.chainId, coin: network.coin) + tokenInfoCache.map(\.value) let userAssets: [BraveWallet.BlockchainToken] = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens } let unknownTokenContractAddresses = transaction.tokenContractAddresses @@ -107,9 +105,10 @@ class TransactionDetailsStore: ObservableObject, WalletObserverStore { if transaction.coin == .sol { (solEstimatedTxFee, _, _) = await solanaTxManagerProxy.estimatedTxFee(network.chainId, txMetaId: transaction.id) } + let allAccounts = await keyringService.allAccounts().accounts guard let parsedTransaction = transaction.parsedTransaction( network: network, - accountInfos: keyring.accountInfos, + accountInfos: allAccounts, userAssets: userAssets, allTokens: allTokens, assetRatios: assetRatios, diff --git a/Sources/BraveWallet/Crypto/Stores/TransactionsActivityStore.swift b/Sources/BraveWallet/Crypto/Stores/TransactionsActivityStore.swift index 2230020bfe0..6d565eb72ef 100644 --- a/Sources/BraveWallet/Crypto/Stores/TransactionsActivityStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/TransactionsActivityStore.swift @@ -121,10 +121,8 @@ class TransactionsActivityStore: ObservableObject, WalletObserverStore { func update() { updateTask?.cancel() updateTask = Task { @MainActor in - let allKeyrings = await self.keyringService.keyrings( - for: WalletConstants.supportedCoinTypes() - ) - let allAccountInfos = allKeyrings.flatMap(\.accountInfos) + let allAccounts = await keyringService.allAccounts() + let allAccountInfos = allAccounts.accounts // setup network filters if not currently setup if self.networkFilters.isEmpty { self.networkFilters = await self.rpcService.allNetworksForSupportedCoins().map { @@ -136,7 +134,7 @@ class TransactionsActivityStore: ObservableObject, WalletObserverStore { let allNetworksAllCoins = networksForCoin.values.flatMap { $0 } let allTransactions = await txService.allTransactions( - networksForCoin: networksForCoin, for: allKeyrings + networksForCoin: networksForCoin, for: allAccountInfos ).filter { $0.txStatus != .rejected } let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworksAllCoins, includingUserDeleted: true).flatMap(\.tokens) let allTokens = await blockchainRegistry.allTokens( diff --git a/Sources/BraveWallet/Crypto/WalletServiceObservers.swift b/Sources/BraveWallet/Crypto/WalletServiceObservers.swift index f687821cf12..1bd267c905a 100644 --- a/Sources/BraveWallet/Crypto/WalletServiceObservers.swift +++ b/Sources/BraveWallet/Crypto/WalletServiceObservers.swift @@ -9,7 +9,7 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { var _keyringReset: (() -> Void)? var _keyringCreated: ((_ keyringId: BraveWallet.KeyringId) -> Void)? - var _keyringRestored: ((_ keyringId: BraveWallet.KeyringId) -> Void)? + var _walletRestored: (() -> Void)? var _locked: (() -> Void)? var _unlocked: (() -> Void)? var _backedUp: (() -> Void)? @@ -23,7 +23,7 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { keyringService: BraveWalletKeyringService, _keyringReset: (() -> Void)? = nil, _keyringCreated: ((BraveWallet.KeyringId) -> Void)? = nil, - _keyringRestored: ((BraveWallet.KeyringId) -> Void)? = nil, + _walletRestored: (() -> Void)? = nil, _locked: (() -> Void)? = nil, _unlocked: (() -> Void)? = nil, _backedUp: (() -> Void)? = nil, @@ -35,7 +35,7 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { ) { self._keyringReset = _keyringReset self._keyringCreated = _keyringCreated - self._keyringRestored = _keyringRestored + self._walletRestored = _walletRestored self._locked = _locked self._unlocked = _unlocked self._backedUp = _backedUp @@ -53,8 +53,8 @@ class KeyringServiceObserver: BraveWalletKeyringServiceObserver { public func keyringCreated(_ keyringId: BraveWallet.KeyringId) { _keyringCreated?(keyringId) } - public func keyringRestored(_ keyringId: BraveWallet.KeyringId) { - _keyringRestored?(keyringId) + public func walletRestored() { + _walletRestored?() } public func locked() { _locked?() diff --git a/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift b/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift index 31a1bfe167b..c71b925bd80 100644 --- a/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift +++ b/Sources/BraveWallet/Extensions/BraveWalletExtensions.swift @@ -220,7 +220,22 @@ extension BraveWallet.CoinType { extension BraveWallet.KeyringInfo { var coin: BraveWallet.CoinType? { - accountInfos.first?.coin + 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 + } } } diff --git a/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift b/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift index 57de683426e..c061425538f 100644 --- a/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift +++ b/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift @@ -66,12 +66,11 @@ extension BraveWalletKeyringService { /// 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). let keyringId = BraveWallet.KeyringId.keyringId(for: coin, on: chainId) - let keyringInfo = await keyringInfo(keyringId) - // If user restore a wallet, `BraveWallet.KeyringInfo.isKeyringCreated` can be true, - // but `BraveWallet.KeyringInfo.accountInfos` will be empty. - // Hence, we will have to check if `BraveWallet.KeyringInfo.accountInfos` is empty instead of - // checking the boolean of `BraveWallet.KeyringInfo.isKeyringCreated` - return !keyringInfo.accountInfos.isEmpty + // `KeyringInfo.isKeyringCreated` insufficient check as this value can + // be true with no accounts after wallet restore. + let allAccountsForKeyring = await allAccounts().accounts.filter { $0.keyringId == keyringId } + return !allAccountsForKeyring.isEmpty } } diff --git a/Sources/BraveWallet/Extensions/WalletTxServiceExtensions.swift b/Sources/BraveWallet/Extensions/WalletTxServiceExtensions.swift index 36a1dc692fa..7cb4a2814e1 100644 --- a/Sources/BraveWallet/Extensions/WalletTxServiceExtensions.swift +++ b/Sources/BraveWallet/Extensions/WalletTxServiceExtensions.swift @@ -11,30 +11,25 @@ extension BraveWalletTxService { // Fetches all pending transactions for all given keyrings func pendingTransactions( networksForCoin: [BraveWallet.CoinType: [BraveWallet.NetworkInfo]], - for keyrings: [BraveWallet.KeyringInfo] + for accounts: [BraveWallet.AccountInfo] ) async -> [BraveWallet.TransactionInfo] { - await allTransactions(networksForCoin: networksForCoin, for: keyrings) + await allTransactions(networksForCoin: networksForCoin, for: accounts) .filter { $0.txStatus == .unapproved } } // Fetches all transactions for all given keyrings func allTransactions( networksForCoin: [BraveWallet.CoinType: [BraveWallet.NetworkInfo]], - for keyrings: [BraveWallet.KeyringInfo] + for accounts: [BraveWallet.AccountInfo] ) async -> [BraveWallet.TransactionInfo] { return await withTaskGroup( of: [BraveWallet.TransactionInfo].self, body: { @MainActor group in - for keyring in keyrings { - guard let keyringCoin = keyring.coin, - let networksForKeyringCoin = networksForCoin[keyringCoin] else { - continue - } - for info in keyring.accountInfos { - for network in networksForKeyringCoin where network.supportedKeyrings.contains(keyring.id.rawValue as NSNumber) { - group.addTask { @MainActor in - await self.allTransactionInfo(info.coin, chainId: network.chainId, from: info.accountId) - } + for account in accounts { + guard let networksForAccount = networksForCoin[account.coin] else { continue } + for network in networksForAccount where network.supportedKeyrings.contains(account.keyringId.rawValue as NSNumber) { + group.addTask { @MainActor in + await self.allTransactionInfo(account.coin, chainId: network.chainId, from: account.accountId) } } } diff --git a/Sources/BraveWallet/Panels/Connect/EditSiteConnectionView.swift b/Sources/BraveWallet/Panels/Connect/EditSiteConnectionView.swift index 1065fc81d7d..4ab8803e15a 100644 --- a/Sources/BraveWallet/Panels/Connect/EditSiteConnectionView.swift +++ b/Sources/BraveWallet/Panels/Connect/EditSiteConnectionView.swift @@ -131,7 +131,7 @@ struct EditSiteConnectionView: View { } private var accountInfos: [BraveWallet.AccountInfo] { - keyringStore.allKeyrings.first(where: { $0.coin == coin })?.accountInfos ?? [] + keyringStore.allAccounts.filter { $0.coin == coin } } var body: some View { diff --git a/Sources/BraveWallet/Panels/Connect/NewSiteConnectionView.swift b/Sources/BraveWallet/Panels/Connect/NewSiteConnectionView.swift index 6698bff5ac6..df3b48a9810 100644 --- a/Sources/BraveWallet/Panels/Connect/NewSiteConnectionView.swift +++ b/Sources/BraveWallet/Panels/Connect/NewSiteConnectionView.swift @@ -41,7 +41,7 @@ public struct NewSiteConnectionView: View { @State private var isConfirmationViewVisible: Bool = false private var accountInfos: [BraveWallet.AccountInfo] { - let allAccounts = keyringStore.allKeyrings.first(where: { $0.coin == coin })?.accountInfos ?? [] + let allAccounts = keyringStore.allAccounts.filter { $0.coin == coin } return allAccounts.filter { self.accounts.contains($0.address) } } @@ -194,7 +194,7 @@ public struct NewSiteConnectionView: View { } private var accountsAddressesToConfirm: String { - keyringStore.defaultKeyring.accountInfos + accountInfos .filter { selectedAccounts.contains($0.id) } .map(\.address.truncatedAddress) .joined(separator: ", ") @@ -228,7 +228,7 @@ public struct NewSiteConnectionView: View { } Section { Button { - let accounts = keyringStore.allKeyrings.flatMap(\.accountInfos) + let accounts = accountInfos .filter { selectedAccounts.contains($0.id) } .map(\.address) onConnect(accounts) diff --git a/Sources/BraveWallet/Panels/RequestContainerView.swift b/Sources/BraveWallet/Panels/RequestContainerView.swift index 80a91285882..b1edec8a041 100644 --- a/Sources/BraveWallet/Panels/RequestContainerView.swift +++ b/Sources/BraveWallet/Panels/RequestContainerView.swift @@ -62,6 +62,11 @@ struct RequestContainerView: View { networkStore: cryptoStore.networkStore, onDismiss: onDismiss ) + case let .signMessageError(signMessageErrors): + SignMessageErrorView( + signMessageErrors: signMessageErrors, + cryptoStore: cryptoStore + ) case let .getEncryptionPublicKey(request): EncryptionView( request: .getEncryptionPublicKey(request), diff --git a/Sources/BraveWallet/Panels/Signature Request/SignMessageErrorView.swift b/Sources/BraveWallet/Panels/Signature Request/SignMessageErrorView.swift new file mode 100644 index 00000000000..f8dfe9d1d8b --- /dev/null +++ b/Sources/BraveWallet/Panels/Signature Request/SignMessageErrorView.swift @@ -0,0 +1,103 @@ +// Copyright 2023 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import SwiftUI +import BraveStrings +import BraveCore +import DesignSystem + +struct SignMessageErrorView: View { + + var signMessageErrors: [BraveWallet.SignMessageError] + var cryptoStore: CryptoStore + + @State private var currentIndex: Int = 0 + @Environment(\.presentationMode) @Binding private var presentationMode + + var body: some View { + ScrollView { + VStack(spacing: 16) { + if signMessageErrors.count > 1 { + signMessageErrorIndexDisplay + } + errorContainer + Button(action: { + guard let currentRequest = signMessageErrors[safe: currentIndex] else { return } + let isLastRequest = signMessageErrors.count <= 1 + cryptoStore.handleWebpageRequestResponse(.signMessageError(errorId: currentRequest.id)) + if isLastRequest { + presentationMode.dismiss() + } + }) { + Text(Strings.Wallet.confirmedTransactionCloseButtonTitle) + .frame(maxWidth: .infinity) + } + .buttonStyle(BraveFilledButtonStyle(size: .large)) + .disabled(currentIndex > 0) + } + .padding(.horizontal, 16) + .padding(.top, 16) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(braveSystemName: .containerBackground).ignoresSafeArea()) + .navigationTitle(Strings.Wallet.securityRiskDetectedTitle) + .navigationBarTitleDisplayMode(.inline) + } + + private var signMessageErrorIndexDisplay: some View { + HStack { + Text(String.localizedStringWithFormat(Strings.Wallet.transactionCount, currentIndex + 1, signMessageErrors.count)) + .fontWeight(.semibold) + Button(action: { + if currentIndex + 1 < signMessageErrors.count { + currentIndex += 1 + } else { + currentIndex = 0 + } + }) { + Text(Strings.Wallet.next) + .fontWeight(.semibold) + .foregroundColor(Color(.braveBlurpleTint)) + } + } + .frame(maxWidth: .infinity, alignment: .trailing) + } + + private var errorContainer: some View { + VStack(spacing: 0) { + if let currentSignMessageError = signMessageErrors[safe: currentIndex] { + Image(braveSystemName: "leo.warning.circle-filled") + .imageScale(.large) + .foregroundColor(Color(braveSystemName: .systemfeedbackErrorIcon)) + .padding(.bottom, 10) + Text(verbatim: currentSignMessageError.originInfo.eTldPlusOne) + .foregroundColor(Color(braveSystemName: .textPrimary)) + .font(.headline.weight(.semibold)) + .padding(.bottom, 8) + Text(originInfo: currentSignMessageError.originInfo) + .foregroundColor(Color(braveSystemName: .systemfeedbackErrorText)) + .font(.subheadline) + .padding(.bottom, 16) + Text(currentSignMessageError.localizedErrMsg) + .font(.body) + .padding(.bottom, 40) + } + } + .multilineTextAlignment(.center) + .padding(20) + .background(Color(braveSystemName: .systemfeedbackErrorBackground).cornerRadius(12)) + } +} + +#if DEBUG +struct SignMessageErrorView_Previews: PreviewProvider { + static var previews: some View { + SignMessageErrorView( + signMessageErrors: [], + cryptoStore: .previewStore + ) + } +} +#endif diff --git a/Sources/BraveWallet/Panels/Signature Request/SignatureRequestView.swift b/Sources/BraveWallet/Panels/Signature Request/SignatureRequestView.swift index cfda4dc843d..b067af14a56 100644 --- a/Sources/BraveWallet/Panels/Signature Request/SignatureRequestView.swift +++ b/Sources/BraveWallet/Panels/Signature Request/SignatureRequestView.swift @@ -43,7 +43,7 @@ struct SignatureRequestView: View { /// Request display text, used as fallback. private var requestDisplayText: String { - if currentRequest.domain.isEmpty { + if requestDomain.isEmpty { return requestMessage } return """ @@ -62,7 +62,7 @@ struct SignatureRequestView: View { let regularFont = metrics.scaledFont(for: UIFont.systemFont(ofSize: desc.pointSize, weight: .regular)) let regularAttributes: [NSAttributedString.Key: Any] = [ .font: regularFont, .foregroundColor: UIColor.braveLabel] - if currentRequest.domain.isEmpty { + if requestDomain.isEmpty { // if we don't show domain, we don't need the titles so we // can fallback to `requestDisplayText` string for perf reasons return nil @@ -83,14 +83,19 @@ struct SignatureRequestView: View { return attrString } + private var currentRequestDomain: String? { + currentRequest.signData.ethSignTypedData?.domain + } + private var requestDomain: String { + guard let domain = currentRequestDomain else { return "" } if showOrignalMessage[requestIndex] == true { - return currentRequest.domain + return domain } else { let uuid = UUID() - var result = currentRequest.domain + var result = domain if needPilcrowFormatted[requestIndex] == true { - var copy = currentRequest.domain + var copy = domain while copy.range(of: "\\n{2,}", options: .regularExpression) != nil { if let range = copy.range(of: "\\n{2,}", options: .regularExpression) { let newlines = String(copy[range]) @@ -99,22 +104,53 @@ struct SignatureRequestView: View { } } } - if currentRequest.domain.hasUnknownUnicode { + if domain.hasUnknownUnicode { result = result.printableWithUnknownUnicode } - + return result.replacingOccurrences(of: uuid.uuidString, with: "\u{00B6}") } } + private var currentRequestMessage: String? { + if let ethSignTypedData = currentRequest.signData.ethSignTypedData { + return ethSignTypedData.message + } else if let ethStandardSignData = currentRequest.signData.ethStandardSignData { + return ethStandardSignData.message + } else if let solanaSignData = currentRequest.signData.solanaSignData { + return solanaSignData.message + } else if let ethSiweData = currentRequest.signData.ethSiweData { + // TODO: Replace with custom UI: https://github.com/brave/brave-ios/issues/7827 + var message = "Origin: \(ethSiweData.origin.host)" + message += "\nAddress: \(ethSiweData.address)" + if let statement = ethSiweData.statement { + message += "\nStatement: \(statement)" + } + message += "\nURI: \(ethSiweData.uri.absoluteString)" + message += "\nVersion: \(ethSiweData.version)" + message += "\nChain Id: \(ethSiweData.chainId)" + message += "\nNonce: \(ethSiweData.nonce)" + message += "\nIssued At: \(ethSiweData.issuedAt)" + if let expirationTime = ethSiweData.expirationTime { + message += "\nExpiration Time: \(expirationTime)" + } + return message + } else { // ethSiweData will have separate UI + return nil + } + } + private var requestMessage: String { + guard let message = currentRequestMessage else { + return "" + } if showOrignalMessage[requestIndex] == true { - return currentRequest.message + return message } else { let uuid = UUID() - var result = currentRequest.message + var result = message if needPilcrowFormatted[requestIndex] == true { - var copy = currentRequest.message + var copy = message while copy.range(of: "\\n{3,}", options: .regularExpression) != nil { if let range = copy.range(of: "\\n{3,}", options: .regularExpression) { let newlines = String(copy[range]) @@ -123,10 +159,10 @@ struct SignatureRequestView: View { } } } - if currentRequest.message.hasUnknownUnicode { + if message.hasUnknownUnicode { result = result.printableWithUnknownUnicode } - + return result.replacingOccurrences(of: uuid.uuidString, with: "\u{00B6}") } } @@ -189,7 +225,7 @@ struct SignatureRequestView: View { Text(Strings.Wallet.signatureRequestSubtitle) .font(.headline) .foregroundColor(Color(.bravePrimary)) - if needPilcrowFormatted[requestIndex] == true || currentRequest.message.hasUnknownUnicode == true { + if needPilcrowFormatted[requestIndex] == true || currentRequestMessage?.hasUnknownUnicode == true { VStack(spacing: 8) { if needPilcrowFormatted[requestIndex] == true { Text("\(Image(systemName: "exclamationmark.triangle.fill")) \(Strings.Wallet.signMessageConsecutiveNewlineWarning)") @@ -197,7 +233,7 @@ struct SignatureRequestView: View { .foregroundColor(Color(.braveLabel)) .multilineTextAlignment(.center) } - if currentRequest.message.hasUnknownUnicode == true { + if currentRequestMessage?.hasUnknownUnicode == true { Text("\(Image(systemName: "exclamationmark.triangle.fill")) \(Strings.Wallet.signMessageRequestUnknownUnicodeWarning)") .font(.subheadline.weight(.medium)) .foregroundColor(Color(.braveLabel)) @@ -266,14 +302,14 @@ struct SignatureRequestView: View { alignment: .bottom ) .frame(maxWidth: .infinity) - .navigationTitle(Strings.Wallet.signatureRequestTitle) + .navigationTitle(navigationTitle) .navigationBarTitleDisplayMode(.inline) .foregroundColor(Color(.braveLabel)) .background(Color(.braveGroupedBackground).edgesIgnoringSafeArea(.all)) .introspectTextView { textView in // A flash to show users message is overflowing the text view (related to issue https://github.com/brave/brave-ios/issues/6277) if showOrignalMessage[requestIndex] == true { - let currentRequestHasConsecutiveNewLines = currentRequest.domain.hasConsecutiveNewLines || currentRequest.message.hasConsecutiveNewLines + let currentRequestHasConsecutiveNewLines = currentRequestDomain?.hasConsecutiveNewLines == true || currentRequestMessage?.hasConsecutiveNewLines == true if textView.contentSize.height > staticTextViewHeight && currentRequestHasConsecutiveNewLines { needPilcrowFormatted[requestIndex] = true textView.flashScrollIndicators() @@ -284,6 +320,13 @@ struct SignatureRequestView: View { } } + private var navigationTitle: String { + guard let _ = currentRequest.signData.ethSiweData else { + return Strings.Wallet.signatureRequestTitle + } + return Strings.Wallet.signInWithBraveWallet + } + private var isButtonsDisabled: Bool { requestIndex != 0 } diff --git a/Sources/BraveWallet/Preview Content/MockBraveWalletService.swift b/Sources/BraveWallet/Preview Content/MockBraveWalletService.swift index 90f8dc585b9..c6c2ddc32f0 100644 --- a/Sources/BraveWallet/Preview Content/MockBraveWalletService.swift +++ b/Sources/BraveWallet/Preview Content/MockBraveWalletService.swift @@ -266,5 +266,13 @@ class MockBraveWalletService: BraveWalletBraveWalletService { func convertFevm(toFvmAddress isMainnet: Bool, fevmAddresses: [String], completion: @escaping ([String: String]) -> Void) { completion([:]) } + + func pendingSignMessageErrors(_ completion: @escaping ([BraveWallet.SignMessageError]) -> Void) { + completion([]) + } + + func notifySignMessageErrorProcessed(_ errorId: String) { + + } } #endif diff --git a/Sources/BraveWallet/Preview Content/MockContent.swift b/Sources/BraveWallet/Preview Content/MockContent.swift index 91dc5cca746..34446078d85 100644 --- a/Sources/BraveWallet/Preview Content/MockContent.swift +++ b/Sources/BraveWallet/Preview Content/MockContent.swift @@ -205,7 +205,6 @@ extension BraveWallet.TransactionInfo { submittedTime: Date(timeIntervalSince1970: 1636399673), // Monday, November 8, 2021 7:27:53 PM confirmedTime: Date(timeIntervalSince1970: 1636402508), // Monday, November 8, 2021 8:15:08 PM originInfo: .init(), - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: "0x3f2116ef98fcab1a9c3c2d8988e0064ab59acfca" ) @@ -245,7 +244,6 @@ extension BraveWallet.TransactionInfo { submittedTime: Date(timeIntervalSince1970: 1636399673), // Monday, November 8, 2021 7:27:53 PM confirmedTime: Date(timeIntervalSince1970: 1636402508), // Monday, November 8, 2021 8:15:08 PM originInfo: .init(), - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: "0xdef1c0ded9bec7f1a1670819833240f027b25eff" ) @@ -283,7 +281,6 @@ extension BraveWallet.TransactionInfo { submittedTime: Date(timeIntervalSince1970: 1636399673), // Monday, November 8, 2021 7:27:53 PM confirmedTime: Date(timeIntervalSince1970: 1636402508), // Monday, November 8, 2021 8:15:08 PM originInfo: .init(), - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: BraveWallet.BlockchainToken.previewDaiToken.contractAddress ) @@ -322,7 +319,6 @@ extension BraveWallet.TransactionInfo { submittedTime: Date(timeIntervalSince1970: 1667854810), // Monday, November 7, 2022 9:00:10 PM GMT confirmedTime: Date(timeIntervalSince1970: 1667854820), // Monday, November 7, 2022 9:00:20 PM GMT originInfo: .init(), - groupId: nil, chainId: BraveWallet.SolanaMainnet, effectiveRecipient: nil // Currently only available for ETH and FIL ) @@ -361,7 +357,6 @@ extension BraveWallet.TransactionInfo { submittedTime: Date(timeIntervalSince1970: 1636399673), // Monday, November 8, 2021 7:27:53 PM confirmedTime: Date(timeIntervalSince1970: 1636402508), // Monday, November 8, 2021 8:15:08 PM originInfo: .init(), - groupId: nil, chainId: BraveWallet.SolanaMainnet, effectiveRecipient: nil // Currently only available for ETH and FIL ) @@ -392,7 +387,6 @@ extension BraveWallet.TransactionInfo { submittedTime: Date(timeIntervalSince1970: 1636399673), // Monday, November 8, 2021 7:27:53 PM confirmedTime: Date(timeIntervalSince1970: 1636402508), // Monday, November 8, 2021 8:15:08 PM originInfo: nil, - groupId: nil, chainId: BraveWallet.FilecoinMainnet, effectiveRecipient: nil ) @@ -408,12 +402,15 @@ extension BraveWallet.SignMessageRequest { originInfo: .init(originSpec: "https://app.uniswap.org", eTldPlusOne: "uniswap.org"), id: 1, accountId: BraveWallet.AccountInfo.previewAccount.accountId, - domain: "example.com", - message: "To avoid digital cat burglars, sign below to authenticate with CryptoKitties.", - isEip712: false, - domainHash: "", - primaryHash: "", - messageBytes: [], + signData: .init( + ethSignTypedData: .init( + message: "To avoid digital cat burglars, sign below to authenticate with CryptoKitties.", + domain: "", + domainHash: nil, + primaryHash: nil, + meta: nil + ) + ), coin: .eth, chainId: BraveWallet.MainnetChainId ) diff --git a/Sources/BraveWallet/Preview Content/MockEthTxService.swift b/Sources/BraveWallet/Preview Content/MockEthTxService.swift index e04004a9610..dae9b47b5f8 100644 --- a/Sources/BraveWallet/Preview Content/MockEthTxService.swift +++ b/Sources/BraveWallet/Preview Content/MockEthTxService.swift @@ -19,7 +19,7 @@ class MockTxService: BraveWalletTxService { completion(txs.first(where: { $0.id == txMetaId })) } - func addUnapprovedTransaction(_ txDataUnion: BraveWallet.TxDataUnion, from: BraveWallet.AccountId, origin: URLOrigin?, groupId: String?, completion: @escaping (Bool, String, String) -> Void) { + func addUnapprovedTransaction(_ txDataUnion: BraveWallet.TxDataUnion, from: BraveWallet.AccountId, completion: @escaping (Bool, String, String) -> Void) { completion(true, "txMetaId", "") } diff --git a/Sources/BraveWallet/Preview Content/MockJsonRpcService.swift b/Sources/BraveWallet/Preview Content/MockJsonRpcService.swift index 552d725b723..effd60fb19c 100644 --- a/Sources/BraveWallet/Preview Content/MockJsonRpcService.swift +++ b/Sources/BraveWallet/Preview Content/MockJsonRpcService.swift @@ -250,11 +250,11 @@ class MockJsonRpcService: BraveWalletJsonRpcService { completion(true, .success, "") } - func ethTokenSymbol(_ chainId: String, contractAddress: String, completion: @escaping (String, BraveWallet.ProviderError, String) -> Void) { + func ethTokenSymbol(_ contractAddress: String, chainId: String, completion: @escaping (String, BraveWallet.ProviderError, String) -> Void) { completion("", .internalError, "Error Message") } - func ethTokenDecimals(_ chainId: String, contractAddress: String, completion: @escaping (String, BraveWallet.ProviderError, String) -> Void) { + func ethTokenDecimals(_ contractAddress: String, chainId: String, completion: @escaping (String, BraveWallet.ProviderError, String) -> Void) { completion("", .internalError, "Error Message") } } diff --git a/Sources/BraveWallet/Preview Content/MockKeyringService.swift b/Sources/BraveWallet/Preview Content/MockKeyringService.swift index 1677758a7e3..669ce72c697 100644 --- a/Sources/BraveWallet/Preview Content/MockKeyringService.swift +++ b/Sources/BraveWallet/Preview Content/MockKeyringService.swift @@ -11,7 +11,15 @@ 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, accountInfos: [])] + private var keyrings: [BraveWallet.KeyringInfo] = [ + .init( + id: BraveWallet.KeyringId.default, + isKeyringCreated: false, + isLocked: false, + isBackedUp: true + ) + ] + private var allAccounts: [BraveWallet.AccountInfo] = [] private var privateKeys: [String: String] = [:] private var password = "" // Not a real phrase, has a duplicated word for testing @@ -74,7 +82,7 @@ class MockKeyringService: BraveWalletKeyringService { name: accountName, hardware: nil ) - defaultKeyring.accountInfos.append(info) + allAccounts.append(info) observers.allObjects.forEach { $0.accountsChanged() } @@ -148,7 +156,7 @@ class MockKeyringService: BraveWalletKeyringService { self.password = password // Test store does not test phrase validity observers.allObjects.forEach { - $0.keyringRestored(BraveWallet.KeyringId.default) + $0.walletRestored() } completion(true) } @@ -206,7 +214,7 @@ class MockKeyringService: BraveWalletKeyringService { hardware: nil ) privateKeys[info.address] = privateKey - defaultKeyring.accountInfos.append(info) + allAccounts.append(info) observers.allObjects.forEach { $0.accountsChanged() } @@ -242,11 +250,11 @@ class MockKeyringService: BraveWalletKeyringService { } func removeAccount(_ accountId: BraveWallet.AccountId, password: String, completion: @escaping (Bool) -> Void) { - guard let index = defaultKeyring.accountInfos.firstIndex(where: { $0.address == accountId.address }) else { + guard let index = allAccounts.firstIndex(where: { $0.address == accountId.address }) else { completion(false) return } - defaultKeyring.accountInfos.remove(at: index) + allAccounts.remove(at: index) observers.allObjects.forEach { $0.accountsChanged() } @@ -268,7 +276,7 @@ class MockKeyringService: BraveWalletKeyringService { } func setSelectedAccount(_ accountId: BraveWallet.AccountId, completion: @escaping (Bool) -> Void) { - guard let account = defaultKeyring.accountInfos.first(where: { $0.address == accountId.address }) else { + guard let account = allAccounts.first(where: { $0.address == accountId.address }) else { completion(false) return } @@ -300,14 +308,12 @@ class MockKeyringService: BraveWalletKeyringService { } func setAccountName(_ accountId: BraveWallet.AccountId, name: String, completion: @escaping (Bool) -> Void) { - keyringInfo(accountId.keyringId) { keyring in - if let account = keyring.accountInfos.first(where: { $0.accountId == accountId }) { - account.name = name - completion(true) - return - } + guard let account = allAccounts.first(where: { $0.address == accountId.address }) else { completion(false) + return } + account.name = name + completion(true) } func addHardwareAccounts(_ info: [BraveWallet.HardwareWalletAccount]) async -> [BraveWallet.AccountInfo]? { @@ -418,31 +424,41 @@ extension BraveWallet.KeyringInfo { id: BraveWallet.KeyringId.default, isKeyringCreated: true, isLocked: false, - isBackedUp: false, - accountInfos: [.mockEthAccount] + isBackedUp: false ) static let mockSolanaKeyringInfo: BraveWallet.KeyringInfo = .init( id: BraveWallet.KeyringId.solana, isKeyringCreated: true, isLocked: false, - isBackedUp: false, - accountInfos: [.mockSolAccount] + isBackedUp: false ) static let mockFilecoinKeyringInfo: BraveWallet.KeyringInfo = .init( id: BraveWallet.KeyringId.filecoin, isKeyringCreated: true, isLocked: false, - isBackedUp: false, - accountInfos: [.mockFilAccount] + isBackedUp: false ) static let mockFilecoinTestnetKeyringInfo: BraveWallet.KeyringInfo = .init( id: BraveWallet.KeyringId.filecoinTestnet, isKeyringCreated: true, isLocked: false, - isBackedUp: false, - accountInfos: [.mockFilTestnetAccount] + isBackedUp: false + ) +} + +extension BraveWallet.AllAccountsInfo { + static let mock: BraveWallet.AllAccountsInfo = .init( + accounts: [ + .mockEthAccount, + .mockSolAccount, + .mockFilAccount, + .mockFilTestnetAccount + ], + selectedAccount: .mockEthAccount, + ethDappSelectedAccount: .mockEthAccount, + solDappSelectedAccount: .mockSolAccount ) } diff --git a/Sources/BraveWallet/WalletStrings.swift b/Sources/BraveWallet/WalletStrings.swift index 84c780c2874..f3dd9eac01e 100644 --- a/Sources/BraveWallet/WalletStrings.swift +++ b/Sources/BraveWallet/WalletStrings.swift @@ -4633,5 +4633,19 @@ extension Strings { value: "An internal error has occurred", comment: "The title of a button that Deselects all visible options." ) + public static let signInWithBraveWallet = NSLocalizedString( + "wallet.signInWithBraveWallet", + tableName: "BraveWallet", + bundle: .module, + value: "Sign in with Brave Wallet", + comment: "The title of the view shown above a Sign In With Ethereum request." + ) + public static let securityRiskDetectedTitle = NSLocalizedString( + "wallet.securityRiskDetectedTitle", + tableName: "BraveWallet", + bundle: .module, + value: "Security Risk Detected", + comment: "The title of the view shown when a security issue is detected with a Sign In With Ethereum request." + ) } } diff --git a/Tests/BraveWalletTests/AccountActivityStoreTests.swift b/Tests/BraveWalletTests/AccountActivityStoreTests.swift index 41f2ce9657c..7e74f87baec 100644 --- a/Tests/BraveWalletTests/AccountActivityStoreTests.swift +++ b/Tests/BraveWalletTests/AccountActivityStoreTests.swift @@ -55,6 +55,9 @@ class AccountActivityStoreTests: XCTestCase { completion(.mockDefaultKeyringInfo) } } + keyringService._allAccounts = { + $0(.mock) + } let rpcService = BraveWallet.TestJsonRpcService() rpcService._addObserver = { _ in } @@ -414,7 +417,6 @@ class AccountActivityStoreTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.FilecoinMainnet, effectiveRecipient: nil ) diff --git a/Tests/BraveWalletTests/AssetDetailStoreTests.swift b/Tests/BraveWalletTests/AssetDetailStoreTests.swift index 8e789aef588..fe5861f2823 100644 --- a/Tests/BraveWalletTests/AssetDetailStoreTests.swift +++ b/Tests/BraveWalletTests/AssetDetailStoreTests.swift @@ -27,6 +27,9 @@ class AssetDetailStoreTests: XCTestCase { keyringService._keyringInfo = { $1(.mockDefaultKeyringInfo) } + keyringService._allAccounts = { completion in + completion(.mock) + } keyringService._addObserver = { _ in } let mockEthBalance: Double = 1 @@ -235,15 +238,10 @@ class AssetDetailStoreTests: XCTestCase { keyringService._keyringInfo = { $1(keyring) } - keyringService._addObserver = { _ in } keyringService._allAccounts = { completion in - completion(.init( - accounts: keyring.accountInfos, - selectedAccount: keyring.accountInfos.first, - ethDappSelectedAccount: keyring.accountInfos.first, - solDappSelectedAccount: nil - )) + completion(.mock) } + keyringService._addObserver = { _ in } let mockEthBalance: Double = 1 let ethBalanceWei = formatter.weiString( @@ -251,7 +249,6 @@ class AssetDetailStoreTests: XCTestCase { radix: .hex, decimals: Int(BraveWallet.BlockchainToken.previewToken.decimals) ) ?? "" - let formattedEthBalance = currencyFormatter.string(from: NSNumber(value: mockEthBalance)) ?? "" let rpcService = BraveWallet.TestJsonRpcService() rpcService._network = { $2(.mockMainnet) diff --git a/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift b/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift index d291a2fa5e1..4a8e5bc325d 100644 --- a/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift +++ b/Tests/BraveWalletTests/NetworkSelectionStoreTests.swift @@ -25,13 +25,11 @@ import Preferences let keyringService = BraveWallet.TestKeyringService() keyringService._keyringInfo = { keyringId, completion in - let isEthereumKeyringId = keyringId == BraveWallet.KeyringId.default let keyring: BraveWallet.KeyringInfo = .init( id: BraveWallet.KeyringId.default, isKeyringCreated: true, isLocked: false, - isBackedUp: true, - accountInfos: isEthereumKeyringId ? [.previewAccount] : [] + isBackedUp: true ) completion(keyring) } @@ -217,23 +215,11 @@ import Preferences ] keyringService._keyringInfo = { keyringId, completion in - let accountInfos: [BraveWallet.AccountInfo] - switch keyringId { - case BraveWallet.KeyringId.default: - accountInfos = accountInfosDict[.eth, default: []] - case BraveWallet.KeyringId.solana: - accountInfos = accountInfosDict[.sol, default: []] - case BraveWallet.KeyringId.filecoin: - accountInfos = accountInfosDict[.fil, default: []] - default: - accountInfos = [] - } let keyring: BraveWallet.KeyringInfo = .init( id: keyringId, isKeyringCreated: true, isLocked: false, - isBackedUp: false, - accountInfos: accountInfos + isBackedUp: false ) completion(keyring) } diff --git a/Tests/BraveWalletTests/NetworkStoreTests.swift b/Tests/BraveWalletTests/NetworkStoreTests.swift index d16846dcb30..425269de906 100644 --- a/Tests/BraveWalletTests/NetworkStoreTests.swift +++ b/Tests/BraveWalletTests/NetworkStoreTests.swift @@ -31,13 +31,11 @@ import Preferences let keyringService = BraveWallet.TestKeyringService() keyringService._keyringInfo = { keyringId, completion in - let isEthereumKeyringId = keyringId == BraveWallet.KeyringId.default let keyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.default, + id: keyringId, isKeyringCreated: true, isLocked: false, - isBackedUp: true, - accountInfos: isEthereumKeyringId ? [.previewAccount] : [] + isBackedUp: true ) completion(keyring) } diff --git a/Tests/BraveWalletTests/PortfolioStoreTests.swift b/Tests/BraveWalletTests/PortfolioStoreTests.swift index d7435b243d0..648665219d6 100644 --- a/Tests/BraveWalletTests/PortfolioStoreTests.swift +++ b/Tests/BraveWalletTests/PortfolioStoreTests.swift @@ -118,7 +118,6 @@ import Preferences let formatter = WeiFormatter(decimalFormatStyle: .decimals(precision: 18)) // config filecoin on mainnet - let mockFilAccountInfos: [BraveWallet.AccountInfo] = [filAccount1, filAccount2] let mockFilUserAssets: [BraveWallet.BlockchainToken] = [ BraveWallet.NetworkInfo.mockFilecoinMainnet.nativeToken.copy(asVisibleAsset: true) ] @@ -128,7 +127,6 @@ import Preferences decimals: Int(BraveWallet.BlockchainToken.mockFilToken.decimals) ) ?? "" // config filecoin on testnet - let mockFilTestnetAccountInfos: [BraveWallet.AccountInfo] = [filTestnetAccount] let mockFilTestnetBalanceInWei = formatter.weiString( from: mockFILBalanceTestnet, radix: .decimal, @@ -136,13 +134,11 @@ import Preferences ) ?? "" // config Solana - let mockSolAccountInfos: [BraveWallet.AccountInfo] = [solAccount1, solAccount2] let mockSolUserAssets: [BraveWallet.BlockchainToken] = [ BraveWallet.NetworkInfo.mockSolana.nativeToken.copy(asVisibleAsset: true), .mockSpdToken // Verify non-visible assets not displayed #6386 ] // config Ethereum - let mockEthAccountInfos: [BraveWallet.AccountInfo] = [ethAccount1, ethAccount2] let mockEthUserAssets: [BraveWallet.BlockchainToken] = [ .previewToken.copy(asVisibleAsset: true), .previewDaiToken, // Verify non-visible assets not displayed #6386 @@ -172,35 +168,6 @@ import Preferences filTestnet.nativeToken.copy(asVisibleAsset: true) ] - let ethKeyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.default, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true, - accountInfos: mockEthAccountInfos - ) - let solKeyring: BraveWallet.KeyringInfo = .init( - id: BraveWallet.KeyringId.solana, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true, - accountInfos: mockSolAccountInfos - ) - let filKeyring: BraveWallet.KeyringInfo = .init( - id: .filecoin, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true, - accountInfos: mockFilAccountInfos - ) - let filTestnetKeyring: BraveWallet.KeyringInfo = .init( - id: .filecoinTestnet, - isKeyringCreated: true, - isLocked: false, - isBackedUp: true, - accountInfos: mockFilTestnetAccountInfos - ) - // setup test services let keyringService = BraveWallet.TestKeyringService() keyringService._addObserver = { _ in } @@ -210,10 +177,15 @@ import Preferences } keyringService._allAccounts = { $0(.init( - accounts: ethKeyring.accountInfos + solKeyring.accountInfos + filKeyring.accountInfos + filTestnetKeyring.accountInfos, - selectedAccount: ethKeyring.accountInfos.first, - ethDappSelectedAccount: ethKeyring.accountInfos.first, - solDappSelectedAccount: solKeyring.accountInfos.first + accounts: [ + self.ethAccount1, self.ethAccount2, + self.solAccount1, self.solAccount2, + self.filAccount1, self.filAccount2, + self.filTestnetAccount + ], + selectedAccount: self.ethAccount1, + ethDappSelectedAccount: self.ethAccount1, + solDappSelectedAccount: self.solAccount1 )) } let rpcService = BraveWallet.TestJsonRpcService() diff --git a/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift b/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift index 42a52109fb1..6472fbd57a8 100644 --- a/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift +++ b/Tests/BraveWalletTests/SelectAccountTokenStoreTests.swift @@ -145,8 +145,7 @@ import Preferences id: BraveWallet.KeyringId.default, isKeyringCreated: true, isLocked: false, - isBackedUp: true, - accountInfos: [.mockEthAccount, self.mockEthAccount2] + isBackedUp: true ) completion(keyring) case .solana: @@ -154,8 +153,7 @@ import Preferences id: BraveWallet.KeyringId.solana, isKeyringCreated: true, isLocked: false, - isBackedUp: true, - accountInfos: [.mockSolAccount] + isBackedUp: true ) completion(keyring) case .filecoin: @@ -166,6 +164,20 @@ import Preferences completion(.mockDefaultKeyringInfo) } } + keyringService._allAccounts = { + $0(.init( + accounts: [ + .mockEthAccount, + self.mockEthAccount2, + .mockSolAccount, + .mockFilAccount, + .mockFilTestnetAccount + ], + selectedAccount: .mockEthAccount, + ethDappSelectedAccount: .mockEthAccount, + solDappSelectedAccount: .mockSolAccount + )) + } let rpcService = BraveWallet.TestJsonRpcService() rpcService._allNetworks = { coin, completion in completion(self.allNetworks[coin] ?? []) diff --git a/Tests/BraveWalletTests/SettingsStoreTests.swift b/Tests/BraveWalletTests/SettingsStoreTests.swift index d0f0c75889b..b5f8883b1c9 100644 --- a/Tests/BraveWalletTests/SettingsStoreTests.swift +++ b/Tests/BraveWalletTests/SettingsStoreTests.swift @@ -16,7 +16,6 @@ class SettingsStoreTests: XCTestCase { /// Sets up TestKeyringService, TestBraveWalletService and TestTxService with some default values. private func setupServices() -> (BraveWallet.TestKeyringService, BraveWallet.TestBraveWalletService, BraveWallet.TestJsonRpcService, BraveWallet.TestTxService, IpfsAPI) { - let mockAccountInfos: [BraveWallet.AccountInfo] = [.previewAccount] let mockUserAssets: [BraveWallet.BlockchainToken] = [.previewToken.copy(asVisibleAsset: true)] let keyringService = BraveWallet.TestKeyringService() @@ -25,8 +24,8 @@ class SettingsStoreTests: XCTestCase { id: BraveWallet.KeyringId.default, isKeyringCreated: true, isLocked: false, - isBackedUp: true, - accountInfos: mockAccountInfos) + isBackedUp: true + ) completion(keyring) } keyringService._addObserver = { _ in } diff --git a/Tests/BraveWalletTests/SwapTokenStoreTests.swift b/Tests/BraveWalletTests/SwapTokenStoreTests.swift index 720340cd73b..49c2f2e107d 100644 --- a/Tests/BraveWalletTests/SwapTokenStoreTests.swift +++ b/Tests/BraveWalletTests/SwapTokenStoreTests.swift @@ -253,7 +253,7 @@ class SwapStoreTests: XCTestCase { completion(nil, "") } let txService = BraveWallet.TestTxService() - txService._addUnapprovedTransaction = { $4(true, "tx-meta-id", "") } + txService._addUnapprovedTransaction = { $2(true, "tx-meta-id", "") } let walletService = BraveWallet.TestBraveWalletService() let mockAssetManager = TestableWalletUserAssetManager() mockAssetManager._getAllUserAssetsInNetworkAssets = { _, _ in @@ -545,7 +545,7 @@ class SwapStoreTests: XCTestCase { @MainActor func testSwapERC20EIP1559Transaction() async { let (keyringService, blockchainRegistry, rpcService, swapService, txService, walletService, ethTxManagerProxy, solTxManagerProxy, mockAssetManager) = setupServices() var submittedTxData: BraveWallet.TxDataUnion? - txService._addUnapprovedTransaction = { txData, _, _, _, completion in + txService._addUnapprovedTransaction = { txData, _, completion in submittedTxData = txData completion(true, "tx-meta-id", "") } @@ -575,7 +575,7 @@ class SwapStoreTests: XCTestCase { // Celo Mainnet / `.mockCelo` is not EIP1559 let (keyringService, blockchainRegistry, rpcService, swapService, txService, walletService, ethTxManagerProxy, solTxManagerProxy, mockAssetManager) = setupServices(network: .mockCelo) var submittedTxData: BraveWallet.TxDataUnion? - txService._addUnapprovedTransaction = { txData, _, _, _, completion in + txService._addUnapprovedTransaction = { txData, _, completion in submittedTxData = txData completion(true, "tx-meta-id", "") } @@ -605,7 +605,7 @@ class SwapStoreTests: XCTestCase { @MainActor func testSwapETHSwapEIP1559Transaction() async { let (keyringService, blockchainRegistry, rpcService, swapService, txService, walletService, ethTxManagerProxy, solTxManagerProxy, mockAssetManager) = setupServices() var submittedTxData: BraveWallet.TxDataUnion? - txService._addUnapprovedTransaction = { txData, _, _, _, completion in + txService._addUnapprovedTransaction = { txData, _, completion in submittedTxData = txData completion(true, "tx-meta-id", "") } @@ -636,7 +636,7 @@ class SwapStoreTests: XCTestCase { // Celo Mainnet / `.mockCelo` is not EIP1559 let (keyringService, blockchainRegistry, rpcService, swapService, txService, walletService, ethTxManagerProxy, solTxManagerProxy, mockAssetManager) = setupServices(network: .mockCelo) var submittedTxData: BraveWallet.TxDataUnion? - txService._addUnapprovedTransaction = { txData, _, _, _, completion in + txService._addUnapprovedTransaction = { txData, _, completion in submittedTxData = txData completion(true, "tx-meta-id", "") } @@ -685,7 +685,7 @@ class SwapStoreTests: XCTestCase { completion(.init(), .success, "") } var submittedTxData: BraveWallet.TxDataUnion? - txService._addUnapprovedTransaction = { txData, _, _, _, completion in + txService._addUnapprovedTransaction = { txData, _, completion in submittedTxData = txData completion(true, "tx-meta-id", "") } diff --git a/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift b/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift index dd6877f2efa..30e23693f63 100644 --- a/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift +++ b/Tests/BraveWalletTests/TransactionConfirmationStoreTests.swift @@ -114,17 +114,18 @@ import Preferences id: id, isKeyringCreated: true, isLocked: false, - isBackedUp: true, - accountInfos: []) - if id == BraveWallet.KeyringId.default { - keyring.accountInfos = accountInfos.filter { $0.coin == .eth } - } else if id == .solana { - keyring.accountInfos = accountInfos.filter { $0.coin == .sol } - } else { - keyring.accountInfos = accountInfos.filter { $0.coin == .fil } - } + isBackedUp: true + ) completion(keyring) } + keyringService._allAccounts = { + $0(.init( + accounts: accountInfos, + selectedAccount: accountInfos.first, + ethDappSelectedAccount: accountInfos.first(where: { $0.coin == .eth }), + solDappSelectedAccount: accountInfos.first(where: { $0.coin == .sol }) + )) + } let solTxManagerProxy = BraveWallet.TestSolanaTxManagerProxy() solTxManagerProxy._estimatedTxFee = { $2(0, .success, "") } diff --git a/Tests/BraveWalletTests/TransactionParserTests.swift b/Tests/BraveWalletTests/TransactionParserTests.swift index 0c4724858ee..9f8b6368df3 100644 --- a/Tests/BraveWalletTests/TransactionParserTests.swift +++ b/Tests/BraveWalletTests/TransactionParserTests.swift @@ -114,7 +114,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -210,7 +209,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -297,7 +295,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -388,7 +385,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -475,7 +471,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -560,7 +555,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -649,7 +643,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.MainnetChainId, effectiveRecipient: transactionData.baseData.to ) @@ -735,7 +728,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.SolanaMainnet, effectiveRecipient: nil ) @@ -833,7 +825,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.SolanaMainnet, effectiveRecipient: nil ) @@ -918,7 +909,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.SolanaMainnet, effectiveRecipient: nil ) @@ -1129,7 +1119,6 @@ class TransactionParserTests: XCTestCase { submittedTime: Date(), confirmedTime: Date(), originInfo: nil, - groupId: nil, chainId: BraveWallet.FilecoinTestnet, effectiveRecipient: nil ) diff --git a/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift b/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift index 3aa3f14b2ba..598f0f27683 100644 --- a/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift +++ b/Tests/BraveWalletTests/TransactionsActivityStoreTests.swift @@ -65,6 +65,9 @@ class TransactionsActivityStoreTests: XCTestCase { completion(.mockDefaultKeyringInfo) } } + keyringService._allAccounts = { + $0(.mock) + } let rpcService = BraveWallet.TestJsonRpcService() rpcService._allNetworks = { coin, completion in diff --git a/package-lock.json b/package-lock.json index 1ba135067af..26f8a934e61 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.59.122/brave-core-ios-1.59.122.tgz", + "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.60.96/brave-core-ios-1.60.96.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.59.122", - "resolved": "https://github.com/brave/brave-browser/releases/download/v1.59.122/brave-core-ios-1.59.122.tgz", - "integrity": "sha512-UmtfTW7xZ1ttbzKNQY/vsnD+lfEnkyQ/Ofgn8hW+9bH3DdRe//+z/tw2RWuloOeWmG0fS9bNJLN+YRZpIDFYjQ==", + "version": "1.60.96", + "resolved": "https://github.com/brave/brave-browser/releases/download/v1.60.96/brave-core-ios-1.60.96.tgz", + "integrity": "sha512-Ni2lFUIu9+avKYKZrlSRokCOld+jlRBIFrHIXrvCpMXKhAUCVl85B6AMrUMaxNIh4dWM0eJRMDAwntg+9YEe5g==", "license": "ISC" }, "node_modules/browserslist": { @@ -3171,8 +3171,8 @@ } }, "brave-core-ios": { - "version": "https://github.com/brave/brave-browser/releases/download/v1.59.122/brave-core-ios-1.59.122.tgz", - "integrity": "sha512-UmtfTW7xZ1ttbzKNQY/vsnD+lfEnkyQ/Ofgn8hW+9bH3DdRe//+z/tw2RWuloOeWmG0fS9bNJLN+YRZpIDFYjQ==" + "version": "https://github.com/brave/brave-browser/releases/download/v1.60.96/brave-core-ios-1.60.96.tgz", + "integrity": "sha512-Ni2lFUIu9+avKYKZrlSRokCOld+jlRBIFrHIXrvCpMXKhAUCVl85B6AMrUMaxNIh4dWM0eJRMDAwntg+9YEe5g==" }, "browserslist": { "version": "4.17.1", diff --git a/package.json b/package.json index da91e174c8b..3b2a1dcff86 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.59.122/brave-core-ios-1.59.122.tgz", + "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.60.96/brave-core-ios-1.60.96.tgz", "leo": "github:brave/leo#7f2dfddb70aff1501ef5a2f3c640a8c74a7343ee", "leo-sf-symbols": "github:brave/leo-sf-symbols#d6056328b8d6ef06e68996ff02a22e06f52590c3", "page-metadata-parser": "^1.1.3",