Compare commits

..

15 Commits

Author SHA1 Message Date
thunderbiscuit
0648075555 Bump version to 0.11.0 2022-11-08 10:11:38 -05:00
thunderbiscuit
3f81346e6b Refactor from_str() method on the Mnemonic struct to from_string() 2022-11-08 09:54:50 -05:00
Steve Myers
a25fb1348d Merge bitcoindevkit/bdk-ffi#208: Add FeeRate struct and PSBT fee_amount and fee_rate functions
ae1ea99ed3 Add FeeRate struct and fee_amount() and fee_rate() functions on PartiallySignedTransaction (Steve Myers)
9a381f6d32 Rename PartiallySignedBitcoinTransaction to PartiallySignedTransaction (Steve Myers)

Pull request description:

  <!-- You can erase any parts of this template not applicable to your Pull Request. -->

  ### Description

  Add FeeRate struct and fee_amount() and fee_rate() functions on PartiallySignedTransaction.

  ### Notes to the reviewers

  This PR is dependent on https://github.com/bitcoindevkit/bdk/pull/782.

  ### Changelog notice

  - Breaking Changes
    - Renamed PartiallySignedBitcoinTransaction to PartiallySignedTransaction to be consistent with `rust-bitcoin`
  - APIs Added
    - Add FeeRate struct
    - Add fee_amount() and fee_rate() functions on PartiallySignedTransaction

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

ACKs for top commit:
  thunderbiscuit:
    Re-ACK [ae1ea99](ae1ea99ed3).

Tree-SHA512: 2c3f792e9ef092cd3ba233601122f4960c496d132caad54ef2f7f41d7113dd16600a863bb8fd78d2e5b978adebdb7ddd9529c21b3d46cd0b16e0db4eb90de01d
2022-11-07 14:15:35 -06:00
Steve Myers
ae1ea99ed3 Add FeeRate struct and fee_amount() and fee_rate() functions on PartiallySignedTransaction 2022-11-07 11:55:36 -06:00
Steve Myers
9a381f6d32 Rename PartiallySignedBitcoinTransaction to PartiallySignedTransaction 2022-11-07 11:55:36 -06:00
Steve Myers
3a07b4838a Merge bitcoindevkit/bdk-ffi#221: Bump bdk version to 0.24.0
29de6f2d06 Bump bdk version to 0.24.0 (thunderbiscuit)

Pull request description:

  ## Description
  This PR updates BDK to the latest version, `0.24.0`.

  ### Notes to the reviewers
  This PR is currently open only for CI testing and review. Only merge once bdk 0.24.0 is out and the PR has been updated.

  ### Changelog notice
  ```txt
  - Update BDK to latest version 0.24.0 [#221]

  [#221](https://github.com/bitcoindevkit/bdk-ffi/pull/221)
  ```

  #### All Submissions:
  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  notmandatory:
    ACK 29de6f2d06

Tree-SHA512: 256eb4387728467704f732ce1151de9569b6121916bb1d814bb48c75faf20026846e6170a384ca7e5e9ac3652bd9dfe5511e019f13c972ae755f0b37f9db8b83
2022-11-07 11:47:45 -06:00
thunderbiscuit
29de6f2d06 Bump bdk version to 0.24.0 2022-11-07 12:33:00 -05:00
Steve Myers
73ba73fd03 Merge bitcoindevkit/bdk-ffi#219: Added Mnemonic Interface
9866649fdc Added Mnemonic Interface (dhruvbaliyan)

Pull request description:

  ### Description
  This PR adds `interface Mnemonic` which will make the API to generate new DescriptorSecretKey have type-safe arguments.

  <!-- Describe the purpose of this PR, what's being adding and/or fixed -->

  ### Notes to the reviewers

  This PR doesn't have any issue linked to it, as it was discusses on a call during the implementation of `DescriptorSecretKey` (PR #154). It was discussed to make `Mnemonic` an interface and use that instead of string `Mnemonic` so that the API to generate `DescriptorSecretKey` doesn't have any potential failure (like in case it's provided with incorrect Mnemonic words).

  APIs added
  ```
  // generates and returns Mnemonic with random entropy
  Mnemonic::new(word_count: WordCount) -> Self { ... }
  // converts string Mnemonic to Mnemonic type with error (in case of incorrect string Mnemonic)
  Mnemonic::from_str(mnemonic: String) -> Result<Self, BdkError> { ... }
  // generates and returns Mnemonic with given entropy
  Mnemonic::from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {...}
  // view mnemonic as string
  Mnemonic::as_string(&self) -> String { ... }
  ```
  Along with some changes to `DescriptorSecretKey::new()` to fit these new APIs

  ### Changelog notice
  ```
  - Added Struct Mnemonic with following methods [#219]
    - new(word_count: WordCount) generates and returns Mnemonic with random entropy
    - from_str(mnemonic: String) converts string Mnemonic to Mnemonic type with error
    - from_entropy(entropy: Vec<u8>) generates and returns Mnemonic with given entropy
    - as_string() view Mnemonic as string
  - API removed [#219]
    - generate_mnemonic(word_count: WordCount)

  [#219](https://github.com/bitcoindevkit/bdk-ffi/pull/219)
  ```
  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### New Features:

  * [x] I've added docs for the new feature

  #### Bugfixes:

  * [x] This pull request breaks the existing API
      * Top level function `generate_mnemonic(...)` was removed

ACKs for top commit:
  thunderbiscuit:
    ACK 9866649fdc.
  notmandatory:
    ACK 9866649fdc

Tree-SHA512: 45f9158beb6fe7bfe2a901c3f17126db855fe0b4b479ecb2a16381e06a415eed295fe6be3c840bd1d1fc8cffaf58bd97dc27bdc1e82699367a827d700e8fd09b
2022-11-07 11:27:41 -06:00
dhruvbaliyan
9866649fdc Added Mnemonic Interface 2022-11-03 22:33:38 +05:30
Steve Myers
c2aecb0597 Merge bitcoindevkit/bdk-ffi#220: Add build profile 'release-smaller'
ba71a7a27c Add build profile 'release-smaller' (Steve Myers)

Pull request description:

  ### Description

  New profile turns on all the non-experimental rust build size optimizations.

  ### Notes to the reviewers

  This PR is the first step to fixing bitcoindevkit/bdk-swift#25.

  ### Changelog notice

  None.

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  thunderbiscuit:
    ACK [ba71a7a](ba71a7a27c).

Tree-SHA512: b12cf3a3ad3683dccbb89f611e98246db4a604b674077a45b78e30e9e20021f443dfec68e8ab511e0bb64d84c5c7064b4078b578fc3b4c1fb2e1119680a656a6
2022-11-01 18:57:52 -05:00
Steve Myers
ba71a7a27c Add build profile 'release-smaller' 2022-10-29 22:02:59 -05:00
Steve Myers
036e790a75 Merge bitcoindevkit/bdk-ffi#215: Add simple kotlin, swift and python integration tests
ee6ee8139a Add simple kotlin,swift, and python integration tests (Steve Myers)

Pull request description:

  ### Description

  Add simple kotlin, swift and python integration tests. These tests confirm fixes in #216 and #214.

  ### Notes to the reviewers

  To skip integration tests use:

  `cargo test --lib`.

  Otherwise java, kotlin, swift, and python need to be installed, and you must run tests with:

  `CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test`

  ### Changelog notice

  - Integration tests added, see tests/README.md for updated instructions for running tests. #215

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

  #### Bugfixes:

  * [x] I've added tests to reproduce the issue which are now passing

ACKs for top commit:
  thunderbiscuit:
    ACK [ee6ee81](ee6ee8139a).
  waterst0ne:
    > ACK [ee6ee81](ee6ee8139a).

Tree-SHA512: 06ab14da1185de431c16b767f187bc8e7792106df54314242b26f225e3a8ddada28317b7cb8bec47b8b248d3088d0305ab777770525540c72d2815349a73728b
2022-10-27 13:38:29 -05:00
Steve Myers
ee6ee8139a Add simple kotlin,swift, and python integration tests 2022-10-21 15:14:15 -05:00
Steve Myers
3bec5d2cab Merge bitcoindevkit/bdk-ffi#216: Update uniffi dependencies to 0.21.0
b9aa0a2cf1 Update uniffi dependencies to 0.21.0 (Steve Myers)

Pull request description:

  ### Description

  Update uniffi dependencies to 0.21.0

  ### Notes to the reviewers

  This is required to pickup my PR to handle swift keywords. https://github.com/mozilla/uniffi-rs/compare/v0.20.0...v0.21.0

  ### Changelog notice

  Update uniffi-rs to latest version 0.20.0 #216

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  thunderbiscuit:
    ACK [b9aa0a2](b9aa0a2cf1).

Tree-SHA512: 8bd585a22e6df2186d3985cc4d41a86dc35644b1e8dc06c1153de04a85df2cb6b345e15c0eb26e1b87c41cb00f15acf29f1b6a5b23736ead397fa6ee0fe0af0e
2022-10-21 13:26:36 -05:00
Steve Myers
b9aa0a2cf1 Update uniffi dependencies to 0.21.0 2022-10-21 13:18:38 -05:00
10 changed files with 215 additions and 52 deletions

View File

@@ -41,7 +41,7 @@ jobs:
if: ${{ matrix.rust.clippy }}
run: cargo clippy --all-targets -- -D warnings
- name: Test
run: cargo test
run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test
fmt:
name: Rust fmt

View File

@@ -1,23 +1,31 @@
[package]
name = "bdk-ffi"
version = "0.10.0"
version = "0.11.0"
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
[workspace]
members = [".","bdk-ffi-bindgen"]
default-members = [".", "bdk-ffi-bindgen"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["staticlib", "cdylib"]
name = "bdkffi"
[dependencies]
bdk = { version = "0.23", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
bdk = { version = "0.24", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
uniffi_macros = { version = "0.21.0", features = ["builtin-bindgen"] }
uniffi = { version = "0.21.0", features = ["builtin-bindgen"] }
[build-dependencies]
uniffi_build = { version = "0.21.0", features = ["builtin-bindgen"] }
[profile.release-smaller]
inherits = "release"
opt-level = 'z' # Optimize for size.
lto = true # Enable Link Time Optimization
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
panic = 'abort' # Abort on panic
strip = true # Strip symbols from binary*

View File

@@ -1,6 +1,5 @@
namespace bdk {
[Throws=BdkError]
string generate_mnemonic(WordCount word_count);
};
[Error]
@@ -33,9 +32,9 @@ enum BdkError {
"ProgressUpdateError",
"InvalidOutpoint",
"Descriptor",
"AddressValidator",
"Encode",
"Miniscript",
"MiniscriptPsbt",
"Bip32",
"Secp256k1",
"Json",
@@ -138,7 +137,7 @@ interface Blockchain {
constructor(BlockchainConfig config);
[Throws=BdkError]
void broadcast([ByRef] PartiallySignedBitcoinTransaction psbt);
void broadcast([ByRef] PartiallySignedTransaction psbt);
[Throws=BdkError]
u32 get_height();
@@ -189,7 +188,7 @@ interface Wallet {
Balance get_balance();
[Throws=BdkError]
boolean sign([ByRef] PartiallySignedBitcoinTransaction psbt);
boolean sign([ByRef] PartiallySignedTransaction psbt);
[Throws=BdkError]
sequence<TransactionDetails> list_transactions();
@@ -203,7 +202,14 @@ interface Wallet {
sequence<LocalUtxo> list_unspent();
};
interface PartiallySignedBitcoinTransaction {
interface FeeRate {
[Name=from_sat_per_vb]
constructor(float sat_per_vb);
float as_sat_per_vb();
};
interface PartiallySignedTransaction {
[Throws=BdkError]
constructor(string psbt_base64);
@@ -214,11 +220,15 @@ interface PartiallySignedBitcoinTransaction {
sequence<u8> extract_tx();
[Throws=BdkError]
PartiallySignedBitcoinTransaction combine(PartiallySignedBitcoinTransaction other);
PartiallySignedTransaction combine(PartiallySignedTransaction other);
u64? fee_amount();
FeeRate? fee_rate();
};
dictionary TxBuilderResult {
PartiallySignedBitcoinTransaction psbt;
PartiallySignedTransaction psbt;
TransactionDetails transaction_details;
};
@@ -271,7 +281,19 @@ interface BumpFeeTxBuilder {
BumpFeeTxBuilder enable_rbf_with_sequence(u32 nsequence);
[Throws=BdkError]
PartiallySignedBitcoinTransaction finish([ByRef] Wallet wallet);
PartiallySignedTransaction finish([ByRef] Wallet wallet);
};
interface Mnemonic {
constructor(WordCount word_count);
[Name=from_string, Throws=BdkError]
constructor(string mnemonic);
[Name=from_entropy, Throws=BdkError]
constructor(sequence<u8> entropy);
string as_string();
};
interface DerivationPath {
@@ -280,8 +302,7 @@ interface DerivationPath {
};
interface DescriptorSecretKey {
[Throws=BdkError]
constructor(Network network, string mnemonic, string? password);
constructor(Network network, Mnemonic mnemonic, string? password);
[Throws=BdkError]
DescriptorSecretKey derive(DerivationPath path);

View File

@@ -3,7 +3,8 @@ use bdk::bitcoin::hashes::hex::ToHex;
use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::util::psbt::serialize::Serialize;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoin::Sequence;
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid};
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
use bdk::blockchain::GetBlockHash;
@@ -15,12 +16,13 @@ use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress};
use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration};
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
use bdk::descriptor::DescriptorXKey;
use bdk::keys::bip39::{Language, Mnemonic, WordCount};
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
use bdk::keys::{
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
};
use bdk::miniscript::BareCtx;
use bdk::psbt::PsbtUtils;
use bdk::wallet::tx_builder::ChangeSpendPolicy;
use bdk::wallet::AddressIndex as BdkAddressIndex;
use bdk::wallet::AddressInfo as BdkAddressInfo;
@@ -209,7 +211,7 @@ impl Blockchain {
self.blockchain_mutex.lock().expect("blockchain")
}
fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<(), BdkError> {
fn broadcast(&self, psbt: &PartiallySignedTransaction) -> Result<(), BdkError> {
let tx = psbt.internal.lock().unwrap().clone().extract_tx();
self.get_blockchain().broadcast(&tx)
}
@@ -340,14 +342,15 @@ impl fmt::Debug for ProgressHolder {
}
#[derive(Debug)]
pub struct PartiallySignedBitcoinTransaction {
internal: Mutex<PartiallySignedTransaction>,
pub struct PartiallySignedTransaction {
internal: Mutex<BdkPartiallySignedTransaction>,
}
impl PartiallySignedBitcoinTransaction {
impl PartiallySignedTransaction {
fn new(psbt_base64: String) -> Result<Self, BdkError> {
let psbt: PartiallySignedTransaction = PartiallySignedTransaction::from_str(&psbt_base64)?;
Ok(PartiallySignedBitcoinTransaction {
let psbt: BdkPartiallySignedTransaction =
BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
Ok(PartiallySignedTransaction {
internal: Mutex::new(psbt),
})
}
@@ -378,16 +381,30 @@ impl PartiallySignedBitcoinTransaction {
/// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
fn combine(
&self,
other: Arc<PartiallySignedBitcoinTransaction>,
) -> Result<Arc<PartiallySignedBitcoinTransaction>, BdkError> {
other: Arc<PartiallySignedTransaction>,
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
let other_psbt = other.internal.lock().unwrap().clone();
let mut original_psbt = self.internal.lock().unwrap().clone();
original_psbt.combine(other_psbt)?;
Ok(Arc::new(PartiallySignedBitcoinTransaction {
Ok(Arc::new(PartiallySignedTransaction {
internal: Mutex::new(original_psbt),
}))
}
/// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
/// If the PSBT is missing a TxOut for an input returns None.
fn fee_amount(&self) -> Option<u64> {
self.internal.lock().unwrap().fee_amount()
}
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the
/// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the
/// transaction.
/// If the PSBT is missing a TxOut for an input returns None.
fn fee_rate(&self) -> Option<Arc<FeeRate>> {
self.internal.lock().unwrap().fee_rate().map(Arc::new)
}
}
/// A Bitcoin wallet.
@@ -459,7 +476,7 @@ impl Wallet {
}
/// Sign a transaction with all the wallets signers.
fn sign(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<bool, BdkError> {
fn sign(&self, psbt: &PartiallySignedTransaction) -> Result<bool, BdkError> {
let mut psbt = psbt.internal.lock().unwrap();
self.get_wallet().sign(&mut psbt, SignOptions::default())
}
@@ -531,7 +548,7 @@ enum RbfValue {
/// The result after calling the TxBuilder finish() function. Contains unsigned PSBT and
/// transaction details.
pub struct TxBuilderResult {
pub psbt: Arc<PartiallySignedBitcoinTransaction>,
pub psbt: Arc<PartiallySignedTransaction>,
pub transaction_details: TransactionDetails,
}
@@ -758,7 +775,7 @@ impl TxBuilder {
tx_builder.enable_rbf();
}
RbfValue::Value(nsequence) => {
tx_builder.enable_rbf_with_sequence(nsequence);
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
}
}
}
@@ -769,7 +786,7 @@ impl TxBuilder {
tx_builder
.finish()
.map(|(psbt, tx_details)| TxBuilderResult {
psbt: Arc::new(PartiallySignedBitcoinTransaction {
psbt: Arc::new(PartiallySignedTransaction {
internal: Mutex::new(psbt),
}),
transaction_details: TransactionDetails::from(&tx_details),
@@ -827,7 +844,7 @@ impl BumpFeeTxBuilder {
}
/// Finish building the transaction. Returns the BIP174 PSBT.
fn finish(&self, wallet: &Wallet) -> Result<Arc<PartiallySignedBitcoinTransaction>, BdkError> {
fn finish(&self, wallet: &Wallet) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
let wallet = wallet.get_wallet();
let txid = Txid::from_str(self.txid.as_str())?;
let mut tx_builder = wallet.build_fee_bump(txid)?;
@@ -844,23 +861,53 @@ impl BumpFeeTxBuilder {
tx_builder.enable_rbf();
}
RbfValue::Value(nsequence) => {
tx_builder.enable_rbf_with_sequence(nsequence);
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
}
}
}
tx_builder
.finish()
.map(|(psbt, _)| PartiallySignedBitcoinTransaction {
.map(|(psbt, _)| PartiallySignedTransaction {
internal: Mutex::new(psbt),
})
.map(Arc::new)
}
}
fn generate_mnemonic(word_count: WordCount) -> Result<String, BdkError> {
let mnemonic: GeneratedKey<_, BareCtx> =
Mnemonic::generate((word_count, Language::English)).unwrap();
Ok(mnemonic.to_string())
/// Mnemonic phrases are a human-readable version of the private keys.
/// Supported number of words are 12, 15, 18, 21 and 24.
struct Mnemonic {
internal: BdkMnemonic,
}
impl Mnemonic {
/// Generates Mnemonic with a random entropy
fn new(word_count: WordCount) -> Self {
let generated_key: GeneratedKey<_, BareCtx> =
BdkMnemonic::generate((word_count, Language::English)).unwrap();
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap();
Mnemonic { internal: mnemonic }
}
/// Parse a Mnemonic with given string
fn from_string(mnemonic: String) -> Result<Self, BdkError> {
BdkMnemonic::from_str(&mnemonic)
.map(|m| Mnemonic { internal: m })
.map_err(|e| BdkError::Generic(e.to_string()))
}
/// Create a new Mnemonic in the specified language from the given entropy.
/// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.
fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
BdkMnemonic::from_entropy(entropy.as_slice())
.map(|m| Mnemonic { internal: m })
.map_err(|e| BdkError::Generic(e.to_string()))
}
/// Returns Mnemonic as string
fn as_string(&self) -> String {
self.internal.to_string()
}
}
struct DerivationPath {
@@ -882,19 +929,18 @@ struct DescriptorSecretKey {
}
impl DescriptorSecretKey {
fn new(network: Network, mnemonic: String, password: Option<String>) -> Result<Self, BdkError> {
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic)
.map_err(|e| BdkError::Generic(e.to_string()))?;
let xkey: ExtendedKey = (mnemonic, password).into_extended_key()?;
fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
let mnemonic = mnemonic.internal.clone();
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: None,
xkey: xkey.into_xprv(network).unwrap(),
derivation_path: BdkDerivationPath::master(),
wildcard: bdk::descriptor::Wildcard::Unhardened,
});
Ok(Self {
Self {
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
})
}
}
fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
@@ -918,7 +964,7 @@ impl DescriptorSecretKey {
descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
}))
}
BdkDescriptorSecretKey::SinglePriv(_) => {
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
}
@@ -940,7 +986,7 @@ impl DescriptorSecretKey {
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
})
}
BdkDescriptorSecretKey::SinglePriv(_) => {
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
}
@@ -952,7 +998,7 @@ impl DescriptorSecretKey {
.descriptor_secret_key_mutex
.lock()
.unwrap()
.as_public(&secp)
.to_public(&secp)
.unwrap();
Arc::new(DescriptorPublicKey {
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
@@ -966,7 +1012,7 @@ impl DescriptorSecretKey {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
}
BdkDescriptorSecretKey::SinglePriv(_) => {
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
};
@@ -1006,7 +1052,7 @@ impl DescriptorPublicKey {
descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
}))
}
BdkDescriptorPublicKey::SinglePub(_) => {
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
}
@@ -1028,7 +1074,7 @@ impl DescriptorPublicKey {
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
})
}
BdkDescriptorPublicKey::SinglePub(_) => {
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
}
@@ -1118,9 +1164,8 @@ mod test {
}
fn get_descriptor_secret_key() -> DescriptorSecretKey {
let mnemonic =
"chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string();
DescriptorSecretKey::new(Testnet, mnemonic, None).unwrap()
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
DescriptorSecretKey::new(Testnet, Arc::new(mnemonic), None)
}
fn derive_dsk(
@@ -1217,4 +1262,32 @@ mod test {
"e93315d6ce401eb4db803a56232f0ed3e69b053774e6047df54f1bd00e5ea936"
)
}
#[test]
fn test_psbt_fee() {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet {
wallet_mutex: Mutex::new(funded_wallet),
};
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let tx_builder = TxBuilder::new()
.fee_rate(2.0)
.drain_wallet()
.drain_to(drain_to_address.clone());
//dbg!(&tx_builder);
assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_address));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
assert!(tx_builder_result.psbt.fee_rate().is_some());
assert_eq!(
tx_builder_result.psbt.fee_rate().unwrap().as_sat_per_vb(),
2.682927
);
assert!(tx_builder_result.psbt.fee_amount().is_some());
assert_eq!(tx_builder_result.psbt.fee_amount().unwrap(), 220);
}
}

21
tests/README.md Normal file
View File

@@ -0,0 +1,21 @@
# Integration tests for bdk-ffi
This contains simple tests to make sure bdk-ffi can be used as a dependency for each of the
supported bindings languages.
To skip integration tests and only run unit tests use `cargo test --lib`.
To run all tests including integration tests use `CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test`.
Before running integration tests you must install the following development tools:
1. [Java](https://openjdk.org/) and [Kotlin](https://kotlinlang.org/),
[sdkman](https://sdkman.io/) can help:
```shell
sdk install java 11.0.16.1-zulu
sdk install kotlin 1.7.20`
```
2. [Swift](https://www.swift.org/)
3. [Python](https://www.python.org/)

8
tests/bindings/test.kts Normal file
View File

@@ -0,0 +1,8 @@
/*
* This is a basic test kotlin program that does nothing but confirm that the kotlin bindings compile
* and that a program that depends on them will run.
*/
import org.bitcoindevkit.*
val network = Network.TESTNET

15
tests/bindings/test.py Normal file
View File

@@ -0,0 +1,15 @@
import unittest
from bdk import *
class TestBdk(unittest.TestCase):
def test_some_enum(self):
network = Network.TESTNET
def test_some_dict(self):
a = AddressInfo(index=42, address="testaddress")
self.assertEqual(42, a.index)
self.assertEqual("testaddress", a.address)
if __name__=='__main__':
unittest.main()

View File

@@ -0,0 +1,9 @@
/*
* This is a basic test swift program that does nothing but confirm that the swift bindings compile
* and that a program that depends on them will run.
*/
import Foundation
import bdk
let network = Network.testnet

BIN
tests/jna/jna-5.8.0.jar Normal file

Binary file not shown.

View File

@@ -0,0 +1,8 @@
uniffi_macros::build_foreign_language_testcases!(
["src/bdk.udl",],
[
"tests/bindings/test.kts",
"tests/bindings/test.swift",
"tests/bindings/test.py"
]
);