diff --git a/bdk-android/lib/build.gradle.kts b/bdk-android/lib/build.gradle.kts index a7f540d9..4e240092 100644 --- a/bdk-android/lib/build.gradle.kts +++ b/bdk-android/lib/build.gradle.kts @@ -52,13 +52,11 @@ java { dependencies { implementation("net.java.dev.jna:jna:5.14.0@aar") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") implementation("androidx.appcompat:appcompat:1.4.0") implementation("androidx.core:core-ktx:1.7.0") api("org.slf4j:slf4j-api:1.7.30") androidTestImplementation("com.github.tony19:logback-android:2.0.0") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") androidTestImplementation("androidx.test.ext:junit:1.1.3") androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") androidTestImplementation("org.jetbrains.kotlin:kotlin-test:1.6.10") diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/KyotoTest.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/KyotoTest.kt deleted file mode 100644 index 27379d00..00000000 --- a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/KyotoTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.bitcoindevkit - -import org.junit.Test -import androidx.test.ext.junit.runners.AndroidJUnit4 -import kotlinx.coroutines.runBlocking -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class KyotoTest { - private val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.SIGNET) - private val changeDescriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", Network.SIGNET) - - @Test - fun testKyoto() { - // val wallet: Wallet = Wallet(descriptor, changeDescriptor, Network.SIGNET) - runBlocking { - println("Running test Kyoto") - val (node, client) = buildKyotoClient() - runNode(node) - client.update() - println("Done running test Kyoto") - } - } -} diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 3a240cfe..d4e89643 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -667,7 +667,7 @@ interface LightClient { Update? update(NodeEventHandler? logger); [Async, Throws=LightClientError] - void broadcast(Transaction transaction); + void broadcast([ByRef] Transaction transaction); [Async, Throws=LightClientError] void watch_address(Address address); diff --git a/bdk-ffi/src/bitcoin.rs b/bdk-ffi/src/bitcoin.rs index c189c957..5bb702b0 100644 --- a/bdk-ffi/src/bitcoin.rs +++ b/bdk-ffi/src/bitcoin.rs @@ -77,7 +77,7 @@ impl From for Address { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Transaction(pub(crate) BdkTransaction); +pub struct Transaction(BdkTransaction); impl Transaction { pub fn new(transaction_bytes: Vec) -> Result { diff --git a/bdk-ffi/src/kyoto.rs b/bdk-ffi/src/kyoto.rs index 367b2113..5490dbbb 100644 --- a/bdk-ffi/src/kyoto.rs +++ b/bdk-ffi/src/kyoto.rs @@ -109,9 +109,9 @@ impl LightClient { update.map(|update| Arc::new(Update(update.into()))) } - pub async fn broadcast(&self, transaction: Arc) -> Result<(), LightClientError> { + pub async fn broadcast(&self, transaction: &Transaction) -> Result<(), LightClientError> { let client = self.client.lock().await; - let tx = transaction.0.clone(); + let tx = transaction.into(); client .broadcast(tx, bdk_kyoto::TxBroadcastPolicy::RandomPeer) .await diff --git a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/KyotoTest.kt b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/KyotoTest.kt deleted file mode 100644 index 782ddc59..00000000 --- a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/KyotoTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.bitcoindevkit - -import kotlinx.coroutines.runBlocking -import kotlin.test.Test - -class KyotoTest { - private val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.SIGNET) - private val changeDescriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", Network.SIGNET) - - @Test - fun testKyoto() { - // val wallet: Wallet = Wallet(descriptor, changeDescriptor, Network.SIGNET) - runBlocking { - val (node, client) = buildKyotoClient() - runNode(node) - client.update() - } - } -} diff --git a/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveKyotoTest.kt b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveKyotoTest.kt new file mode 100644 index 00000000..674b9635 --- /dev/null +++ b/bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveKyotoTest.kt @@ -0,0 +1,49 @@ +package org.bitcoindevkit +import org.rustbitcoin.bitcoin.Network + +import kotlinx.coroutines.runBlocking +import kotlin.test.Test +import kotlin.test.AfterTest +import kotlin.test.assertNotNull + +import java.nio.file.Files +import java.nio.file.Paths +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.deleteRecursively + +class LiveKyotoTest { + private val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.SIGNET) + private val changeDescriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", Network.SIGNET) + private val ip: IpAddress = IpAddress.fromIpv4(68u, 47u, 229u, 218u) + private val peer: Peer = Peer(ip, null, false) + private val currentPath = Paths.get(".").toAbsolutePath().normalize() + private val persistenceFilePath = Files.createTempDirectory(currentPath, "tempDirPrefix_") + + @OptIn(ExperimentalPathApi::class) + @AfterTest + fun cleanup() { + persistenceFilePath.deleteRecursively() + } + + @Test + fun testKyoto() { + val conn: Connection = Connection.newInMemory() + val wallet: Wallet = Wallet(descriptor, changeDescriptor, Network.SIGNET, conn) + val peers = listOf(peer) + runBlocking { + val nodePair = buildLightClient(wallet, peers, 1u, null, persistenceFilePath.toString()) + val client = nodePair.client + val node = nodePair.node + println("Node running") + runNode(node) + val updateOpt: Update? = client.update(null) + val update = assertNotNull(updateOpt) + wallet.applyUpdate(update) + assert(wallet.balance().total.toSat() > 0uL) { + "Wallet balance must be greater than 0! Please send funds to ${wallet.revealNextAddress(KeychainKind.EXTERNAL).address} and try again." + } + client.shutdown() + println("Test completed successfully") + } + } +} diff --git a/bdk-python/tests/test_live_kyoto.py b/bdk-python/tests/test_live_kyoto.py new file mode 100644 index 00000000..27e139d3 --- /dev/null +++ b/bdk-python/tests/test_live_kyoto.py @@ -0,0 +1,54 @@ +from bdkpython import * +from bdkpython.bitcoin import * +import unittest +import os + +network: Network = Network.SIGNET + +ip: IpAddress = IpAddress.from_ipv4(68, 47, 229, 218) +peer: Peer = Peer(address=ip, port=None, v2_transport=False) + +descriptor: Descriptor = Descriptor( + "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", + network=network +) +change_descriptor: Descriptor = Descriptor( + "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", + network=network +) + +class LiveKyotoTest(unittest.IsolatedAsyncioTestCase): + + def tearDown(self) -> None: + if os.path.exists("./bdk_persistence.sqlite"): + os.remove("./bdk_persistence.sqlite") + if os.path.exists("./data/signet/headers.db"): + os.remove("./data/signet/headers.db") + if os.path.exists("./data/signet/peers.db"): + os.remove("./data/signet/peers.db") + + async def testKyoto(self) -> None: + connection: Connection = Connection.new_in_memory() + wallet: Wallet = Wallet( + descriptor, + change_descriptor, + network, + connection + ) + peers = [peer] + node_pair: NodePair = build_light_client(wallet, peers, 1, None, ".") + client: LightClient = node_pair.client + node: LightNode = node_pair.node + run_node(node) + update: Update = await client.update(None) + self.assertIsNotNone(update, "Update is None. This should not be possible.") + wallet.apply_update(update) + self.assertGreater( + wallet.balance().total.to_sat(), + 0, + f"Wallet balance must be greater than 0! Please send funds to {wallet.reveal_next_address(KeychainKind.EXTERNAL).address} and try again." + ) + await client.shutdown() + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/bdk-swift/Tests/BitcoinDevKitTests/LiveKyotoTests.swift b/bdk-swift/Tests/BitcoinDevKitTests/LiveKyotoTests.swift index d3926c3b..078c8b72 100644 --- a/bdk-swift/Tests/BitcoinDevKitTests/LiveKyotoTests.swift +++ b/bdk-swift/Tests/BitcoinDevKitTests/LiveKyotoTests.swift @@ -8,7 +8,6 @@ import XCTest @testable import BitcoinDevKit -private let PEER = IpAddress.fromIpv4(q1: 68, q2: 47, q3: 229, q4: 218) final class LiveKyotoTests: XCTestCase { private let descriptor = try! Descriptor( @@ -19,6 +18,15 @@ final class LiveKyotoTests: XCTestCase { descriptor: "wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/1/*)", network: Network.signet ) + private let peer = IpAddress.fromIpv4(q1: 68, q2: 47, q3: 229, q4: 218) + private let cwd = FileManager.default.currentDirectoryPath.appending("/temp") + + override func tearDownWithError() throws { + let fileManager = FileManager.default + if fileManager.fileExists(atPath: cwd) { + try fileManager.removeItem(atPath: cwd) + } + } func testSuccessfullySyncs() async throws { let connection = try Connection.newInMemory() @@ -28,8 +36,8 @@ final class LiveKyotoTests: XCTestCase { network: Network.signet, connection: connection ) - let trusted_peer = Peer(address: PEER, port: nil, v2Transport: false) - let nodePair = try! buildLightClient(wallet: wallet, peers: [trusted_peer], connections: 1, recoveryHeight: nil, dataDir: ".") + let trusted_peer = Peer(address: peer, port: nil, v2Transport: false) + let nodePair = try buildLightClient(wallet: wallet, peers: [trusted_peer], connections: 1, recoveryHeight: nil, dataDir: cwd) let client = nodePair.client let node = nodePair.node runNode(node: node)