99//! Command Handlers
1010//!
1111//! This module describes all the command handling logic used by bdk-cli.
12+
1213use crate :: commands:: OfflineWalletSubCommand :: * ;
1314use crate :: commands:: * ;
1415use crate :: config:: { WalletConfig , WalletConfigInner } ;
@@ -694,8 +695,85 @@ pub(crate) async fn handle_online_wallet_subcommand(
694695 }
695696 Ok ( serde_json:: to_string_pretty ( & json ! ( { } ) ) ?)
696697 }
697- Sync => {
698- sync_wallet ( client, wallet) . await ?;
698+
699+ #[ cfg( any( feature = "electrum" , feature = "esplora" ) ) ]
700+ let request = wallet
701+ . start_sync_with_revealed_spks( )
702+ . inspect( |item, progress| {
703+ let pc = ( 100 * progress. consumed ( ) ) as f32 / progress. total ( ) as f32 ;
704+ eprintln ! ( "[ SCANNING {pc:03.0}% ] {item}" ) ;
705+ } ) ;
706+
707+ match client {
708+ #[ cfg( feature = "electrum" ) ]
709+ Electrum { client, batch_size } => {
710+ // Populate the electrum client's transaction cache so it doesn't re-download transaction we
711+ // already have.
712+ client
713+ . populate_tx_cache( wallet. tx_graph( ) . full_txs( ) . map( |tx_node| tx_node. tx) ) ;
714+
715+ let update = client. sync( request, batch_size, false ) ?;
716+ wallet. apply_update( update) ?;
717+ }
718+ #[ cfg( feature = "esplora" ) ]
719+ Esplora {
720+ client,
721+ parallel_requests,
722+ } => {
723+ let update = client
724+ . sync( request, parallel_requests)
725+ . await
726+ . map_err( |e| * e) ?;
727+ wallet. apply_update( update) ?;
728+ }
729+ #[ cfg( feature = "rpc" ) ]
730+ RpcClient { client } => {
731+ let blockchain_info = client. get_blockchain_info( ) ?;
732+ let wallet_cp = wallet. latest_checkpoint( ) ;
733+
734+ // reload the last 200 blocks in case of a reorg
735+ let emitter_height = wallet_cp. height( ) . saturating_sub( 200 ) ;
736+ let mut emitter = Emitter :: new(
737+ & * client,
738+ wallet_cp,
739+ emitter_height,
740+ wallet
741+ . tx_graph( )
742+ . list_canonical_txs(
743+ wallet. local_chain( ) ,
744+ wallet. local_chain( ) . tip( ) . block_id( ) ,
745+ CanonicalizationParams :: default( ) ,
746+ )
747+ . filter( |tx| tx. chain_position . is_unconfirmed ( ) ) ,
748+ ) ;
749+
750+ while let Some ( block_event) = emitter. next_block( ) ? {
751+ if block_event. block_height( ) % 10_000 == 0 {
752+ let percent_done = f64:: from( block_event. block_height( ) )
753+ / f64:: from( blockchain_info. headers as u32 )
754+ * 100f64 ;
755+ println ! (
756+ "Applying block at height: {}, {:.2}% done." ,
757+ block_event. block_height( ) ,
758+ percent_done
759+ ) ;
760+ }
761+
762+ wallet. apply_block_connected_to(
763+ & block_event. block,
764+ block_event. block_height( ) ,
765+ block_event. connected_to( ) ,
766+ ) ?;
767+ }
768+
769+ let mempool_txs = emitter. mempool( ) ?;
770+ wallet. apply_unconfirmed_txs( mempool_txs. update) ;
771+ }
772+ #[ cfg( feature = "cbf" ) ]
773+ KyotoClient { client } => {
774+ sync_kyoto_client( wallet, client) . await ?;
775+ }
776+ }
699777 Ok ( serde_json:: to_string_pretty( & json ! ( { } ) ) ?)
700778 }
701779 Broadcast { psbt, tx } => {
@@ -715,7 +793,68 @@ pub(crate) async fn handle_online_wallet_subcommand(
715793 ( Some ( _) , Some ( _) ) => panic ! ( "Both `psbt` and `tx` options not allowed" ) ,
716794 ( None , None ) => panic ! ( "Missing `psbt` and `tx` option" ) ,
717795 } ;
718- let txid = broadcast_transaction ( client, tx) . await ?;
796+
797+ let txid = match client {
798+ #[ cfg( feature = "electrum" ) ]
799+ Electrum {
800+ client,
801+ batch_size : _,
802+ } => client
803+ . transaction_broadcast( & tx)
804+ . map_err( |e| Error :: Generic ( e. to_string( ) ) ) ?,
805+ #[ cfg( feature = "esplora" ) ]
806+ Esplora {
807+ client,
808+ parallel_requests : _,
809+ } => client
810+ . broadcast( & tx)
811+ . await
812+ . map( |( ) | tx. compute_txid( ) )
813+ . map_err( |e| Error :: Generic ( e. to_string( ) ) ) ?,
814+ #[ cfg( feature = "rpc" ) ]
815+ RpcClient { client } => client
816+ . send_raw_transaction( & tx)
817+ . map_err( |e| Error :: Generic ( e. to_string( ) ) ) ?,
818+
819+ #[ cfg( feature = "cbf" ) ]
820+ KyotoClient { client } => {
821+ let LightClient {
822+ requester,
823+ mut info_subscriber,
824+ mut warning_subscriber,
825+ update_subscriber : _,
826+ node,
827+ } = * client;
828+
829+ let subscriber = tracing_subscriber:: FmtSubscriber :: new( ) ;
830+ tracing:: subscriber:: set_global_default( subscriber)
831+ . map_err( |e| Error :: Generic ( format ! ( "SetGlobalDefault error: {e}" ) ) ) ?;
832+
833+ tokio:: task:: spawn( async move { node. run( ) . await } ) ;
834+ tokio:: task:: spawn( async move {
835+ select! {
836+ info = info_subscriber. recv( ) => {
837+ if let Some ( info) = info {
838+ tracing : : info ! ( "{info}" ) ;
839+ }
840+ } ,
841+ warn = warning_subscriber. recv( ) => {
842+ if let Some ( warn) = warn {
843+ tracing : : warn ! ( "{warn}" ) ;
844+ }
845+ }
846+ }
847+ } ) ;
848+ let txid = tx. compute_txid( ) ;
849+ let wtxid = requester. broadcast_random( tx. clone( ) ) . await . map_err( |_| {
850+ tracing:: warn!( "Broadcast was unsuccessful" ) ;
851+ Error :: Generic ( "Transaction broadcast timed out after 30 seconds". into( ) )
852+ } ) ?;
853+ tracing:: info!( "Successfully broadcast WTXID : { wtxid} ") ;
854+ txid
855+ }
856+ } ;
857+
719858 Ok ( serde_json:: to_string_pretty( & json!( { "txid": txid } ) ) ?)
720859 }
721860 ReceivePayjoin {
0 commit comments