Merge commit 'refs/pull/407/head' of github.com:bitcoindevkit/bdk
This commit is contained in:
commit
2b0c4f0817
@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Added `RpcBlockchain` in the `AnyBlockchain` struct to allow using Rpc backend where `AnyBlockchain` is used (eg `bdk-cli`)
|
||||||
|
|
||||||
### Wallet
|
### Wallet
|
||||||
|
|
||||||
- Removed and replaced `set_single_recipient` with more general `drain_to` and replaced `maintain_single_recipient` with `allow_shrinking`.
|
- Removed and replaced `set_single_recipient` with more general `drain_to` and replaced `maintain_single_recipient` with `allow_shrinking`.
|
||||||
|
@ -94,6 +94,8 @@ macro_rules! impl_inner_method {
|
|||||||
AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
|
AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
|
||||||
#[cfg(feature = "compact_filters")]
|
#[cfg(feature = "compact_filters")]
|
||||||
AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
|
AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
|
||||||
|
#[cfg(feature = "rpc")]
|
||||||
|
AnyBlockchain::Rpc(inner) => inner.$name( $($args, )* ),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,6 +118,10 @@ pub enum AnyBlockchain {
|
|||||||
#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
|
||||||
/// Compact filters client
|
/// Compact filters client
|
||||||
CompactFilters(compact_filters::CompactFiltersBlockchain),
|
CompactFilters(compact_filters::CompactFiltersBlockchain),
|
||||||
|
#[cfg(feature = "rpc")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
|
||||||
|
/// RPC client
|
||||||
|
Rpc(rpc::RpcBlockchain),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[maybe_async]
|
#[maybe_async]
|
||||||
@ -157,6 +163,7 @@ impl Blockchain for AnyBlockchain {
|
|||||||
impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
|
impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
|
||||||
impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
|
impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
|
||||||
impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
|
impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
|
||||||
|
impl_from!(rpc::RpcBlockchain, AnyBlockchain, Rpc, #[cfg(feature = "rpc")]);
|
||||||
|
|
||||||
/// Type that can contain any of the blockchain configurations defined by the library
|
/// Type that can contain any of the blockchain configurations defined by the library
|
||||||
///
|
///
|
||||||
@ -206,6 +213,10 @@ pub enum AnyBlockchainConfig {
|
|||||||
#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
|
||||||
/// Compact filters client
|
/// Compact filters client
|
||||||
CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
|
CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
|
||||||
|
#[cfg(feature = "rpc")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
|
||||||
|
/// RPC client configuration
|
||||||
|
Rpc(rpc::RpcConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigurableBlockchain for AnyBlockchain {
|
impl ConfigurableBlockchain for AnyBlockchain {
|
||||||
@ -225,6 +236,10 @@ impl ConfigurableBlockchain for AnyBlockchain {
|
|||||||
AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
|
AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
|
||||||
compact_filters::CompactFiltersBlockchain::from_config(inner)?,
|
compact_filters::CompactFiltersBlockchain::from_config(inner)?,
|
||||||
),
|
),
|
||||||
|
#[cfg(feature = "rpc")]
|
||||||
|
AnyBlockchainConfig::Rpc(inner) => {
|
||||||
|
AnyBlockchain::Rpc(rpc::RpcBlockchain::from_config(inner)?)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,3 +247,4 @@ impl ConfigurableBlockchain for AnyBlockchain {
|
|||||||
impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
|
impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
|
||||||
impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
|
impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
|
||||||
impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
|
impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
|
||||||
|
impl_from!(rpc::RpcConfig, AnyBlockchainConfig, Rpc, #[cfg(feature = "rpc")]);
|
||||||
|
@ -30,9 +30,19 @@ use crate::FeeRate;
|
|||||||
#[cfg(any(feature = "electrum", feature = "esplora"))]
|
#[cfg(any(feature = "electrum", feature = "esplora"))]
|
||||||
pub(crate) mod utils;
|
pub(crate) mod utils;
|
||||||
|
|
||||||
#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))]
|
#[cfg(any(
|
||||||
|
feature = "electrum",
|
||||||
|
feature = "esplora",
|
||||||
|
feature = "compact_filters",
|
||||||
|
feature = "rpc"
|
||||||
|
))]
|
||||||
pub mod any;
|
pub mod any;
|
||||||
#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))]
|
#[cfg(any(
|
||||||
|
feature = "electrum",
|
||||||
|
feature = "esplora",
|
||||||
|
feature = "compact_filters",
|
||||||
|
feature = "rpc"
|
||||||
|
))]
|
||||||
pub use any::{AnyBlockchain, AnyBlockchainConfig};
|
pub use any::{AnyBlockchain, AnyBlockchainConfig};
|
||||||
|
|
||||||
#[cfg(feature = "electrum")]
|
#[cfg(feature = "electrum")]
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
//! ## Example
|
//! ## Example
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! # use bdk::blockchain::{RpcConfig, RpcBlockchain, ConfigurableBlockchain};
|
//! # use bdk::blockchain::{RpcConfig, RpcBlockchain, ConfigurableBlockchain, rpc::Auth};
|
||||||
//! let config = RpcConfig {
|
//! let config = RpcConfig {
|
||||||
//! url: "127.0.0.1:18332".to_string(),
|
//! url: "127.0.0.1:18332".to_string(),
|
||||||
//! auth: bitcoincore_rpc::Auth::CookieFile("/home/user/.bitcoin/.cookie".into()),
|
//! auth: Auth::Cookie {
|
||||||
|
//! file: "/home/user/.bitcoin/.cookie".into(),
|
||||||
|
//! },
|
||||||
//! network: bdk::bitcoin::Network::Testnet,
|
//! network: bdk::bitcoin::Network::Testnet,
|
||||||
//! wallet_name: "wallet_name".to_string(),
|
//! wallet_name: "wallet_name".to_string(),
|
||||||
//! skip_blocks: None,
|
//! skip_blocks: None,
|
||||||
@ -41,10 +43,12 @@ use bitcoincore_rpc::json::{
|
|||||||
ImportMultiRequestScriptPubkey, ImportMultiRescanSince,
|
ImportMultiRequestScriptPubkey, ImportMultiRescanSince,
|
||||||
};
|
};
|
||||||
use bitcoincore_rpc::jsonrpc::serde_json::Value;
|
use bitcoincore_rpc::jsonrpc::serde_json::Value;
|
||||||
use bitcoincore_rpc::{Auth, Client, RpcApi};
|
use bitcoincore_rpc::Auth as RpcAuth;
|
||||||
|
use bitcoincore_rpc::{Client, RpcApi};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// The main struct for RPC backend implementing the [crate::blockchain::Blockchain] trait
|
/// The main struct for RPC backend implementing the [crate::blockchain::Blockchain] trait
|
||||||
@ -64,7 +68,7 @@ pub struct RpcBlockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// RpcBlockchain configuration options
|
/// RpcBlockchain configuration options
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
pub struct RpcConfig {
|
pub struct RpcConfig {
|
||||||
/// The bitcoin node url
|
/// The bitcoin node url
|
||||||
pub url: String,
|
pub url: String,
|
||||||
@ -78,6 +82,39 @@ pub struct RpcConfig {
|
|||||||
pub skip_blocks: Option<u32>,
|
pub skip_blocks: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This struct is equivalent to [bitcoincore_rpc::Auth] but it implements [serde::Serialize]
|
||||||
|
/// To be removed once upstream equivalent is implementing Serialize (json serialization format
|
||||||
|
/// should be the same) https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/181
|
||||||
|
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Auth {
|
||||||
|
/// None authentication
|
||||||
|
None,
|
||||||
|
/// Authentication with username and password, usually [Auth::Cookie] should be preferred
|
||||||
|
UserPass {
|
||||||
|
/// Username
|
||||||
|
username: String,
|
||||||
|
/// Password
|
||||||
|
password: String,
|
||||||
|
},
|
||||||
|
/// Authentication with a cookie file
|
||||||
|
Cookie {
|
||||||
|
/// Cookie file
|
||||||
|
file: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Auth> for RpcAuth {
|
||||||
|
fn from(auth: Auth) -> Self {
|
||||||
|
match auth {
|
||||||
|
Auth::None => RpcAuth::None,
|
||||||
|
Auth::UserPass { username, password } => RpcAuth::UserPass(username, password),
|
||||||
|
Auth::Cookie { file } => RpcAuth::CookieFile(file),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RpcBlockchain {
|
impl RpcBlockchain {
|
||||||
fn get_node_synced_height(&self) -> Result<u32, Error> {
|
fn get_node_synced_height(&self) -> Result<u32, Error> {
|
||||||
let info = self.client.get_address_info(&self._storage_address)?;
|
let info = self.client.get_address_info(&self._storage_address)?;
|
||||||
@ -320,7 +357,7 @@ impl ConfigurableBlockchain for RpcBlockchain {
|
|||||||
let wallet_url = format!("{}/wallet/{}", config.url, &wallet_name);
|
let wallet_url = format!("{}/wallet/{}", config.url, &wallet_name);
|
||||||
debug!("connecting to {} auth:{:?}", wallet_url, config.auth);
|
debug!("connecting to {} auth:{:?}", wallet_url, config.auth);
|
||||||
|
|
||||||
let client = Client::new(wallet_url, config.auth.clone())?;
|
let client = Client::new(wallet_url, config.auth.clone().into())?;
|
||||||
let loaded_wallets = client.list_wallets()?;
|
let loaded_wallets = client.list_wallets()?;
|
||||||
if loaded_wallets.contains(&wallet_name) {
|
if loaded_wallets.contains(&wallet_name) {
|
||||||
debug!("wallet already loaded {:?}", wallet_name);
|
debug!("wallet already loaded {:?}", wallet_name);
|
||||||
@ -427,7 +464,7 @@ crate::bdk_blockchain_tests! {
|
|||||||
fn test_instance(test_client: &TestClient) -> RpcBlockchain {
|
fn test_instance(test_client: &TestClient) -> RpcBlockchain {
|
||||||
let config = RpcConfig {
|
let config = RpcConfig {
|
||||||
url: test_client.bitcoind.rpc_url(),
|
url: test_client.bitcoind.rpc_url(),
|
||||||
auth: Auth::CookieFile(test_client.bitcoind.params.cookie_file.clone()),
|
auth: Auth::Cookie { file: test_client.bitcoind.params.cookie_file.clone() },
|
||||||
network: Network::Regtest,
|
network: Network::Regtest,
|
||||||
wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ),
|
wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ),
|
||||||
skip_blocks: None,
|
skip_blocks: None,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user