use std::time::Duration;
use ::bitcoin::{Amount, Txid};
use async_trait::async_trait;
use thiserror::Error;
pub mod bitcoin;
pub mod liquid;
pub use self::{
bitcoin::{BitcoinChainClient, BitcoinEsplora},
liquid::{LiquidChainClient, LiquidEsplora},
};
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
#[derive(Debug, Error)]
pub enum EsploraError {
#[error(transparent)]
Client(#[from] esplora_client::Error),
#[error(transparent)]
Http(#[from] reqwest::Error),
#[error("invalid fee rate: {0} sat/vB")]
InvalidFeeRate(f64),
#[error("no fee estimate within {0} blocks")]
NoFeeEstimate(usize),
#[error("invalid Esplora response: {0}")]
InvalidResponse(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Outspend {
pub txid: Txid,
pub vin: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EsploraUtxo {
pub txid: Txid,
pub vout: u32,
pub value: Amount,
}
#[derive(Debug, Error)]
pub enum ChainClientError {
#[error(transparent)]
Other(#[from] anyhow::Error),
}
impl From<crate::transaction::TxError> for ChainClientError {
fn from(e: crate::transaction::TxError) -> Self {
Self::Other(e.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Utxo {
pub txid: String,
pub vout: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddressUtxo {
pub txid: String,
pub vout: u32,
pub value: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OutpointSpend {
Unspent,
Spent(SpendingTx),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SpendingTx {
pub txid: String,
pub vin: u32,
pub confirmations: u32,
pub tx_hex: String,
}
#[async_trait]
pub trait ChainClient: Send + Sync {
async fn get_fee_rate(&self, target: usize) -> Result<f64, ChainClientError>;
async fn get_tx_confirmations(&self, txid: &str) -> Result<Option<u32>, ChainClientError>;
async fn get_tx(&self, txid: &str) -> Result<Option<String>, ChainClientError>;
async fn broadcast(&self, tx_hex: &str) -> Result<String, ChainClientError>;
async fn get_height(&self) -> Result<u32, ChainClientError>;
async fn get_confirmation_height(&self, txid: &str) -> Result<Option<u32>, ChainClientError>;
async fn address_utxos(&self, address: &str) -> Result<Vec<AddressUtxo>, ChainClientError>;
async fn outpoint_spend(
&self,
txid: &str,
vout: u32,
) -> Result<OutpointSpend, ChainClientError>;
}