diff --git a/.github/workflows/test-android.yaml b/.github/workflows/test-android.yaml index dbe6db07..5b335b3c 100644 --- a/.github/workflows/test-android.yaml +++ b/.github/workflows/test-android.yaml @@ -20,6 +20,23 @@ jobs: test: name: "Test Android library" runs-on: ubuntu-24.04 + + services: + bitcoin-regtest: + image: ghcr.io/thunderbiscuit/podman-regtest-infinity-pro:0.3.2 + ports: + - 18443:18443 + - 18444:18444 + - 3002:3002 + - 3003:3003 + - 60401:60401 + # The container initialization step will wait until everything is ready before allowing other steps to run + options: >- + --health-cmd "test $(bitcoin-cli -regtest -rpcuser=regtest -rpcpassword=password getblockcount) -gt 0" + --health-interval 10s + --health-timeout 5s + --health-retries 6 + steps: - name: "Checkout PR branch" uses: actions/checkout@v4 diff --git a/bdk-android/lib/build.gradle.kts b/bdk-android/lib/build.gradle.kts index 647d956f..9532a1f9 100644 --- a/bdk-android/lib/build.gradle.kts +++ b/bdk-android/lib/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") androidTestImplementation("org.jetbrains.kotlin:kotlin-test:1.6.10") androidTestImplementation("org.jetbrains.kotlin:kotlin-test-junit:1.6.10") + androidTestImplementation("org.kotlinbitcointools:regtest-toolbox:0.2.0") } mavenPublishing { diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/Constants.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/Constants.kt index ed6bda92..3403b46a 100644 --- a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/Constants.kt +++ b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/Constants.kt @@ -41,3 +41,5 @@ val NON_EXTENDED_DESCRIPTOR_1: Descriptor = Descriptor( const val TEST_EXTENDED_PRIVKEY_0 = "tprv8ZgxMBicQKsPdWAHbugK2tjtVtRjKGixYVZUdL7xLHMgXZS6BFbFi1UDb1CHT25Z5PU1F9j7wGxwUiRhqz9E3nZRztikGUV6HoRDYcqPhM4" const val BIP84_TEST_RECEIVE_PATH_0 = "84h/1h/0h/0" val TEST_BIP84_DESCRIPTOR_0 = Descriptor("wpkh($TEST_EXTENDED_PRIVKEY_0/$BIP84_TEST_RECEIVE_PATH_0/*)", Network.REGTEST) + +const val ESPLORA_REGTEST_URL = "http://10.0.2.2:3002" diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/EsploraClientTest.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/EsploraClientTest.kt new file mode 100644 index 00000000..8822a357 --- /dev/null +++ b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/EsploraClientTest.kt @@ -0,0 +1,55 @@ +package org.bitcoindevkit + +import kotlin.test.Test +import androidx.test.ext.junit.runners.AndroidJUnit4 +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import org.junit.runner.RunWith +import org.kotlinbitcointools.regtesttoolbox.regenv.RegEnv +import kotlin.time.Duration.Companion.milliseconds + +@RunWith(AndroidJUnit4::class) +class EsploraClientTest { + private val conn: Persister = Persister.newInMemory() + + @Test + fun walletSyncWithEsploraClient() { + runBlocking { + val regtestEnv = RegEnv.connectTo( + host = "10.0.2.2", + walletName = "faucet", + username = "regtest", + password = "password", + ) + + val wallet: Wallet = Wallet.createSingle( + descriptor = BIP86_DESCRIPTOR, + network = Network.REGTEST, + persister = conn + ) + val newAddress = wallet.revealNextAddress(KeychainKind.EXTERNAL).address + + val txidString = regtestEnv.send(newAddress.toString(), 0.12345678, 2.0) + regtestEnv.mine(2) + + val esploraClient = EsploraClient(ESPLORA_REGTEST_URL) + val txid = Txid.fromString(txidString) + // Wait for the Esplora client to see the transaction. Try 5x per second for 20 seconds. + repeat(100) { + if (esploraClient.getTx(txid) != null) return@repeat + delay(200.milliseconds) + } + + val fullScanRequest: FullScanRequest = wallet.startFullScan().build() + val update = esploraClient.fullScan(fullScanRequest, 10uL, 1uL) + + wallet.applyUpdate(update) + wallet.persist(conn) + + val balance = wallet.balance().total.toSat() + assert(balance > 0uL) { + "Balance should be greater than zero, but was $balance" + } + } + } +}