Files
bdk/crates/wallet
Steve Myers a112b4d97c Merge bitcoindevkit/bdk#1416: [chain] Change tx_last_seen to Option<u64>
af75817d4b ref(tx_graph): Change last_seen to `HashMap<Txid, u64>` (valued mammal)
6204d2c766 feat(tx_graph): Add method `txs_with_no_anchor_or_last_seen` (valued mammal)
496601b8b1 test(tx_graph): Add test for `list_canonical_txs` (valued mammal)
c4057297a9 wallet: delete method `insert_anchor` (valued mammal)
b34790c6b6 ref(tx_graph)!: Rename `list_chain_txs` to `list_canonical_txs` (valued mammal)
2ce4bb4dfc test(indexed_tx_graph): Add test_get_chain_position (valued mammal)
36f58870cb test(wallet): Add test_insert_tx_balance_and_utxos (valued mammal)
bbc19c3536 fix(tx_graph)!: Change tx_last_seen to `Option<u64>` (valued mammal)
324eeb3eb4 fix(wallet)!: Rework `Wallet::insert_tx` to no longer insert anchors (valued mammal)

Pull request description:

  The PR changes the type of last_seen to `Option<u64>` for `txs` member of `TxGraph`.

  This fixes an issue where unbroadcast and otherwise non-canonical transactions were returned from methods `list_chain_txs` and `Wallet::transactions` because every new tx inserted had a last_seen of 0 making it appear unconfirmed.

  fixes #1446
  fixes #1396

  ### Notes to the reviewers

  ### Changelog notice

  Changed
  - Member `last_seen_unconfirmed` of `TxNode` is changed to `Option<u64>`
  - Renamed `TxGraph` method `list_chain_txs` to `list_canonical_txs`
  - Changed `Wallet::insert_tx` to take a single `tx: Transaction` as parameter

  Added
  - Add method `txs_with_no_anchor_or_last_seen` for `TxGraph`
  - Add method `unbroadcast_transactions` for `Wallet`

  ### 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

  #### Bugfixes:

  * [x] This pull request breaks the existing API
  * [x] I've added tests to reproduce the issue which are now passing
  * [x] I'm linking the issue being fixed by this PR

ACKs for top commit:
  notmandatory:
    Re ACK af75817d4b

Tree-SHA512: e664b3b49e2f547873923f15dffbbc7fa032b6240e5b856b180e9e26123ca141864d10448912dc4a31bbb200c75bef4251a910a4330dac17ee6841b564612d13
2024-07-02 16:50:26 -05:00
..

BDK

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

Crate Info MIT or Apache-2.0 Licensed CI Status API Docs Rustc Version 1.63.0+ Chat on Discord

Project Homepage | Documentation

BDK Wallet

The bdk_wallet crate provides the Wallet type which is a simple, high-level interface built from the low-level components of bdk_chain. Wallet is a good starting point for many simple applications as well as a good demonstration of how to use the other mechanisms to construct a wallet. It has two keychains (external and internal) which are defined by miniscript descriptors and uses them to generate addresses. When you give it chain data it also uses the descriptors to find transaction outputs owned by them. From there, you can create and sign transactions.

For details about the API of Wallet see the module-level documentation.

Blockchain data

In order to get blockchain data for Wallet to consume, you should configure a client from an available chain source. Typically you make a request to the chain source and get a response that the Wallet can use to update its view of the chain.

Blockchain Data Sources

  • bdk_esplora: Grabs blockchain data from Esplora for updating BDK structures.
  • bdk_electrum: Grabs blockchain data from Electrum for updating BDK structures.
  • bdk_bitcoind_rpc: Grabs blockchain data from Bitcoin Core for updating BDK structures.

Examples

Persistence

To persist Wallet state data use a data store crate that reads and writes [bdk_chain::CombinedChangeSet].

Implementations

  • bdk_file_store: Stores wallet changes in a simple flat file.
  • bdk_sqlite: Stores wallet changes in a SQLite relational database file.

Example

use bdk_wallet::{bitcoin::Network, KeychainKind, wallet::{ChangeSet, Wallet}};

// Open or create a new file store for wallet data.
let mut db =
    bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "/tmp/my_wallet.db")
        .expect("create store");

// Create a wallet with initial wallet data read from the file store.
let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
let changeset = db.aggregate_changesets().expect("changeset loaded");
let mut wallet =
    Wallet::new_or_load(descriptor, change_descriptor, changeset, Network::Testnet)
        .expect("create or load wallet");

// Get a new address to receive bitcoin.
let receive_address = wallet.reveal_next_address(KeychainKind::External);
// Persist staged wallet data changes to the file store.
let staged_changeset = wallet.take_staged();
if let Some(changeset) = staged_changeset {
    db.append_changeset(&changeset)
        .expect("must commit changes to database");
}
println!("Your new receive address is: {}", receive_address.address);

Testing

Unit testing

cargo test

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.