diff --git a/ios/brave-ios/Sources/Brave/Frontend/Settings/Debug/Brave Wallet/BraveWalletDebugMenu.swift b/ios/brave-ios/Sources/Brave/Frontend/Settings/Debug/Brave Wallet/BraveWalletDebugMenu.swift new file mode 100644 index 00000000000..bc51d5065cc --- /dev/null +++ b/ios/brave-ios/Sources/Brave/Frontend/Settings/Debug/Brave Wallet/BraveWalletDebugMenu.swift @@ -0,0 +1,26 @@ +// Copyright 2021 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 https://mozilla.org/MPL/2.0/. + +import BraveUI +import BraveWallet +import Preferences +import SwiftUI + +struct BraveWalletDebugMenu: View { + + @ObservedObject var enableBitcoinTestnet = Preferences.Wallet.isBitcoinTestnetEnabled + + var body: some View { + List { + Section { + Toggle("Enable Bitcoin Testnet", isOn: $enableBitcoinTestnet.value) + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + } + } + .listBackgroundColor(Color(UIColor.braveGroupedBackground)) + .navigationTitle("Brave Wallet Debug") + .navigationBarTitleDisplayMode(.inline) + } +} diff --git a/ios/brave-ios/Sources/Brave/Frontend/Settings/SettingsViewController.swift b/ios/brave-ios/Sources/Brave/Frontend/Settings/SettingsViewController.swift index 289410ddf16..d544089cb07 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Settings/SettingsViewController.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Settings/SettingsViewController.swift @@ -163,6 +163,13 @@ class SettingsViewController: TableViewController { navigationController?.pushViewController(hostingController, animated: true) } + private func displayBraveWalletDebugMenu() { + let hostingController = + UIHostingController(rootView: BraveWalletDebugMenu()) + + navigationController?.pushViewController(hostingController, animated: true) + } + /// The function for refreshing VPN status for menu /// - Parameter notification: NEVPNStatusDidChange @objc private func vpnConfigChanged(notification: NSNotification) { @@ -1062,6 +1069,14 @@ class SettingsViewController: TableViewController { accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self ), + Row( + text: "View Brave Wallet Debug Menu", + selection: { [unowned self] in + self.displayBraveWalletDebugMenu() + }, + accessory: .disclosureIndicator, + cellClass: MultilineValue1Cell.self + ), Row( text: "Consolidate Privacy Report Data", detailText: diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift index d12ce6abcca..9df962bc620 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Accounts/Add/AddAccountView.swift @@ -6,6 +6,7 @@ import BraveCore import BraveUI import DesignSystem +import Preferences import Strings import SwiftUI @@ -419,8 +420,14 @@ struct AddAccountView: View { private var isKeyringSelectionRequired: Bool { guard !selectedCoinNetworks.isEmpty else { return false } - return (selectedCoin == .fil || selectedCoin == .btc) - || (preSelectedCoin == .fil || preSelectedCoin == .btc) + if selectedCoin == .fil || preSelectedCoin == .fil { + return true + } else if (selectedCoin == .btc || preSelectedCoin == .btc) + && Preferences.Wallet.isBitcoinTestnetEnabled.value + { + return true + } + return false } } diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/AccountsStore.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/AccountsStore.swift index d0fd91a8eb8..ae6d66bfd8c 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/AccountsStore.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/AccountsStore.swift @@ -108,7 +108,7 @@ class AccountsStore: ObservableObject, WalletObserverStore { } let tokens = allTokensPerNetwork.flatMap(\.tokens) - var allAccounts = await keyringService.allAccounts().accounts + var allAccounts = await keyringService.allAccountInfos() var accountDetails = buildAccountDetails(accounts: allAccounts, tokens: tokens) self.primaryAccounts = accountDetails @@ -123,7 +123,7 @@ class AccountsStore: ObservableObject, WalletObserverStore { ) // if new accounts added while balances were being fetched. - allAccounts = await keyringService.allAccounts().accounts + allAccounts = await keyringService.allAccountInfos() accountDetails = buildAccountDetails(accounts: allAccounts, tokens: tokens) self.primaryAccounts = accountDetails diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/DepositTokenStore.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/DepositTokenStore.swift index 99f1375775d..baf8bb972d1 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/DepositTokenStore.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/DepositTokenStore.swift @@ -113,9 +113,7 @@ class DepositTokenStore: ObservableObject, WalletObserverStore { accounts: allAccounts.filter({ $0.coin == .btc }) ) } - self.allNetworks = await rpcService.allNetworksForSupportedCoins( - respectTestnetPreference: true - ) + self.allNetworks = await rpcService.allNetworksForSupportedCoins() self.update() } } diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift index db7501c8b37..4ca36d7a015 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift @@ -194,6 +194,9 @@ public class KeyringStore: ObservableObject, WalletObserverStore { self.keychain = keychain setupObservers() + + Preferences.Wallet.isBitcoinTestnetEnabled.observe(from: self) + updateInfo() Task { @MainActor in @@ -655,3 +658,23 @@ public class KeyringStore: ObservableObject, WalletObserverStore { keychain.getPasswordFromKeychain(key: Self.passwordKeychainKey) } } + +extension KeyringStore: PreferencesObserver { + public func preferencesDidChange(for key: String) { + if Preferences.Wallet.isBitcoinTestnetEnabled.value == false { + // user disabled Bitcoin Testnet + Task { @MainActor in + let allAccounts = await keyringService.allAccounts() + if let currentlySelectedAccount = allAccounts.selectedAccount, + currentlySelectedAccount.keyringId == .bitcoin84Testnet, + let firstAvailableAccount = allAccounts.accounts.first(where: { + $0.keyringId != currentlySelectedAccount.keyringId + }) + { + // we need to switch to the first available account + setSelectedAccount(to: firstAvailableAccount) + } + } + } + } +} diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NFTStore.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NFTStore.swift index 1872da9fbbd..03c1eeef3e1 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NFTStore.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NFTStore.swift @@ -293,7 +293,7 @@ public class NFTStore: ObservableObject, WalletObserverStore { let isLocked = await keyringService.isLocked() guard !isLocked else { return } // `update() will be called after unlock` - self.allAccounts = await keyringService.allAccounts().accounts + self.allAccounts = await keyringService.allAccountInfos() .filter { account in WalletConstants.supportedCoinTypes().contains(account.coin) } diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift index 098be2da49a..f06554755df 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/NetworkStore.swift @@ -383,7 +383,12 @@ extension Array where Element == BraveWallet.NetworkInfo { /// Returns the known test networks in Self. var testNetworks: [BraveWallet.NetworkInfo] { filter { - WalletConstants.supportedTestNetworkChainIds.contains($0.chainId) + if !Preferences.Wallet.isBitcoinTestnetEnabled.value + && $0.chainId == BraveWallet.BitcoinTestnet + { + return false + } + return WalletConstants.supportedTestNetworkChainIds.contains($0.chainId) } } } diff --git a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/PortfolioStore.swift b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/PortfolioStore.swift index efe3b537ad6..6bab7848da0 100644 --- a/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/PortfolioStore.swift +++ b/ios/brave-ios/Sources/BraveWallet/Crypto/Stores/PortfolioStore.swift @@ -437,7 +437,7 @@ public class PortfolioStore: ObservableObject, WalletObserverStore { guard !isLocked else { return } // `update() will be called after unlock` self.isLoadingBalances = true - self.allAccounts = await keyringService.allAccounts().accounts + self.allAccounts = await keyringService.allAccountInfos() .filter { account in WalletConstants.supportedCoinTypes().contains(account.coin) } diff --git a/ios/brave-ios/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift b/ios/brave-ios/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift index 5f90c58d5c2..b4018a94e04 100644 --- a/ios/brave-ios/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift +++ b/ios/brave-ios/Sources/BraveWallet/Extensions/KeyringServiceExtensions.swift @@ -6,6 +6,7 @@ import BraveCore import Foundation import OrderedCollections +import Preferences extension BraveWalletKeyringService { @@ -19,4 +20,14 @@ extension BraveWalletKeyringService { let allAccountsForKeyring = await allAccounts().accounts.filter { $0.keyringId == keyringId } return !allAccountsForKeyring.isEmpty } + + /// Return a list of all accounts with checking if Bitcoin testnet is enabled + /// The list of account will not include Bitcoin Testnet Accounts if Bitcoin testnet is disabled. + func allAccountInfos(checkBTCTestnet: Bool = true) async -> [BraveWallet.AccountInfo] { + var accounts = await self.allAccounts().accounts + if checkBTCTestnet, !Preferences.Wallet.isBitcoinTestnetEnabled.value { + accounts = accounts.filter({ $0.keyringId != BraveWallet.KeyringId.bitcoin84Testnet }) + } + return accounts + } } diff --git a/ios/brave-ios/Sources/BraveWallet/Extensions/RpcServiceExtensions.swift b/ios/brave-ios/Sources/BraveWallet/Extensions/RpcServiceExtensions.swift index a088ff10ef2..3c3ad4f28fd 100644 --- a/ios/brave-ios/Sources/BraveWallet/Extensions/RpcServiceExtensions.swift +++ b/ios/brave-ios/Sources/BraveWallet/Extensions/RpcServiceExtensions.swift @@ -388,6 +388,11 @@ extension BraveWalletJsonRpcService { $0 == network.chainId }) } + if Preferences.Wallet.showTestNetworks.value && respectTestnetPreference + && network.chainId == BraveWallet.BitcoinTestnet + { // if testnets are enabled, we still need to check if bitcoin testnet is enabled + return Preferences.Wallet.isBitcoinTestnetEnabled.value + } return true } return allChains.sorted { lhs, rhs in diff --git a/ios/brave-ios/Sources/BraveWallet/WalletPreferences.swift b/ios/brave-ios/Sources/BraveWallet/WalletPreferences.swift index cdae1ab0936..d0ec247879d 100644 --- a/ios/brave-ios/Sources/BraveWallet/WalletPreferences.swift +++ b/ios/brave-ios/Sources/BraveWallet/WalletPreferences.swift @@ -158,6 +158,12 @@ extension Preferences { key: "wallet.show-wallet-is-onboarding-completed", default: false ) + + /// Used for Debug section for anyone wants to test with Bitcoin Testnet network or account + public static let isBitcoinTestnetEnabled = Option( + key: "wallet.is-bitcoin-testnet-enabled", + default: false + ) } } diff --git a/ios/brave-ios/Sources/BraveWallet/WalletUserAssetManager.swift b/ios/brave-ios/Sources/BraveWallet/WalletUserAssetManager.swift index 1cb0cc8010c..8851444e4b2 100644 --- a/ios/brave-ios/Sources/BraveWallet/WalletUserAssetManager.swift +++ b/ios/brave-ios/Sources/BraveWallet/WalletUserAssetManager.swift @@ -378,7 +378,7 @@ public class WalletUserAssetManager: WalletUserAssetManagerType, WalletObserverS public func refreshBalances(_ completion: (() -> Void)? = nil) { refreshBalanceTask?.cancel() refreshBalanceTask = Task { @MainActor in - let accounts = await keyringService.allAccounts().accounts + let accounts = await keyringService.allAccountInfos() let allNetworks = await rpcService.allNetworksForSupportedCoins() let allUserAssets: [NetworkAssets] = self.getAllUserAssetsInNetworkAssets( networks: allNetworks, diff --git a/ios/brave-ios/Tests/BraveWalletTests/AccountsStoreTests.swift b/ios/brave-ios/Tests/BraveWalletTests/AccountsStoreTests.swift index bbce22fdc70..5ca69406b4e 100644 --- a/ios/brave-ios/Tests/BraveWalletTests/AccountsStoreTests.swift +++ b/ios/brave-ios/Tests/BraveWalletTests/AccountsStoreTests.swift @@ -12,6 +12,12 @@ import XCTest @MainActor class AccountsStoreTests: XCTestCase { + override class func tearDown() { + super.tearDown() + Preferences.Wallet.showTestNetworks.reset() + Preferences.Wallet.isBitcoinTestnetEnabled.reset() + } + private var cancellables: Set = .init() let ethAccount1: BraveWallet.AccountInfo = .mockEthAccount @@ -96,8 +102,9 @@ import XCTest let formatter = WeiFormatter(decimalFormatStyle: .decimals(precision: 18)) - func testUpdate() async { + func updateHelper(bitcoinTestnetEnabled: Bool) async { Preferences.Wallet.showTestNetworks.value = true + Preferences.Wallet.isBitcoinTestnetEnabled.value = bitcoinTestnetEnabled let ethBalanceWei = formatter.weiString( from: mockETHBalanceAccount1, @@ -295,7 +302,8 @@ import XCTest XCTFail("Expected account details models") return } - XCTAssertEqual(accountDetails.count, 7) + let accountNumber = bitcoinTestnetEnabled ? 7 : 6 + XCTAssertEqual(accountDetails.count, accountNumber) XCTAssertEqual(accountDetails[safe: 0]?.account, self.ethAccount1) XCTAssertEqual(accountDetails[safe: 0]?.tokensWithBalance, self.ethMainnetTokens) @@ -325,9 +333,11 @@ import XCTest XCTAssertEqual(accountDetails[safe: 5]?.tokensWithBalance, []) // BTC 0 value XCTAssertEqual(accountDetails[safe: 5]?.totalBalanceFiat, "$0.00") - XCTAssertEqual(accountDetails[safe: 6]?.account, self.btcTestnetAccount) - XCTAssertEqual(accountDetails[safe: 6]?.tokensWithBalance, []) // BTC 0 value - XCTAssertEqual(accountDetails[safe: 6]?.totalBalanceFiat, "$0.00") + if bitcoinTestnetEnabled { + XCTAssertEqual(accountDetails[safe: 6]?.account, self.btcTestnetAccount) + XCTAssertEqual(accountDetails[safe: 6]?.tokensWithBalance, []) // BTC 0 value + XCTAssertEqual(accountDetails[safe: 6]?.totalBalanceFiat, "$0.00") + } }.store(in: &cancellables) store.update() @@ -335,8 +345,11 @@ import XCTest await fulfillment(of: [updateExpectation], timeout: 1) } - override class func tearDown() { - super.tearDown() - Preferences.Wallet.showTestNetworks.reset() + func testUpdate() async { + await updateHelper(bitcoinTestnetEnabled: false) + } + + func testUpdateBitcoinTestnet() async { + await updateHelper(bitcoinTestnetEnabled: true) } } diff --git a/ios/brave-ios/Tests/BraveWalletTests/PortfolioStoreTests.swift b/ios/brave-ios/Tests/BraveWalletTests/PortfolioStoreTests.swift index 92c7f897599..79a194a4f20 100644 --- a/ios/brave-ios/Tests/BraveWalletTests/PortfolioStoreTests.swift +++ b/ios/brave-ios/Tests/BraveWalletTests/PortfolioStoreTests.swift @@ -31,6 +31,7 @@ import XCTest Preferences.Wallet.isHidingSmallBalancesFilter.reset() Preferences.Wallet.nonSelectedAccountsFilter.reset() Preferences.Wallet.nonSelectedNetworksFilter.reset() + Preferences.Wallet.isBitcoinTestnetEnabled.reset() } // Accounts @@ -432,7 +433,7 @@ import XCTest return } - // ETH on Ethereum mainnet, SOL on Solana mainnet, USDC on Ethereum mainnet, ETH on Goerli, FIL on Filecoin mainnet, FIL on Filecoin testnet, BTC on Bitcoin mainnet, BTC on Bitcoin testnet + // ETH on Ethereum mainnet, SOL on Solana mainnet, USDC on Ethereum mainnet, ETH on Goerli, FIL on Filecoin mainnet, FIL on Filecoin testnet, BTC on Bitcoin mainnet. No BTC on Bitcoin testnet XCTAssertEqual(group.assets.count, 5) // ETH Mainnet (value ~= $2741.7510399999996) XCTAssertEqual( @@ -526,7 +527,7 @@ import XCTest // ETH Goerli (value = 0), hidden because test networks not selected by default // FIL Testnet (value = $400.00), hidden because test networks not selected by default - // FIL Testnet (value = 0.00), hidden because test networks not selected by default + // BIT Testnet (value = 0.00), hidden because Bitcoin testnet is disabled by default XCTAssertNil(group.assets[safe: 5]) } .store(in: &cancellables) @@ -617,8 +618,9 @@ import XCTest } /// Test `assetGroups` will be sorted to from smallest to highest fiat value when `sortOrder` filter is `valueAsc`. - func testFilterSort() async { + func filterSortHelper(bitcoinTestnetEnabled: Bool) async { Preferences.Wallet.showTestNetworks.value = true + Preferences.Wallet.isBitcoinTestnetEnabled.value = bitcoinTestnetEnabled let store = setupStore() let sortExpectation = expectation(description: "update-sortOrder") store.$assetGroups @@ -636,69 +638,80 @@ import XCTest XCTFail("Unexpected test result") return } - // USDC on Ethereum mainnet, SOL on Solana mainnet, ETH on Ethereum mainnet, FIL on Filecoin mainnet, FIL on Filecoin testnet, BTC on Bitcoin mainnet and BTC on Bitcoin testnet - XCTAssertEqual(group.assets.count, 8) + // USDC on Ethereum mainnet, SOL on Solana mainnet, ETH on Ethereum mainnet, FIL on Filecoin mainnet, FIL on Filecoin testnet, BTC on Bitcoin mainnet. No BTC on Bitcoin testnet since Bitcoin tesnet is disabled by default + let assetGroupNumber = bitcoinTestnetEnabled ? 8 : 7 + XCTAssertEqual(group.assets.count, assetGroupNumber) // BTC mainnet (value = $0) XCTAssertEqual( group.assets[safe: 0]?.token.symbol, BraveWallet.BlockchainToken.mockBTCToken.symbol ) XCTAssertEqual(group.assets[safe: 0]?.quantity, String(format: "%.04f", 0)) - // BTC testnet (value = $0) - XCTAssertEqual( - group.assets[safe: 1]?.token.symbol, - BraveWallet.BlockchainToken.mockBTCToken.symbol - ) - XCTAssertEqual(group.assets[safe: 1]?.quantity, String(format: "%.04f", 0)) + var offset = 0 + if bitcoinTestnetEnabled { + offset += 1 + // BTC testnet (value = $0) + XCTAssertEqual( + group.assets[safe: 1]?.token.symbol, + BraveWallet.BlockchainToken.mockBTCToken.symbol + ) + XCTAssertEqual(group.assets[safe: 1]?.quantity, String(format: "%.04f", 0)) + } // ETH Goerli (value = $0) + offset += 1 XCTAssertEqual( - group.assets[safe: 2]?.token.symbol, + group.assets[safe: offset]?.token.symbol, BraveWallet.BlockchainToken.previewToken.symbol ) - XCTAssertEqual(group.assets[safe: 2]?.quantity, String(format: "%.04f", 0)) + XCTAssertEqual(group.assets[safe: offset]?.quantity, String(format: "%.04f", 0)) // USDC (value = $0.04) + offset += 1 XCTAssertEqual( - group.assets[safe: 3]?.token.symbol, + group.assets[safe: offset]?.token.symbol, BraveWallet.BlockchainToken.mockUSDCToken.symbol ) XCTAssertEqual( - group.assets[safe: 3]?.quantity, + group.assets[safe: offset]?.quantity, String(format: "%.04f", self.mockUSDCBalanceAccount1 + self.mockUSDCBalanceAccount2) ) // FIL (value = $4.00) on filecoin mainnet + offset += 1 XCTAssertEqual( - group.assets[safe: 4]?.token.symbol, + group.assets[safe: offset]?.token.symbol, BraveWallet.BlockchainToken.mockFilToken.symbol ) XCTAssertEqual( - group.assets[safe: 4]?.quantity, + group.assets[safe: offset]?.quantity, String(format: "%.04f", self.mockFILBalanceAccount1) ) // FIL (value = $400.00) on filecoin testnet + offset += 1 XCTAssertEqual( - group.assets[safe: 5]?.token.symbol, + group.assets[safe: offset]?.token.symbol, BraveWallet.BlockchainToken.mockFilToken.symbol ) XCTAssertEqual( - group.assets[safe: 5]?.quantity, + group.assets[safe: offset]?.quantity, String(format: "%.04f", self.mockFILBalanceTestnet) ) // SOL (value = $775.3) + offset += 1 XCTAssertEqual( - group.assets[safe: 6]?.token.symbol, + group.assets[safe: offset]?.token.symbol, BraveWallet.BlockchainToken.mockSolToken.symbol ) XCTAssertEqual( - group.assets[safe: 6]?.quantity, + group.assets[safe: offset]?.quantity, String(format: "%.04f", self.mockSOLBalance) ) // ETH Mainnet (value ~= $2741.7510399999996) + offset += 1 XCTAssertEqual( - group.assets[safe: 7]?.token.symbol, + group.assets[safe: offset]?.token.symbol, BraveWallet.BlockchainToken.previewToken.symbol ) XCTAssertEqual( - group.assets[safe: 7]?.quantity, + group.assets[safe: offset]?.quantity, String(format: "%.04f", self.mockETHBalanceAccount1) ) }.store(in: &cancellables) @@ -729,6 +742,14 @@ import XCTest cancellables.removeAll() } + func testFilterSort() async { + await filterSortHelper(bitcoinTestnetEnabled: false) + } + + func testFilterSortBitcoinTestnet() async { + await filterSortHelper(bitcoinTestnetEnabled: true) + } + /// Test `assetGroups` will be filtered to remove small balances when `hideSmallBalances` filter is true. func testHideSmallBalances() async { Preferences.Wallet.showTestNetworks.value = true @@ -801,12 +822,12 @@ import XCTest isShowingNFTNetworkLogo: store.filters.isShowingNFTNetworkLogo, accounts: [ ethAccount1, ethAccount2, solAccount1, solAccount2, filAccount1, filAccount2, - filTestnetAccount, btcAccount1, btcAccount2, btcTestnetAccount, + filTestnetAccount, btcAccount1, btcAccount2, ].map { .init(isSelected: true, model: $0) }, networks: [ - ethNetwork, goerliNetwork, solNetwork, filMainnet, filTestnet, btcMainnet, btcTestnet, + ethNetwork, goerliNetwork, solNetwork, filMainnet, filTestnet, btcMainnet, ].map { .init(isSelected: true, model: $0) } @@ -817,8 +838,10 @@ import XCTest } /// Test `assetGroups` will be filtered by accounts when `accounts` filter is has de-selected accounts. - func testFilterAccounts() async { + func filterAccountsHelper(bitcoinTestnetEnabled: Bool) async { Preferences.Wallet.showTestNetworks.value = true + // test without bitcoin testnet enabled + Preferences.Wallet.isBitcoinTestnetEnabled.value = bitcoinTestnetEnabled let store = setupStore() let accountsExpectation = expectation(description: "update-accounts") store.$assetGroups @@ -837,7 +860,8 @@ import XCTest return } // ETH on Ethereum mainnet, SOL on Solana mainnet, USDC on Ethereum mainnet, ETH on Goerli, FIL on mainnet and testnet, BTC on mainnet and testnet - XCTAssertEqual(group.assets.count, 8) + let assetGroupNumber: Int = bitcoinTestnetEnabled ? 8 : 7 + XCTAssertEqual(group.assets.count, assetGroupNumber) // ETH Mainnet (value ~= $2741.7510399999996) XCTAssertEqual( group.assets[safe: 0]?.token.symbol, @@ -888,17 +912,21 @@ import XCTest group.assets[safe: 5]?.token.symbol, self.btcMainnet.nativeToken.symbol ) - // BTC testnet (value = $0) - XCTAssertEqual( - group.assets[safe: 6]?.token.symbol, - self.btcMainnet.nativeToken.symbol - ) + var goerliOffset: Int = 6 + if bitcoinTestnetEnabled { + // BTC testnet (value = $0) + XCTAssertEqual( + group.assets[safe: 6]?.token.symbol, + self.btcMainnet.nativeToken.symbol + ) + goerliOffset = 7 + } // ETH Goerli (value = $0) XCTAssertEqual( - group.assets[safe: 7]?.token.symbol, + group.assets[safe: goerliOffset]?.token.symbol, self.goerliNetwork.nativeToken.symbol ) - XCTAssertEqual(group.assets[safe: 7]?.quantity, String(format: "%.04f", 0)) + XCTAssertEqual(group.assets[safe: goerliOffset]?.quantity, String(format: "%.04f", 0)) }.store(in: &cancellables) isLocked = false store.saveFilters( @@ -925,6 +953,14 @@ import XCTest cancellables.removeAll() } + func testFilterAccounts() async { + await filterAccountsHelper(bitcoinTestnetEnabled: false) + } + + func testFilterAccountsWithBitcoinTestnet() async { + await filterAccountsHelper(bitcoinTestnetEnabled: true) + } + /// Test `assetGroups` will be filtered by network when `networks` filter is has de-selected networks. func testFilterNetworks() async { Preferences.Wallet.showTestNetworks.value = true @@ -1027,8 +1063,9 @@ import XCTest /// Test `assetGroups` will be grouped by account when `GroupBy` filter is assigned `.account`. /// Additionally, test de-selecting/hiding one of the available accounts. - func testGroupByAccounts() async { + func groupByAccountsHelper(bitcoinTestnetEnabled: Bool) async { Preferences.Wallet.showTestNetworks.value = true + Preferences.Wallet.isBitcoinTestnetEnabled.value = bitcoinTestnetEnabled let store = setupStore() let assetGroupsExpectation = expectation(description: "update-assetGroups") XCTAssertTrue(store.assetGroups.isEmpty) // Initial state @@ -1042,8 +1079,11 @@ import XCTest XCTFail("Unexpected test result") return } - // grouping by .account; eth has 2 accounts, sol has 2 accounts, fil has 3 accounts, btc has 3 accounts - XCTAssertEqual(lastUpdatedAssetGroups.count, 10) + // grouping by .account; eth has 2 accounts, sol has 2 accounts, fil has 3 accounts, btc has 3 accounts (one tesnet) + let assetGroupNumber = bitcoinTestnetEnabled ? 10 : 9 + XCTAssertEqual(lastUpdatedAssetGroups.count, assetGroupNumber) + + var filAccount2Offset = bitcoinTestnetEnabled ? 9 : 8 guard let ethAccount1Group = lastUpdatedAssetGroups[safe: 0], let solAccount1Group = lastUpdatedAssetGroups[safe: 1], let filTestnetAccountGroup = lastUpdatedAssetGroups[safe: 2], @@ -1052,13 +1092,32 @@ import XCTest let solAccount2Group = lastUpdatedAssetGroups[safe: 5], let btcAccount1Group = lastUpdatedAssetGroups[safe: 6], let btcAccount2Group = lastUpdatedAssetGroups[safe: 7], - let btcTestnetAccountGroup = lastUpdatedAssetGroups[safe: 8], - let filAccount2Group = lastUpdatedAssetGroups[safe: 9] + let filAccount2Group = lastUpdatedAssetGroups[safe: filAccount2Offset] else { XCTFail("Unexpected test result") return } + if bitcoinTestnetEnabled { + guard let btcTestnetAccountGroup = lastUpdatedAssetGroups[safe: 8] + else { + XCTFail("Unexpected test result") + return + } + + XCTAssertEqual(btcTestnetAccountGroup.groupType, .account(self.btcTestnetAccount)) + XCTAssertEqual(btcTestnetAccountGroup.assets.count, 1) + // BTC (value = $0) + XCTAssertEqual( + btcTestnetAccountGroup.assets[safe: 0]?.token.symbol, + BraveWallet.BlockchainToken.mockBTCToken.symbol + ) + XCTAssertEqual( + btcTestnetAccountGroup.assets[safe: 0]?.quantity, + String(format: "%.04f", 0) + ) + } + XCTAssertEqual(ethAccount1Group.groupType, .account(self.ethAccount1)) XCTAssertEqual(ethAccount1Group.assets.count, 3) // ETH Mainnet, USDC, ETH Goerli // ETH Mainnet (value ~= $2741.7510399999996) @@ -1174,15 +1233,6 @@ import XCTest ) XCTAssertEqual(btcAccount2Group.assets[safe: 0]?.quantity, String(format: "%.04f", 0)) - XCTAssertEqual(btcTestnetAccountGroup.groupType, .account(self.btcTestnetAccount)) - XCTAssertEqual(btcTestnetAccountGroup.assets.count, 1) - // BTC (value = $0) - XCTAssertEqual( - btcTestnetAccountGroup.assets[safe: 0]?.token.symbol, - BraveWallet.BlockchainToken.mockBTCToken.symbol - ) - XCTAssertEqual(btcTestnetAccountGroup.assets[safe: 0]?.quantity, String(format: "%.04f", 0)) - XCTAssertEqual(filAccount2Group.groupType, .account(self.filAccount2)) XCTAssertEqual(filAccount2Group.assets.count, 1) // FIL (value = $0) @@ -1326,10 +1376,19 @@ import XCTest await fulfillment(of: [accountsExpectation], timeout: 1) } + func testGroupByAccounts() async { + await groupByAccountsHelper(bitcoinTestnetEnabled: false) + } + + func testGroupByAccountsBitcoinTestnet() async { + await groupByAccountsHelper(bitcoinTestnetEnabled: true) + } + /// Test `assetGroups` will be grouped by network when `GroupBy` filter is assigned `.network`. /// Additionally, test de-selecting/hiding one of the available networks. - func testGroupByNetworks() async { + func groupByNetworksHelper(bitcoinTestnetEnabled: Bool) async { Preferences.Wallet.showTestNetworks.value = true + Preferences.Wallet.isBitcoinTestnetEnabled.value = bitcoinTestnetEnabled let store = setupStore() let assetGroupsExpectation = expectation(description: "update-assetGroups") XCTAssertTrue(store.assetGroups.isEmpty) // Initial state @@ -1343,20 +1402,37 @@ import XCTest XCTFail("Unexpected test result") return } - // grouping by .network; 1 for each of the 2 networks + // grouping by .network; 1 for each of the 2 networks (Bitcoin testnet can be disabled) // network groups order should be the same as the order of all networks in `Filters` - XCTAssertEqual(lastUpdatedAssetGroups.count, 7) + let assetGroupNumber = bitcoinTestnetEnabled ? 7 : 6 + XCTAssertEqual(lastUpdatedAssetGroups.count, assetGroupNumber) guard let ethMainnetGroup = lastUpdatedAssetGroups[safe: 0], let solMainnetGroup = lastUpdatedAssetGroups[safe: 1], let filTestnetGroup = lastUpdatedAssetGroups[safe: 2], let filMainnetGroup = lastUpdatedAssetGroups[safe: 3], let btcMainnetGroup = lastUpdatedAssetGroups[safe: 4], - let ethGoerliGroup = lastUpdatedAssetGroups[safe: 5], - let btcTestnetGroup = lastUpdatedAssetGroups[safe: 6] + let ethGoerliGroup = lastUpdatedAssetGroups[safe: 5] else { XCTFail("Unexpected test result") return } + + if bitcoinTestnetEnabled { + guard let btcTestnetGroup = lastUpdatedAssetGroups[safe: 6] + else { + XCTFail("Unexpected test result") + return + } + XCTAssertEqual(btcTestnetGroup.groupType, .network(self.btcTestnet)) + XCTAssertEqual(btcTestnetGroup.assets.count, 1) + // BTC testnet (value = $0) + XCTAssertEqual( + btcTestnetGroup.assets[safe: 0]?.token.symbol, + BraveWallet.BlockchainToken.mockBTCToken.symbol + ) + XCTAssertEqual(btcTestnetGroup.assets[safe: 0]?.quantity, String(format: "%.04f", 0)) + } + XCTAssertEqual(ethMainnetGroup.groupType, .network(.mockMainnet)) XCTAssertEqual(ethMainnetGroup.assets.count, 2) // ETH Mainnet, USDC // ETH (value ~= $2741.7510399999996) @@ -1432,15 +1508,6 @@ import XCTest ) XCTAssertEqual(btcMainnetGroup.assets[safe: 0]?.quantity, String(format: "%.04f", 0)) - XCTAssertEqual(btcTestnetGroup.groupType, .network(self.btcTestnet)) - XCTAssertEqual(btcTestnetGroup.assets.count, 1) - // BTC testnet (value = $0) - XCTAssertEqual( - btcTestnetGroup.assets[safe: 0]?.token.symbol, - BraveWallet.BlockchainToken.mockBTCToken.symbol - ) - XCTAssertEqual(btcTestnetGroup.assets[safe: 0]?.quantity, String(format: "%.04f", 0)) - // Verify NFTs not used in Portfolio #7945 let noAssetsAreNFTs = lastUpdatedAssetGroups.flatMap(\.assets).allSatisfy({ !($0.token.isNft || $0.token.isErc721) @@ -1560,6 +1627,14 @@ import XCTest await fulfillment(of: [networksExpectation], timeout: 1) cancellables.removeAll() } + + func testGroupByNetworks() async { + await groupByNetworksHelper(bitcoinTestnetEnabled: false) + } + + func testGroupByNetworkBitcoinTestnet() async { + await groupByNetworksHelper(bitcoinTestnetEnabled: true) + } } extension BraveWallet.BlockchainToken {