From: rajarshimaitra Date: Fri, 9 Sep 2022 07:59:37 +0000 (+0530) Subject: Update nodes.rs X-Git-Tag: v0.6.0~5^2~5 X-Git-Url: http://internal-gitweb-vhost/script/%22https:/enum.FileError.html?a=commitdiff_plain;h=aa6a687c904eac52202e4d3fbdd1fe4e6954bacd;p=bdk-cli Update nodes.rs Add the backend Node mechanism. --- diff --git a/src/nodes.rs b/src/nodes.rs index f3873e8..fd2686f 100644 --- a/src/nodes.rs +++ b/src/nodes.rs @@ -8,14 +8,120 @@ //! The Node structures //! -//! This module defines the the backend node structures for `regtest-*` features +//! This module defines containers for different backend clients. +//! These Backends are auto-deployed in `regtest-*` features to spawn a blockchain +//! interface of selected types, and connects the bdk-cli wallet to it. +//! +//! For more information check TODO: [Add readme section for `regtest-*` features.] + +#[cfg(feature = "regtest-node")] +use { + crate::commands::NodeSubCommand, + bdk::{ + bitcoin::{Address, Amount}, + Error, + }, + electrsd::bitcoind::bitcoincore_rpc::{Client, RpcApi}, + serde_json::Value, + std::str::FromStr, +}; #[allow(dead_code)] // Different regtest node types activated with `regtest-*` mode. // If `regtest-*` feature not activated, then default is `None`. pub enum Nodes { None, - Bitcoin { rpc_url: String, rpc_auth: String }, - Electrum { electrum_url: String }, - Esplora { esplora_url: String }, + #[cfg(feature = "regtest-bitcoin")] + // A bitcoin core backend. Wallet connected to it via RPC. + Bitcoin { + bitcoind: Box, + }, + #[cfg(feature = "regtest-electrum")] + // An Electrum backend, with an underlying bitcoin core + // Wallet connected to it, via the electrum url + Electrum { + bitcoind: Box, + electrsd: Box, + }, + // An Esplora backend with underlying bitcoin core. + // Wallet connected to it, via the esplora url + #[cfg(any(feature = "regtest-esplora-ureq", feature = "regtest-esplora-reqwest"))] + Esplora { + bitcoind: Box, + esplorad: Box, + }, +} + +#[cfg(feature = "regtest-node")] +impl Nodes { + /// Execute a [`NodeSubCommand`] in the backend + pub fn exec_cmd(&self, cmd: NodeSubCommand) -> Result { + let client = self.get_client()?; + match cmd { + NodeSubCommand::GetInfo => Ok(serde_json::to_value( + client + .get_blockchain_info() + .map_err(|e| Error::Generic(e.to_string()))?, + )?), + + NodeSubCommand::GetNewAddress => Ok(serde_json::to_value( + client + .get_new_address(None, None) + .map_err(|e| Error::Generic(e.to_string()))?, + )?), + + NodeSubCommand::Generate { block_num } => { + let core_addrs = client + .get_new_address(None, None) + .map_err(|e| Error::Generic(e.to_string()))?; + let block_hashes = client + .generate_to_address(block_num, &core_addrs) + .map_err(|e| Error::Generic(e.to_string()))?; + Ok(serde_json::to_value(block_hashes)?) + } + + NodeSubCommand::GetBalance => Ok(serde_json::to_value( + client + .get_balance(None, None) + .map_err(|e| Error::Generic(e.to_string()))? + .to_string(), + )?), + + NodeSubCommand::SendToAddress { address, amount } => { + let address = + Address::from_str(&address).map_err(|e| Error::Generic(e.to_string()))?; + let amount = Amount::from_sat(amount); + let txid = client + .send_to_address(&address, amount, None, None, None, None, None, None) + .map_err(|e| Error::Generic(e.to_string()))?; + Ok(serde_json::to_value(&txid)?) + } + + NodeSubCommand::BitcoinCli(args) => { + let cmd = &args[0]; + let args = args[1..] + .iter() + .map(|arg| serde_json::Value::from_str(arg)) + .collect::, _>>()?; + client + .call::(cmd, &args) + .map_err(|e| Error::Generic(e.to_string())) + } + } + } + + // Expose the underlying RPC client + pub fn get_client(&self) -> Result<&Client, Error> { + match self { + Self::None => Err(Error::Generic( + "No backend available. Cannot execute node commands".to_string(), + )), + #[cfg(feature = "regtest-bitcoin")] + Self::Bitcoin { bitcoind } => Ok(&bitcoind.client), + #[cfg(feature = "regtest-electrum")] + Self::Electrum { bitcoind, .. } => Ok(&bitcoind.client), + #[cfg(any(feature = "regtest-esplora-ureq", feature = "regtest-esplora-reqwest"))] + Self::Esplora { bitcoind, .. } => Ok(&bitcoind.client), + } + } }