use std::fmt;
use std::path::{Path, PathBuf};
use anyhow::Context;
use bitcoin::{FeeRate, Network};
use bitcoin_ext::{BlockDelta, BlockHeight};
use crate::chain::ChainSourceSpec;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum BarkNetwork {
Mainnet,
Signet,
Mutinynet,
Regtest,
}
impl BarkNetwork {
pub fn as_bitcoin(&self) -> Network {
match self {
Self::Mainnet => Network::Bitcoin,
Self::Signet => Network::Signet,
Self::Mutinynet => Network::Signet,
Self::Regtest => Network::Regtest,
}
}
}
impl fmt::Display for BarkNetwork {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Mainnet => f.write_str("mainnet"),
Self::Signet => f.write_str("signet"),
Self::Mutinynet => f.write_str("mutinynet"),
Self::Regtest => f.write_str("regtest"),
}
}
}
impl fmt::Debug for BarkNetwork {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub server_address: String,
pub server_access_token: Option<String>,
pub esplora_address: Option<String>,
pub bitcoind_address: Option<String>,
pub bitcoind_cookiefile: Option<PathBuf>,
pub bitcoind_user: Option<String>,
pub bitcoind_pass: Option<String>,
pub vtxo_refresh_expiry_threshold: BlockHeight,
pub vtxo_exit_margin: BlockDelta,
pub htlc_recv_claim_delta: BlockDelta,
pub lightning_receive_claim_retries: u8,
#[cfg(feature = "socks5-proxy")]
pub socks5_proxy: Option<String>,
pub fallback_fee_rate: Option<FeeRate>,
pub round_tx_required_confirmations: BlockHeight,
pub offboard_required_confirmations: BlockHeight,
pub daemon_sync_interval_secs: u64,
pub daemon_manual_sync: bool,
}
impl Config {
pub fn network_default(network: Network) -> Self {
let mut ret = Self {
server_address: "http://127.0.0.1:3535".to_owned(),
server_access_token: None,
esplora_address: None,
bitcoind_address: None,
bitcoind_cookiefile: None,
bitcoind_user: None,
bitcoind_pass: None,
#[cfg(feature = "socks5-proxy")]
socks5_proxy: None,
vtxo_refresh_expiry_threshold: 144,
vtxo_exit_margin: 12,
htlc_recv_claim_delta: 18,
lightning_receive_claim_retries: 5,
fallback_fee_rate: Some(FeeRate::from_sat_per_vb_u32(2)),
round_tx_required_confirmations: 1,
offboard_required_confirmations: 2,
daemon_sync_interval_secs: 60,
daemon_manual_sync: false,
};
if network != Network::Bitcoin {
ret.vtxo_refresh_expiry_threshold = 12;
ret.fallback_fee_rate = Some(FeeRate::from_sat_per_vb_u32(1));
ret.round_tx_required_confirmations = 1;
ret.offboard_required_confirmations = 0;
}
ret
}
pub fn load(network: Network, path: impl AsRef<Path>) -> anyhow::Result<Config> {
let default = config::Config::try_from(&Self::network_default(network))
.expect("default config failed to deconstruct");
Ok(config::Config::builder()
.add_source(default)
.add_source(config::File::from(path.as_ref()).required(false))
.add_source(config::Environment::with_prefix("BARK"))
.build().context("error building config")?
.try_deserialize::<Config>().context("error parsing config")?)
}
pub fn chain_source(&self) -> anyhow::Result<ChainSourceSpec> {
if let Some(ref url) = self.esplora_address {
Ok(ChainSourceSpec::Esplora {
url: url.clone(),
})
} else if let Some(ref url) = self.bitcoind_address {
let auth = if let Some(ref c) = self.bitcoind_cookiefile {
bitcoin_ext::rpc::Auth::CookieFile(c.clone())
} else {
bitcoin_ext::rpc::Auth::UserPass(
self.bitcoind_user.clone().context("need bitcoind auth config")?,
self.bitcoind_pass.clone().context("need bitcoind auth config")?,
)
};
Ok(ChainSourceSpec::Bitcoind {
url: url.clone(),
auth,
})
} else {
bail!("Need to either provide esplora or bitcoind info");
}
}
}