Merge commit 'refs/pull/365/head' of github.com:bitcoindevkit/bdk into release/0.8.0
This commit is contained in:
commit
9205295332
4
.github/workflows/cont_integration.yml
vendored
4
.github/workflows/cont_integration.yml
vendored
@ -162,7 +162,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Set default toolchain
|
- name: Set default toolchain
|
||||||
run: rustup default 1.51.0 # STABLE
|
run: rustup default nightly
|
||||||
- name: Set profile
|
- name: Set profile
|
||||||
run: rustup set profile minimal
|
run: rustup set profile minimal
|
||||||
- name: Add rustfmt
|
- name: Add rustfmt
|
||||||
@ -170,4 +170,4 @@ jobs:
|
|||||||
- name: Update toolchain
|
- name: Update toolchain
|
||||||
run: rustup update
|
run: rustup update
|
||||||
- name: Check fmt
|
- name: Check fmt
|
||||||
run: cargo fmt --all -- --check
|
run: cargo fmt --all -- --config format_code_in_doc_comments=true --check
|
||||||
|
@ -37,7 +37,7 @@ pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use bdk::descriptor::error::Error as DescriptorError;
|
/// use bdk::descriptor::error::Error as DescriptorError;
|
||||||
/// use bdk::keys::{KeyError, IntoDescriptorKey};
|
/// use bdk::keys::{IntoDescriptorKey, KeyError};
|
||||||
/// use bdk::miniscript::Legacy;
|
/// use bdk::miniscript::Legacy;
|
||||||
/// use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
|
/// use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
|
||||||
///
|
///
|
||||||
|
@ -192,7 +192,7 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
|
|||||||
/// ```
|
/// ```
|
||||||
/// use bdk::bitcoin::PublicKey;
|
/// use bdk::bitcoin::PublicKey;
|
||||||
///
|
///
|
||||||
/// use bdk::keys::{DescriptorKey, KeyError, ScriptContext, IntoDescriptorKey};
|
/// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError, ScriptContext};
|
||||||
///
|
///
|
||||||
/// pub struct MyKeyType {
|
/// pub struct MyKeyType {
|
||||||
/// pubkey: PublicKey,
|
/// pubkey: PublicKey,
|
||||||
@ -211,8 +211,8 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
|
|||||||
/// use bdk::bitcoin::PublicKey;
|
/// use bdk::bitcoin::PublicKey;
|
||||||
///
|
///
|
||||||
/// use bdk::keys::{
|
/// use bdk::keys::{
|
||||||
/// mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError,
|
/// mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub,
|
||||||
/// ScriptContext, IntoDescriptorKey,
|
/// IntoDescriptorKey, KeyError, ScriptContext,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// pub struct MyKeyType {
|
/// pub struct MyKeyType {
|
||||||
@ -237,7 +237,7 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
|
|||||||
/// ```
|
/// ```
|
||||||
/// use bdk::bitcoin::PublicKey;
|
/// use bdk::bitcoin::PublicKey;
|
||||||
///
|
///
|
||||||
/// use bdk::keys::{DescriptorKey, ExtScriptContext, KeyError, ScriptContext, IntoDescriptorKey};
|
/// use bdk::keys::{DescriptorKey, ExtScriptContext, IntoDescriptorKey, KeyError, ScriptContext};
|
||||||
///
|
///
|
||||||
/// pub struct MyKeyType {
|
/// pub struct MyKeyType {
|
||||||
/// is_legacy: bool,
|
/// is_legacy: bool,
|
||||||
@ -266,7 +266,7 @@ impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
|
|||||||
/// use bdk::bitcoin::PublicKey;
|
/// use bdk::bitcoin::PublicKey;
|
||||||
/// use std::str::FromStr;
|
/// use std::str::FromStr;
|
||||||
///
|
///
|
||||||
/// use bdk::keys::{DescriptorKey, KeyError, IntoDescriptorKey};
|
/// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
|
||||||
///
|
///
|
||||||
/// pub struct MySegwitOnlyKeyType {
|
/// pub struct MySegwitOnlyKeyType {
|
||||||
/// pubkey: PublicKey,
|
/// pubkey: PublicKey,
|
||||||
|
164
src/lib.rs
164
src/lib.rs
@ -14,9 +14,6 @@
|
|||||||
// only enables the `doc_cfg` feature when
|
// only enables the `doc_cfg` feature when
|
||||||
// the `docsrs` configuration attribute is defined
|
// the `docsrs` configuration attribute is defined
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
// only enables the nightly `external_doc` feature when
|
|
||||||
// `test-md-docs` is enabled
|
|
||||||
#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
|
|
||||||
|
|
||||||
//! A modern, lightweight, descriptor-based wallet library written in Rust.
|
//! A modern, lightweight, descriptor-based wallet library written in Rust.
|
||||||
//!
|
//!
|
||||||
@ -45,34 +42,37 @@
|
|||||||
//! ```toml
|
//! ```toml
|
||||||
//! bdk = "0.7.0"
|
//! bdk = "0.7.0"
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
#![cfg_attr(
|
||||||
//! ## Sync the balance of a descriptor
|
feature = "electrum",
|
||||||
//!
|
doc = r##"
|
||||||
//! ### Example
|
## Sync the balance of a descriptor
|
||||||
//! ```ignore
|
|
||||||
//! use bdk::Wallet;
|
### Example
|
||||||
//! use bdk::database::MemoryDatabase;
|
```no_run
|
||||||
//! use bdk::blockchain::{noop_progress, ElectrumBlockchain};
|
use bdk::Wallet;
|
||||||
//!
|
use bdk::database::MemoryDatabase;
|
||||||
//! use bdk::electrum_client::Client;
|
use bdk::blockchain::{noop_progress, ElectrumBlockchain};
|
||||||
//!
|
use bdk::electrum_client::Client;
|
||||||
//! fn main() -> Result<(), bdk::Error> {
|
|
||||||
//! let client = Client::new("ssl://electrum.blockstream.info:60002")?;
|
fn main() -> Result<(), bdk::Error> {
|
||||||
//! let wallet = Wallet::new(
|
let client = Client::new("ssl://electrum.blockstream.info:60002")?;
|
||||||
//! "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
let wallet = Wallet::new(
|
||||||
//! Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
||||||
//! bitcoin::Network::Testnet,
|
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
||||||
//! MemoryDatabase::default(),
|
bitcoin::Network::Testnet,
|
||||||
//! ElectrumBlockchain::from(client)
|
MemoryDatabase::default(),
|
||||||
//! )?;
|
ElectrumBlockchain::from(client)
|
||||||
//!
|
)?;
|
||||||
//! wallet.sync(noop_progress(), None)?;
|
|
||||||
//!
|
wallet.sync(noop_progress(), None)?;
|
||||||
//! println!("Descriptor balance: {} SAT", wallet.get_balance()?);
|
|
||||||
//!
|
println!("Descriptor balance: {} SAT", wallet.get_balance()?);
|
||||||
//! Ok(())
|
|
||||||
//! }
|
Ok(())
|
||||||
//! ```
|
}
|
||||||
|
```
|
||||||
|
"##
|
||||||
|
)]
|
||||||
//!
|
//!
|
||||||
//! ## Generate a few addresses
|
//! ## Generate a few addresses
|
||||||
//!
|
//!
|
||||||
@ -97,61 +97,65 @@
|
|||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
#![cfg_attr(
|
||||||
//! ## Create a transaction
|
feature = "electrum",
|
||||||
//!
|
doc = r##"
|
||||||
//! ### Example
|
## Create a transaction
|
||||||
//! ```ignore
|
|
||||||
//! use base64::decode;
|
### Example
|
||||||
//! use bdk::{FeeRate, Wallet};
|
```no_run
|
||||||
//! use bdk::database::MemoryDatabase;
|
use base64::decode;
|
||||||
//! use bdk::blockchain::{noop_progress, ElectrumBlockchain};
|
|
||||||
//!
|
use bdk::{FeeRate, Wallet};
|
||||||
//! use bdk::electrum_client::Client;
|
use bdk::database::MemoryDatabase;
|
||||||
//!
|
use bdk::blockchain::{noop_progress, ElectrumBlockchain};
|
||||||
//! use bitcoin::consensus::serialize;
|
use bdk::electrum_client::Client;
|
||||||
//! use bdk::wallet::AddressIndex::New;
|
|
||||||
//!
|
use bitcoin::consensus::serialize;
|
||||||
//! fn main() -> Result<(), bdk::Error> {
|
use bdk::wallet::AddressIndex::New;
|
||||||
//! let client = Client::new("ssl://electrum.blockstream.info:60002")?;
|
|
||||||
//! let wallet = Wallet::new(
|
fn main() -> Result<(), bdk::Error> {
|
||||||
//! "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
let client = Client::new("ssl://electrum.blockstream.info:60002")?;
|
||||||
//! Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
let wallet = Wallet::new(
|
||||||
//! bitcoin::Network::Testnet,
|
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
||||||
//! MemoryDatabase::default(),
|
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
||||||
//! ElectrumBlockchain::from(client)
|
bitcoin::Network::Testnet,
|
||||||
//! )?;
|
MemoryDatabase::default(),
|
||||||
//!
|
ElectrumBlockchain::from(client)
|
||||||
//! wallet.sync(noop_progress(), None)?;
|
)?;
|
||||||
//!
|
|
||||||
//! let send_to = wallet.get_address(New)?;
|
wallet.sync(noop_progress(), None)?;
|
||||||
//! let (psbt, details) = {
|
|
||||||
//! let mut builder = wallet.build_tx();
|
let send_to = wallet.get_address(New)?;
|
||||||
//! builder
|
let (psbt, details) = {
|
||||||
//! .add_recipient(send_to.script_pubkey(), 50_000)
|
let mut builder = wallet.build_tx();
|
||||||
//! .enable_rbf()
|
builder
|
||||||
//! .do_not_spend_change()
|
.add_recipient(send_to.script_pubkey(), 50_000)
|
||||||
//! .fee_rate(FeeRate::from_sat_per_vb(5.0))
|
.enable_rbf()
|
||||||
//! builder.finish()?
|
.do_not_spend_change()
|
||||||
//! };
|
.fee_rate(FeeRate::from_sat_per_vb(5.0));
|
||||||
//!
|
builder.finish()?
|
||||||
//! println!("Transaction details: {:#?}", details);
|
};
|
||||||
//! println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
|
|
||||||
//!
|
println!("Transaction details: {:#?}", details);
|
||||||
//! Ok(())
|
println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
|
||||||
//! }
|
|
||||||
//! ```
|
Ok(())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"##
|
||||||
|
)]
|
||||||
//!
|
//!
|
||||||
//! ## Sign a transaction
|
//! ## Sign a transaction
|
||||||
//!
|
//!
|
||||||
//! ### Example
|
//! ### Example
|
||||||
//! ```ignore
|
//! ```no_run
|
||||||
//! use base64::decode;
|
//! use base64::decode;
|
||||||
//! use bdk::{Wallet};
|
|
||||||
//! use bdk::database::MemoryDatabase;
|
|
||||||
//!
|
|
||||||
//! use bitcoin::consensus::deserialize;
|
//! use bitcoin::consensus::deserialize;
|
||||||
//!
|
//!
|
||||||
|
//! use bdk::{Wallet, SignOptions};
|
||||||
|
//! use bdk::database::MemoryDatabase;
|
||||||
|
//!
|
||||||
//! fn main() -> Result<(), bdk::Error> {
|
//! fn main() -> Result<(), bdk::Error> {
|
||||||
//! let wallet = Wallet::new_offline(
|
//! let wallet = Wallet::new_offline(
|
||||||
//! "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
|
//! "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
|
||||||
@ -163,7 +167,7 @@
|
|||||||
//! let psbt = "...";
|
//! let psbt = "...";
|
||||||
//! let mut psbt = deserialize(&base64::decode(psbt).unwrap())?;
|
//! let mut psbt = deserialize(&base64::decode(psbt).unwrap())?;
|
||||||
//!
|
//!
|
||||||
//! let finalized = wallet.sign(&mut psbt, None)?;
|
//! let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
//!
|
//!
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
|
@ -46,17 +46,25 @@
|
|||||||
//! let mut selected_amount = 0;
|
//! let mut selected_amount = 0;
|
||||||
//! let mut additional_weight = 0;
|
//! let mut additional_weight = 0;
|
||||||
//! let all_utxos_selected = required_utxos
|
//! let all_utxos_selected = required_utxos
|
||||||
//! .into_iter().chain(optional_utxos)
|
//! .into_iter()
|
||||||
//! .scan((&mut selected_amount, &mut additional_weight), |(selected_amount, additional_weight), weighted_utxo| {
|
//! .chain(optional_utxos)
|
||||||
//! **selected_amount += weighted_utxo.utxo.txout().value;
|
//! .scan(
|
||||||
//! **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight;
|
//! (&mut selected_amount, &mut additional_weight),
|
||||||
//! Some(weighted_utxo.utxo)
|
//! |(selected_amount, additional_weight), weighted_utxo| {
|
||||||
//! })
|
//! **selected_amount += weighted_utxo.utxo.txout().value;
|
||||||
|
//! **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight;
|
||||||
|
//! Some(weighted_utxo.utxo)
|
||||||
|
//! },
|
||||||
|
//! )
|
||||||
//! .collect::<Vec<_>>();
|
//! .collect::<Vec<_>>();
|
||||||
//! let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
|
//! let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
|
||||||
//! let amount_needed_with_fees = (fee_amount + additional_fees).ceil() as u64 + amount_needed;
|
//! let amount_needed_with_fees =
|
||||||
//! if amount_needed_with_fees > selected_amount {
|
//! (fee_amount + additional_fees).ceil() as u64 + amount_needed;
|
||||||
//! return Err(bdk::Error::InsufficientFunds{ needed: amount_needed_with_fees, available: selected_amount });
|
//! if amount_needed_with_fees > selected_amount {
|
||||||
|
//! return Err(bdk::Error::InsufficientFunds {
|
||||||
|
//! needed: amount_needed_with_fees,
|
||||||
|
//! available: selected_amount,
|
||||||
|
//! });
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! Ok(CoinSelectionResult {
|
//! Ok(CoinSelectionResult {
|
||||||
@ -72,8 +80,7 @@
|
|||||||
//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
|
//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
|
||||||
//! let (psbt, details) = {
|
//! let (psbt, details) = {
|
||||||
//! let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
|
//! let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
|
||||||
//! builder
|
//! builder.add_recipient(to_address.script_pubkey(), 50_000);
|
||||||
//! .add_recipient(to_address.script_pubkey(), 50_000);
|
|
||||||
//! builder.finish()?
|
//! builder.finish()?
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
|
@ -87,9 +87,9 @@ impl TxBuilderContext for BumpFee {}
|
|||||||
/// let (psbt1, details) = {
|
/// let (psbt1, details) = {
|
||||||
/// let mut builder = wallet.build_tx();
|
/// let mut builder = wallet.build_tx();
|
||||||
/// builder
|
/// builder
|
||||||
/// .ordering(TxOrdering::Untouched)
|
/// .ordering(TxOrdering::Untouched)
|
||||||
/// .add_recipient(addr1.script_pubkey(), 50_000)
|
/// .add_recipient(addr1.script_pubkey(), 50_000)
|
||||||
/// .add_recipient(addr2.script_pubkey(), 50_000);
|
/// .add_recipient(addr2.script_pubkey(), 50_000);
|
||||||
/// builder.finish()?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
@ -103,7 +103,10 @@ impl TxBuilderContext for BumpFee {}
|
|||||||
/// builder.finish()?
|
/// builder.finish()?
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// assert_eq!(psbt1.global.unsigned_tx.output[..2], psbt2.global.unsigned_tx.output[..2]);
|
/// assert_eq!(
|
||||||
|
/// psbt1.global.unsigned_tx.output[..2],
|
||||||
|
/// psbt2.global.unsigned_tx.output[..2]
|
||||||
|
/// );
|
||||||
/// # Ok::<(), bdk::Error>(())
|
/// # Ok::<(), bdk::Error>(())
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -246,7 +249,8 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderConte
|
|||||||
/// let mut path = BTreeMap::new();
|
/// let mut path = BTreeMap::new();
|
||||||
/// path.insert("aabbccdd".to_string(), vec![0, 1]);
|
/// path.insert("aabbccdd".to_string(), vec![0, 1]);
|
||||||
///
|
///
|
||||||
/// let builder = wallet.build_tx()
|
/// let builder = wallet
|
||||||
|
/// .build_tx()
|
||||||
/// .add_recipient(to_address.script_pubkey(), 50_000)
|
/// .add_recipient(to_address.script_pubkey(), 50_000)
|
||||||
/// .policy_path(path, KeychainKind::External);
|
/// .policy_path(path, KeychainKind::External);
|
||||||
///
|
///
|
||||||
|
Loading…
x
Reference in New Issue
Block a user