From 69d1837b0aec5d0f963b89d13792e06129cc3010 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Thu, 8 Feb 2024 16:02:15 -0500 Subject: [PATCH] test: fix tests to account for persistence --- .../org/bitcoindevkit/LiveTxBuilderTest.kt | 24 +++- .../org/bitcoindevkit/LiveWalletTest.kt | 22 ++- .../org/bitcoindevkit/OfflineWalletTest.kt | 20 ++- bdk-jvm/lib/build.gradle.kts | 6 +- .../org/bitcoindevkit/LiveTxBuilderTest.kt | 100 +++++++------ .../org/bitcoindevkit/LiveWalletTest.kt | 121 +++++++++------- .../org/bitcoindevkit/OfflineWalletTest.kt | 69 +++++---- bdk-python/tests/test_live_tx_builder.py | 120 ++++++++-------- bdk-python/tests/test_live_wallet.py | 121 ++++++++-------- bdk-python/tests/test_offline_descriptor.py | 2 +- bdk-python/tests/test_offline_wallet.py | 61 ++++---- .../LiveTxBuilderTests.swift | 123 +++++++++------- .../BitcoinDevKitTests/LiveWalletTests.swift | 135 ++++++++++-------- .../OfflineWalletTests.swift | 61 ++++---- 14 files changed, 566 insertions(+), 419 deletions(-) diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt index 6943878a..874a5b3b 100644 --- a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt +++ b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt @@ -1,17 +1,31 @@ package org.bitcoindevkit -import org.junit.Test import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Test import org.junit.runner.RunWith +import java.io.File +import kotlin.test.AfterTest import kotlin.test.assertTrue @RunWith(AndroidJUnit4::class) class LiveTxBuilderTest { + private val persistenceFilePath = InstrumentationRegistry + .getInstrumentation().targetContext.filesDir.path + "/bdk_persistence.db" + + @AfterTest + fun cleanup() { + val file = File(persistenceFilePath) + if (file.exists()) { + file.delete() + } + } + @Test fun testTxBuilder() { val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) - val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET) - val esploraClient = EsploraClient("https://mempool.space/testnet/api") + val wallet = Wallet(descriptor, null, persistenceFilePath, Network.TESTNET) + val esploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") val update = esploraClient.fullScan(wallet, 10uL, 1uL) wallet.applyUpdate(update) println("Balance: ${wallet.getBalance().total}") @@ -32,8 +46,8 @@ class LiveTxBuilderTest { fun complexTxBuilder() { val externalDescriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) val changeDescriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", Network.TESTNET) - val wallet = Wallet.newNoPersist(externalDescriptor, changeDescriptor, Network.TESTNET) - val esploraClient = EsploraClient("https://mempool.space/testnet/api") + val wallet = Wallet(externalDescriptor, changeDescriptor, persistenceFilePath, Network.TESTNET) + val esploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") val update = esploraClient.fullScan(wallet, 10uL, 1uL) wallet.applyUpdate(update) println("Balance: ${wallet.getBalance().total}") diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveWalletTest.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveWalletTest.kt index f514e695..47bf82b6 100644 --- a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveWalletTest.kt +++ b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveWalletTest.kt @@ -2,16 +2,30 @@ package org.bitcoindevkit import org.junit.Test import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import org.junit.runner.RunWith +import java.io.File +import kotlin.test.AfterTest import kotlin.test.assertTrue @RunWith(AndroidJUnit4::class) class LiveWalletTest { + private val persistenceFilePath = InstrumentationRegistry + .getInstrumentation().targetContext.filesDir.path + "/bdk_persistence.db" + + @AfterTest + fun cleanup() { + val file = File(persistenceFilePath) + if (file.exists()) { + file.delete() + } + } + @Test fun testSyncedBalance() { val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) - val wallet: Wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET) - val esploraClient: EsploraClient = EsploraClient("https://mempool.space/testnet/api") + val wallet: Wallet = Wallet(descriptor, null, persistenceFilePath, Network.TESTNET) + val esploraClient: EsploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") val update = esploraClient.fullScan(wallet, 10uL, 1uL) wallet.applyUpdate(update) println("Balance: ${wallet.getBalance().total}") @@ -33,8 +47,8 @@ class LiveWalletTest { @Test fun testBroadcastTransaction() { val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) - val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET) - val esploraClient = EsploraClient("https://mempool.space/testnet/api") + val wallet = Wallet(descriptor, null, persistenceFilePath, Network.TESTNET) + val esploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") val update = esploraClient.fullScan(wallet, 10uL, 1uL) wallet.applyUpdate(update) diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/OfflineWalletTest.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/OfflineWalletTest.kt index cbdfbc14..4f66969f 100644 --- a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/OfflineWalletTest.kt +++ b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/OfflineWalletTest.kt @@ -5,10 +5,24 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.assertFalse import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import org.junit.runner.RunWith +import java.io.File +import kotlin.test.AfterTest @RunWith(AndroidJUnit4::class) class OfflineWalletTest { + private val persistenceFilePath = InstrumentationRegistry + .getInstrumentation().targetContext.filesDir.path + "/bdk_persistence.db" + + @AfterTest + fun cleanup() { + val file = File(persistenceFilePath) + if (file.exists()) { + file.delete() + } + } + @Test fun testDescriptorBip86() { val mnemonic: Mnemonic = Mnemonic(WordCount.WORDS12) @@ -24,9 +38,10 @@ class OfflineWalletTest { "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET ) - val wallet: Wallet = Wallet.newNoPersist( + val wallet: Wallet = Wallet( descriptor, null, + persistenceFilePath, Network.TESTNET ) val addressInfo: AddressInfo = wallet.getAddress(AddressIndex.New) @@ -48,9 +63,10 @@ class OfflineWalletTest { "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET ) - val wallet: Wallet = Wallet.newNoPersist( + val wallet: Wallet = Wallet( descriptor, null, + persistenceFilePath, Network.TESTNET ) diff --git a/bdk-jvm/lib/build.gradle.kts b/bdk-jvm/lib/build.gradle.kts index 859cc6c9..52ee2414 100644 --- a/bdk-jvm/lib/build.gradle.kts +++ b/bdk-jvm/lib/build.gradle.kts @@ -61,8 +61,10 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7") implementation("net.java.dev.jna:jna:5.14.0") api("org.slf4j:slf4j-api:1.7.30") - testImplementation("junit:junit:4.13.2") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2") + + // testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1") + // testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1") + // testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2") testImplementation("ch.qos.logback:logback-classic:1.2.3") testImplementation("ch.qos.logback:logback-core:1.2.3") } diff --git a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt index fa4fa959..8b8df554 100644 --- a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt +++ b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt @@ -1,61 +1,73 @@ package org.bitcoindevkit -import kotlin.test.Ignore +import java.io.File +import kotlin.test.AfterTest import kotlin.test.Test import kotlin.test.assertTrue class LiveTxBuilderTest { - @Ignore("The Esplora client's fullScan method requires a Wallet instead of a WalletNoPersist.") + private val persistenceFilePath = run { + val currentDirectory = System.getProperty("user.dir") + "$currentDirectory/bdk_persistence.db" + } + + @AfterTest + fun cleanup() { + val file = File(persistenceFilePath) + if (file.exists()) { + file.delete() + } + } + @Test fun testTxBuilder() { val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) - // val wallet = WalletNoPersist(descriptor, null, Network.TESTNET) - val esploraClient = EsploraClient("https://mempool.space/testnet/api") - // val update = esploraClient.fullScan(wallet, 10uL, 1uL) - // wallet.applyUpdate(update) - // println("Balance: ${wallet.getBalance().total}") - // - // assert(wallet.getBalance().total > 0uL) - // - // val recipient: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET) - // val psbt: PartiallySignedTransaction = TxBuilder() - // .addRecipient(recipient.scriptPubkey(), 4200uL) - // .feeRate(FeeRate.fromSatPerVb(2.0f)) - // .finish(wallet) - // - // println(psbt.serialize()) - // - // assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'") + val wallet = Wallet(descriptor, null, persistenceFilePath, Network.TESTNET) + val esploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") + val update = esploraClient.fullScan(wallet, 10uL, 1uL) + wallet.applyUpdate(update) + println("Balance: ${wallet.getBalance().total}") + + assert(wallet.getBalance().total > 0uL) + + val recipient: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET) + val psbt: PartiallySignedTransaction = TxBuilder() + .addRecipient(recipient.scriptPubkey(), 4200uL) + .feeRate(FeeRate.fromSatPerVb(2.0f)) + .finish(wallet) + + println(psbt.serialize()) + + assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'") } - @Ignore("The Esplora client's fullScan method requires a Wallet instead of a WalletNoPersist.") @Test fun complexTxBuilder() { val externalDescriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) val changeDescriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", Network.TESTNET) - // val wallet = WalletNoPersist(externalDescriptor, changeDescriptor, Network.TESTNET) - // val esploraClient = EsploraClient("https://mempool.space/testnet/api") - // val update = esploraClient.fullScan(wallet, 10uL, 1uL) - // wallet.applyUpdate(update) - // println("Balance: ${wallet.getBalance().total}") - // - // assert(wallet.getBalance().total > 0uL) - // - // val recipient1: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET) - // val recipient2: Address = Address("tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6", Network.TESTNET) - // val allRecipients: List = listOf( - // ScriptAmount(recipient1.scriptPubkey(), 4200uL), - // ScriptAmount(recipient2.scriptPubkey(), 4200uL), - // ) - // - // val psbt: PartiallySignedTransaction = TxBuilder() - // .setRecipients(allRecipients) - // .feeRate(FeeRate.fromSatPerVb(4.0f)) - // .changePolicy(ChangeSpendPolicy.CHANGE_FORBIDDEN) - // .enableRbf() - // .finish(wallet) - // - // wallet.sign(psbt) - // assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'") + val wallet = Wallet(externalDescriptor, changeDescriptor, persistenceFilePath, Network.TESTNET) + val esploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") + val update = esploraClient.fullScan(wallet, 10uL, 1uL) + wallet.applyUpdate(update) + println("Balance: ${wallet.getBalance().total}") + + assert(wallet.getBalance().total > 0uL) + + val recipient1: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET) + val recipient2: Address = Address("tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6", Network.TESTNET) + val allRecipients: List = listOf( + ScriptAmount(recipient1.scriptPubkey(), 4200uL), + ScriptAmount(recipient2.scriptPubkey(), 4200uL), + ) + + val psbt: PartiallySignedTransaction = TxBuilder() + .setRecipients(allRecipients) + .feeRate(FeeRate.fromSatPerVb(4.0f)) + .changePolicy(ChangeSpendPolicy.CHANGE_FORBIDDEN) + .enableRbf() + .finish(wallet) + + wallet.sign(psbt) + assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'") } } diff --git a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt index 0870057e..7d2c5e30 100644 --- a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt +++ b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt @@ -1,71 +1,84 @@ package org.bitcoindevkit -import kotlin.test.Ignore +import java.io.File +import kotlin.test.AfterTest import kotlin.test.Test import kotlin.test.assertTrue class LiveWalletTest { - @Ignore("The Esplora client's fullScan method requires a Wallet instead of a WalletNoPersist.") + private val persistenceFilePath = run { + val currentDirectory = System.getProperty("user.dir") + "$currentDirectory/bdk_persistence.db" + } + + @AfterTest + fun cleanup() { + val file = File(persistenceFilePath) + if (file.exists()) { + file.delete() + } + } + @Test fun testSyncedBalance() { val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) - // val wallet: WalletNoPersist = WalletNoPersist(descriptor, null, Network.TESTNET) - val esploraClient: EsploraClient = EsploraClient("https://mempool.space/testnet/api") + val wallet: Wallet = Wallet(descriptor, null, persistenceFilePath, Network.TESTNET) + val esploraClient: EsploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") + // val esploraClient: EsploraClient = EsploraClient("https://mempool.space/testnet/api") // val esploraClient = EsploraClient("https://blockstream.info/testnet/api") - // val update = esploraClient.fullScan(wallet, 10uL, 1uL) - // wallet.applyUpdate(update) - // println("Balance: ${wallet.getBalance().total}") - // - // assert(wallet.getBalance().total > 0uL) - // - // println("Transactions count: ${wallet.transactions().count()}") - // val transactions = wallet.transactions().take(3) - // for (tx in transactions) { - // val sentAndReceived = wallet.sentAndReceived(tx) - // println("Transaction: ${tx.txid()}") - // println("Sent ${sentAndReceived.sent}") - // println("Received ${sentAndReceived.received}") - // } + val update = esploraClient.fullScan(wallet, 10uL, 1uL) + wallet.applyUpdate(update) + println("Balance: ${wallet.getBalance().total}") + + assert(wallet.getBalance().total > 0uL) + + println("Transactions count: ${wallet.transactions().count()}") + val transactions = wallet.transactions().take(3) + for (tx in transactions) { + val sentAndReceived = wallet.sentAndReceived(tx) + println("Transaction: ${tx.txid()}") + println("Sent ${sentAndReceived.sent}") + println("Received ${sentAndReceived.received}") + } } - @Ignore("The Esplora client's fullScan method requires a Wallet instead of a WalletNoPersist.") @Test fun testBroadcastTransaction() { val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) - // val wallet = WalletNoPersist(descriptor, null, Network.TESTNET) - val esploraClient = EsploraClient("https://mempool.space/testnet/api") - // val update = esploraClient.fullScan(wallet, 10uL, 1uL) - // - // wallet.applyUpdate(update) - // println("Balance: ${wallet.getBalance().total}") - // println("New address: ${wallet.getAddress(AddressIndex.New).address.asString()}") - // - // assert(wallet.getBalance().total > 0uL) { - // "Wallet balance must be greater than 0! Please send funds to ${wallet.getAddress(AddressIndex.New).address} and try again." - // } - // - // val recipient: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET) - // - // val psbt: PartiallySignedTransaction = TxBuilder() - // .addRecipient(recipient.scriptPubkey(), 4200uL) - // .feeRate(FeeRate.fromSatPerVb(2.0f)) - // .finish(wallet) - // - // println(psbt.serialize()) - // assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'") - // - // val walletDidSign = wallet.sign(psbt) - // assertTrue(walletDidSign) - // - // val tx: Transaction = psbt.extractTx() - // println("Txid is: ${tx.txid()}") - // - // val txFee: ULong = wallet.calculateFee(tx) - // println("Tx fee is: ${txFee}") - // - // val feeRate: FeeRate = wallet.calculateFeeRate(tx) - // println("Tx fee rate is: ${feeRate.asSatPerVb()} sat/vB") - // - // esploraClient.broadcast(tx) + val wallet: Wallet = Wallet(descriptor, null, persistenceFilePath, Network.TESTNET) + val esploraClient = EsploraClient("https://esplora.testnet.kuutamo.cloud/") + val update = esploraClient.fullScan(wallet, 10uL, 1uL) + + wallet.applyUpdate(update) + println("Balance: ${wallet.getBalance().total}") + println("New address: ${wallet.getAddress(AddressIndex.New).address.asString()}") + + assert(wallet.getBalance().total > 0uL) { + "Wallet balance must be greater than 0! Please send funds to ${wallet.getAddress(AddressIndex.New).address} and try again." + } + + val recipient: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET) + + val psbt: PartiallySignedTransaction = TxBuilder() + .addRecipient(recipient.scriptPubkey(), 4200uL) + .feeRate(FeeRate.fromSatPerVb(2.0f)) + .finish(wallet) + + println(psbt.serialize()) + assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'") + + val walletDidSign = wallet.sign(psbt) + assertTrue(walletDidSign) + + val tx: Transaction = psbt.extractTx() + println("Txid is: ${tx.txid()}") + + val txFee: ULong = wallet.calculateFee(tx) + println("Tx fee is: ${txFee}") + + val feeRate: FeeRate = wallet.calculateFeeRate(tx) + println("Tx fee rate is: ${feeRate.asSatPerVb()} sat/vB") + + esploraClient.broadcast(tx) } } diff --git a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/OfflineWalletTest.kt b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/OfflineWalletTest.kt index 51d687a5..f66ad242 100644 --- a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/OfflineWalletTest.kt +++ b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/OfflineWalletTest.kt @@ -1,11 +1,26 @@ package org.bitcoindevkit +import java.io.File +import kotlin.test.AfterTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.assertFalse class OfflineWalletTest { + private val persistenceFilePath = run { + val currentDirectory = System.getProperty("user.dir") + "$currentDirectory/bdk_persistence.db" + } + + @AfterTest + fun cleanup() { + val file = File(persistenceFilePath) + if (file.exists()) { + file.delete() + } + } + @Test fun testDescriptorBip86() { val mnemonic: Mnemonic = Mnemonic(WordCount.WORDS12) @@ -21,22 +36,23 @@ class OfflineWalletTest { "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET ) - // val wallet: Wallet = WalletNoPersist( - // descriptor, - // null, - // Network.TESTNET - // ) - // val addressInfo: AddressInfo = wallet.getAddress(AddressIndex.New) - // - // assertTrue(addressInfo.address.isValidForNetwork(Network.TESTNET), "Address is not valid for testnet network") - // assertTrue(addressInfo.address.isValidForNetwork(Network.SIGNET), "Address is not valid for signet network") - // assertFalse(addressInfo.address.isValidForNetwork(Network.REGTEST), "Address is valid for regtest network, but it shouldn't be") - // assertFalse(addressInfo.address.isValidForNetwork(Network.BITCOIN), "Address is valid for bitcoin network, but it shouldn't be") - // - // assertEquals( - // expected = "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", - // actual = addressInfo.address.asString() - // ) + val wallet: Wallet = Wallet( + descriptor, + null, + persistenceFilePath, + Network.TESTNET + ) + val addressInfo: AddressInfo = wallet.getAddress(AddressIndex.New) + + assertTrue(addressInfo.address.isValidForNetwork(Network.TESTNET), "Address is not valid for testnet network") + assertTrue(addressInfo.address.isValidForNetwork(Network.SIGNET), "Address is not valid for signet network") + assertFalse(addressInfo.address.isValidForNetwork(Network.REGTEST), "Address is valid for regtest network, but it shouldn't be") + assertFalse(addressInfo.address.isValidForNetwork(Network.BITCOIN), "Address is valid for bitcoin network, but it shouldn't be") + + assertEquals( + expected = "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", + actual = addressInfo.address.asString() + ) } @Test @@ -45,15 +61,16 @@ class OfflineWalletTest { "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET ) - // val wallet: WalletNoPersist = WalletNoPersist( - // descriptor, - // null, - // Network.TESTNET - // ) - - // assertEquals( - // expected = 0uL, - // actual = wallet.getBalance().total - // ) + val wallet: Wallet = Wallet( + descriptor, + null, + persistenceFilePath, + Network.TESTNET + ) + + assertEquals( + expected = 0uL, + actual = wallet.getBalance().total + ) } } diff --git a/bdk-python/tests/test_live_tx_builder.py b/bdk-python/tests/test_live_tx_builder.py index 7c010c5b..792d929f 100644 --- a/bdk-python/tests/test_live_tx_builder.py +++ b/bdk-python/tests/test_live_tx_builder.py @@ -1,37 +1,42 @@ import bdkpython as bdk import unittest +import os -class TestLiveTxBuilder(unittest.TestCase): +class LiveTxBuilderTest(unittest.TestCase): + + def tearDown(self) -> None: + if os.path.exists("./bdk_persistence.db"): + os.remove("./bdk_persistence.db") def test_tx_builder(self): descriptor: bdk.Descriptor = bdk.Descriptor( "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", bdk.Network.TESTNET ) - # wallet: bdk.Wallet = bdk.Wallet.new_no_persist( - # descriptor, - # None, - # bdk.Network.TESTNET - # ) - # esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://mempool.space/testnet/api") - # update = esploraClient.full_scan( - # wallet = wallet, - # stop_gap = 10, - # parallel_requests = 1 - # ) - # wallet.apply_update(update) - # - # self.assertGreater(wallet.get_balance().total, 0) - # - # recipient = bdk.Address( - # address = "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", - # network = bdk.Network.TESTNET - # ) - # - # psbt = bdk.TxBuilder().add_recipient(script=recipient.script_pubkey(), amount=4200).fee_rate(fee_rate=bdk.FeeRate.from_sat_per_vb(2.0)).finish(wallet) - # # print(psbt.serialize()) - # - # self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi") + wallet: bdk.Wallet = bdk.Wallet( + descriptor, + None, + "./bdk_persistence.db", + bdk.Network.TESTNET + ) + esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://esplora.testnet.kuutamo.cloud/") + update = esploraClient.full_scan( + wallet = wallet, + stop_gap = 10, + parallel_requests = 1 + ) + wallet.apply_update(update) + + self.assertGreater(wallet.get_balance().total, 0) + + recipient = bdk.Address( + address = "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", + network = bdk.Network.TESTNET + ) + + psbt = bdk.TxBuilder().add_recipient(script=recipient.script_pubkey(), amount=4200).fee_rate(fee_rate=bdk.FeeRate.from_sat_per_vb(2.0)).finish(wallet) + + self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi") def complex_tx_builder(self): descriptor: bdk.Descriptor = bdk.Descriptor( @@ -42,38 +47,39 @@ def complex_tx_builder(self): "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)", bdk.Network.TESTNET ) - # wallet: bdk.Wallet = bdk.Wallet.new_no_persist( - # descriptor, - # change_descriptor, - # bdk.Network.TESTNET - # ) - # esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://mempool.space/testnet/api") - # update = esploraClient.full_scan( - # wallet = wallet, - # stop_gap = 10, - # parallel_requests = 1 - # ) - # wallet.apply_update(update) - # - # self.assertGreater(wallet.get_balance().total, 0) - # - # recipient1 = bdk.Address( - # address = "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", - # network = bdk.Network.TESTNET - # ) - # recipient2 = bdk.Address( - # address = "tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6", - # network = bdk.Network.TESTNET - # ) - # all_recipients = list( - # bdk.ScriptAmount(recipient1.script_pubkey, 4200), - # bdk.ScriptAmount(recipient2.script_pubkey, 4200) - # ) - # - # psbt: bdk.PartiallySignedTransaction = bdk.TxBuilder().add_recipient(script=recipient.script_pubkey(), amount=4200).fee_rate(fee_rate=bdk.FeeRate.from_sat_per_vb(2.0)).finish(wallet) - # wallet.sign(psbt) - # - # self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi") + wallet: bdk.Wallet = bdk.Wallet( + descriptor, + change_descriptor, + "./bdk_persistence.db", + bdk.Network.TESTNET + ) + esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://esplora.testnet.kuutamo.cloud/") + update = esploraClient.full_scan( + wallet = wallet, + stop_gap = 10, + parallel_requests = 1 + ) + wallet.apply_update(update) + + self.assertGreater(wallet.get_balance().total, 0) + + recipient1 = bdk.Address( + address = "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", + network = bdk.Network.TESTNET + ) + recipient2 = bdk.Address( + address = "tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6", + network = bdk.Network.TESTNET + ) + all_recipients = list( + bdk.ScriptAmount(recipient1.script_pubkey, 4200), + bdk.ScriptAmount(recipient2.script_pubkey, 4200) + ) + + psbt: bdk.PartiallySignedTransaction = bdk.TxBuilder().set_recipients(all_recipients).fee_rate(fee_rate=bdk.FeeRate.from_sat_per_vb(2.0)).enable_rbf().finish(wallet) + wallet.sign(psbt) + + self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi") if __name__ == '__main__': diff --git a/bdk-python/tests/test_live_wallet.py b/bdk-python/tests/test_live_wallet.py index 09bbccbc..a2945973 100644 --- a/bdk-python/tests/test_live_wallet.py +++ b/bdk-python/tests/test_live_wallet.py @@ -1,35 +1,41 @@ import bdkpython as bdk import unittest +import os -class TestLiveWallet(unittest.TestCase): +class LiveWalletTest(unittest.TestCase): + + def tearDown(self) -> None: + if os.path.exists("./bdk_persistence.db"): + os.remove("./bdk_persistence.db") def test_synced_balance(self): descriptor: bdk.Descriptor = bdk.Descriptor( "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", bdk.Network.TESTNET ) - # wallet: bdk.Wallet = bdk.Wallet.new_no_persist( - # descriptor, - # None, - # bdk.Network.TESTNET - # ) - # esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://mempool.space/testnet/api") - # update = esploraClient.full_scan( - # wallet = wallet, - # stop_gap = 10, - # parallel_requests = 1 - # ) - # wallet.apply_update(update) - # - # self.assertGreater(wallet.get_balance().total, 0) - # - # print(f"Transactions count: {len(wallet.transactions())}") - # transactions = wallet.transactions()[:3] - # for tx in transactions: - # sent_and_received = wallet.sent_and_received(tx) - # print(f"Transaction: {tx.txid()}") - # print(f"Sent {sent_and_received.sent}") - # print(f"Received {sent_and_received.received}") + wallet: bdk.Wallet = bdk.Wallet( + descriptor, + None, + "./bdk_persistence.db", + bdk.Network.TESTNET + ) + esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://esplora.testnet.kuutamo.cloud/") + update = esploraClient.full_scan( + wallet = wallet, + stop_gap = 10, + parallel_requests = 1 + ) + wallet.apply_update(update) + + self.assertGreater(wallet.get_balance().total, 0) + + print(f"Transactions count: {len(wallet.transactions())}") + transactions = wallet.transactions()[:3] + for tx in transactions: + sent_and_received = wallet.sent_and_received(tx) + print(f"Transaction: {tx.txid()}") + print(f"Sent {sent_and_received.sent}") + print(f"Received {sent_and_received.received}") def test_broadcast_transaction(self): @@ -37,40 +43,41 @@ def test_broadcast_transaction(self): "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", bdk.Network.TESTNET ) - # wallet: bdk.Wallet = bdk.Wallet.new_no_persist( - # descriptor, - # None, - # bdk.Network.TESTNET - # ) - # esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://mempool.space/testnet/api") - # update = esploraClient.full_scan( - # wallet = wallet, - # stop_gap = 10, - # parallel_requests = 1 - # ) - # wallet.apply_update(update) - # - # self.assertGreater(wallet.get_balance().total, 0) - # - # recipient = bdk.Address( - # address = "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", - # network = bdk.Network.TESTNET - # ) - # - # psbt = bdk.TxBuilder().add_recipient(script=recipient.script_pubkey(), amount=4200).fee_rate(fee_rate=bdk.FeeRate.from_sat_per_vb(2.0)).finish(wallet) - # # print(psbt.serialize()) - # self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi") - # - # walletDidSign = wallet.sign(psbt) - # self.assertTrue(walletDidSign) - # tx = psbt.extract_tx() - # print(f"Transaction Id: {tx.txid}") - # fee = wallet.calculate_fee(tx) - # print(f"Transaction Fee: {fee}") - # fee_rate = wallet.calculate_fee_rate(tx) - # print(f"Transaction Fee Rate: {fee_rate.as_sat_per_vb()} sat/vB") - # - # esploraClient.broadcast(tx) + wallet: bdk.Wallet = bdk.Wallet( + descriptor, + None, + "./bdk_persistence.db", + bdk.Network.TESTNET + ) + esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://esplora.testnet.kuutamo.cloud/") + update = esploraClient.full_scan( + wallet = wallet, + stop_gap = 10, + parallel_requests = 1 + ) + wallet.apply_update(update) + + self.assertGreater(wallet.get_balance().total, 0) + + recipient = bdk.Address( + address = "tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", + network = bdk.Network.TESTNET + ) + + psbt = bdk.TxBuilder().add_recipient(script=recipient.script_pubkey(), amount=4200).fee_rate(fee_rate=bdk.FeeRate.from_sat_per_vb(2.0)).finish(wallet) + # print(psbt.serialize()) + self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi") + + walletDidSign = wallet.sign(psbt) + self.assertTrue(walletDidSign) + tx = psbt.extract_tx() + print(f"Transaction Id: {tx.txid()}") + fee = wallet.calculate_fee(tx) + print(f"Transaction Fee: {fee}") + fee_rate = wallet.calculate_fee_rate(tx) + print(f"Transaction Fee Rate: {fee_rate.as_sat_per_vb()} sat/vB") + + esploraClient.broadcast(tx) if __name__ == '__main__': diff --git a/bdk-python/tests/test_offline_descriptor.py b/bdk-python/tests/test_offline_descriptor.py index 15f49180..9c35023c 100644 --- a/bdk-python/tests/test_offline_descriptor.py +++ b/bdk-python/tests/test_offline_descriptor.py @@ -1,7 +1,7 @@ import bdkpython as bdk import unittest -class TestSimpleWallet(unittest.TestCase): +class OfflineDescriptorTest(unittest.TestCase): def test_descriptor_bip86(self): mnemonic: bdk.Mnemonic = bdk.Mnemonic.from_string("space echo position wrist orient erupt relief museum myself grain wisdom tumble") diff --git a/bdk-python/tests/test_offline_wallet.py b/bdk-python/tests/test_offline_wallet.py index c8e9f049..f9e607c6 100644 --- a/bdk-python/tests/test_offline_wallet.py +++ b/bdk-python/tests/test_offline_wallet.py @@ -1,39 +1,46 @@ import bdkpython as bdk import unittest +import os -class TestSimpleWallet(unittest.TestCase): +class OfflineWalletTest(unittest.TestCase): + def tearDown(self) -> None: + if os.path.exists("./bdk_persistence.db"): + os.remove("./bdk_persistence.db") + def test_new_address(self): descriptor: bdk.Descriptor = bdk.Descriptor( "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", bdk.Network.TESTNET ) - # wallet: Wallet = bdk.Wallet.new_no_persist( - # descriptor, - # None, - # bdk.Network.TESTNET - # ) - # address_info: bdk.AddressInfo = wallet.get_address(bdk.AddressIndex.NEW()) - # - # self.assertTrue(address_info.address.is_valid_for_network(bdk.Network.TESTNET), "Address is not valid for testnet network") - # self.assertTrue(address_info.address.is_valid_for_network(bdk.Network.SIGNET), "Address is not valid for signet network") - # self.assertFalse(address_info.address.is_valid_for_network(bdk.Network.REGTEST), "Address is valid for regtest network, but it shouldn't be") - # self.assertFalse(address_info.address.is_valid_for_network(bdk.Network.BITCOIN), "Address is valid for bitcoin network, but it shouldn't be") - # - # self.assertEqual("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address_info.address.as_string()) - # - # def test_balance(self): - # descriptor: bdk.Descriptor = bdk.Descriptor( - # "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", - # bdk.Network.TESTNET - # ) - # wallet: bdk.Wallet = bdk.Wallet.new_no_persist( - # descriptor, - # None, - # bdk.Network.TESTNET - # ) - # - # self.assertEqual(wallet.get_balance().total, 0) + wallet: Wallet = bdk.Wallet( + descriptor, + None, + "./bdk_persistence.db", + bdk.Network.TESTNET + ) + address_info: bdk.AddressInfo = wallet.get_address(bdk.AddressIndex.NEW()) + + self.assertTrue(address_info.address.is_valid_for_network(bdk.Network.TESTNET), "Address is not valid for testnet network") + self.assertTrue(address_info.address.is_valid_for_network(bdk.Network.SIGNET), "Address is not valid for signet network") + self.assertFalse(address_info.address.is_valid_for_network(bdk.Network.REGTEST), "Address is valid for regtest network, but it shouldn't be") + self.assertFalse(address_info.address.is_valid_for_network(bdk.Network.BITCOIN), "Address is valid for bitcoin network, but it shouldn't be") + + self.assertEqual("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address_info.address.as_string()) + + def test_balance(self): + descriptor: bdk.Descriptor = bdk.Descriptor( + "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", + bdk.Network.TESTNET + ) + wallet: bdk.Wallet = bdk.Wallet( + descriptor, + None, + "./bdk_persistence.db", + bdk.Network.TESTNET + ) + + self.assertEqual(wallet.get_balance().total, 0) if __name__ == '__main__': unittest.main() diff --git a/bdk-swift/Tests/BitcoinDevKitTests/LiveTxBuilderTests.swift b/bdk-swift/Tests/BitcoinDevKitTests/LiveTxBuilderTests.swift index 9fe44bed..691a339a 100644 --- a/bdk-swift/Tests/BitcoinDevKitTests/LiveTxBuilderTests.swift +++ b/bdk-swift/Tests/BitcoinDevKitTests/LiveTxBuilderTests.swift @@ -2,34 +2,46 @@ import XCTest @testable import BitcoinDevKit final class LiveTxBuilderTests: XCTestCase { + override func tearDownWithError() throws { + let fileManager = FileManager.default + let dbFileName = "bdk_persistence.db" + let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! + let dbFilePath: URL = documentDirectory.appendingPathComponent(dbFileName) + + if fileManager.fileExists(atPath: dbFilePath.path) { + try fileManager.removeItem(at: dbFilePath) + } + } + func testTxBuilder() throws { let descriptor = try Descriptor( 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( + descriptor: descriptor, + changeDescriptor: nil, + persistenceBackendPath: "bdk_persistence.db", + network: .testnet + ) + let esploraClient = EsploraClient(url: "https://esplora.testnet.kuutamo.cloud/") + 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 +53,38 @@ 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( + descriptor: descriptor, + changeDescriptor: changeDescriptor, + persistenceBackendPath: "bdk_persistence.db", + network: .testnet + ) + let esploraClient = EsploraClient(url: "https://esplora.testnet.kuutamo.cloud/") + 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") } } diff --git a/bdk-swift/Tests/BitcoinDevKitTests/LiveWalletTests.swift b/bdk-swift/Tests/BitcoinDevKitTests/LiveWalletTests.swift index bf4f2c58..a38f0a33 100644 --- a/bdk-swift/Tests/BitcoinDevKitTests/LiveWalletTests.swift +++ b/bdk-swift/Tests/BitcoinDevKitTests/LiveWalletTests.swift @@ -2,34 +2,46 @@ import XCTest @testable import BitcoinDevKit final class LiveWalletTests: XCTestCase { + override func tearDownWithError() throws { + let fileManager = FileManager.default + let dbFileName = "bdk_persistence.db" + let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! + let dbFilePath: URL = documentDirectory.appendingPathComponent(dbFileName) + + if fileManager.fileExists(atPath: dbFilePath.path) { + try fileManager.removeItem(at: dbFilePath) + } + } + func testSyncedBalance() throws { let descriptor = try Descriptor( 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( + descriptor: descriptor, + changeDescriptor: nil, + persistenceBackendPath: "bdk_persistence.db", + network: .testnet + ) + let esploraClient = EsploraClient(url: "https://esplora.testnet.kuutamo.cloud/") + 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 +49,44 @@ 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( + descriptor: descriptor, + changeDescriptor: nil, + persistenceBackendPath: "bdk_persistence.db", + network: .testnet + ) + let esploraClient = EsploraClient(url: "https://esplora.testnet.kuutamo.cloud/") + 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) } } diff --git a/bdk-swift/Tests/BitcoinDevKitTests/OfflineWalletTests.swift b/bdk-swift/Tests/BitcoinDevKitTests/OfflineWalletTests.swift index e9b147b0..07eabd84 100644 --- a/bdk-swift/Tests/BitcoinDevKitTests/OfflineWalletTests.swift +++ b/bdk-swift/Tests/BitcoinDevKitTests/OfflineWalletTests.swift @@ -2,28 +2,40 @@ import XCTest @testable import BitcoinDevKit final class OfflineWalletTests: XCTestCase { + override func tearDownWithError() throws { + let fileManager = FileManager.default + let dbFileName = "bdk_persistence.db" + let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! + let dbFilePath: URL = documentDirectory.appendingPathComponent(dbFileName) + + if fileManager.fileExists(atPath: dbFilePath.path) { + try fileManager.removeItem(at: dbFilePath) + } + } + func testNewAddress() throws { let descriptor: Descriptor = try Descriptor( 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( + descriptor: descriptor, + changeDescriptor: nil, + persistenceBackendPath: "bdk_persistence.db", + 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 +43,13 @@ 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( + descriptor: descriptor, + changeDescriptor: nil, + persistenceBackendPath: "bdk_persistence.db", + network: .testnet + ) + + XCTAssertEqual(wallet.getBalance().total, 0) } }