bitcoindevkit / bdk

A modern, lightweight, descriptor-based wallet library written in Rust!
Other
863 stars 309 forks source link

[feature request] Include history and balance for each address in `ElectrumBlockchain` wallets #516

Open w0xlt opened 2 years ago

w0xlt commented 2 years ago

Electrum servers provide a useful feature that shows transaction history and balance by address. Those methods for this are blockchain.scripthash.get_history and blockchain.scripthash.get_balance. This can be seen in Electrum client.

https://user-images.githubusercontent.com/29142493/49842943-b1e4ac80-fdbd-11e8-9400-03d88f4a86ea.png

It would be great if the BDK wallet instance had this information. The AddressInfo struct (which is returned when wallet.get_address() is called) could have these fields as optional. If the wallet is not type Electrum, they can have the value None .

I developed the code below that does this. But a better approach would be if this were done during wallet synchronization, to avoid two requests to the server

pub struct AdditionalAddrInfo {
    pub index: u64,
    pub address: String,
    pub tx_count: u64,
    pub balance: u64
}

pub fn get_batch_history_and_balance(electrum_url: &str, scripts: &Vec::<Script>) -> Vec::<AdditionalAddrInfo> {

    let client = Client::new(electrum_url).unwrap();

    let history_list = client.batch_script_get_history(scripts).unwrap();
    let balance_list = client.batch_script_get_balance(scripts).unwrap();

    let mut result = Vec::<AdditionalAddrInfo>::new();

    for n in 0..scripts.len() {
        let index: u64 = n.try_into().expect("cannot convert");
        let script = &scripts[n];
        let address = Address::from_script(&script, Network::Testnet).unwrap().to_string();
        let balance = balance_list[n].confirmed;
        let tx_count = history_list[n].len().try_into().expect("cannot convert");;

        result.push(AdditionalAddrInfo {
            index,
            address,
            tx_count,
            balance
        });

    }

    return result;
}
LLFourn commented 2 years ago

Rather than doing this differently for different backends couldn't we just scan the transactions in the database and build up an address history that way?

rajarshimaitra commented 2 years ago

@LLFourn yes I think we can. And it would be an useful feature to have. Better to make it out of our DB and have it backend agnostic.

w0xlt commented 2 years ago

Although a backend agnostic implementation would be great, I am not sure if it is possible.

I think there is no way to retrieve transaction count per address in Bitcoin Core RPC, specially in the pruned nodes. I also think the same applies to Compact Block Filters / Neutrino backend.

The balance per address can be agnostic, as this information is in the UTXO set.

rajarshimaitra commented 2 years ago

We don't need the capabilities from blockchain backend. We store all transaction data in DB for each scriptpubkey at each sync. So in theory this should be doable just with the DB. Although I haven't looked in much detail.