Skip to content

spm: bdk-ffi 2.0 #302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions BDKSwiftExampleWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
AE6716012A9AC089005C193F /* KeyServiceError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE6716002A9AC089005C193F /* KeyServiceError.swift */; };
AE6F34D82AA6C1800087E700 /* Network+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE6F34D72AA6C1800087E700 /* Network+Extensions.swift */; };
AE6F34DA2AA6C1E00087E700 /* Balance+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE6F34D92AA6C1E00087E700 /* Balance+Extensions.swift */; };
AE7053262DE79AA30091DD78 /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = AE7053252DE79AA30091DD78 /* BitcoinDevKit */; };
AE7323992DF9BF9700D9BAE2 /* TxDetails+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7323982DF9BF9700D9BAE2 /* TxDetails+Extensions.swift */; };
AE73239B2DF9C00F00D9BAE2 /* TxId+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE73239A2DF9C00F00D9BAE2 /* TxId+Extensions.swift */; };
AE7839FD2AB4E18D005F0CBA /* AmountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7839FC2AB4E18D005F0CBA /* AmountView.swift */; };
AE783A012AB4E5E1005F0CBA /* BuildTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE783A002AB4E5E1005F0CBA /* BuildTransactionView.swift */; };
AE783A032AB4ECC2005F0CBA /* AddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE783A022AB4ECC2005F0CBA /* AddressView.swift */; };
Expand All @@ -77,6 +80,7 @@
AE91CEED2C0FDB70000AAD20 /* SentAndReceivedValues+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE91CEEC2C0FDB70000AAD20 /* SentAndReceivedValues+Extensions.swift */; };
AE91CEEF2C0FDBC7000AAD20 /* CanonicalTx+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE91CEEE2C0FDBC7000AAD20 /* CanonicalTx+Extensions.swift */; };
AE96F6622A424C400055623C /* BDKSwiftExampleWalletReceiveViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE96F6612A424C400055623C /* BDKSwiftExampleWalletReceiveViewModelTests.swift */; };
AEA0A6272E297203008A525B /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = AEA0A6262E297203008A525B /* BitcoinDevKit */; };
AEAB03112ABDDB86000C9528 /* FeeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEAB03102ABDDB86000C9528 /* FeeViewModel.swift */; };
AEAB03132ABDDBF4000C9528 /* AmountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEAB03122ABDDBF4000C9528 /* AmountViewModel.swift */; };
AEAF83B62B7BD4D10019B23B /* CodeScanner in Frameworks */ = {isa = PBXBuildFile; productRef = AEAF83B52B7BD4D10019B23B /* CodeScanner */; };
Expand All @@ -99,6 +103,7 @@
AEE6C74C2ABCB3E200442ADD /* Transaction+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6C74B2ABCB3E200442ADD /* Transaction+Extensions.swift */; };
AEE6C74F2ABCBA4600442ADD /* WalletSyncState.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6C74E2ABCBA4600442ADD /* WalletSyncState.swift */; };
AEE83A492C07F54B00834468 /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = AEE83A482C07F54B00834468 /* BitcoinDevKit */; };
AEEA0E402DEF80B600C83255 /* Outpoint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEEA0E3F2DEF80B600C83255 /* Outpoint+Extensions.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -161,6 +166,8 @@
AE6716002A9AC089005C193F /* KeyServiceError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyServiceError.swift; sourceTree = "<group>"; };
AE6F34D72AA6C1800087E700 /* Network+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Network+Extensions.swift"; sourceTree = "<group>"; };
AE6F34D92AA6C1E00087E700 /* Balance+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Balance+Extensions.swift"; sourceTree = "<group>"; };
AE7323982DF9BF9700D9BAE2 /* TxDetails+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TxDetails+Extensions.swift"; sourceTree = "<group>"; };
AE73239A2DF9C00F00D9BAE2 /* TxId+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TxId+Extensions.swift"; sourceTree = "<group>"; };
AE7839FC2AB4E18D005F0CBA /* AmountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmountView.swift; sourceTree = "<group>"; };
AE783A002AB4E5E1005F0CBA /* BuildTransactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildTransactionView.swift; sourceTree = "<group>"; };
AE783A022AB4ECC2005F0CBA /* AddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -197,14 +204,17 @@
AED79FC42A97D47D00FD3C7D /* BDKSwiftExampleWalletSendViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BDKSwiftExampleWalletSendViewModelTests.swift; sourceTree = "<group>"; };
AEE6C74B2ABCB3E200442ADD /* Transaction+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Transaction+Extensions.swift"; sourceTree = "<group>"; };
AEE6C74E2ABCBA4600442ADD /* WalletSyncState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletSyncState.swift; sourceTree = "<group>"; };
AEEA0E3F2DEF80B600C83255 /* Outpoint+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Outpoint+Extensions.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
AE4984752A1BBBD6009951E2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
AE7053262DE79AA30091DD78 /* BitcoinDevKit in Frameworks */,
AE2DD83F2D6FEF3600E5F212 /* BitcoinDevKit in Frameworks */,
AEA0A6272E297203008A525B /* BitcoinDevKit in Frameworks */,
AE187D782C9BB3B50081D0C3 /* BitcoinDevKit in Frameworks */,
AE29ED0F2BBE2E7100EB9C4F /* BitcoinDevKit in Frameworks */,
AEAF83B62B7BD4D10019B23B /* CodeScanner in Frameworks */,
Expand Down Expand Up @@ -563,6 +573,9 @@
AE184EFB2BFE52C800374362 /* Amount+Extensions.swift */,
AE91CEEC2C0FDB70000AAD20 /* SentAndReceivedValues+Extensions.swift */,
AE91CEEE2C0FDBC7000AAD20 /* CanonicalTx+Extensions.swift */,
AEEA0E3F2DEF80B600C83255 /* Outpoint+Extensions.swift */,
AE7323982DF9BF9700D9BAE2 /* TxDetails+Extensions.swift */,
AE73239A2DF9C00F00D9BAE2 /* TxId+Extensions.swift */,
);
path = "BDK+Extensions";
sourceTree = "<group>";
Expand Down Expand Up @@ -595,6 +608,8 @@
AE2DD8382D6FE9B000E5F212 /* BitcoinDevKit */,
AE2DD83B2D6FEC3100E5F212 /* BitcoinDevKit */,
AE2DD83E2D6FEF3600E5F212 /* BitcoinDevKit */,
AE7053252DE79AA30091DD78 /* BitcoinDevKit */,
AEA0A6262E297203008A525B /* BitcoinDevKit */,
);
productName = BDKSwiftExampleWallet;
productReference = AE4984782A1BBBD6009951E2 /* BDKSwiftExampleWallet.app */;
Expand Down Expand Up @@ -652,7 +667,7 @@
AE7D5A0C2A7EE62200EAC8CE /* XCRemoteSwiftPackageReference "KeychainAccess" */,
AEB735D12B2CC4B900F99DBB /* XCRemoteSwiftPackageReference "BitcoinUI" */,
AEAF83B42B7BD4D10019B23B /* XCRemoteSwiftPackageReference "CodeScanner" */,
AEA2DEF12D70F8840067C0EB /* XCRemoteSwiftPackageReference "bdk-swift" */,
AEA0A6252E297203008A525B /* XCRemoteSwiftPackageReference "bdk-swift" */,
);
productRefGroup = AE4984792A1BBBD6009951E2 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -728,12 +743,14 @@
AE2ADD742B61E8F500C2A823 /* SettingsView.swift in Sources */,
AE2381AF2C605B1D00F6B00C /* ActivityListViewModel.swift in Sources */,
AE6F34D82AA6C1800087E700 /* Network+Extensions.swift in Sources */,
AE73239B2DF9C00F00D9BAE2 /* TxId+Extensions.swift in Sources */,
AE1390C72A7DB0AF0098127A /* KeyService.swift in Sources */,
AED4CC0A2A1D297600CE1831 /* BDKService.swift in Sources */,
AED4CC102A1D522100CE1831 /* WalletView.swift in Sources */,
AE7F67092A7451AA00CED561 /* Price.swift in Sources */,
AE184EFC2BFE52C800374362 /* Amount+Extensions.swift in Sources */,
779E70892DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift in Sources */,
AEEA0E402DEF80B600C83255 /* Outpoint+Extensions.swift in Sources */,
AE2381B12C60690900F6B00C /* LocalOutput+Extensions.swift in Sources */,
779E70872DB9C98A006E22D3 /* WalletSyncScriptInspector.swift in Sources */,
AE7F67072A744CE200CED561 /* Double+Extensions.swift in Sources */,
Expand All @@ -755,6 +772,7 @@
AE34DDAE2B6B320F00F04AD4 /* WalletRecoveryViewModel.swift in Sources */,
AE0C30F92A804B65008F1EAE /* OnboardingViewModel.swift in Sources */,
AE3902A42A3B4CD900BEC318 /* HomeView.swift in Sources */,
AE7323992DF9BF9700D9BAE2 /* TxDetails+Extensions.swift in Sources */,
AE0C30FD2A804BC1008F1EAE /* ReceiveViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1063,12 +1081,12 @@
version = 4.2.2;
};
};
AEA2DEF12D70F8840067C0EB /* XCRemoteSwiftPackageReference "bdk-swift" */ = {
AEA0A6252E297203008A525B /* XCRemoteSwiftPackageReference "bdk-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/bitcoindevkit/bdk-swift";
requirement = {
kind = exactVersion;
version = 1.2.0;
version = 2.0.0;
};
};
AEAF83B42B7BD4D10019B23B /* XCRemoteSwiftPackageReference "CodeScanner" */ = {
Expand Down Expand Up @@ -1118,11 +1136,20 @@
isa = XCSwiftPackageProductDependency;
productName = BitcoinDevKit;
};
AE7053252DE79AA30091DD78 /* BitcoinDevKit */ = {
isa = XCSwiftPackageProductDependency;
productName = BitcoinDevKit;
};
AE7D5A0D2A7EE62200EAC8CE /* KeychainAccess */ = {
isa = XCSwiftPackageProductDependency;
package = AE7D5A0C2A7EE62200EAC8CE /* XCRemoteSwiftPackageReference "KeychainAccess" */;
productName = KeychainAccess;
};
AEA0A6262E297203008A525B /* BitcoinDevKit */ = {
isa = XCSwiftPackageProductDependency;
package = AEA0A6252E297203008A525B /* XCRemoteSwiftPackageReference "bdk-swift" */;
productName = BitcoinDevKit;
};
AEAF83B52B7BD4D10019B23B /* CodeScanner */ = {
isa = XCSwiftPackageProductDependency;
package = AEAF83B42B7BD4D10019B23B /* XCRemoteSwiftPackageReference "CodeScanner" */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ extension Amount: @retroactive Equatable {
return lhs.toSat() == rhs.toSat()
}
}

extension Amount {
static let mock = Amount.fromSat(satoshi: 100_000)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,27 @@ extension CanonicalTx {
confirmationBlockTime: .init(
blockId: .init(
height: UInt32(12),
hash: "hash"
// hash: try! BlockHash.fromBytes(
// bytes: Data([
// 0xc1, 0xf9, 0xfe, 0x0d, 0x7f, 0x97, 0xc6, 0x49,
// 0x0f, 0x83, 0x60, 0xcf, 0x71, 0xbb, 0xef, 0x15,
// 0x1f, 0x2e, 0x73, 0x30, 0x2b, 0xd0, 0x6f, 0x16,
// 0x90, 0xd6, 0x40, 0xb9, 0x6f, 0xb9, 0x44, 0x57,
// ])
// )
hash: try! BlockHash.fromString(hex: String.mockHashHex)
),
confirmationTime: UInt64(21)
),
transitively: "c1f9fe0d7f97c6490f8360cf71bbef151f2e73302bd06f1690d640b96fb94457"
// transitively: try! Txid.fromBytes(
// bytes: Data([
// 0xc1, 0xf9, 0xfe, 0x0d, 0x7f, 0x97, 0xc6, 0x49,
// 0x0f, 0x83, 0x60, 0xcf, 0x71, 0xbb, 0xef, 0x15,
// 0x1f, 0x2e, 0x73, 0x30, 0x2b, 0xd0, 0x6f, 0x16,
// 0x90, 0xd6, 0x40, 0xb9, 0x6f, 0xb9, 0x44, 0x57,
// ])
// )
transitively: try! Txid.fromString(hex: String.mockHashHex)
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ extension ChainPosition {
}
}
}

extension ChainPosition {
static let mock = ChainPosition.unconfirmed(timestamp: nil)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import BitcoinDevKit
import Foundation

extension Connection {
static func createConnection() throws -> Connection {
extension Persister {
static func createConnection() throws -> Persister {
let documentsDirectoryURL = URL.documentsDirectory
let walletDataDirectoryURL = documentsDirectoryURL.appendingPathComponent("wallet_data")

Expand All @@ -14,7 +14,7 @@ extension Connection {
try FileManager.default.removeOldFlatFileIfNeeded(at: documentsDirectoryURL)
let persistenceBackendPath = walletDataDirectoryURL.appendingPathComponent("wallet.sqlite")
.path
let connection = try Connection(path: persistenceBackendPath)
return connection
let persister = try Persister.newSqlite(path: persistenceBackendPath)
return persister
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@
//

import BitcoinDevKit
import Foundation

//#if DEBUG
extension LocalOutput {
static var mock = LocalOutput(
outpoint: OutPoint(
txid: "txid",
// txid: try! Txid.fromBytes(
// bytes: Data([
// 0xc1, 0xf9, 0xfe, 0x0d, 0x7f, 0x97, 0xc6, 0x49,
// 0x0f, 0x83, 0x60, 0xcf, 0x71, 0xbb, 0xef, 0x15,
// 0x1f, 0x2e, 0x73, 0x30, 0x2b, 0xd0, 0x6f, 0x16,
// 0x90, 0xd6, 0x40, 0xb9, 0x6f, 0xb9, 0x44, 0x57,
// ])
// ),
txid: try! Txid.fromString(hex: String.mockHashHex),
vout: UInt32(1)
),
txout: TxOut(
value: UInt64(1),
scriptPubkey: Script(rawOutputScript: [UInt8(1)])
value: .fromSat(satoshi: 1),
scriptPubkey: Script.init(rawOutputScript: Data([0x51]))
),
keychain: .external,
isSpent: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Outpoint+Extensions.swift
// BDKSwiftExampleWallet
//
// Created by Matthew Ramsden on 6/3/25.
//

import BitcoinDevKit
import Foundation

extension OutPoint: Hashable {
public static func == (lhs: OutPoint, rhs: OutPoint) -> Bool {
lhs.txid == rhs.txid && lhs.vout == rhs.vout
}

public func hash(into hasher: inout Hasher) {
hasher.combine(txid)
hasher.combine(vout)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
//

import BitcoinDevKit
import Foundation

extension Transaction {
var transactionID: String {
return self.computeTxid()
return "\(self.computeTxid())"
}
}

//#if DEBUG
extension Transaction {
static var mock = try? Transaction(
transactionBytes: String.mockTransactionHex.hexStringToByteArray()
transactionBytes: Data(String.mockTransactionHex.hexStringToByteArray())
)
}
//#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// TxDetails+Extensions.swift
// BDKSwiftExampleWallet
//
// Created by Matthew Ramsden on 6/11/25.
//

import BitcoinDevKit
import Foundation

extension TxDetails {
static let mock = TxDetails(
txid: .mock!,
sent: .mock,
received: .mock,
fee: nil,
feeRate: nil,
balanceDelta: Int64(0),
chainPosition: .mock,
tx: .mock!
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// TxId+Extensions.swift
// BDKSwiftExampleWallet
//
// Created by Matthew Ramsden on 6/11/25.
//

import BitcoinDevKit
import Foundation

extension Txid {
static let mock = try? Txid.fromBytes(
bytes: Data([
0xc1, 0xf9, 0xfe, 0x0d, 0x7f, 0x97, 0xc6, 0x49,
0x0f, 0x83, 0x60, 0xcf, 0x71, 0xbb, 0xef, 0x15,
0x1f, 0x2e, 0x73, 0x30, 0x2b, 0xd0, 0x6f, 0x16,
0x90, 0xd6, 0x40, 0xb9, 0x6f, 0xb9, 0x44, 0x57,
])
)
}
13 changes: 13 additions & 0 deletions BDKSwiftExampleWallet/Extensions/Int+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,16 @@ extension UInt64 {
return Date(timeIntervalSince1970: TimeInterval(self))
}
}

extension Int64 {
private static var numberFormatter: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal

return numberFormatter
}()

var delimiter: String {
return Int64.numberFormatter.string(from: NSNumber(value: self)) ?? ""
}
}
5 changes: 5 additions & 0 deletions BDKSwiftExampleWallet/Extensions/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@ extension String {
static var mockTransactionHex =
"01000000000101604350f234b3b4b5fde5513ff89d222e91cabf452182ba0b8d076cf08a3813a30100000000ffffffff0240420f0000000000225120c8b7757fff5ceb41908a43bfadf749afbb97b50ece0896e88f2cd14f90844d7b8df6731d00000000225120ff38f143374565d74648006f8aabef9dad548344549d8516177ff613e26f7d360140298823f597d3cb7f4934a5ef0b1814e2ca8caa9f9da0a0b59a73922d98f83ec62587add48e3fa0d0b7cf704b2fce0277e2a70f9aed8a41f2823b810b92e0421d00000000"
}
extension String {
static var mockHashHex: String {
"c1f9fe0d7f97c6490f8360cf71bbef151f2e73302bd06f1690d640b96fb94457"
}
}
//#endif
14 changes: 14 additions & 0 deletions BDKSwiftExampleWallet/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
}
},
"- %llu sats" : {
"extractionState" : "stale",
"localizations" : {
"fr" : {
"stringUnit" : {
Expand All @@ -82,6 +83,7 @@
}
},
"?" : {
"extractionState" : "stale",
"localizations" : {
"fr" : {
"stringUnit" : {
Expand Down Expand Up @@ -183,6 +185,16 @@
}
}
},
"%@%lld sats" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$@%2$lld sats"
}
}
}
},
"%lld Output%@" : {
"localizations" : {
"en" : {
Expand Down Expand Up @@ -254,6 +266,7 @@
}
},
"%llu sats" : {
"extractionState" : "stale",
"localizations" : {
"fr" : {
"stringUnit" : {
Expand All @@ -270,6 +283,7 @@
}
},
"+ %llu sats" : {
"extractionState" : "stale",
"localizations" : {
"fr" : {
"stringUnit" : {
Expand Down
Loading