Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wallet): Add a debug option to enable bitcoin testnet #22971

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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))
StephenHeaps marked this conversation as resolved.
Show resolved Hide resolved
.navigationTitle("Brave Wallet Debug")
.navigationBarTitleDisplayMode(.inline)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import BraveCore
import BraveUI
import DesignSystem
import Preferences
import Strings
import SwiftUI

Expand Down Expand Up @@ -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
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ public class KeyringStore: ObservableObject, WalletObserverStore {
self.keychain = keychain

setupObservers()

Preferences.Wallet.isBitcoinTestnetEnabled.observe(from: self)

updateInfo()

Task { @MainActor in
Expand Down Expand Up @@ -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)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import BraveCore
import Foundation
import OrderedCollections
import Preferences

extension BraveWalletKeyringService {

Expand All @@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions ios/brave-ios/Sources/BraveWallet/WalletPreferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Bool>(
key: "wallet.is-bitcoin-testnet-enabled",
default: false
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
29 changes: 21 additions & 8 deletions ios/brave-ios/Tests/BraveWalletTests/AccountsStoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<AnyCancellable> = .init()

let ethAccount1: BraveWallet.AccountInfo = .mockEthAccount
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -325,18 +333,23 @@ 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()

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)
}
}
Loading
Loading