diff --git a/Bitkit.xcodeproj/project.pbxproj b/Bitkit.xcodeproj/project.pbxproj index c6d63955..edaca895 100644 --- a/Bitkit.xcodeproj/project.pbxproj +++ b/Bitkit.xcodeproj/project.pbxproj @@ -15,12 +15,30 @@ 961058EB2C35793000E1F1D8 /* WalletNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6DC2C32EAA8004A92FC /* WalletNetwork.swift */; }; 961058EE2C35798C00E1F1D8 /* LDKNode in Frameworks */ = {isa = PBXBuildFile; productRef = 961058ED2C35798C00E1F1D8 /* LDKNode */; }; 961058F02C35799400E1F1D8 /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = 961058EF2C35799400E1F1D8 /* BitcoinDevKit */; }; + 961301882C50202A00878183 /* MigrationsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961301872C50202A00878183 /* MigrationsService.swift */; }; + 9613018C2C5022D700878183 /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = 9613018B2C5022D700878183 /* SQLite */; }; + 9613018E2C50288900878183 /* LdkMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9613018D2C50288900878183 /* LdkMigration.swift */; }; + 9613018F2C5028CC00878183 /* MigrationsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961301872C50202A00878183 /* MigrationsService.swift */; }; 9637E6D32C32CE79004A92FC /* Env.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6D22C32CE79004A92FC /* Env.swift */; }; 9637E6D52C32D811004A92FC /* OnChainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6D42C32D811004A92FC /* OnChainService.swift */; }; 9637E6D82C32D8A7004A92FC /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9637E6D72C32D8A7004A92FC /* BitcoinDevKit */; }; 9637E6DA2C32E573004A92FC /* OnChainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6D92C32E573004A92FC /* OnChainViewModel.swift */; }; 9637E6DD2C32EAA8004A92FC /* WalletNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6DC2C32EAA8004A92FC /* WalletNetwork.swift */; }; 9637E6DF2C32ED7B004A92FC /* LnPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6DE2C32ED7B004A92FC /* LnPeer.swift */; }; + 966DE6612C502C7E00A7B0EF /* Env.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6D22C32CE79004A92FC /* Env.swift */; }; + 966DE6622C502C8600A7B0EF /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F261352C369D2400167439 /* Errors.swift */; }; + 966DE6632C502C8600A7B0EF /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96FE5A1A2C46A4DD00860ADC /* Logger.swift */; }; + 966DE6642C502CA300A7B0EF /* ServiceQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F261312C369C2100167439 /* ServiceQueue.swift */; }; + 966DE6652C502CAD00A7B0EF /* WalletNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6DC2C32EAA8004A92FC /* WalletNetwork.swift */; }; + 966DE6662C502CBD00A7B0EF /* LnPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6DE2C32ED7B004A92FC /* LnPeer.swift */; }; + 966DE6672C50372600A7B0EF /* LightningService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B12A022C2EC65000DD07B0 /* LightningService.swift */; }; + 966DE6682C50372900A7B0EF /* OnChainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9637E6D42C32D811004A92FC /* OnChainService.swift */; }; + 966DE66B2C50FA6A00A7B0EF /* channel_manager.bin in Resources */ = {isa = PBXBuildFile; fileRef = 966DE66A2C50FA6A00A7B0EF /* channel_manager.bin */; }; + 966DE66D2C50FA7600A7B0EF /* adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin in Resources */ = {isa = PBXBuildFile; fileRef = 966DE66C2C50FA7600A7B0EF /* adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin */; }; + 966DE6702C51210000A7B0EF /* LightningDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = 966DE66F2C51210000A7B0EF /* LightningDevKit */; }; + 966DE6722C512C1E00A7B0EF /* seed.bin in Resources */ = {isa = PBXBuildFile; fileRef = 966DE6712C512C1E00A7B0EF /* seed.bin */; }; + 966DE6742C512C9300A7B0EF /* HexBytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966DE6732C512C9300A7B0EF /* HexBytes.swift */; }; + 966DE6752C512FD100A7B0EF /* HexBytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966DE6732C512C9300A7B0EF /* HexBytes.swift */; }; 96B129FD2C2EC05D00DD07B0 /* LDKNode in Frameworks */ = {isa = PBXBuildFile; productRef = 96B129FC2C2EC05D00DD07B0 /* LDKNode */; }; 96B12A002C2EC37B00DD07B0 /* LightningViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B129FF2C2EC37B00DD07B0 /* LightningViewModel.swift */; }; 96B12A032C2EC65000DD07B0 /* LightningService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B12A022C2EC65000DD07B0 /* LightningService.swift */; }; @@ -82,11 +100,17 @@ 961058DC2C355B5500E1F1D8 /* BitkitNotification.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BitkitNotification.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 961058DE2C355B5500E1F1D8 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 961058E02C355B5500E1F1D8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 961301872C50202A00878183 /* MigrationsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationsService.swift; sourceTree = ""; }; + 9613018D2C50288900878183 /* LdkMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LdkMigration.swift; sourceTree = ""; }; 9637E6D22C32CE79004A92FC /* Env.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Env.swift; sourceTree = ""; }; 9637E6D42C32D811004A92FC /* OnChainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnChainService.swift; sourceTree = ""; }; 9637E6D92C32E573004A92FC /* OnChainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnChainViewModel.swift; sourceTree = ""; }; 9637E6DC2C32EAA8004A92FC /* WalletNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletNetwork.swift; sourceTree = ""; }; 9637E6DE2C32ED7B004A92FC /* LnPeer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LnPeer.swift; sourceTree = ""; }; + 966DE66A2C50FA6A00A7B0EF /* channel_manager.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = channel_manager.bin; sourceTree = ""; }; + 966DE66C2C50FA7600A7B0EF /* adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin; sourceTree = ""; }; + 966DE6712C512C1E00A7B0EF /* seed.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = seed.bin; sourceTree = ""; }; + 966DE6732C512C9300A7B0EF /* HexBytes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexBytes.swift; sourceTree = ""; }; 96B129FF2C2EC37B00DD07B0 /* LightningViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightningViewModel.swift; sourceTree = ""; }; 96B12A022C2EC65000DD07B0 /* LightningService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightningService.swift; sourceTree = ""; }; 96C246C32C455AF60058222C /* BitkitNotification.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BitkitNotification.entitlements; sourceTree = ""; }; @@ -121,7 +145,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9613018C2C5022D700878183 /* SQLite in Frameworks */, 9637E6D82C32D8A7004A92FC /* BitcoinDevKit in Frameworks */, + 966DE6702C51210000A7B0EF /* LightningDevKit in Frameworks */, 96B129FD2C2EC05D00DD07B0 /* LDKNode in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -163,6 +189,7 @@ 961058F12C35904F00E1F1D8 /* Extensions */ = { isa = PBXGroup; children = ( + 966DE6732C512C9300A7B0EF /* HexBytes.swift */, ); path = Extensions; sourceTree = ""; @@ -184,6 +211,16 @@ path = Models; sourceTree = ""; }; + 966DE6692C50FA5800A7B0EF /* ldk-backup */ = { + isa = PBXGroup; + children = ( + 966DE6712C512C1E00A7B0EF /* seed.bin */, + 966DE66A2C50FA6A00A7B0EF /* channel_manager.bin */, + 966DE66C2C50FA7600A7B0EF /* adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin */, + ); + path = "ldk-backup"; + sourceTree = ""; + }; 96B129FE2C2EC0ED00DD07B0 /* ViewModels */ = { isa = PBXGroup; children = ( @@ -198,6 +235,7 @@ children = ( 96B12A022C2EC65000DD07B0 /* LightningService.swift */, 9637E6D42C32D811004A92FC /* OnChainService.swift */, + 961301872C50202A00878183 /* MigrationsService.swift */, 96F261312C369C2100167439 /* ServiceQueue.swift */, ); path = Services; @@ -265,7 +303,9 @@ 96FE1F752C2DE6AC006D0C8B /* BitkitTests */ = { isa = PBXGroup; children = ( + 966DE6692C50FA5800A7B0EF /* ldk-backup */, 96FE1F762C2DE6AC006D0C8B /* BitkitTests.swift */, + 9613018D2C50288900878183 /* LdkMigration.swift */, ); path = BitkitTests; sourceTree = ""; @@ -329,6 +369,8 @@ packageProductDependencies = ( 96B129FC2C2EC05D00DD07B0 /* LDKNode */, 9637E6D72C32D8A7004A92FC /* BitcoinDevKit */, + 9613018B2C5022D700878183 /* SQLite */, + 966DE66F2C51210000A7B0EF /* LightningDevKit */, ); productName = Bitkit; productReference = 96FE1F612C2DE6AA006D0C8B /* Bitkit.app */; @@ -408,6 +450,8 @@ packageReferences = ( 96B129FB2C2EC05D00DD07B0 /* XCRemoteSwiftPackageReference "ldk-node" */, 9637E6D62C32D8A7004A92FC /* XCRemoteSwiftPackageReference "bdk-swift" */, + 961301892C50215500878183 /* XCRemoteSwiftPackageReference "SQLite.swift" */, + 966DE66E2C51210000A7B0EF /* XCRemoteSwiftPackageReference "ldk-swift" */, ); productRefGroup = 96FE1F622C2DE6AA006D0C8B /* Products */; projectDirPath = ""; @@ -442,6 +486,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 966DE66B2C50FA6A00A7B0EF /* channel_manager.bin in Resources */, + 966DE6722C512C1E00A7B0EF /* seed.bin in Resources */, + 966DE66D2C50FA7600A7B0EF /* adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -476,6 +523,7 @@ files = ( 9637E6D32C32CE79004A92FC /* Env.swift in Sources */, 96FE5A192C46594500860ADC /* LogView.swift in Sources */, + 961301882C50202A00878183 /* MigrationsService.swift in Sources */, 96B12A002C2EC37B00DD07B0 /* LightningViewModel.swift in Sources */, 9637E6DD2C32EAA8004A92FC /* WalletNetwork.swift in Sources */, 96F261362C369D2400167439 /* Errors.swift in Sources */, @@ -485,6 +533,7 @@ 96FE1F672C2DE6AA006D0C8B /* ContentView.swift in Sources */, 96FE5A1B2C46A4DD00860ADC /* Logger.swift in Sources */, 96B12A032C2EC65000DD07B0 /* LightningService.swift in Sources */, + 966DE6742C512C9300A7B0EF /* HexBytes.swift in Sources */, 9637E6D52C32D811004A92FC /* OnChainService.swift in Sources */, 96FE1F652C2DE6AA006D0C8B /* BitkitApp.swift in Sources */, ); @@ -494,7 +543,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 966DE6622C502C8600A7B0EF /* Errors.swift in Sources */, + 966DE6652C502CAD00A7B0EF /* WalletNetwork.swift in Sources */, + 966DE6672C50372600A7B0EF /* LightningService.swift in Sources */, + 966DE6632C502C8600A7B0EF /* Logger.swift in Sources */, + 9613018E2C50288900878183 /* LdkMigration.swift in Sources */, + 966DE6662C502CBD00A7B0EF /* LnPeer.swift in Sources */, + 966DE6612C502C7E00A7B0EF /* Env.swift in Sources */, + 9613018F2C5028CC00878183 /* MigrationsService.swift in Sources */, + 966DE6642C502CA300A7B0EF /* ServiceQueue.swift in Sources */, + 966DE6752C512FD100A7B0EF /* HexBytes.swift in Sources */, 96FE1F772C2DE6AC006D0C8B /* BitkitTests.swift in Sources */, + 966DE6682C50372900A7B0EF /* OnChainService.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -922,6 +982,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 961301892C50215500878183 /* XCRemoteSwiftPackageReference "SQLite.swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/stephencelis/SQLite.swift.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.15.3; + }; + }; 9637E6D62C32D8A7004A92FC /* XCRemoteSwiftPackageReference "bdk-swift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/bitcoindevkit/bdk-swift"; @@ -930,6 +998,14 @@ minimumVersion = 0.31.1; }; }; + 966DE66E2C51210000A7B0EF /* XCRemoteSwiftPackageReference "ldk-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/lightningdevkit/ldk-swift/"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.0.123; + }; + }; 96B129FB2C2EC05D00DD07B0 /* XCRemoteSwiftPackageReference "ldk-node" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/lightningdevkit/ldk-node"; @@ -951,11 +1027,21 @@ package = 9637E6D62C32D8A7004A92FC /* XCRemoteSwiftPackageReference "bdk-swift" */; productName = BitcoinDevKit; }; + 9613018B2C5022D700878183 /* SQLite */ = { + isa = XCSwiftPackageProductDependency; + package = 961301892C50215500878183 /* XCRemoteSwiftPackageReference "SQLite.swift" */; + productName = SQLite; + }; 9637E6D72C32D8A7004A92FC /* BitcoinDevKit */ = { isa = XCSwiftPackageProductDependency; package = 9637E6D62C32D8A7004A92FC /* XCRemoteSwiftPackageReference "bdk-swift" */; productName = BitcoinDevKit; }; + 966DE66F2C51210000A7B0EF /* LightningDevKit */ = { + isa = XCSwiftPackageProductDependency; + package = 966DE66E2C51210000A7B0EF /* XCRemoteSwiftPackageReference "ldk-swift" */; + productName = LightningDevKit; + }; 96B129FC2C2EC05D00DD07B0 /* LDKNode */ = { isa = XCSwiftPackageProductDependency; package = 96B129FB2C2EC05D00DD07B0 /* XCRemoteSwiftPackageReference "ldk-node" */; diff --git a/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6090409f..0a255e6b 100644 --- a/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "957b506793f070febdbc6a14c01a0fcfc0c18f7f437da5a1d36c9627c119b759", + "originHash" : "b03b44bd686d6a1f548992eefdc3c205f03696d1af255697a0c62fecb4ff0cca", "pins" : [ { "identity" : "bdk-swift", @@ -18,6 +18,24 @@ "branch" : "main", "revision" : "66fec694f2b1de81dcb3d40073698a03dfe25522" } + }, + { + "identity" : "ldk-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/lightningdevkit/ldk-swift/", + "state" : { + "revision" : "e3fa435166527b1089787fd4ab0ce398849fb916", + "version" : "0.0.123" + } + }, + { + "identity" : "sqlite.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/stephencelis/SQLite.swift.git", + "state" : { + "revision" : "a95fc6df17d108bd99210db5e8a9bac90fe984b8", + "version" : "0.15.3" + } } ], "version" : 3 diff --git a/Bitkit.xcodeproj/project.xcworkspace/xcuserdata/jason.xcuserdatad/UserInterfaceState.xcuserstate b/Bitkit.xcodeproj/project.xcworkspace/xcuserdata/jason.xcuserdatad/UserInterfaceState.xcuserstate index cbdf6c87..0eed7408 100644 Binary files a/Bitkit.xcodeproj/project.xcworkspace/xcuserdata/jason.xcuserdatad/UserInterfaceState.xcuserstate and b/Bitkit.xcodeproj/project.xcworkspace/xcuserdata/jason.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Bitkit.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist b/Bitkit.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist index 1f42bbf1..fbe57dc5 100644 --- a/Bitkit.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Bitkit.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist @@ -14,6 +14,27 @@ orderHint 1 + SQLite (Playground) 1.xcscheme + + isShown + + orderHint + 3 + + SQLite (Playground) 2.xcscheme + + isShown + + orderHint + 4 + + SQLite (Playground).xcscheme + + isShown + + orderHint + 2 + SuppressBuildableAutocreation diff --git a/Bitkit/BitkitApp.swift b/Bitkit/BitkitApp.swift index 83cd449c..b4cc52b6 100644 --- a/Bitkit/BitkitApp.swift +++ b/Bitkit/BitkitApp.swift @@ -70,17 +70,22 @@ struct BitkitApp: App { var body: some Scene { WindowGroup { - ContentView() - .onAppear { - //TODO move this elsewhere - requestPushNotificationPermision { (granted, error) in - if granted { - Logger.info("Push notification permission granted") - } else { - Logger.warn("Push notification permission denied") + if Env.isUnitTest { + Text("Running unit tests...") + } else { + ContentView() + .onAppear { + //TODO move this elsewhere + requestPushNotificationPermision { (granted, error) in + if granted { + Logger.info("Push notification permission granted") + } else { + Logger.warn("Push notification permission denied") + } } } - } + } + } } } diff --git a/Bitkit/Constants/Env.swift b/Bitkit/Constants/Env.swift index 4ef40052..e2b34f70 100644 --- a/Bitkit/Constants/Env.swift +++ b/Bitkit/Constants/Env.swift @@ -29,11 +29,9 @@ struct Env { static var esploraServerUrl: String { switch network { case .regtest: + return "https://electrs-regtest.synonym.to" //cargo run --release --bin electrs -- -vvv --jsonrpc-import --daemon-rpc-addr 127.0.0.1:18443 --cookie polaruser:polarpass -// return "https://jaybird-logical-sadly.ngrok-free.app" -// return "http://127.0.0.1:3000" - - return "http://192.168.0.106:3000" + //return "http://127.0.0.1:3000" case .bitcoin: fatalError("Bitcoin network not implemented") case .testnet: @@ -49,15 +47,30 @@ struct Env { fatalError("Could not find documents directory") } + if isUnitTest { + return documentsDirectory.appendingPathComponent("unit-tests") + } + return documentsDirectory } static var ldkStorage: URL { - let storageDirPath = appStorageUrl.appendingPathComponent("ldk") - switch network { case .regtest: - return storageDirPath.appendingPathComponent("regtest") + return appStorageUrl.appendingPathComponent("regtest").appendingPathComponent("ldk") + case .bitcoin: + fatalError("Bitcoin network not implemented") + case .testnet: + fatalError("Testnet network not implemented") + case .signet: + fatalError("Signet network not implemented") + } + } + + static var bdkStorage: URL { + switch network { + case .regtest: + return appStorageUrl.appendingPathComponent("regtest").appendingPathComponent("bdk") case .bitcoin: fatalError("Bitcoin network not implemented") case .testnet: @@ -84,9 +97,7 @@ struct Env { switch network { case .regtest: return [ - .init(nodeId: "03e26fdad23b9e17f6a6b1dd0a019c6fcd9e778a1c2af6ae62a0951c8352efbbc3", address: "192.168.0.106:9735") -// .init(nodeId: "0218ab1da83a4768e154fada54deb5d835199aad116c4212e6844d0dce0f82cab1", address: "192.168.0.106:9737"), -// .init(nodeId: "021de6ad59a78caf8f376cbd022e8c6ede2a1ef0a4fa035174e8b9c25ad5866584", address: "192.168.0.106:9738") + .init(nodeId: "02b61365f14c5070465e014485fa91cee5a131cf2a4b7cb37309fcd1cc53975238", address: "192.168.0.106:9735") ] case .bitcoin: return [] @@ -96,4 +107,6 @@ struct Env { return [] } } + + static let testMnemonic = "pool curve feature leader elite dilemma exile toast smile couch crane public" } diff --git a/Bitkit/ContentView.swift b/Bitkit/ContentView.swift index ba274d41..a8990bc7 100644 --- a/Bitkit/ContentView.swift +++ b/Bitkit/ContentView.swift @@ -149,23 +149,17 @@ struct ContentView: View { .sheet(isPresented: $showLogs) { LogView() } - .onAppear { + .onAppear { Logger.debug("App appeared, spinning up services...") Task { do { try await lnViewModel.start() try await lnViewModel.sync() - } catch { - Logger.error(error, context: "Failed to start LN") - } - } - - Task { - do { + try await onChainViewModel.start() try await onChainViewModel.sync() } catch { - Logger.error(error, context: "Failed to start on chain") + Logger.error(error, context: "Failed to start wallet services") } } } diff --git a/Bitkit/Extensions/HexBytes.swift b/Bitkit/Extensions/HexBytes.swift new file mode 100644 index 00000000..b95fa9c7 --- /dev/null +++ b/Bitkit/Extensions/HexBytes.swift @@ -0,0 +1,28 @@ +// +// String.swift +// Bitkit +// +// Created by Jason van den Berg on 2024/07/24. +// + +import Foundation + +extension Data { + var hex: String { + map { String(format: "%02hhx", $0) }.joined() + } +} + +extension StringProtocol { + var hexaData: Data { .init(hexa) } + var hexaBytes: [UInt8] { .init(hexa) } + + private var hexa: UnfoldSequence { + sequence(state: startIndex) { startIndex in + guard startIndex < endIndex else { return nil } + let endIndex = index(startIndex, offsetBy: 2, limitedBy: endIndex) ?? endIndex + defer { startIndex = endIndex } + return UInt8(self[startIndex..("primary_namespace") + let snCol = Expression("secondary_namespace") + let keyCol = Expression("key") + let valueCol = Expression("value") + + try db.run(table.create { t in + t.column(pnCol, primaryKey: true) + t.column(snCol) + t.column(keyCol) + t.column(valueCol) + }) + + //TODO: use create statement directly from LDK-node instead + //CREATE TABLE IF NOT EXISTS {} ( + // primary_namespace TEXT NOT NULL, + // secondary_namespace TEXT DEFAULT \"\" NOT NULL, + // key TEXT NOT NULL CHECK (key <> ''), + // value BLOB, PRIMARY KEY ( primary_namespace, secondary_namespace, key ) + // ); + + let insert = table.insert(pnCol <- "", snCol <- "", keyCol <- "manager", valueCol <- manager) + let rowid = try db.run(insert) + Logger.debug(rowid, context: "Inserted manager") + + let seconds = UInt64(NSDate().timeIntervalSince1970) + let nanoSeconds = UInt32.init(truncating: NSNumber(value: seconds * 1000 * 1000)) + let keysManager = KeysManager( + seed: [UInt8](seed), + startingTimeSecs: seconds, + startingTimeNanos: nanoSeconds + ) + + for monitor in monitors { + //MARK: get funding_tx and index using plain LDK + //https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#definition-of-channel_id + guard let channelMonitor = Bindings.readThirtyTwoBytesChannelMonitor(ser: [UInt8](monitor), argA: keysManager.asEntropySource(), argB: keysManager.asSignerProvider()).getValue()?.1 else { + Logger.error("Could not read channel monitor using readThirtyTwoBytesChannelMonitor") + throw AppError(serviceError: .ldkToLdkNodeMigration) + } + + let fundingTx = Data(channelMonitor.getFundingTxo().0.getTxid()!.reversed()).hex + let index = channelMonitor.getFundingTxo().0.getIndex() + + let key = "\(fundingTx)_\(index)" + let insert = table.insert( + pnCol <- "monitors", + snCol <- "", + keyCol <- key, + valueCol <- monitor + ) + + try db.run(insert) + Logger.debug(key, context: "Inserted monitor") + } + } +} diff --git a/Bitkit/Services/OnChainService.swift b/Bitkit/Services/OnChainService.swift index 615585bb..f772e652 100644 --- a/Bitkit/Services/OnChainService.swift +++ b/Bitkit/Services/OnChainService.swift @@ -12,7 +12,7 @@ class OnChainService { private var wallet: Wallet? private var blockchainConfig: BlockchainConfig? - static var shared: OnChainService = OnChainService() + static var shared = OnChainService() private init() {} @@ -59,7 +59,7 @@ class OnChainService { descriptor: descriptor, changeDescriptor: changeDescriptor, network: Env.network.bdkNetwork, - databaseConfig: .memory //TODO use sqlite + databaseConfig: .sled(config: .init(path: Env.bdkStorage.path, treeName: "")) ) } diff --git a/Bitkit/Services/ServiceQueue.swift b/Bitkit/Services/ServiceQueue.swift index cc734ff4..ee372623 100644 --- a/Bitkit/Services/ServiceQueue.swift +++ b/Bitkit/Services/ServiceQueue.swift @@ -11,12 +11,14 @@ import Foundation class ServiceQueue { private static let ldkQueue = DispatchQueue(label: "ldk-queue", qos: .utility) private static let bdkQueue = DispatchQueue(label: "bdk-queue", qos: .utility) - + private static let migrationQueue = DispatchQueue(label: "migration-queue", qos: .utility) + private init() {} enum ServiceTypes { case ldk case bdk + case migration var queue: DispatchQueue { switch self { @@ -24,6 +26,8 @@ class ServiceQueue { return ServiceQueue.ldkQueue case .bdk: return ServiceQueue.bdkQueue + case .migration: + return ServiceQueue.migrationQueue } } } diff --git a/Bitkit/Utilities/Errors.swift b/Bitkit/Utilities/Errors.swift index 3effd0b6..62e066a6 100644 --- a/Bitkit/Utilities/Errors.swift +++ b/Bitkit/Utilities/Errors.swift @@ -12,6 +12,8 @@ import BitcoinDevKit enum CustomServiceError: Error { case nodeNotStarted case onchainWalletNotCreated + case ldkNodeSqliteAlreadyExists + case ldkToLdkNodeMigration } /// Translates LDK and BDK error messages into translated messages that can be displayed to end users @@ -41,14 +43,12 @@ struct AppError: LocalizedError { return } - self.init(message: "Unknown error", debugMessage: error.localizedDescription) + self.init(message: "Error", debugMessage: error.localizedDescription) } init(message: String, debugMessage: String?) { self.message = message self.debugMessage = debugMessage - - Logger.error("\(message) [\(debugMessage ?? "")]", context: "generic app error") } init(serviceError: CustomServiceError) { @@ -59,6 +59,12 @@ struct AppError: LocalizedError { case .onchainWalletNotCreated: message = "Onchain wallet not created" debugMessage = nil + case .ldkNodeSqliteAlreadyExists: + message = "LDK-node SQLite file already exists" + debugMessage = nil + case .ldkToLdkNodeMigration: + message = "LDK to LDK-node migration issue" + debugMessage = nil } Logger.error("\(message) [\(debugMessage ?? "")]", context: "service error") diff --git a/Bitkit/ViewModels/LightningViewModel.swift b/Bitkit/ViewModels/LightningViewModel.swift index 00a7b04e..270f4942 100644 --- a/Bitkit/ViewModels/LightningViewModel.swift +++ b/Bitkit/ViewModels/LightningViewModel.swift @@ -19,7 +19,7 @@ class LightningViewModel: ObservableObject { @Published var payments: [PaymentDetails]? func start() async throws { - let mnemonic = "always coconut smooth scatter steel web version exist broken motion damage board trap dinosaur include alone dust flag paddle give divert journey garden bench" // = generateEntropyMnemonic() + let mnemonic = Env.testMnemonic // = generateEntropyMnemonic() let passphrase: String? = nil syncState() diff --git a/Bitkit/ViewModels/OnChainViewModel.swift b/Bitkit/ViewModels/OnChainViewModel.swift index cfa6a06b..19d96d26 100644 --- a/Bitkit/ViewModels/OnChainViewModel.swift +++ b/Bitkit/ViewModels/OnChainViewModel.swift @@ -15,7 +15,7 @@ class OnChainViewModel: ObservableObject { @Published var address: String? func start() async throws { - let mnemonic = "always coconut smooth scatter steel web version exist broken motion damage board trap dinosaur include alone dust flag paddle give divert journey garden bench" // = generateEntropyMnemonic() + let mnemonic = Env.testMnemonic // = generateEntropyMnemonic() let passphrase: String? = nil try OnChainService.shared.setup() diff --git a/BitkitNotification/NotificationService.swift b/BitkitNotification/NotificationService.swift index c703a4a9..7efff6bb 100644 --- a/BitkitNotification/NotificationService.swift +++ b/BitkitNotification/NotificationService.swift @@ -19,7 +19,7 @@ class NotificationService: UNNotificationServiceExtension { Task { do { - let mnemonic = "always coconut smooth scatter steel web version exist broken motion damage board trap dinosaur include alone dust flag paddle give divert journey garden bench" // = generateEntropyMnemonic() + let mnemonic = Env.testMnemonic // = generateEntropyMnemonic() let passphrase: String? = nil try await LightningService.shared.setup(mnemonic: mnemonic, passphrase: passphrase) diff --git a/BitkitTests/LdkMigration.swift b/BitkitTests/LdkMigration.swift new file mode 100644 index 00000000..8cb15b9c --- /dev/null +++ b/BitkitTests/LdkMigration.swift @@ -0,0 +1,76 @@ +// +// LdkMigration.swift +// BitkitTests +// +// Created by Jason van den Berg on 2024/07/23. +// + +import XCTest + +final class LdkMigration: XCTestCase { + + override func setUpWithError() throws { + try? FileManager.default.removeItem(at: Env.appStorageUrl) //Removes 'unit-test' directory + } + + override func tearDownWithError() throws { + dumpLdkLogs() + } + + func testLdkToLdkNode() async throws { + guard let seedFile = Bundle(for: type(of: self)).url(forResource: "seed", withExtension: "bin") else { + XCTFail("Missing file: seed.bin") + return + } + + guard let managerFile = Bundle(for: type(of: self)).url(forResource: "channel_manager", withExtension: "bin") else { + XCTFail("Missing file: channel_manager.bin") + return + } + + guard let channelFile = Bundle(for: type(of: self)).url(forResource: "adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630", withExtension: "bin") else { + XCTFail("Missing file: adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin") + return + } + + try MigrationsService.shared.ldkToLdkNode( + seed: try Data(contentsOf: seedFile), + manager: try Data(contentsOf: managerFile), + monitors: [ + try Data(contentsOf: channelFile) + ] + ) + + try await LightningService.shared.setup(mnemonic: Env.testMnemonic, passphrase: nil) + try await LightningService.shared.start() + + XCTAssertEqual(LightningService.shared.nodeId, "02cd08b7b375e4263849121f9f0ffb2732a0b88d0fb74487575ac539b374f45a55") + + let channels = LightningService.shared.channels + XCTAssertEqual(channels?.count, 1) + + try await LightningService.shared.stop() + } + + func dumpLdkLogs() { + let dir = Env.ldkStorage + let fileURL = dir.appendingPathComponent("ldk_node_latest.log") + + guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { + return + } + let lines = text.components(separatedBy: "\n").map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) }) + print("*****LDK-NODE LOG******") + lines.suffix(20).forEach { line in + print(line) + } + print("*****END LOG******") + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } +} diff --git a/BitkitTests/ldk-backup/adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin b/BitkitTests/ldk-backup/adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin new file mode 100644 index 00000000..b63e3f64 Binary files /dev/null and b/BitkitTests/ldk-backup/adb1de43b448b04b3fdde638155929cd2163d2c53d36bb40b517d7acc44d1630.bin differ diff --git a/BitkitTests/ldk-backup/channel_manager.bin b/BitkitTests/ldk-backup/channel_manager.bin new file mode 100644 index 00000000..c95428d2 Binary files /dev/null and b/BitkitTests/ldk-backup/channel_manager.bin differ diff --git a/BitkitTests/ldk-backup/seed.bin b/BitkitTests/ldk-backup/seed.bin new file mode 100644 index 00000000..754d9499 --- /dev/null +++ b/BitkitTests/ldk-backup/seed.bin @@ -0,0 +1 @@ +nì õçJÓL¦Çm¨ÀΚÚþL&‰ÚíéÇ¥Ó4¬œ~Þ \ No newline at end of file