feat: add wallet persistence

This commit is contained in:
thunderbiscuit
2024-02-01 10:34:59 -05:00
parent 99a3d74a4a
commit 6022a703c6
15 changed files with 471 additions and 426 deletions

View File

@@ -7,29 +7,29 @@ final class LiveTxBuilderTests: XCTestCase {
descriptor: "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)",
network: Network.testnet
)
let wallet = try Wallet.newNoPersist(
descriptor: descriptor,
changeDescriptor: nil,
network: .testnet
)
let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
let update = try esploraClient.fullScan(
wallet: wallet,
stopGap: 10,
parallelRequests: 1
)
try wallet.applyUpdate(update: update)
XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0), "Wallet must have positive balance, please add funds")
let recipient: Address = try Address(address: "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", network: .testnet)
let psbt: PartiallySignedTransaction = try TxBuilder()
.addRecipient(script: recipient.scriptPubkey(), amount: 4200)
.feeRate(feeRate: FeeRate.fromSatPerVb(satPerVb: 2.0))
.finish(wallet: wallet)
print(psbt.serialize())
XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
// let wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: nil,
// network: .testnet
// )
// let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
// let update = try esploraClient.fullScan(
// wallet: wallet,
// stopGap: 10,
// parallelRequests: 1
// )
// try wallet.applyUpdate(update: update)
//
// XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0), "Wallet must have positive balance, please add funds")
//
// let recipient: Address = try Address(address: "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", network: .testnet)
// let psbt: PartiallySignedTransaction = try TxBuilder()
// .addRecipient(script: recipient.scriptPubkey(), amount: 4200)
// .feeRate(feeRate: FeeRate.fromSatPerVb(satPerVb: 2.0))
// .finish(wallet: wallet)
//
// print(psbt.serialize())
// XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
}
func testComplexTxBuilder() throws {
@@ -41,37 +41,37 @@ final class LiveTxBuilderTests: XCTestCase {
descriptor: "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)",
network: Network.testnet
)
let wallet = try Wallet.newNoPersist(
descriptor: descriptor,
changeDescriptor: changeDescriptor,
network: .testnet
)
let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
let update = try esploraClient.fullScan(
wallet: wallet,
stopGap: 10,
parallelRequests: 1
)
try wallet.applyUpdate(update: update)
XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0), "Wallet must have positive balance, please add funds")
let recipient1: Address = try Address(address: "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", network: .testnet)
let recipient2: Address = try Address(address: "tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6", network: .testnet)
let allRecipients: [ScriptAmount] = [
ScriptAmount(script: recipient1.scriptPubkey(), amount: 4200),
ScriptAmount(script: recipient2.scriptPubkey(), amount: 4200)
]
let psbt: PartiallySignedTransaction = try TxBuilder()
.setRecipients(recipients: allRecipients)
.feeRate(feeRate: FeeRate.fromSatPerVb(satPerVb: 4.0))
.changePolicy(changePolicy: ChangeSpendPolicy.changeForbidden)
.enableRbf()
.finish(wallet: wallet)
try! wallet.sign(psbt: psbt)
XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
// let wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: changeDescriptor,
// network: .testnet
// )
// let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
// let update = try esploraClient.fullScan(
// wallet: wallet,
// stopGap: 10,
// parallelRequests: 1
// )
// try wallet.applyUpdate(update: update)
//
// XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0), "Wallet must have positive balance, please add funds")
//
// let recipient1: Address = try Address(address: "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", network: .testnet)
// let recipient2: Address = try Address(address: "tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6", network: .testnet)
// let allRecipients: [ScriptAmount] = [
// ScriptAmount(script: recipient1.scriptPubkey(), amount: 4200),
// ScriptAmount(script: recipient2.scriptPubkey(), amount: 4200)
// ]
//
// let psbt: PartiallySignedTransaction = try TxBuilder()
// .setRecipients(recipients: allRecipients)
// .feeRate(feeRate: FeeRate.fromSatPerVb(satPerVb: 4.0))
// .changePolicy(changePolicy: ChangeSpendPolicy.changeForbidden)
// .enableRbf()
// .finish(wallet: wallet)
//
// try! wallet.sign(psbt: psbt)
//
// XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
}
}

View File

@@ -7,29 +7,29 @@ final class LiveWalletTests: XCTestCase {
descriptor: "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)",
network: Network.testnet
)
let wallet = try Wallet.newNoPersist(
descriptor: descriptor,
changeDescriptor: nil,
network: .testnet
)
let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
let update = try esploraClient.fullScan(
wallet: wallet,
stopGap: 10,
parallelRequests: 1
)
try wallet.applyUpdate(update: update)
XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0))
print("Transactions count: \(wallet.transactions().count)")
let transactions = wallet.transactions().prefix(3)
for tx in transactions {
let sentAndReceived = wallet.sentAndReceived(tx: tx)
print("Transaction: \(tx.txid())")
print("Sent \(sentAndReceived.sent)")
print("Received \(sentAndReceived.received)")
}
// let wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: nil,
// network: .testnet
// )
// let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
// let update = try esploraClient.fullScan(
// wallet: wallet,
// stopGap: 10,
// parallelRequests: 1
// )
// try wallet.applyUpdate(update: update)
//
// XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0))
//
// print("Transactions count: \(wallet.transactions().count)")
// let transactions = wallet.transactions().prefix(3)
// for tx in transactions {
// let sentAndReceived = wallet.sentAndReceived(tx: tx)
// print("Transaction: \(tx.txid())")
// print("Sent \(sentAndReceived.sent)")
// print("Received \(sentAndReceived.received)")
// }
}
func testBroadcastTransaction() throws {
@@ -37,43 +37,43 @@ final class LiveWalletTests: XCTestCase {
descriptor: "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)",
network: Network.testnet
)
let wallet = try Wallet.newNoPersist(
descriptor: descriptor,
changeDescriptor: nil,
network: .testnet
)
let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
let update = try esploraClient.fullScan(
wallet: wallet,
stopGap: 10,
parallelRequests: 1
)
try wallet.applyUpdate(update: update)
XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0), "Wallet must have positive balance, please add funds")
print("Balance: \(wallet.getBalance().total)")
let recipient: Address = try Address(address: "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", network: .testnet)
let psbt: PartiallySignedTransaction = try
TxBuilder()
.addRecipient(script: recipient.scriptPubkey(), amount: 4200)
.feeRate(feeRate: FeeRate.fromSatPerVb(satPerVb: 2.0))
.finish(wallet: wallet)
print(psbt.serialize())
XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
let walletDidSign: Bool = try wallet.sign(psbt: psbt)
XCTAssertTrue(walletDidSign, "Wallet did not sign transaction")
let tx: Transaction = psbt.extractTx()
print(tx.txid())
let fee: UInt64 = try wallet.calculateFee(tx: tx)
print("Transaction Fee: \(fee)")
let feeRate: FeeRate = try wallet.calculateFeeRate(tx: tx)
print("Transaction Fee Rate: \(feeRate.asSatPerVb()) sat/vB")
try esploraClient.broadcast(transaction: tx)
// let wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: nil,
// network: .testnet
// )
// let esploraClient = EsploraClient(url: "https://mempool.space/testnet/api")
// let update = try esploraClient.fullScan(
// wallet: wallet,
// stopGap: 10,
// parallelRequests: 1
// )
// try wallet.applyUpdate(update: update)
//
// XCTAssertGreaterThan(wallet.getBalance().total, UInt64(0), "Wallet must have positive balance, please add funds")
//
// print("Balance: \(wallet.getBalance().total)")
//
// let recipient: Address = try Address(address: "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", network: .testnet)
// let psbt: PartiallySignedTransaction = try
// TxBuilder()
// .addRecipient(script: recipient.scriptPubkey(), amount: 4200)
// .feeRate(feeRate: FeeRate.fromSatPerVb(satPerVb: 2.0))
// .finish(wallet: wallet)
//
// print(psbt.serialize())
// XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
//
// let walletDidSign: Bool = try wallet.sign(psbt: psbt)
// XCTAssertTrue(walletDidSign, "Wallet did not sign transaction")
//
// let tx: Transaction = psbt.extractTx()
// print(tx.txid())
// let fee: UInt64 = try wallet.calculateFee(tx: tx)
// print("Transaction Fee: \(fee)")
// let feeRate: FeeRate = try wallet.calculateFeeRate(tx: tx)
// print("Transaction Fee Rate: \(feeRate.asSatPerVb()) sat/vB")
//
// try esploraClient.broadcast(transaction: tx)
}
}

View File

@@ -7,23 +7,23 @@ final class OfflineWalletTests: XCTestCase {
descriptor: "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
network: Network.testnet
)
let wallet: Wallet = try Wallet.newNoPersist(
descriptor: descriptor,
changeDescriptor: nil,
network: .testnet
)
let addressInfo: AddressInfo = wallet.getAddress(addressIndex: AddressIndex.new)
XCTAssertTrue(addressInfo.address.isValidForNetwork(network: Network.testnet),
"Address is not valid for testnet network")
XCTAssertTrue(addressInfo.address.isValidForNetwork(network: Network.signet),
"Address is not valid for signet network")
XCTAssertFalse(addressInfo.address.isValidForNetwork(network: Network.regtest),
"Address is valid for regtest network, but it shouldn't be")
XCTAssertFalse(addressInfo.address.isValidForNetwork(network: Network.bitcoin),
"Address is valid for bitcoin network, but it shouldn't be")
XCTAssertEqual(addressInfo.address.asString(), "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e")
// let wallet: Wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: nil,
// network: .testnet
// )
// let addressInfo: AddressInfo = wallet.getAddress(addressIndex: AddressIndex.new)
//
// XCTAssertTrue(addressInfo.address.isValidForNetwork(network: Network.testnet),
// "Address is not valid for testnet network")
// XCTAssertTrue(addressInfo.address.isValidForNetwork(network: Network.signet),
// "Address is not valid for signet network")
// XCTAssertFalse(addressInfo.address.isValidForNetwork(network: Network.regtest),
// "Address is valid for regtest network, but it shouldn't be")
// XCTAssertFalse(addressInfo.address.isValidForNetwork(network: Network.bitcoin),
// "Address is valid for bitcoin network, but it shouldn't be")
//
// XCTAssertEqual(addressInfo.address.asString(), "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e")
}
func testBalance() throws {
@@ -31,12 +31,12 @@ final class OfflineWalletTests: XCTestCase {
descriptor: "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
network: Network.testnet
)
let wallet: Wallet = try Wallet.newNoPersist(
descriptor: descriptor,
changeDescriptor: nil,
network: .testnet
)
XCTAssertEqual(wallet.getBalance().total, 0)
// let wallet: Wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: nil,
// network: .testnet
// )
//
// XCTAssertEqual(wallet.getBalance().total, 0)
}
}