Skip to content

Commit dcb9dc6

Browse files
committed
remove empty wallets from monitor list after restore
1 parent 6f448f0 commit dcb9dc6

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

Bitkit/ViewModels/AppViewModel.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,15 @@ extension AppViewModel {
902902
case let .syncCompleted(syncType, syncedBlockHeight):
903903
Logger.info("Sync completed: \(syncType) at height \(syncedBlockHeight)")
904904

905+
// After mnemonic restore, prune empty address types once sync has completed
906+
if SettingsViewModel.shared.pendingRestoreAddressTypePrune {
907+
SettingsViewModel.shared.pendingRestoreAddressTypePrune = false
908+
Task { @MainActor in
909+
try? await Task.sleep(nanoseconds: 30 * 1_000_000_000) // 30s delay after sync
910+
await SettingsViewModel.shared.pruneEmptyAddressTypesAfterRestore()
911+
}
912+
}
913+
905914
if MigrationsService.shared.needsPostMigrationSync {
906915
Task { @MainActor in
907916
try? await CoreService.shared.activity.syncLdkNodePayments(LightningService.shared.payments ?? [])

Bitkit/ViewModels/SettingsViewModel.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,65 @@ class SettingsViewModel: NSObject, ObservableObject {
385385
addressTypesToMonitor = Self.allAddressTypes
386386
}
387387

388+
private static let pendingRestoreAddressTypePruneKey = "pendingRestoreAddressTypePrune"
389+
390+
/// Tracks whether to prune empty address types after restore (set when user taps Get Started; cleared when prune runs).
391+
var pendingRestoreAddressTypePrune: Bool {
392+
get { UserDefaults.standard.bool(forKey: Self.pendingRestoreAddressTypePruneKey) }
393+
set { UserDefaults.standard.set(newValue, forKey: Self.pendingRestoreAddressTypePruneKey) }
394+
}
395+
396+
/// After restore, disables monitoring for address types with zero balance.
397+
/// Keeps nativeSegwit as primary and monitored; only types with funds stay monitored.
398+
func pruneEmptyAddressTypesAfterRestore() async {
399+
guard !isChangingAddressType else { return }
400+
401+
let nativeWitnessTypes: [AddressScriptType] = [.nativeSegwit, .taproot]
402+
var newMonitored = addressTypesToMonitor
403+
var changed = false
404+
405+
for type in addressTypesToMonitor {
406+
// Always keep nativeSegwit (primary, required for Lightning)
407+
if type == .nativeSegwit { continue }
408+
409+
do {
410+
let balance = try await getBalanceForAddressType(type)
411+
if balance == 0 {
412+
newMonitored.removeAll { $0 == type }
413+
changed = true
414+
Logger.debug("Pruned empty address type from monitoring: \(type)", context: "SettingsViewModel")
415+
}
416+
} catch {
417+
Logger.warn("Could not check balance for \(type), keeping monitored: \(error)")
418+
// Don't disable on error - fail safe
419+
}
420+
}
421+
422+
// Ensure at least one native witness type
423+
if !newMonitored.contains(where: { nativeWitnessTypes.contains($0) }) {
424+
if !newMonitored.contains(.nativeSegwit) {
425+
newMonitored.append(.nativeSegwit)
426+
changed = true
427+
}
428+
}
429+
430+
guard changed else { return }
431+
432+
addressTypesToMonitor = newMonitored
433+
UserDefaults.standard.synchronize()
434+
435+
do {
436+
try await lightningService.restart()
437+
try await lightningService.sync()
438+
Logger.info(
439+
"Pruned empty address types after restore: \(newMonitored.map { Self.addressTypeToString($0) }.joined(separator: ","))",
440+
context: "SettingsViewModel"
441+
)
442+
} catch {
443+
Logger.error("Failed to restart after prune: \(error)")
444+
}
445+
}
446+
388447
/// True if disabling this would leave no native witness wallet (required for Lightning).
389448
func isLastRequiredNativeWitnessWallet(_ addressType: AddressScriptType) -> Bool {
390449
let nativeWitnessTypes: [AddressScriptType] = [.nativeSegwit, .taproot]

Bitkit/Views/Onboarding/WalletRestoreSuccess.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ struct WalletRestoreSuccess: View {
3535
// Mark backup as verified since user just restored with their phrase
3636
app.backupVerified = true
3737
wallet.isRestoringWallet = false
38+
39+
// Prune empty address types on next syncCompleted
40+
SettingsViewModel.shared.pendingRestoreAddressTypePrune = true
3841
}
3942
.accessibilityIdentifier("GetStartedButton")
4043
}

0 commit comments

Comments
 (0)