diff --git a/Bitkit/ViewModels/WalletViewModel.swift b/Bitkit/ViewModels/WalletViewModel.swift index 86f5f094..95c9033f 100644 --- a/Bitkit/ViewModels/WalletViewModel.swift +++ b/Bitkit/ViewModels/WalletViewModel.swift @@ -51,6 +51,14 @@ class WalletViewModel: ObservableObject { private let transferService: TransferService private let sheetViewModel: SheetViewModel + enum BlocktankPeerSimulation: String, CaseIterable { + case none = "None" + case apiFailure = "API Failure" + case unreachablePeers = "Unreachable Peers" + } + + static var peerSimulation: BlocktankPeerSimulation = .none + @Published var isRestoringWallet = false @Published var balanceInTransferToSavings: Int = 0 @Published var balanceInTransferToSpending: Int = 0 @@ -205,12 +213,7 @@ class WalletViewModel: ObservableObject { syncState() - do { - let remotePeers = await fetchTrustedPeersFromBlocktank() - try await lightningService.connectToTrustedPeers(remotePeers: remotePeers) - } catch { - Logger.error("Failed to connect to trusted peers") - } + await reconnectTrustedPeers() // Migration only: fetch peers from remote backup (once) and persist in ldk-node let peerUris = await MigrationsService.shared.tryFetchMigrationPeersFromBackup(walletIndex: walletIndex) @@ -234,6 +237,21 @@ class WalletViewModel: ObservableObject { } private func fetchTrustedPeersFromBlocktank() async -> [LnPeer]? { + switch Self.peerSimulation { + case .apiFailure: + Logger.warn("⚠️ [DEBUG] Simulating Blocktank API failure — returning nil") + return nil + case .unreachablePeers: + Logger.warn("⚠️ [DEBUG] Simulating unreachable API peers") + return [ + LnPeer(nodeId: "000000000000000000000000000000000000000000000000000000000000000001", + host: "192.0.2.1", port: 9735), + ] + case .none: + break + } + + var info: IBtInfo? do { info = try await coreService.blocktank.info(refresh: true) @@ -255,6 +273,15 @@ class WalletViewModel: ObservableObject { return peers.isEmpty ? nil : peers } + func reconnectTrustedPeers() async { + do { + let remotePeers = await fetchTrustedPeersFromBlocktank() + try await lightningService.connectToTrustedPeers(remotePeers: remotePeers) + } catch { + Logger.error("Failed to connect to trusted peers") + } + } + func stopLightningNode(clearEventCallback: Bool = false) async throws { nodeLifecycleState = .stopping try await lightningService.stop(clearEventCallback: clearEventCallback) diff --git a/Bitkit/Views/Settings/LdkDebugScreen.swift b/Bitkit/Views/Settings/LdkDebugScreen.swift index d9932fde..69d1556c 100644 --- a/Bitkit/Views/Settings/LdkDebugScreen.swift +++ b/Bitkit/Views/Settings/LdkDebugScreen.swift @@ -66,6 +66,21 @@ struct LdkDebugScreen: View { } } } + + // Peer Simulation + VStack(alignment: .leading, spacing: 8) { + CaptionMText("Peer Simulation") + + Picker("Peer Simulation", selection: Binding( + get: { WalletViewModel.peerSimulation }, + set: { WalletViewModel.peerSimulation = $0 } + )) { + ForEach(WalletViewModel.BlocktankPeerSimulation.allCases, id: \.self) { mode in + Text(mode.rawValue).tag(mode) + } + } + .pickerStyle(.segmented) + } } } } @@ -109,6 +124,7 @@ struct LdkDebugScreen: View { isRestartingNode = true let lightningService = LightningService.shared try await lightningService.restart() + await wallet.reconnectTrustedPeers() app.toast(type: .success, title: "Node Restarted", description: "Node restarted successfully") } catch { Logger.error("Failed to restart node: \(error)")