diff --git a/Cargo.lock b/Cargo.lock index a48d3d8..5861e63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -342,6 +342,33 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bdk_chain" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "163b064557cee078e8ee5dd2c88944204506f7b2b1524f78e8fcba38c346da7b" +dependencies = [ + "bitcoin", + "miniscript", + "serde", +] + +[[package]] +name = "bdk_wallet" +version = "1.0.0-alpha.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2926afdbfc54ebf7df2caa51af5be4435b90c01c6fbe5578b51b7c2c0a264bd9" +dependencies = [ + "bdk_chain", + "bitcoin", + "getrandom 0.2.15", + "js-sys", + "miniscript", + "rand 0.8.5", + "serde", + "serde_json", +] + [[package]] name = "bech32" version = "0.9.1" @@ -399,6 +426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6" dependencies = [ "base58ck", + "base64 0.21.7", "bech32 0.11.0", "bitcoin-internals", "bitcoin-io", @@ -1626,6 +1654,17 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "miniscript" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b59c67956fd276ceec0cf194fbf80754ef4d88a496d5cf5e4fdf33561466183d" +dependencies = [ + "bech32 0.11.0", + "bitcoin", + "serde", +] + [[package]] name = "miniz_oxide" version = "0.7.3" @@ -2475,6 +2514,7 @@ name = "side-node" version = "0.1.0" dependencies = [ "async-trait", + "bdk_wallet", "bft-crdt-derive", "bft-json-crdt", "bitcoin", diff --git a/side-node/Cargo.toml b/side-node/Cargo.toml index bb9b395..9f4768d 100644 --- a/side-node/Cargo.toml +++ b/side-node/Cargo.toml @@ -10,6 +10,8 @@ async-trait = "0.1.52" bft-json-crdt = { path = "../crates/bft-json-crdt" } bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" } bitcoin = { version = "0.32.2", features = ["rand"] } +bitcoincore-rpc = "0.19.0" +bitcoincore-rpc-json = "0.19.0" clap = { version = "4.5.4", features = ["derive"] } dirs = "5.0.1" ezsockets = { version = "*", features = ["client"] } @@ -23,8 +25,7 @@ tracing = "0.1.32" # tracing-subscriber = "0.3.9" toml = "0.8.14" indexmap = { version = "2.2.6", features = ["serde"] } -bitcoincore-rpc = "0.19.0" -bitcoincore-rpc-json = "0.19.0" +bdk_wallet = { version = "1.0.0-alpha.13", features = ["all-keys"] } [dev-dependencies] uuid = { version = "1.8.0", features = ["v4"] } diff --git a/side-node/src/clients/btc_rpc.rs b/side-node/src/clients/btc_rpc.rs index b7a9166..0c73ece 100644 --- a/side-node/src/clients/btc_rpc.rs +++ b/side-node/src/clients/btc_rpc.rs @@ -1,27 +1,74 @@ use std::str::FromStr; +use bitcoin::{address::NetworkUnchecked, key::Secp256k1, Address, Amount}; use bitcoincore_rpc::{Auth, Client, RpcApi}; +use crate::{keys, utils}; + +pub fn run(wallet_name: &str) { + let rpc = client_for(wallet_name); + let name = rpc.get_wallet_info().unwrap().wallet_name; + println!("Wallet name: {name}"); + let balance = rpc.get_balance(None, None).unwrap(); + let address = get_default_address(rpc); + let account = rpc.generate_to_address(block_num, address); + println!("account {account:?} has balance {balance:?}"); + + // let sammy = Address::from_str("tb1qtd5e44gf6eqqdknymaydqyvw6869fda32w3l06").unwrap(); + // let amount = Amount::from_sat(1000); + // let sammy = parse_and_validate_address(sammy).unwrap(); + // transfer_funds(rpc, amount, sammy); +} + +// fn login(rpc: Client, wallet_name: &str) { +// let passphrase = serde_json::Value::from_str("password").unwrap(); +// rpc.call("walletpassphrase", &[passphrase]).unwrap(); +// } + +fn get_default_address(rpc: Client) -> Address { + let address = rpc.generate_to_address(None, None).unwrap(); + println!("Default address: {address:?}"); + parse_and_validate_address(address).unwrap() +} + +fn get_info(rpc: Client) { + let info = rpc.get_wallet_info().unwrap(); + println!("Wallet info: {info:?}"); +} + fn parse_and_validate_address( - address: &str, - network: bitcoin::Network, + address: bitcoin::Address, ) -> Result { - let address = address - .parse::>()? - .require_network(network)?; + let require_network = address.require_network(bitcoin::Network::Signet); + let address = require_network?; Ok(address) } -pub fn client() { +fn transfer_funds(rpc: Client, amount: Amount, to: Address) { + rpc.send_to_address(&to, amount, None, None, None, None, None, None) + .unwrap(); +} + +fn client_for(wallet_name: &str) -> Client { let rpc = Client::new( "http://127.0.0.1:38332", Auth::UserPass("dave".to_string(), "password".to_string()), ) .unwrap(); - let a = "tb1p4dvr6dzszagw34scnr6kde0dr2yrmu6gew9faza788rmqy3d645sdm9e50"; - let address = parse_and_validate_address(a, bitcoin::Network::Signet).unwrap(); - let info = rpc.get_address_info(&address).unwrap(); + if !rpc + .list_wallets() + .unwrap() + .contains(&wallet_name.to_string()) + { + rpc.load_wallet(wallet_name).unwrap(); + } - println!("info {info:?} "); + rpc.list_wallets().unwrap().iter().for_each(|wallet| { + if wallet != wallet_name { + rpc.unload_wallet(Some(wallet)).unwrap(); + } + }); + + rpc } diff --git a/side-node/src/lib.rs b/side-node/src/lib.rs index 266018f..88a60a8 100644 --- a/side-node/src/lib.rs +++ b/side-node/src/lib.rs @@ -31,7 +31,7 @@ pub async fn run() { node.start().await; } Some(Commands::Btc {}) => { - clients::btc_rpc::client(); + clients::btc_rpc::run("sammy_wallet"); } None => println!("No command provided. Exiting. See --help for more information."), } diff --git a/side-node/src/utils.rs b/side-node/src/utils.rs index 40bac26..8ecad01 100644 --- a/side-node/src/utils.rs +++ b/side-node/src/utils.rs @@ -22,6 +22,7 @@ pub(crate) fn side_paths(prefix: PathBuf) -> (PathBuf, PathBuf, PathBuf) { (bft_crdt_key_path, bitcoin_key_path, config_path) } +/// Returns the path to the home directory for this host OS and the given node name pub(crate) fn home(name: &String) -> std::path::PathBuf { let mut path = dirs::home_dir().unwrap(); path.push(".side");