diff --git a/BDKSwiftExampleWallet/Resources/Localizable.xcstrings b/BDKSwiftExampleWallet/Resources/Localizable.xcstrings index 3c50e8c8..5678d1a6 100644 --- a/BDKSwiftExampleWallet/Resources/Localizable.xcstrings +++ b/BDKSwiftExampleWallet/Resources/Localizable.xcstrings @@ -674,7 +674,6 @@ } }, "Testnet" : { - "extractionState" : "stale", "localizations" : { "fr" : { "stringUnit" : { diff --git a/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift b/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift index 1304131f..29fb2fde 100644 --- a/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift +++ b/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift @@ -13,23 +13,40 @@ private class BDKService { private var balance: Balance? private var connection: Connection? - private let esploraClient: EsploraClient + private var esploraClient: EsploraClient private let keyClient: KeyClient private var needsFullScan: Bool = false - var network: Network + private(set) var network: Network + private(set) var esploraURL: String private var wallet: Wallet? - init( - keyClient: KeyClient = .live - ) { - let storedNetworkString = try! keyClient.getNetwork() ?? Network.signet.description - let storedEsploraURL = - try! keyClient.getEsploraURL() - ?? Constants.Config.EsploraServerURLNetwork.Signet.mutiny - - self.network = Network(stringValue: storedNetworkString) ?? .signet + init(keyClient: KeyClient = .live) { self.keyClient = keyClient - self.esploraClient = EsploraClient(url: storedEsploraURL) + let storedNetworkString = try? keyClient.getNetwork() ?? Network.signet.description + self.network = Network(stringValue: storedNetworkString ?? "") ?? .signet + self.esploraURL = + try! keyClient.getEsploraURL() ?? Constants.Config.EsploraServerURLNetwork.Signet.mutiny + self.esploraClient = EsploraClient(url: self.esploraURL) + } + + func updateNetwork(_ newNetwork: Network) { + if newNetwork != self.network { + self.network = newNetwork + try? keyClient.saveNetwork(newNetwork.description) + updateEsploraClient() + } + } + + func updateEsploraURL(_ newURL: String) { + if newURL != self.esploraURL { + self.esploraURL = newURL + try? keyClient.saveEsploraURL(newURL) + updateEsploraClient() + } + } + + private func updateEsploraClient() { + self.esploraClient = EsploraClient(url: self.esploraURL) } func getAddress() throws -> String { @@ -311,6 +328,10 @@ struct BDKClient { let getBackupInfo: () throws -> BackupInfo let needsFullScan: () -> Bool let setNeedsFullScan: (Bool) -> Void + let getNetwork: () -> Network + let getEsploraURL: () -> String + let updateNetwork: (Network) -> Void + let updateEsploraURL: (String) -> Void } extension BDKClient { @@ -345,7 +366,19 @@ extension BDKClient { }, getBackupInfo: { try BDKService.shared.getBackupInfo() }, needsFullScan: { BDKService.shared.needsFullScanOfWallet() }, - setNeedsFullScan: { value in BDKService.shared.setNeedsFullScan(value) } + setNeedsFullScan: { value in BDKService.shared.setNeedsFullScan(value) }, + getNetwork: { + BDKService.shared.network + }, + getEsploraURL: { + BDKService.shared.esploraURL + }, + updateNetwork: { newNetwork in + BDKService.shared.updateNetwork(newNetwork) + }, + updateEsploraURL: { newURL in + BDKService.shared.updateEsploraURL(newURL) + } ) } @@ -395,7 +428,11 @@ extension BDKClient { ) }, needsFullScan: { true }, - setNeedsFullScan: { _ in } + setNeedsFullScan: { _ in }, + getNetwork: { .signet }, + getEsploraURL: { Constants.Config.EsploraServerURLNetwork.Signet.mutiny }, + updateNetwork: { _ in }, + updateEsploraURL: { _ in } ) } #endif diff --git a/BDKSwiftExampleWallet/View Model/Activity/TransactionDetailViewModel.swift b/BDKSwiftExampleWallet/View Model/Activity/TransactionDetailViewModel.swift index f3cbca2e..02852c18 100644 --- a/BDKSwiftExampleWallet/View Model/Activity/TransactionDetailViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/Activity/TransactionDetailViewModel.swift @@ -13,7 +13,6 @@ import Observation @Observable class TransactionDetailViewModel { let bdkClient: BDKClient - let keyClient: KeyClient var calculateFee: String? var calculateFeeError: CalculateFeeError? @@ -24,11 +23,9 @@ class TransactionDetailViewModel { var transactionDetailsError: AppError? init( - bdkClient: BDKClient = .live, - keyClient: KeyClient = .live + bdkClient: BDKClient = .live ) { self.bdkClient = bdkClient - self.keyClient = keyClient } func getCalulateFee(tx: BitcoinDevKit.Transaction) { @@ -44,28 +41,28 @@ class TransactionDetailViewModel { } func getEsploraUrl() { - do { - let savedEsploraURL = try keyClient.getEsploraURL() - if network == "Signet" { + let savedEsploraURL = bdkClient.getEsploraURL() + + switch network { + case "signet": + if savedEsploraURL == Constants.Config.EsploraServerURLNetwork.Signet.bdk { self.esploraURL = "https://mempool.space/signet" } else { - self.esploraURL = savedEsploraURL + self.esploraURL = "https://mutinynet.com" } - } catch let error as EsploraError { - DispatchQueue.main.async { - self.esploraError = error + case "testnet": + if savedEsploraURL == Constants.Config.EsploraServerURLNetwork.Testnet.blockstream { + self.esploraURL = "https://blockstream.info/testnet" + } else { + self.esploraURL = "https://mempool.space/testnet" } - } catch {} + default: + self.esploraURL = savedEsploraURL + } } func getNetwork() { - do { - self.network = try keyClient.getNetwork() - } catch { - DispatchQueue.main.async { - self.transactionDetailsError = .generic(message: error.localizedDescription) - } - } + self.network = bdkClient.getNetwork().description } func getSentAndReceived(tx: BitcoinDevKit.Transaction) -> SentAndReceivedValues? { diff --git a/BDKSwiftExampleWallet/View Model/Activity/TransactionListViewModel.swift b/BDKSwiftExampleWallet/View Model/Activity/TransactionListViewModel.swift index 5a0c13e0..18a3d6a3 100644 --- a/BDKSwiftExampleWallet/View Model/Activity/TransactionListViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/Activity/TransactionListViewModel.swift @@ -12,17 +12,14 @@ import Foundation @Observable class TransactionListViewModel { let bdkClient: BDKClient - let keyClient: KeyClient var showingWalletTransactionsViewErrorAlert = false var walletTransactionsViewError: AppError? init( - bdkClient: BDKClient = .live, - keyClient: KeyClient = .live + bdkClient: BDKClient = .live ) { self.bdkClient = bdkClient - self.keyClient = keyClient } func getSentAndReceived(tx: BitcoinDevKit.Transaction) -> SentAndReceivedValues? { @@ -38,9 +35,14 @@ class TransactionListViewModel { } } - func getEsploraURL() -> String? { - let savedEsploraURL = try? keyClient.getEsploraURL() + func getEsploraURL() -> String { + let savedEsploraURL = bdkClient.getEsploraURL() return savedEsploraURL } + func getNetwork() -> String { + let savedNetwork = bdkClient.getNetwork().description + return savedNetwork + } + } diff --git a/BDKSwiftExampleWallet/View Model/OnboardingViewModel.swift b/BDKSwiftExampleWallet/View Model/OnboardingViewModel.swift index 51d68175..56b7a706 100644 --- a/BDKSwiftExampleWallet/View Model/OnboardingViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/OnboardingViewModel.swift @@ -14,7 +14,6 @@ import SwiftUI // Feature or Bug? class OnboardingViewModel: ObservableObject { let bdkClient: BDKClient - let keyClient: KeyClient @AppStorage("isOnboarding") var isOnboarding: Bool? @Published var createWithPersistError: CreateWithPersistError? @@ -22,27 +21,14 @@ class OnboardingViewModel: ObservableObject { @Published var onboardingViewError: AppError? @Published var selectedNetwork: Network = .signet { didSet { - do { - let networkString = selectedNetwork.description - try keyClient.saveNetwork(networkString) - selectedURL = availableURLs.first ?? "" - try keyClient.saveEsploraURL(selectedURL) - } catch { - DispatchQueue.main.async { - self.onboardingViewError = .generic(message: error.localizedDescription) - } - } + bdkClient.updateNetwork(selectedNetwork) + selectedURL = availableURLs.first ?? "" + bdkClient.updateEsploraURL(selectedURL) } } @Published var selectedURL: String = "" { didSet { - do { - try keyClient.saveEsploraURL(selectedURL) - } catch { - DispatchQueue.main.async { - self.onboardingViewError = .generic(message: error.localizedDescription) - } - } + bdkClient.updateEsploraURL(selectedURL) } } @Published var words: String = "" { @@ -77,27 +63,11 @@ class OnboardingViewModel: ObservableObject { } init( - bdkClient: BDKClient = .live, - keyClient: KeyClient = .live + bdkClient: BDKClient = .live ) { self.bdkClient = bdkClient - self.keyClient = keyClient - do { - if let networkString = try keyClient.getNetwork() { - self.selectedNetwork = Network(stringValue: networkString) ?? .signet - } else { - self.selectedNetwork = .signet - } - if let esploraURL = try keyClient.getEsploraURL() { - self.selectedURL = esploraURL - } else { - self.selectedURL = availableURLs.first ?? "" - } - } catch { - DispatchQueue.main.async { - self.onboardingViewError = .generic(message: error.localizedDescription) - } - } + self.selectedNetwork = bdkClient.getNetwork() + self.selectedURL = bdkClient.getEsploraURL() } func createWallet() { diff --git a/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift b/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift index 9cc78d7d..341fff1e 100644 --- a/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift @@ -11,7 +11,6 @@ import SwiftUI class SettingsViewModel: ObservableObject { let bdkClient: BDKClient - let keyClient: KeyClient @AppStorage("isOnboarding") var isOnboarding: Bool = true @Published var esploraURL: String? @@ -22,24 +21,20 @@ class SettingsViewModel: ObservableObject { @Published var walletSyncState: WalletSyncState = .notStarted init( - bdkClient: BDKClient = .live, - keyClient: KeyClient = .live + bdkClient: BDKClient = .live ) { self.bdkClient = bdkClient - self.keyClient = keyClient + self.network = bdkClient.getNetwork().description + self.esploraURL = bdkClient.getEsploraURL() } func delete() { do { try bdkClient.deleteWallet() - DispatchQueue.main.async { - self.isOnboarding = true - } + isOnboarding = true } catch { - DispatchQueue.main.async { - self.settingsError = .generic(message: error.localizedDescription) - self.showingSettingsViewErrorAlert = true - } + self.settingsError = .generic(message: error.localizedDescription) + self.showingSettingsViewErrorAlert = true } } @@ -81,24 +76,11 @@ class SettingsViewModel: ObservableObject { } func getNetwork() { - do { - self.network = try keyClient.getNetwork() - } catch { - DispatchQueue.main.async { - self.settingsError = .generic(message: error.localizedDescription) - self.showingSettingsViewErrorAlert = true - } - } + self.network = bdkClient.getNetwork().description } func getEsploraUrl() { - do { - self.esploraURL = try keyClient.getEsploraURL() - } catch { - DispatchQueue.main.async { - self.settingsError = .generic(message: error.localizedDescription) - } - } + self.esploraURL = bdkClient.getEsploraURL() } private func updateProgressFullScan(inspected: UInt64) { diff --git a/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift b/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift index bf43c117..ad6d7d59 100644 --- a/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift +++ b/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift @@ -172,7 +172,9 @@ struct TransactionDetailView: View { #if DEBUG #Preview { TransactionDetailView( - viewModel: .init(bdkClient: .mock, keyClient: .mock), + viewModel: .init( + bdkClient: .mock + ), amount: UInt64(1_000_000), canonicalTx: .mock ) diff --git a/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift b/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift index 098d4183..5e340335 100644 --- a/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift +++ b/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift @@ -38,7 +38,10 @@ struct TransactionListView: View { let mutinyFaucetURL = URL(string: "https://faucet.mutinynet.com") let signetFaucetURL = URL(string: "https://signetfaucet.com") - if let mutinyFaucetURL, let signetFaucetURL { + if let mutinyFaucetURL, + let signetFaucetURL, + viewModel.getNetwork() != Network.testnet.description + { Button { UIApplication.shared.open( @@ -75,7 +78,9 @@ struct TransactionListView: View { NavigationLink( destination: TransactionDetailView( - viewModel: .init(bdkClient: .live, keyClient: .live), + viewModel: .init( + bdkClient: .live + ), amount: sentAndReceivedValues.sent.toSat() == 0 ? sentAndReceivedValues.received.toSat() : sentAndReceivedValues.sent.toSat() diff --git a/BDKSwiftExampleWallet/View/OnboardingView.swift b/BDKSwiftExampleWallet/View/OnboardingView.swift index 8b1e3e97..09965740 100644 --- a/BDKSwiftExampleWallet/View/OnboardingView.swift +++ b/BDKSwiftExampleWallet/View/OnboardingView.swift @@ -77,10 +77,16 @@ struct OnboardingView: View { } .padding() - Text("Signet") - .foregroundStyle(.primary) - .fontWeight(.light) - .accessibilityLabel("Select Bitcoin Network") + Picker( + "Network", + selection: $viewModel.selectedNetwork + ) { + Text("Signet").tag(Network.signet) + Text("Testnet").tag(Network.testnet) + } + .pickerStyle(.automatic) + .tint(.primary) + .accessibilityLabel("Select Bitcoin Network") Picker( "Esplora Server", diff --git a/BDKSwiftExampleWallet/View/Settings/SettingsView.swift b/BDKSwiftExampleWallet/View/Settings/SettingsView.swift index 38644295..5fb8b45b 100644 --- a/BDKSwiftExampleWallet/View/Settings/SettingsView.swift +++ b/BDKSwiftExampleWallet/View/Settings/SettingsView.swift @@ -144,6 +144,10 @@ struct SettingsView: View { #if DEBUG #Preview { - SettingsView(viewModel: .init(bdkClient: .mock, keyClient: .mock)) + SettingsView( + viewModel: .init( + bdkClient: .mock + ) + ) } #endif