66//
77
88import BitcoinDevKit
9+ import BackgroundTasks
910import SwiftUI
1011
1112@main
1213struct BDKSwiftExampleWalletApp : App {
1314 @AppStorage ( " isOnboarding " ) var isOnboarding : Bool = true
1415 @State private var navigationPath = NavigationPath ( )
1516 @State private var refreshTrigger = UUID ( )
17+ @Environment ( \. scenePhase) private var scenePhase
18+
19+ init ( ) {
20+ BackgroundCBFSyncTask . register ( )
21+ BackgroundCBFSyncTask . schedule ( )
22+ }
1623
1724 var body : some Scene {
1825 WindowGroup {
@@ -30,6 +37,11 @@ struct BDKSwiftExampleWalletApp: App {
3037 BDKClient . live. setNeedsFullScan ( true )
3138 navigationPath = NavigationPath ( )
3239 }
40+ . onChange ( of: scenePhase) { _, newValue in
41+ if newValue == . background {
42+ BackgroundCBFSyncTask . schedule ( )
43+ }
44+ }
3345 }
3446 }
3547}
@@ -42,3 +54,69 @@ extension BDKSwiftExampleWalletApp {
4254 return ( try ? KeyClient . live. getBackupInfo ( ) ) != nil
4355 }
4456}
57+
58+ private enum BackgroundCBFSyncTask {
59+ static let identifier = " com.bitcoindevkit.bdkswiftexamplewallet.cbf-sync "
60+ private static let minimumInterval : TimeInterval = 60 * 60 * 24 * 7
61+
62+ static func register( ) {
63+ BGTaskScheduler . shared. register (
64+ forTaskWithIdentifier: identifier,
65+ using: nil
66+ ) { task in
67+ guard let processingTask = task as? BGProcessingTask else {
68+ task. setTaskCompleted ( success: false )
69+ return
70+ }
71+ handle ( processingTask)
72+ }
73+ }
74+
75+ static func schedule( ) {
76+ let request = BGProcessingTaskRequest ( identifier: identifier)
77+ request. requiresNetworkConnectivity = true
78+ request. requiresExternalPower = true
79+ request. earliestBeginDate = Date ( timeIntervalSinceNow: minimumInterval)
80+
81+ do {
82+ try BGTaskScheduler . shared. submit ( request)
83+ } catch {
84+ print ( " [BackgroundCBF] Failed to schedule task: \( error) " )
85+ }
86+ }
87+
88+ private static func handle( _ task: BGProcessingTask ) {
89+ schedule ( )
90+
91+ let syncTask = Task . detached ( priority: . background) {
92+ do {
93+ try await runKyotoSync ( )
94+ task. setTaskCompleted ( success: true )
95+ } catch {
96+ print ( " [BackgroundCBF] Background sync failed: \( error) " )
97+ task. setTaskCompleted ( success: false )
98+ }
99+ }
100+
101+ task. expirationHandler = {
102+ syncTask. cancel ( )
103+ }
104+ }
105+
106+ private static func runKyotoSync( ) async throws {
107+ let bdkClient = BDKClient . live
108+
109+ guard ( try ? bdkClient. getBackupInfo ( ) ) != nil else {
110+ return
111+ }
112+
113+ try bdkClient. loadWallet ( )
114+
115+ guard bdkClient. getClientType ( ) == . kyoto else {
116+ return
117+ }
118+
119+ let inspector = WalletSyncScriptInspector ( updateProgress: { _, _ in } )
120+ try await bdkClient. syncWithInspector ( inspector)
121+ }
122+ }
0 commit comments