diff --git a/BDKSwiftExampleWallet/Extensions/BDK+Extensions/Persister+Extensions.swift b/BDKSwiftExampleWallet/Extensions/BDK+Extensions/Persister+Extensions.swift index c45afcf8..ceccf5f6 100644 --- a/BDKSwiftExampleWallet/Extensions/BDK+Extensions/Persister+Extensions.swift +++ b/BDKSwiftExampleWallet/Extensions/BDK+Extensions/Persister+Extensions.swift @@ -9,13 +9,13 @@ extension Persister { let persister = try Persister.newSqlite(path: URL.persistenceBackendPath) return persister } - + static func loadConnection() throws -> Persister { let persistenceBackendPath = URL.persistenceBackendPath let persister = try Persister.newSqlite(path: persistenceBackendPath) return persister } - + static func deleteConnection() throws { let walletDataDirectoryURL = URL.walletDataDirectoryURL if FileManager.default.fileExists(atPath: walletDataDirectoryURL.path) { diff --git a/BDKSwiftExampleWallet/Extensions/Int+Extensions.swift b/BDKSwiftExampleWallet/Extensions/Int+Extensions.swift index 98e57bff..cafd2edb 100644 --- a/BDKSwiftExampleWallet/Extensions/Int+Extensions.swift +++ b/BDKSwiftExampleWallet/Extensions/Int+Extensions.swift @@ -40,49 +40,49 @@ extension UInt64 { numberFormatter.usesGroupingSeparator = true numberFormatter.groupingSeparator = "," numberFormatter.generatesDecimalNumbers = false - + return numberFormatter } - + func formattedSatoshis() -> String { if self == 0 { return "0.00 000 000" } else { // Convert satoshis to BTC (1 BTC = 100,000,000 sats) let btcValue = Double(self) / 100_000_000.0 - + // Format BTC value to exactly 8 decimal places let btcString = String(format: "%.8f", btcValue) - + // Split the string at the decimal point let parts = btcString.split(separator: ".") guard parts.count == 2 else { return btcString } - + let wholePart = String(parts[0]) let decimalPart = String(parts[1]) - + // Ensure decimal part is exactly 8 digits let paddedDecimal = decimalPart.padding(toLength: 8, withPad: "0", startingAt: 0) - + // Format as XX.XX XXX XXX let first = paddedDecimal.prefix(2) let second = paddedDecimal.dropFirst(2).prefix(3) let third = paddedDecimal.dropFirst(5).prefix(3) - + let formattedBalance = "\(wholePart).\(first) \(second) \(third)" return formattedBalance } } - + func formattedBip177() -> String { if self != .zero && self >= 1_000_000 && self % 1_000_000 == .zero { return "\(self / 1_000_000)M" - + } else if self != .zero && self % 1_000 == 0 { return "\(self / 1_000)K" } - + return numberFormatter.string(from: NSNumber(value: self)) ?? "0" } } diff --git a/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift b/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift index 7b9e69ca..1ab1bd5d 100644 --- a/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift +++ b/BDKSwiftExampleWallet/Service/BDK Service/BDKService.swift @@ -253,15 +253,52 @@ private class BDKService { self.wallet = wallet } - private func loadWallet(descriptor: Descriptor, changeDescriptor: Descriptor) throws { - let persister = try Persister.loadConnection() - self.persister = persister - let wallet = try Wallet.load( - descriptor: descriptor, - changeDescriptor: changeDescriptor, - persister: persister - ) - self.wallet = wallet + private func loadWallet( + descriptor: Descriptor, + changeDescriptor: + Descriptor + ) throws { + // If database doesn't exist, create it from the descriptors + if !FileManager.default.fileExists( + atPath: + URL.persistenceBackendPath + ) { + let persister = try Persister.createConnection() + self.persister = persister + let wallet = try Wallet( + descriptor: descriptor, + changeDescriptor: changeDescriptor, + network: self.network, + persister: persister + ) + self.wallet = wallet + } else { + // Database exists, try to load the wallet + do { + let persister = try Persister.loadConnection() + self.persister = persister + let wallet = try Wallet.load( + descriptor: descriptor, + changeDescriptor: changeDescriptor, + persister: persister + ) + self.wallet = wallet + } catch is LoadWithPersistError { + // Database is corrupted or incompatible, delete and recreate + print("Wallet database is corrupted, recreating...") + try Persister.deleteConnection() + + let persister = try Persister.createConnection() + self.persister = persister + let wallet = try Wallet( + descriptor: descriptor, + changeDescriptor: changeDescriptor, + network: self.network, + persister: persister + ) + self.wallet = wallet + } + } } func loadWalletFromBackup() throws { diff --git a/BDKSwiftExampleWalletTests/Extensions/BDKSwiftExampleWalletInt+Extensions.swift b/BDKSwiftExampleWalletTests/Extensions/BDKSwiftExampleWalletInt+Extensions.swift index 06497472..f52a462d 100644 --- a/BDKSwiftExampleWalletTests/Extensions/BDKSwiftExampleWalletInt+Extensions.swift +++ b/BDKSwiftExampleWalletTests/Extensions/BDKSwiftExampleWalletInt+Extensions.swift @@ -34,34 +34,34 @@ final class BDKSwiftExampleWalletInt_Extensions: XCTestCase { func testBip177() { let oneHundred = UInt64(100).formattedBip177() XCTAssertEqual(oneHundred, "100") - + let oneThousand = UInt64(1000).formattedBip177() XCTAssertEqual(oneThousand, "1K") - + let oneThousandOne = UInt64(1001).formattedBip177() XCTAssertEqual(oneThousandOne, "1,001") - + let tenThousand = UInt64(10000).formattedBip177() XCTAssertEqual(tenThousand, "10K") - + let tenThousandOne = UInt64(10001).formattedBip177() XCTAssertEqual(tenThousandOne, "10,001") - + let oneHundredThousand = UInt64(100000).formattedBip177() XCTAssertEqual(oneHundredThousand, "100K") - + let oneHundredThousandOne = UInt64(100001).formattedBip177() XCTAssertEqual(oneHundredThousandOne, "100,001") - - let oneMillion = UInt64(1000000).formattedBip177() + + let oneMillion = UInt64(1_000_000).formattedBip177() XCTAssertEqual(oneMillion, "1M") - - let oneMillionOne = UInt64(1000001).formattedBip177() + + let oneMillionOne = UInt64(1_000_001).formattedBip177() XCTAssertEqual(oneMillionOne, "1,000,001") - + let treeMillions = UInt64(325_000_000).formattedBip177() XCTAssertEqual(treeMillions, "325M") - + let treeMillionsOne = UInt64(325_000_001).formattedBip177() XCTAssertEqual(treeMillionsOne, "325,000,001") }