bdk_sqlite 0.5.0

SQLite store for BDK using sqlx
Documentation
#![allow(unused)]

use std::collections::BTreeSet;
use std::io::Write;

use bdk_esplora::EsploraAsyncExt;
use bdk_esplora::esplora_client;
use bdk_sqlite::Store;
use bdk_wallet::bitcoin;
use bdk_wallet::{KeychainKind, Wallet};

use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};

const DB_PATH: &str = "test.db";
const NETWORK: bitcoin::Network = bitcoin::Network::Testnet4;
const EXTERNAL_DESC: &str = "wpkh([e273fe42/84'/1'/0']tpubDCmr3Luq75npLaYmRqqW1rLfSbfpnBXwLwAmUbR333fp95wjCHar3zoc9zSWovZFwrWr53mm3NTVqt6d1Pt6G26uf4etQjc3Pr5Hxe9QEQ2/0/*)";
const INTERNAL_DESC: &str = "wpkh([e273fe42/84'/1'/0']tpubDCmr3Luq75npLaYmRqqW1rLfSbfpnBXwLwAmUbR333fp95wjCHar3zoc9zSWovZFwrWr53mm3NTVqt6d1Pt6G26uf4etQjc3Pr5Hxe9QEQ2/1/*)";
const ESPLORA_URL: &str = "https://mempool.space/testnet4/api";
const STOP_GAP: usize = 20;
const PARALLEL_REQUESTS: usize = 1;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Get a new in memory `Store` for testing.
    // let mut db = Store::new_memory().await?;

    // Configure the options yourself and connect lazily when creating a `Store`.
    let mut options = SqliteConnectOptions::new();
    options = options.filename(DB_PATH);
    options = options.create_if_missing(true);
    let mut pool = SqlitePoolOptions::new()
        .max_connections(10)
        .connect_lazy_with(options);
    let mut db = Store::new_pool(pool).await?;

    // Or connect to the database straight away.
    // let mut db = Store::new(DB_PATH).await?;

    let mut wallet = match Wallet::load().load_wallet_async(&mut db).await? {
        Some(wallet) => wallet,
        None => {
            Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
                .network(NETWORK)
                .create_wallet_async(&mut db)
                .await?
        }
    };

    // Scan
    let client = esplora_client::Builder::new(ESPLORA_URL).build_async()?;

    let request = wallet.start_full_scan().inspect({
        let mut once = BTreeSet::<KeychainKind>::new();
        move |keychain, spk_i, _| {
            if once.insert(keychain) {
                print!("\nScanning keychain [{keychain:?}]");
            }
            print!(" {spk_i:<3}");
            std::io::stdout().flush().unwrap();
        }
    });

    let update = client
        .full_scan(request, STOP_GAP, PARALLEL_REQUESTS)
        .await?;

    wallet.apply_update(update)?;
    println!();

    println!(
        "Address: {}",
        wallet.next_unused_address(KeychainKind::External)
    );

    wallet.persist_async(&mut db).await?;

    println!("{}", wallet.balance().total());

    Ok(())
}