Alekos Filini ccbbad3e9e
[keys] Improve the API of DerivableKey
A new `ExtendedKey` type has been added, which is basically an enum of
`bip32::ExtendedPubKey` and `bip32::ExtendedPrivKey`, with some extra metadata
regarding the `ScriptContext`.

This type has some methods that make it very easy to extract its content as
either an `xprv` or `xpub`.

The `DerivableKey` trait has been updated so that the user now only has to
implement a method (`DerivableKey::into_extended_key()`) to perform the
conversion into an `ExtendedKey`.

The method that was previously called `add_metadata()` has now been renamed
to `into_descriptor_key()`, and it has
a blanket implementation.
2021-01-29 15:21:36 -05:00
2021-01-27 14:53:48 -08:00
2021-01-13 22:58:02 -06:00
2020-09-14 15:13:43 -07:00
2021-01-09 10:41:48 -08:00
2020-11-16 12:09:14 +01:00
2021-01-18 10:46:06 -08:00
2020-02-07 12:28:29 +01:00

BDK

A modern, lightweight, descriptor-based wallet library written in Rust!

Crate Info MIT Licensed CI Status API Docs Rustc Version 1.45+ Chat on Discord

Project Homepage | Documentation

About

The bdk library aims to be the core building block for Bitcoin wallets of any kind.

  • It uses Miniscript to support descriptors with generalized conditions. This exact same library can be used to build single-sig wallets, multisigs, timelocked contracts and more.
  • It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
  • It's built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
  • It's very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.

Examples

Sync the balance of a descriptor

use bdk::Wallet;
use bdk::database::MemoryDatabase;
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")?;
    let wallet = Wallet::new(
        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
        ElectrumBlockchain::from(client)
    )?;

    wallet.sync(noop_progress(), None)?;

    println!("Descriptor balance: {} SAT", wallet.get_balance()?);

    Ok(())
}

Generate a few addresses

use bdk::{Wallet, database::MemoryDatabase};

fn main() -> Result<(), bdk::Error> {
    let wallet = Wallet::new_offline(
        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
    )?;

    println!("Address #0: {}", wallet.get_new_address()?);
    println!("Address #1: {}", wallet.get_new_address()?);
    println!("Address #2: {}", wallet.get_new_address()?);

    Ok(())
}

Create a transaction

use bdk::{FeeRate, TxBuilder, Wallet};
use bdk::database::MemoryDatabase;
use bdk::blockchain::{noop_progress, ElectrumBlockchain};

use bdk::electrum_client::Client;

use bitcoin::consensus::serialize;

fn main() -> Result<(), bdk::Error> {
    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    let wallet = Wallet::new(
        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
        ElectrumBlockchain::from(client)
    )?;

    wallet.sync(noop_progress(), None)?;

    let send_to = wallet.get_new_address()?;
    let (psbt, details) = wallet.create_tx(
        TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
            .enable_rbf()
            .do_not_spend_change()
            .fee_rate(FeeRate::from_sat_per_vb(5.0))
    )?;

    println!("Transaction details: {:#?}", details);
    println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));

    Ok(())
}

Sign a transaction

use bdk::{Wallet, database::MemoryDatabase};

use bitcoin::consensus::deserialize;

fn main() -> Result<(), bdk::Error> {
    let wallet = Wallet::new_offline(
        "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
        Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
        bitcoin::Network::Testnet,
        MemoryDatabase::default(),
    )?;

    let psbt = "...";
    let psbt = deserialize(&base64::decode(psbt).unwrap())?;

    let (signed_psbt, finalized) = wallet.sign(psbt, None)?;

    Ok(())
}
Languages
Rust 99.9%