#![crate_name = "bitcoind_client"]
#![forbid(unsafe_code)]
#![allow(bare_trait_objects)]
#![allow(ellipsis_inclusive_range_patterns)]
#![warn(rustdoc::broken_intra_doc_links)]
#![warn(missing_docs)]
pub mod bitcoind_client;
mod convert;
#[cfg(feature = "dummy-source")]
pub mod dummy;
pub mod esplora_client;
pub mod follower;
#[cfg(test)]
mod test_utils;
pub mod txoo_follower;
pub use self::bitcoind_client::{BitcoindClient, BlockSource};
pub use self::convert::BlockchainInfo;
pub use crate::bitcoind_client::bitcoind_client_from_url;
use crate::esplora_client::EsploraClient;
use async_trait::async_trait;
use bitcoin::OutPoint;
use bitcoin::{Network, Transaction};
use core::fmt;
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
use url::Url;
#[derive(Debug)]
pub enum Error {
JsonRpc(jsonrpc_async::error::Error),
Json(serde_json::error::Error),
Io(std::io::Error),
Esplora(String),
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str(format!("{:?}", self).as_str())
}
}
impl std::error::Error for Error {}
impl From<jsonrpc_async::error::Error> for Error {
fn from(e: jsonrpc_async::error::Error) -> Error {
Error::JsonRpc(e)
}
}
impl From<serde_json::error::Error> for Error {
fn from(e: serde_json::error::Error) -> Error {
Error::Json(e)
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Error {
Error::Io(e)
}
}
#[async_trait]
pub trait Explorer {
async fn get_utxo_confirmations(&self, txout: &OutPoint) -> Result<Option<u64>, Error>;
async fn broadcast_transaction(&self, tx: &Transaction) -> Result<(), Error>;
async fn get_utxo_spending_tx(&self, txout: &OutPoint) -> Result<Option<Transaction>, Error>;
}
pub enum BlockExplorerType {
Bitcoind,
Esplora,
}
pub async fn explorer_from_url(
network: Network,
block_explorer_type: BlockExplorerType,
url: Url,
) -> Box<dyn Explorer> {
match block_explorer_type {
BlockExplorerType::Bitcoind => Box::new(bitcoind_client_from_url(url, network).await),
BlockExplorerType::Esplora => Box::new(EsploraClient::new(url).await),
}
}
fn bitcoin_network_path(base_path: PathBuf, network: Network) -> PathBuf {
match network {
Network::Bitcoin => base_path,
Network::Testnet => base_path.join("testnet3"),
Network::Signet => base_path.join("signet"),
Network::Regtest => base_path.join("regtest"),
_ => unreachable!()
}
}
pub fn default_bitcoin_rpc_url(rpc: Option<String>, network: Network) -> String {
rpc.unwrap_or_else(|| {
match network {
Network::Bitcoin => "http://localhost:8332",
Network::Testnet => "http://localhost:18332",
Network::Signet => "http://localhost:38442",
Network::Regtest => "http://localhost:18443",
_ => unreachable!(),
}
.to_owned()
})
}