diff --git a/BDKSwiftExampleWallet.xcodeproj/project.pbxproj b/BDKSwiftExampleWallet.xcodeproj/project.pbxproj index 15bda4f0..eda6edb2 100644 --- a/BDKSwiftExampleWallet.xcodeproj/project.pbxproj +++ b/BDKSwiftExampleWallet.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 774586B52DB7B2BC00A631E1 /* BalanceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774586B42DB7B2BC00A631E1 /* BalanceView.swift */; }; + 779E70872DB9C98A006E22D3 /* WalletSyncScriptInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779E70862DB9C98A006E22D3 /* WalletSyncScriptInspector.swift */; }; + 779E70892DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779E70882DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift */; }; 77F0FDC92DA9A93D00B30E4F /* Connection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F0FDC82DA9A93700B30E4F /* Connection+Extensions.swift */; }; A733D6D02A81113000F333B4 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = A733D6CF2A81113000F333B4 /* Localizable.xcstrings */; }; A73F7A362A3B778E00B87FC6 /* Int+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73F7A352A3B778E00B87FC6 /* Int+Extensions.swift */; }; @@ -110,6 +112,8 @@ /* Begin PBXFileReference section */ 774586B42DB7B2BC00A631E1 /* BalanceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceView.swift; sourceTree = ""; }; + 779E70862DB9C98A006E22D3 /* WalletSyncScriptInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletSyncScriptInspector.swift; sourceTree = ""; }; + 779E70882DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletFullScanScriptInspector.swift; sourceTree = ""; }; 77F0FDC82DA9A93700B30E4F /* Connection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Extensions.swift"; sourceTree = ""; }; A733D6CF2A81113000F333B4 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; A73F7A352A3B778E00B87FC6 /* Int+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+Extensions.swift"; sourceTree = ""; }; @@ -222,6 +226,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 779E70832DB9C94C006E22D3 /* Actor */ = { + isa = PBXGroup; + children = ( + 779E70862DB9C98A006E22D3 /* WalletSyncScriptInspector.swift */, + 779E70882DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift */, + ); + path = Actor; + sourceTree = ""; + }; A7FBCE392A72944C007C960E /* Resources */ = { isa = PBXGroup; children = ( @@ -414,6 +427,7 @@ AE1C34222A424440008F807A /* App */, AE7F670A2A7451B600CED561 /* Model */, AE1C341F2A424415008F807A /* View */, + 779E70832DB9C94C006E22D3 /* Actor */, AE0C31002A804C05008F1EAE /* View Model */, AEB905C52A7EECD900CD0337 /* Service */, AE1C341E2A42440A008F807A /* Extensions */, @@ -708,7 +722,9 @@ AED4CC102A1D522100CE1831 /* WalletView.swift in Sources */, AE7F67092A7451AA00CED561 /* Price.swift in Sources */, AE184EFC2BFE52C800374362 /* Amount+Extensions.swift in Sources */, + 779E70892DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift in Sources */, AE2381B12C60690900F6B00C /* LocalOutput+Extensions.swift in Sources */, + 779E70872DB9C98A006E22D3 /* WalletSyncScriptInspector.swift in Sources */, AE7F67072A744CE200CED561 /* Double+Extensions.swift in Sources */, A73F7A362A3B778E00B87FC6 /* Int+Extensions.swift in Sources */, AE7839FD2AB4E18D005F0CBA /* AmountView.swift in Sources */, diff --git a/BDKSwiftExampleWallet/Actor/WalletFullScanScriptInspector.swift b/BDKSwiftExampleWallet/Actor/WalletFullScanScriptInspector.swift new file mode 100644 index 00000000..3a6563a1 --- /dev/null +++ b/BDKSwiftExampleWallet/Actor/WalletFullScanScriptInspector.swift @@ -0,0 +1,22 @@ +// +// WalletFullScanScriptInspector.swift +// BDKSwiftExampleWallet +// +// Created by Rubens Machion on 23/04/25. +// + +import BitcoinDevKit + +actor WalletFullScanScriptInspector: @preconcurrency FullScanScriptInspector { + private let updateProgress: @Sendable (UInt64) -> Void + private var inspectedCount: UInt64 = 0 + + init(updateProgress: @escaping @Sendable (UInt64) -> Void) { + self.updateProgress = updateProgress + } + + func inspect(keychain: KeychainKind, index: UInt32, script: Script) { + inspectedCount += 1 + updateProgress(inspectedCount) + } +} diff --git a/BDKSwiftExampleWallet/Actor/WalletSyncScriptInspector.swift b/BDKSwiftExampleWallet/Actor/WalletSyncScriptInspector.swift new file mode 100644 index 00000000..519bc671 --- /dev/null +++ b/BDKSwiftExampleWallet/Actor/WalletSyncScriptInspector.swift @@ -0,0 +1,43 @@ +// +// WalletSyncScriptInspector.swift +// BDKSwiftExampleWallet +// +// Created by Rubens Machion on 23/04/25. +// + +import BitcoinDevKit +import Foundation + +actor WalletSyncScriptInspector: @preconcurrency SyncScriptInspector { + private let updateProgress: @Sendable (UInt64, UInt64) -> Void + private var inspectedCount: UInt64 = 0 + private var totalCount: UInt64 = 0 + + init(updateProgress: @escaping @Sendable (UInt64, UInt64) -> Void) { + self.updateProgress = updateProgress + } + + func inspect(script: Script, total: UInt64) { + totalCount = total + inspectedCount += 1 + + let delay: TimeInterval = + if total <= 5 { + 0.2 + } else if total < 10 { + 0.15 + } else if total < 20 { + 0.1 + } else { + 0 + } + if delay > 0 { + Task { + try? await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000)) + updateProgress(inspectedCount, totalCount) + } + } else { + updateProgress(inspectedCount, totalCount) + } + } +} diff --git a/BDKSwiftExampleWallet/View Model/Activity/ActivityListViewModel.swift b/BDKSwiftExampleWallet/View Model/Activity/ActivityListViewModel.swift index 47e7643b..5519e3d3 100644 --- a/BDKSwiftExampleWallet/View Model/Activity/ActivityListViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/Activity/ActivityListViewModel.swift @@ -23,6 +23,16 @@ class ActivityListViewModel { var walletSyncState: WalletSyncState var walletViewError: AppError? + private var updateProgress: @Sendable (UInt64, UInt64) -> Void { + { [weak self] inspected, total in + DispatchQueue.main.async { + self?.totalScripts = total + self?.inspectedScripts = inspected + self?.progress = total > 0 ? Float(inspected) / Float(total) : 0 + } + } + } + enum DisplayMode { case transactions case outputs @@ -90,13 +100,4 @@ class ActivityListViewModel { func syncOrFullScan() async { await startSyncWithProgress() } - - private func updateProgress(inspected: UInt64, total: UInt64) { - DispatchQueue.main.async { - self.totalScripts = total - self.inspectedScripts = inspected - self.progress = total > 0 ? Float(inspected) / Float(total) : 0 - } - } - } diff --git a/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift b/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift index d09157bc..790fc87b 100644 --- a/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/Settings/SettingsViewModel.swift @@ -21,6 +21,14 @@ class SettingsViewModel: ObservableObject { @Published var showingSettingsViewErrorAlert = false @Published var walletSyncState: WalletSyncState = .notStarted + private var updateProgressFullScan: @Sendable (UInt64) -> Void { + { [weak self] inspected in + DispatchQueue.main.async { + self?.inspectedScripts = inspected + } + } + } + init( bdkClient: BDKClient = .live ) { @@ -83,11 +91,4 @@ class SettingsViewModel: ObservableObject { func getEsploraUrl() { self.esploraURL = bdkClient.getEsploraURL() } - - private func updateProgressFullScan(inspected: UInt64) { - DispatchQueue.main.async { - self.inspectedScripts = inspected - } - } - } diff --git a/BDKSwiftExampleWallet/View Model/WalletViewModel.swift b/BDKSwiftExampleWallet/View Model/WalletViewModel.swift index da99f535..724713b9 100644 --- a/BDKSwiftExampleWallet/View Model/WalletViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/WalletViewModel.swift @@ -40,6 +40,24 @@ class WalletViewModel { var walletSyncState: WalletSyncState var walletViewError: AppError? + private var updateProgress: @Sendable (UInt64, UInt64) -> Void { + { [weak self] inspected, total in + DispatchQueue.main.async { + self?.totalScripts = total + self?.inspectedScripts = inspected + self?.progress = total > 0 ? Float(inspected) / Float(total) : 0 + } + } + } + + private var updateProgressFullScan: @Sendable (UInt64) -> Void { + { [weak self] inspected in + DispatchQueue.main.async { + self?.inspectedScripts = inspected + } + } + } + init( bdkClient: BDKClient = .live, keyClient: KeyClient = .live, @@ -144,61 +162,4 @@ class WalletViewModel { await startSyncWithProgress() } } - - private func updateProgress(inspected: UInt64, total: UInt64) { - DispatchQueue.main.async { - self.totalScripts = total - self.inspectedScripts = inspected - self.progress = total > 0 ? Float(inspected) / Float(total) : 0 - } - } - - private func updateProgressFullScan(inspected: UInt64) { - DispatchQueue.main.async { - self.inspectedScripts = inspected - } - } - -} - -class WalletSyncScriptInspector: SyncScriptInspector { - private let updateProgress: (UInt64, UInt64) -> Void - private var inspectedCount: UInt64 = 0 - private var totalCount: UInt64 = 0 - - init(updateProgress: @escaping (UInt64, UInt64) -> Void) { - self.updateProgress = updateProgress - } - - func inspect(script: Script, total: UInt64) { - totalCount = total - inspectedCount += 1 - - let delay: TimeInterval = - if total <= 5 { - 0.2 - } else if total < 10 { - 0.15 - } else if total < 20 { - 0.1 - } else { - 0 - } - Thread.sleep(forTimeInterval: delay) - updateProgress(inspectedCount, totalCount) - } -} - -class WalletFullScanScriptInspector: FullScanScriptInspector { - private let updateProgress: (UInt64) -> Void - private var inspectedCount: UInt64 = 0 - - init(updateProgress: @escaping (UInt64) -> Void) { - self.updateProgress = updateProgress - } - - func inspect(keychain: KeychainKind, index: UInt32, script: Script) { - inspectedCount += 1 - updateProgress(inspectedCount) - } }