1313
1414// TODO: Consider making it part of descriptor wallet onchain library
1515
16+ use std:: collections:: BTreeMap ;
1617use std:: sync:: mpsc;
1718use std:: thread:: { self , JoinHandle } ;
1819use std:: time:: Duration ;
1920
20- use bitcoin:: { Transaction , Txid } ;
21+ use bitcoin:: { Script , Transaction , Txid } ;
2122use electrum_client:: { Client as ElectrumClient , ElectrumApi , HeaderNotification } ;
2223
24+ use crate :: bus:: TxConfirmation ;
25+
2326#[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash , Debug , Display , Error , From ) ]
2427#[ display( "failed electrum watcher channel" ) ]
2528#[ from( mpsc:: SendError <ElectrumCmd >) ]
@@ -48,6 +51,9 @@ pub enum ElectrumUpdate {
4851 #[ display( "tx_batch(...)" ) ]
4952 TxBatch ( Vec < Transaction > , f32 ) ,
5053
54+ #[ display( "tx_confirmations(...)" ) ]
55+ TxConfirmations ( Vec < TxConfirmation > , u32 ) ,
56+
5157 #[ display( "channel_disconnected" ) ]
5258 ChannelDisconnected ,
5359
@@ -82,7 +88,6 @@ impl ElectrumWorker {
8288 . spawn ( move || loop {
8389 thread:: sleep ( Duration :: from_secs ( interval) ) ;
8490 sender. send ( ElectrumCmd :: GetTrasactions ) . expect ( "Electrum thread is dead" ) ;
85- sender. send ( ElectrumCmd :: PopHeader ) . expect ( "Electrum thread is dead" )
8691 } )
8792 . expect ( "unable to start blockchain watcher pacemaker thread" ) ;
8893
@@ -190,20 +195,53 @@ impl ElectrumProcessor {
190195 & mut self ,
191196 txids : & Vec < Txid > ,
192197 ) -> Result < Option < ElectrumUpdate > , electrum_client:: Error > {
193- if self . tracks . is_empty ( ) {
198+ if self . tracks . is_empty ( ) || txids. is_empty ( ) {
199+ return Ok ( None ) ;
200+ }
201+ let transactions = self . client . batch_transaction_get ( txids) ?;
202+ let scripts: Vec < Script > =
203+ transactions. into_iter ( ) . map ( |tx| tx. output [ 0 ] . script_pubkey . clone ( ) ) . collect ( ) ;
204+
205+ let hist = self . client . batch_script_get_history ( & scripts) ?;
206+
207+ let mut items = vec ! [ ] ;
208+ hist. into_iter ( ) . for_each ( |mut item| items. append ( & mut item) ) ;
209+
210+ if items. is_empty ( ) {
194211 return Ok ( None ) ;
195212 }
196- self . client . batch_transaction_get ( txids) . map ( |res| Some ( ElectrumUpdate :: TxBatch ( res, 0.0 ) ) )
213+
214+ let transactions: BTreeMap < Txid , i32 > =
215+ items. into_iter ( ) . map ( |h| ( h. tx_hash , h. height ) ) . collect ( ) ;
216+
217+ let min_height = transactions. clone ( ) . into_iter ( ) . map ( |( _, h) | h) . min ( ) ;
218+ let min_height = min_height. unwrap_or_default ( ) ;
219+
220+ let block_headers = self . client . block_headers ( min_height as usize , 50 ) ?;
221+ let block_total = block_headers. headers . len ( ) as i32 ;
222+
223+ let confirmations: BTreeMap < Txid , i32 > = transactions
224+ . into_iter ( )
225+ . filter ( |( _, height) | min_height + block_total > height. to_owned ( ) )
226+ . collect ( ) ;
227+
228+ let confirmations: Vec < TxConfirmation > = confirmations
229+ . into_iter ( )
230+ . map ( |( tx_id, height) | TxConfirmation {
231+ txid : tx_id,
232+ confirmations : ( min_height + block_total - height) as u32 ,
233+ } )
234+ . collect ( ) ;
235+
236+ Ok ( Some ( ElectrumUpdate :: TxConfirmations ( confirmations. clone ( ) , confirmations. len ( ) as u32 ) ) )
197237 }
198238
199239 fn track_transaction (
200240 & mut self ,
201241 txid : Txid ,
202242 ) -> Result < Option < ElectrumUpdate > , electrum_client:: Error > {
203243 self . tracks . push ( txid) ;
204- self . client
205- . transaction_get ( & txid. clone ( ) )
206- . map ( |res| Some ( ElectrumUpdate :: TxBatch ( [ res] . to_vec ( ) , 0.0 ) ) )
244+ self . get_transactions ( & self . tracks . clone ( ) )
207245 }
208246
209247 fn untrack_transaction (
@@ -212,8 +250,6 @@ impl ElectrumProcessor {
212250 ) -> Result < Option < ElectrumUpdate > , electrum_client:: Error > {
213251 let index = self . tracks . iter ( ) . position ( |x| * x == txid) . unwrap ( ) ;
214252 self . tracks . remove ( index) ;
215- self . client
216- . transaction_get ( & txid. clone ( ) )
217- . map ( |res| Some ( ElectrumUpdate :: TxBatch ( [ res] . to_vec ( ) , 0.0 ) ) )
253+ self . get_transactions ( & self . tracks . clone ( ) )
218254 }
219255}
0 commit comments