fedimint_bitcoind/
shared.rs
1use std::collections::BTreeMap;
2use std::sync::Arc;
3
4use fedimint_core::Feerate;
5use fedimint_core::task::TaskGroup;
6use fedimint_core::util::SafeUrl;
7use fedimint_logging::LOG_BITCOIN;
8use fedimint_server_core::ServerModuleShared;
9use tokio::sync::{Mutex, watch};
10use tracing::debug;
11
12pub const CONFIRMATION_TARGET: u16 = 1;
21
22use crate::DynBitcoindRpc;
23type SharedKey = (bitcoin::Network, SafeUrl);
24
25struct ServerModuleSharedBitcoinInner {
38 task_group: TaskGroup,
39 feerate_rx: tokio::sync::Mutex<BTreeMap<SharedKey, watch::Receiver<Option<Feerate>>>>,
40 block_count_rx: tokio::sync::Mutex<BTreeMap<SharedKey, watch::Receiver<Option<u64>>>>,
41}
42
43impl ServerModuleSharedBitcoinInner {
44 pub async fn feerate_receiver(
45 &self,
46 network: bitcoin::Network,
47 btc_rpc: DynBitcoindRpc,
48 ) -> anyhow::Result<watch::Receiver<Option<Feerate>>> {
49 let key = (network, btc_rpc.get_bitcoin_rpc_config().url);
50 let mut write = self.feerate_rx.lock().await;
51
52 if let Some(v) = write.get(&key) {
53 return Ok(v.clone());
54 }
55
56 let (tx, rx) = watch::channel(None);
57
58 btc_rpc
59 .clone()
60 .spawn_fee_rate_update_task(&self.task_group, network, 1, {
61 move |feerate| {
62 debug!(target: LOG_BITCOIN, %feerate, "New feerate");
63 tx.send_replace(Some(feerate));
64 }
65 })?;
66
67 write.insert(key, rx.clone());
68
69 Ok(rx)
70 }
71 pub async fn block_count_receiver(
72 &self,
73 network: bitcoin::Network,
74 btc_rpc: DynBitcoindRpc,
75 ) -> watch::Receiver<Option<u64>> {
76 let key = (network, btc_rpc.get_bitcoin_rpc_config().url);
77 let mut write = self.block_count_rx.lock().await;
78
79 if let Some(v) = write.get(&key) {
80 return v.clone();
81 }
82
83 let (tx, rx) = watch::channel(None);
84
85 btc_rpc
86 .clone()
87 .spawn_block_count_update_task(&self.task_group, {
88 move |block_count| {
89 debug!(target: LOG_BITCOIN, %block_count, "New block count");
90 tx.send_replace(Some(block_count));
91 }
92 });
93
94 write.insert(key, rx.clone());
95
96 rx
97 }
98}
99
100#[derive(Clone)]
101pub struct ServerModuleSharedBitcoin {
102 inner: Arc<ServerModuleSharedBitcoinInner>,
103}
104
105impl ServerModuleSharedBitcoin {
106 pub async fn feerate_receiver(
107 &self,
108 network: bitcoin::Network,
109 btc_rpc: DynBitcoindRpc,
110 ) -> anyhow::Result<watch::Receiver<Option<Feerate>>> {
111 self.inner.feerate_receiver(network, btc_rpc).await
112 }
113 pub async fn block_count_receiver(
114 &self,
115 network: bitcoin::Network,
116 btc_rpc: DynBitcoindRpc,
117 ) -> watch::Receiver<Option<u64>> {
118 self.inner.block_count_receiver(network, btc_rpc).await
119 }
120}
121impl ServerModuleShared for ServerModuleSharedBitcoin {
122 fn new(task_group: TaskGroup) -> Self {
123 Self {
124 inner: Arc::new(ServerModuleSharedBitcoinInner {
125 task_group,
126 feerate_rx: Mutex::default(),
127 block_count_rx: Mutex::default(),
128 }),
129 }
130 }
131}