diff --git a/Bitkit.xcodeproj/project.pbxproj b/Bitkit.xcodeproj/project.pbxproj index 8635c470..2dd82f87 100644 --- a/Bitkit.xcodeproj/project.pbxproj +++ b/Bitkit.xcodeproj/project.pbxproj @@ -928,7 +928,7 @@ repositoryURL = "https://github.com/synonymdev/ldk-node"; requirement = { kind = revision; - revision = c5698d00066e0e50f33696afc562d71023da2373; + revision = 1531af727811f03ec0542aec3befb5a26198b192; }; }; 96DEA0382DE8BBA1009932BF /* XCRemoteSwiftPackageReference "bitkit-core" */ = { diff --git a/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e14c1eae..284ed91c 100644 --- a/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -24,7 +24,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/synonymdev/ldk-node", "state" : { - "revision" : "c5698d00066e0e50f33696afc562d71023da2373" + "revision" : "1531af727811f03ec0542aec3befb5a26198b192" } }, { diff --git a/Bitkit/Services/MigrationsService.swift b/Bitkit/Services/MigrationsService.swift index aaea3c21..13cd2d24 100644 --- a/Bitkit/Services/MigrationsService.swift +++ b/Bitkit/Services/MigrationsService.swift @@ -2098,9 +2098,10 @@ extension MigrationsService { } /// Fetches channel manager and monitors from RN remote backup. + /// When `walletIndex` is provided, filters out monitors that already exist in local LDK storage. /// Returns `true` if all monitors were successfully retrieved (or none exist), `false` if some failed. @discardableResult - func fetchRNRemoteLdkData() async -> Bool { + func fetchRNRemoteLdkData(walletIndex: Int? = nil) async -> Bool { do { let files = try await RNBackupClient.shared.listFiles(fileGroup: "ldk") @@ -2109,10 +2110,38 @@ extension MigrationsService { return true } - let expectedCount = files.channel_monitors.count + // Filter out monitors that already exist locally (previously migrated) + var localChannelIds: Set = [] + if let walletIndex { + let ldkPath = Env.ldkStorage(walletIndex: walletIndex) + let channelsPath = ldkPath.appendingPathComponent("channels") + let monitorsPath = ldkPath.appendingPathComponent("monitors") + let monitorDir = FileManager.default.fileExists(atPath: channelsPath.path) ? channelsPath : monitorsPath + + if FileManager.default.fileExists(atPath: monitorDir.path), + let localFiles = try? FileManager.default.contentsOfDirectory(atPath: monitorDir.path) + { + localChannelIds = Set(localFiles.filter { $0.hasSuffix(".bin") }.map { $0.replacingOccurrences(of: ".bin", with: "") }) + } + } + + let remoteMonitorFiles = files.channel_monitors.filter { file in + let channelId = file.replacingOccurrences(of: ".bin", with: "") + return !localChannelIds.contains(channelId) + } + + if !localChannelIds.isEmpty { + let skipped = files.channel_monitors.count - remoteMonitorFiles.count + Logger.info( + "Filtered \(skipped) already-migrated monitors, \(remoteMonitorFiles.count) orphaned remaining", + context: "Migration" + ) + } + + let expectedCount = remoteMonitorFiles.count let monitorResults = await withTaskGroup(of: (String, Data?).self) { group in var results: [(String, Data?)] = [] - for monitorFile in files.channel_monitors { + for monitorFile in remoteMonitorFiles { let channelId = monitorFile.replacingOccurrences(of: ".bin", with: "") group.addTask { await (channelId, self.retrieveChannelMonitorWithRetry(channelId: channelId)) diff --git a/Bitkit/ViewModels/WalletViewModel.swift b/Bitkit/ViewModels/WalletViewModel.swift index 6ea9d86b..50bf9587 100644 --- a/Bitkit/ViewModels/WalletViewModel.swift +++ b/Bitkit/ViewModels/WalletViewModel.swift @@ -275,7 +275,7 @@ class WalletViewModel: ObservableObject { RNBackupClient.shared.reset() try await RNBackupClient.shared.setup(mnemonic: mnemonic, passphrase: passphrase) - let allRetrieved = await migrations.fetchRNRemoteLdkData() + let allRetrieved = await migrations.fetchRNRemoteLdkData(walletIndex: walletIndex) if let migration = migrations.pendingChannelMigration { Logger.info(