test: add excluded-in-CI live tests

This commit is contained in:
thunderbiscuit 2023-10-27 14:13:44 -04:00
parent 13c751cebc
commit d37b2f37b5
No known key found for this signature in database
GPG Key ID: 88253696EB836462
24 changed files with 393 additions and 189 deletions

View File

@ -55,11 +55,12 @@ jobs:
- name: "Build Android library"
run: |
cd bdk-android
./gradlew buildAndroidLib
./gradlew buildAndroidLib --console=plain
# There are currently no unit tests for bdk-android and the integration tests require the macOS image
# which is not working with the older NDK version we are using, so for now we just make sure that the library builds.
# - name: "Run Android unit tests"
# There are currently no unit tests for bdk-android (see the tests in bdk-jvm instead) and the
# integration tests require the macOS image which is not working with the older NDK version we
# are using, so for now we just make sure that the library builds and omit the connectedTest
# - name: "Run Android connected tests"
# run: |
# cd bdk-android
# ./gradlew test --console=rich
# ./gradlew connectedAndroidTest --console=plain

View File

@ -38,4 +38,4 @@ jobs:
- name: "Run JVM tests"
run: |
cd bdk-jvm
./gradlew test
./gradlew test -P excludeConnectedTests

View File

@ -54,7 +54,7 @@ jobs:
run: ${PYBIN}/pip install ./dist/*.whl
- name: "Run tests"
run: ${PYBIN}/python -m unittest tests/test_bdk.py --verbose
run: ${PYBIN}/python -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
@ -97,7 +97,7 @@ jobs:
# - name: "Install wheel and run tests"
# run: |
# pip3 install ./dist/*.whl
# python3 -m unittest tests/test_bdk.py --verbose
# python3 -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
@ -138,7 +138,7 @@ jobs:
run: pip3 install ./dist/*.whl
- name: "Run tests"
run: python3 -m unittest tests/test_bdk.py --verbose
run: python3 -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
@ -186,4 +186,4 @@ jobs:
shell: powershell
- name: "Run tests"
run: python -m unittest tests/test_bdk.py --verbose
run: python -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose

View File

@ -23,4 +23,4 @@ jobs:
- name: "Run Swift tests"
working-directory: bdk-swift
run: swift test
run: swift test --skip LiveWalletTests --skip LiveTxBuilderTests

View File

@ -0,0 +1,30 @@
package org.bitcoindevkit
import org.junit.Test
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
import kotlin.test.assertTrue
@RunWith(AndroidJUnit4::class)
class LiveTxBuilderTest {
@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 update = esploraClient.scan(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(2.0f)
.finish(wallet)
println(psbt.serialize())
assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'")
}
}

View File

@ -0,0 +1,21 @@
package org.bitcoindevkit
import org.junit.Test
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class LiveWalletTest {
@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 esploraClient = EsploraClient("https://blockstream.info/testnet/api")
val update = esploraClient.scan(wallet, 10uL, 1uL)
wallet.applyUpdate(update)
println("Balance: ${wallet.getBalance().total()}")
assert(wallet.getBalance().total() > 0uL)
}
}

View File

@ -0,0 +1,21 @@
package org.bitcoindevkit
import kotlin.test.Test
import kotlin.test.assertTrue
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class OfflineDescriptorTest {
@Test
fun testDescriptorBip86() {
val mnemonic: Mnemonic = Mnemonic.fromString("space echo position wrist orient erupt relief museum myself grain wisdom tumble")
val descriptorSecretKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
val descriptor: Descriptor = Descriptor.newBip86(descriptorSecretKey, KeychainKind.EXTERNAL, Network.TESTNET)
assertEquals(
expected = "tr([be1eec8f/86'/1'/0']tpubDCTtszwSxPx3tATqDrsSyqScPNnUChwQAVAkanuDUCJQESGBbkt68nXXKRDifYSDbeMa2Xg2euKbXaU3YphvGWftDE7ozRKPriT6vAo3xsc/0/*)#m7puekcx",
actual = descriptor.asString()
)
}
}

View File

@ -1,19 +1,13 @@
package org.bitcoindevkit
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class WalletTest {
class OfflineWalletTest {
@Test
fun testDescriptorBip86() {
val mnemonic: Mnemonic = Mnemonic(WordCount.WORDS12)
@ -36,7 +30,10 @@ class WalletTest {
)
val addressInfo: AddressInfo = wallet.getAddress(AddressIndex.New)
assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", addressInfo.address.asString())
assertEquals(
expected = "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e",
actual = addressInfo.address.asString()
)
}
@Test
@ -51,7 +48,9 @@ class WalletTest {
Network.TESTNET
)
assertEquals(0uL, wallet.getBalance().total())
assertEquals(
expected = 0uL,
actual = wallet.getBalance().total()
)
}
}
}

View File

@ -76,10 +76,14 @@ interface Wallet {
AddressInfo get_address(AddressIndex address_index);
AddressInfo get_internal_address(AddressIndex address_index);
Network network();
Balance get_balance();
boolean is_mine(Script script);
[Throws=BdkError]
void apply_update(Update update);
};

View File

@ -38,28 +38,22 @@ impl Wallet {
self.inner_mutex.lock().expect("wallet")
}
// pub fn get_address(&self, address_index: AddressIndex) -> Result<AddressInfo, BdkError> {
pub fn get_address(&self, address_index: AddressIndex) -> AddressInfo {
self.get_wallet().get_address(address_index.into()).into()
// NOTE: I prefer this:
// AddressInfo::from(
// self.get_wallet().get_address(address_index.into())
// )
}
pub fn network(&self) -> Network {
self.get_wallet().network().into()
}
// fn get_internal_address(&mut self, address_index: AddressIndex) -> AddressInfo {
// self.get_wallet()
// .get_internal_address(address_index.into())
// .into()
// }
pub fn get_internal_address(&self, address_index: AddressIndex) -> AddressInfo {
self.get_wallet()
.get_internal_address(address_index.into())
.into()
}
// TODO 16: Why is the Arc required here?
pub fn get_balance(&self) -> Arc<Balance> {
// Arc::new(self.get_wallet().get_balance().into())
let bdk_balance = self.get_wallet().get_balance();
let balance = Balance { inner: bdk_balance };
Arc::new(balance)
@ -71,11 +65,11 @@ impl Wallet {
.map_err(|e| BdkError::Generic(e.to_string()))
}
// pub fn commit(&self) -> Result<(), BdkError> {}
// fn is_mine(&self, script: Arc<Script>) -> bool {
// self.get_wallet().is_mine(&script.inner)
// }
pub fn is_mine(&self, script: Arc<Script>) -> bool {
// TODO: Both of the following lines work. Which is better?
self.get_wallet().is_mine(&script.0)
// self.get_wallet().is_mine(script.0.clone().as_script())
}
}
pub struct Update(pub(crate) BdkUpdate);
@ -98,63 +92,6 @@ pub struct Update(pub(crate) BdkUpdate);
// }
// }
// impl Wallet {
// // pub(crate) fn new(
// // descriptor: Arc<Descriptor>,
// // change_descriptor: Option<Arc<Descriptor>>,
// // db: PersistBackend<ChangeSet>,
// // network: Network,
// // ) -> Result<Self, BdkError> {
// // let any_database_config = match database_config {
// // DatabaseConfig::Memory => AnyDatabaseConfig::Memory(()),
// // DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config),
// // DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(config),
// // };
// // let database = AnyDatabase::from_config(&any_database_config)?;
// // let descriptor: String = descriptor.as_string_private();
// // let change_descriptor: Option<String> = change_descriptor.map(|d| d.as_string_private());
// //
// // let wallet_mutex = Mutex::new(BdkWallet::new(
// // &descriptor,
// // change_descriptor.as_ref(),
// // network,
// // database,
// // )?);
// // Ok(Wallet {
// // inner_mutex: wallet_mutex,
// // })
// // }
//
// pub(crate) fn new_no_persist(
// descriptor: Arc<Descriptor>,
// change_descriptor: Option<Arc<Descriptor>>,
// network: Network,
// ) -> Result<Self, BdkError> {
// let descriptor: String = descriptor.as_string_private();
// let change_descriptor: Option<String> = change_descriptor.map(|d| d.as_string_private());
//
// let wallet = BdkWallet::new_no_persist(
// &descriptor,
// change_descriptor.as_ref(),
// network,
// )?;
//
// Ok(Wallet {
// inner: wallet,
// })
// }
//
// // MIGRATION 1.0: This function is no longer needed right? If I remove the mutex on the wallet,
// // I can just access the wallet directly without causing trouble me thinks.
// pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> {
// self.inner_mutex.lock().expect("wallet")
// }
//
// /// Get the Bitcoin network the wallet is using.
// pub(crate) fn network(&self) -> Network {
// self.inner.network()
// }
//
// /// Return whether or not a script is part of this wallet (either internal or external).
// pub(crate) fn is_mine(&self, script: Arc<Script>) -> bool {
// self.inner.is_mine(&script.inner)

View File

@ -26,6 +26,18 @@ java {
withJavadocJar()
}
// This block ensures that the tests that require access to a blockchain are not
// run if the -P excludeConnectedTests flag is passed to gradle.
// This ensures our CI runs are not fickle by not requiring access to testnet.
// This is a workaround until we have a proper regtest setup for the CI.
// Note that the command in the CI is ./gradlew test -P excludeConnectedTests
tasks.test {
if (project.hasProperty("excludeConnectedTests")) {
exclude("**/LiveWalletTest.class")
exclude("**/LiveTxBuilderTest.class")
}
}
testing {
suites {
val test by getting(JvmTestSuite::class) {

View File

@ -0,0 +1,29 @@
package org.bitcoindevkit
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class LiveTxBuilderTest {
@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 update = esploraClient.scan(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(2.0f)
.finish(wallet)
println(psbt.serialize())
assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'")
}
}

View File

@ -0,0 +1,18 @@
package org.bitcoindevkit
import kotlin.test.Test
class LiveWalletTest {
@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 esploraClient = EsploraClient("https://blockstream.info/testnet/api")
val update = esploraClient.scan(wallet, 10uL, 1uL)
wallet.applyUpdate(update)
println("Balance: ${wallet.getBalance().total()}")
assert(wallet.getBalance().total() > 0uL)
}
}

View File

@ -0,0 +1,18 @@
package org.bitcoindevkit
import kotlin.test.Test
import kotlin.test.assertEquals
class OfflineDescriptorTest {
@Test
fun testDescriptorBip86() {
val mnemonic: Mnemonic = Mnemonic.fromString("space echo position wrist orient erupt relief museum myself grain wisdom tumble")
val descriptorSecretKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
val descriptor: Descriptor = Descriptor.newBip86(descriptorSecretKey, KeychainKind.EXTERNAL, Network.TESTNET)
assertEquals(
expected = "tr([be1eec8f/86'/1'/0']tpubDCTtszwSxPx3tATqDrsSyqScPNnUChwQAVAkanuDUCJQESGBbkt68nXXKRDifYSDbeMa2Xg2euKbXaU3YphvGWftDE7ozRKPriT6vAo3xsc/0/*)#m7puekcx",
actual = descriptor.asString()
)
}
}

View File

@ -4,8 +4,7 @@ import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class WalletTest {
class OfflineWalletTest {
@Test
fun testDescriptorBip86() {
val mnemonic: Mnemonic = Mnemonic(WordCount.WORDS12)
@ -28,7 +27,10 @@ class WalletTest {
)
val addressInfo: AddressInfo = wallet.getAddress(AddressIndex.New)
assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", addressInfo.address.asString())
assertEquals(
expected = "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e",
actual = addressInfo.address.asString()
)
}
@Test
@ -43,18 +45,9 @@ class WalletTest {
Network.TESTNET
)
assertEquals(0uL, wallet.getBalance().total())
assertEquals(
expected = 0uL,
actual = wallet.getBalance().total()
)
}
// @Test
// fun testSyncedBalance() {
// 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 esploraClient = EsploraClient("https://blockstream.info/testnet/api")
// val update = esploraClient.scan(wallet, 10uL, 1uL)
// wallet.applyUpdate(update)
// println("Balance: ${wallet.getBalance().total()}")
// }
}

View File

@ -0,0 +1,38 @@
import bdkpython as bdk
import unittest
class TestLiveTxBuilder(unittest.TestCase):
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.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(2.0).finish(wallet)
# print(psbt.serialize())
self.assertTrue(psbt.serialize().startswith("cHNi"), "The PSBT should start with cHNi")
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,28 @@
import bdkpython as bdk
import unittest
class TestLiveWallet(unittest.TestCase):
def test_synced_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
)
esploraClient: bdk.EsploraClient = bdk.EsploraClient(url = "https://mempool.space/testnet/api")
update = esploraClient.scan(
wallet = wallet,
stop_gap = 10,
parallel_requests = 1
)
wallet.apply_update(update)
self.assertGreater(wallet.get_balance().total(), 0)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,18 @@
import bdkpython as bdk
import unittest
class TestSimpleWallet(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")
descriptor_secret_key: bdk.DescriptorSecretKey = bdk.DescriptorSecretKey(bdk.Network.TESTNET, mnemonic, None)
descriptor: bdk.Descriptor = bdk.Descriptor.new_bip86(descriptor_secret_key, bdk.KeychainKind.EXTERNAL, bdk.Network.TESTNET)
self.assertEqual(
"tr([be1eec8f/86'/1'/0']tpubDCTtszwSxPx3tATqDrsSyqScPNnUChwQAVAkanuDUCJQESGBbkt68nXXKRDifYSDbeMa2Xg2euKbXaU3YphvGWftDE7ozRKPriT6vAo3xsc/0/*)#m7puekcx",
descriptor.as_string()
)
if __name__ == '__main__':
unittest.main()

View File

@ -3,13 +3,6 @@ import unittest
class TestSimpleWallet(unittest.TestCase):
def test_descriptor_bip86(self):
mnemonic: bdk.Mnemonic = bdk.Mnemonic(bdk.WordCount.WORDS12)
descriptor_secret_key: bdk.DescriptorSecretKey = bdk.DescriptorSecretKey(bdk.Network.TESTNET, mnemonic, None)
descriptor: bdk.Descriptor = bdk.Descriptor.new_bip86(descriptor_secret_key, bdk.KeychainKind.EXTERNAL, bdk.Network.TESTNET)
self.assertTrue(descriptor.as_string().startswith("tr"), "Bip86 Descriptor does not start with 'tr'")
def test_new_address(self):
descriptor: bdk.Descriptor = bdk.Descriptor(
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
@ -29,7 +22,7 @@ class TestSimpleWallet(unittest.TestCase):
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
bdk.Network.TESTNET
)
wallet: Wallet = bdk.Wallet.new_no_persist(
wallet: bdk.Wallet = bdk.Wallet.new_no_persist(
descriptor,
None,
bdk.Network.TESTNET

View File

@ -1,68 +0,0 @@
import XCTest
@testable import BitcoinDevKit
final class BitcoinDevKitTests: XCTestCase {
func testDescriptorBip86() {
let mnemonic: Mnemonic = Mnemonic(wordCount: WordCount.words12)
let descriptorSecretKey: DescriptorSecretKey = DescriptorSecretKey(
network: Network.testnet,
mnemonic: mnemonic,
password: nil
)
let descriptor: Descriptor = Descriptor.newBip86(
secretKey: descriptorSecretKey,
keychain: KeychainKind.external,
network: Network.testnet
)
XCTAssertTrue(descriptor.asString().hasPrefix("tr"), "Bip86 Descriptor does not start with 'tr'")
}
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)
XCTAssertEqual(addressInfo.address.asString(), "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e")
}
func testBalance() 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
)
XCTAssertEqual(wallet.getBalance().total(), 0)
}
// func testSyncedBalance() throws {
// let descriptor = try Descriptor(
// descriptor: "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
// network: Network.testnet
// )
// let wallet = try Wallet.newNoPersist(
// descriptor: descriptor,
// changeDescriptor: nil,
// network: .testnet
// )
// let esploraClient = EsploraClient("https://mempool.space/testnet/api")
// let update = esploraClient.scan(wallet, 10, 1)
// wallet.applyUpdate(update)
//
// XCTAssertEqual(wallet.getBalance().total(), 0)
// }
}

View File

@ -0,0 +1,34 @@
import XCTest
@testable import BitcoinDevKit
final class LiveTxBuilderTests: XCTestCase {
func testTxBuilder() throws {
let descriptor = try Descriptor(
descriptor: "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/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.scan(
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(satPerVbyte: 2.0)
.finish(wallet: wallet)
print(psbt.serialize())
XCTAssertTrue(psbt.serialize().hasPrefix("cHNi"), "PSBT should start with cHNI")
}
}

View File

@ -0,0 +1,25 @@
import XCTest
@testable import BitcoinDevKit
final class LiveWalletTests: XCTestCase {
func testSyncedBalance() throws {
let descriptor = try Descriptor(
descriptor: "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/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.scan(
wallet: wallet,
stopGap: 10,
parallelRequests: 1
)
try wallet.applyUpdate(update: update)
XCTAssertGreaterThan(wallet.getBalance().total(), UInt64(0))
}
}

View File

@ -0,0 +1,20 @@
import XCTest
@testable import BitcoinDevKit
final class OfflineDescriptorTests: XCTestCase {
func testDescriptorBip86() throws {
let mnemonic: Mnemonic = try Mnemonic.fromString(mnemonic: "space echo position wrist orient erupt relief museum myself grain wisdom tumble")
let descriptorSecretKey: DescriptorSecretKey = DescriptorSecretKey(
network: Network.testnet,
mnemonic: mnemonic,
password: nil
)
let descriptor: Descriptor = Descriptor.newBip86(
secretKey: descriptorSecretKey,
keychain: KeychainKind.external,
network: Network.testnet
)
XCTAssertEqual(descriptor.asString(), "tr([be1eec8f/86'/1'/0']tpubDCTtszwSxPx3tATqDrsSyqScPNnUChwQAVAkanuDUCJQESGBbkt68nXXKRDifYSDbeMa2Xg2euKbXaU3YphvGWftDE7ozRKPriT6vAo3xsc/0/*)#m7puekcx")
}
}

View File

@ -0,0 +1,33 @@
import XCTest
@testable import BitcoinDevKit
final class OfflineWalletTests: XCTestCase {
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)
XCTAssertEqual(addressInfo.address.asString(), "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e")
}
func testBalance() 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
)
XCTAssertEqual(wallet.getBalance().total(), 0)
}
}