@@ -2380,6 +2380,126 @@ impl Wallet {
23802380 Ok ( ( ) )
23812381 }
23822382
2383+ /// Applies an update to the wallet, stages the changes, and returns events.
2384+ ///
2385+ /// Usually you create an `update` by interacting with some blockchain data source and inserting
2386+ /// transactions related to your wallet into it. Staged changes are NOT persisted.
2387+ ///
2388+ /// After applying updates you should process the events in your app before persisting the
2389+ /// staged wallet changes. For an example of how to persist staged wallet changes see
2390+ /// [`Wallet::reveal_next_address`].
2391+ ///
2392+ /// ```rust,no_run
2393+ /// # use bitcoin::*;
2394+ /// # use bdk_wallet::*;
2395+ /// use bdk_wallet::WalletEvent;
2396+ /// # let wallet_update = Update::default();
2397+ /// # let mut wallet = doctest_wallet!();
2398+ /// let events = wallet.apply_update_events(wallet_update)?;
2399+ /// // Handle wallet relevant events from this update.
2400+ /// events.iter().for_each(|event| {
2401+ /// match event {
2402+ /// // The chain tip changed.
2403+ /// WalletEvent::ChainTipChanged { old_tip, new_tip } => {
2404+ /// todo!() // handle event
2405+ /// }
2406+ /// // An unconfirmed tx is now confirmed in a block.
2407+ /// WalletEvent::TxConfirmed {
2408+ /// txid,
2409+ /// tx,
2410+ /// block_time,
2411+ /// old_block_time: None,
2412+ /// } => {
2413+ /// todo!() // handle event
2414+ /// }
2415+ /// // A confirmed tx is now confirmed in a new block (reorg).
2416+ /// WalletEvent::TxConfirmed {
2417+ /// txid,
2418+ /// tx,
2419+ /// block_time,
2420+ /// old_block_time: Some(old_block_time),
2421+ /// } => {
2422+ /// todo!() // handle event
2423+ /// }
2424+ /// // A new unconfirmed tx was seen in the mempool.
2425+ /// WalletEvent::TxUnconfirmed {
2426+ /// txid,
2427+ /// tx,
2428+ /// old_block_time: None,
2429+ /// } => {
2430+ /// todo!() // handle event
2431+ /// }
2432+ /// // A previously confirmed tx in now unconfirmed in the mempool (reorg).
2433+ /// WalletEvent::TxUnconfirmed {
2434+ /// txid,
2435+ /// tx,
2436+ /// old_block_time: Some(old_block_time),
2437+ /// } => {
2438+ /// todo!() // handle event
2439+ /// }
2440+ /// // An unconfirmed tx was replaced in the mempool (RBF or double spent input).
2441+ /// WalletEvent::TxReplaced {
2442+ /// txid,
2443+ /// tx,
2444+ /// conflicts,
2445+ /// } => {
2446+ /// todo!() // handle event
2447+ /// }
2448+ /// // An unconfirmed tx was dropped from the mempool (fee too low).
2449+ /// WalletEvent::TxDropped { txid, tx } => {
2450+ /// todo!() // handle event
2451+ /// }
2452+ /// _ => {
2453+ /// // unexpected event, do nothing
2454+ /// }
2455+ /// }
2456+ /// // take staged wallet changes
2457+ /// let staged = wallet.take_staged();
2458+ /// // persist staged changes
2459+ /// });
2460+ /// # Ok::<(), anyhow::Error>(())
2461+ /// ```
2462+ /// [`TxBuilder`]: crate::TxBuilder
2463+ pub fn apply_update_events (
2464+ & mut self ,
2465+ update : impl Into < Update > ,
2466+ ) -> Result < Vec < WalletEvent > , CannotConnectError > {
2467+ // snapshot of chain tip and transactions before update
2468+ let chain_tip1 = self . chain . tip ( ) . block_id ( ) ;
2469+ let wallet_txs1 = self
2470+ . transactions ( )
2471+ . map ( |wtx| {
2472+ (
2473+ wtx. tx_node . txid ,
2474+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2475+ )
2476+ } )
2477+ . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2478+
2479+ // apply update
2480+ self . apply_update ( update) ?;
2481+
2482+ // chain tip and transactions after update
2483+ let chain_tip2 = self . chain . tip ( ) . block_id ( ) ;
2484+ let wallet_txs2 = self
2485+ . transactions ( )
2486+ . map ( |wtx| {
2487+ (
2488+ wtx. tx_node . txid ,
2489+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2490+ )
2491+ } )
2492+ . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2493+
2494+ Ok ( wallet_events (
2495+ self ,
2496+ chain_tip1,
2497+ chain_tip2,
2498+ wallet_txs1,
2499+ wallet_txs2,
2500+ ) )
2501+ }
2502+
23832503 /// Get a reference of the staged [`ChangeSet`] that is yet to be committed (if any).
23842504 pub fn staged ( & self ) -> Option < & ChangeSet > {
23852505 if self . stage . is_empty ( ) {
@@ -2490,6 +2610,57 @@ impl Wallet {
24902610 } )
24912611 }
24922612
2613+ /// Introduces a `block` of `height` to the wallet, and tries to connect it to the
2614+ /// `prev_blockhash` of the block's header.
2615+ ///
2616+ /// This is a convenience method that is equivalent to calling
2617+ /// [`apply_block_connected_to_events`] with `prev_blockhash` and `height-1` as the
2618+ /// `connected_to` parameter.
2619+ ///
2620+ /// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
2621+ ///
2622+ /// [`apply_block_connected_to_events`]: Self::apply_block_connected_to_events
2623+ /// [`apply_update_events`]: Self::apply_update_events
2624+ pub fn apply_block_events (
2625+ & mut self ,
2626+ block : & Block ,
2627+ height : u32 ,
2628+ ) -> Result < Vec < WalletEvent > , CannotConnectError > {
2629+ // snapshot of chain tip and transactions before update
2630+ let chain_tip1 = self . chain . tip ( ) . block_id ( ) ;
2631+ let wallet_txs1 = self
2632+ . transactions ( )
2633+ . map ( |wtx| {
2634+ (
2635+ wtx. tx_node . txid ,
2636+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2637+ )
2638+ } )
2639+ . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2640+
2641+ self . apply_block ( block, height) ?;
2642+
2643+ // chain tip and transactions after update
2644+ let chain_tip2 = self . chain . tip ( ) . block_id ( ) ;
2645+ let wallet_txs2 = self
2646+ . transactions ( )
2647+ . map ( |wtx| {
2648+ (
2649+ wtx. tx_node . txid ,
2650+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2651+ )
2652+ } )
2653+ . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2654+
2655+ Ok ( wallet_events (
2656+ self ,
2657+ chain_tip1,
2658+ chain_tip2,
2659+ wallet_txs1,
2660+ wallet_txs2,
2661+ ) )
2662+ }
2663+
24932664 /// Applies relevant transactions from `block` of `height` to the wallet, and connects the
24942665 /// block to the internal chain.
24952666 ///
@@ -2521,6 +2692,56 @@ impl Wallet {
25212692 Ok ( ( ) )
25222693 }
25232694
2695+ /// Applies relevant transactions from `block` of `height` to the wallet, and connects the
2696+ /// block to the internal chain.
2697+ ///
2698+ /// See [`apply_block_connected_to`] for more information.
2699+ ///
2700+ /// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
2701+ ///
2702+ /// [`apply_block_connected_to`]: Self::apply_block_connected_to
2703+ /// [`apply_update_events`]: Self::apply_update_events
2704+ pub fn apply_block_connected_to_events (
2705+ & mut self ,
2706+ block : & Block ,
2707+ height : u32 ,
2708+ connected_to : BlockId ,
2709+ ) -> Result < Vec < WalletEvent > , ApplyHeaderError > {
2710+ // snapshot of chain tip and transactions before update
2711+ let chain_tip1 = self . chain . tip ( ) . block_id ( ) ;
2712+ let wallet_txs1 = self
2713+ . transactions ( )
2714+ . map ( |wtx| {
2715+ (
2716+ wtx. tx_node . txid ,
2717+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2718+ )
2719+ } )
2720+ . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2721+
2722+ self . apply_block_connected_to ( block, height, connected_to) ?;
2723+
2724+ // chain tip and transactions after update
2725+ let chain_tip2 = self . chain . tip ( ) . block_id ( ) ;
2726+ let wallet_txs2 = self
2727+ . transactions ( )
2728+ . map ( |wtx| {
2729+ (
2730+ wtx. tx_node . txid ,
2731+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2732+ )
2733+ } )
2734+ . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2735+
2736+ Ok ( wallet_events (
2737+ self ,
2738+ chain_tip1,
2739+ chain_tip2,
2740+ wallet_txs1,
2741+ wallet_txs2,
2742+ ) )
2743+ }
2744+
25242745 /// Apply relevant unconfirmed transactions to the wallet.
25252746 ///
25262747 /// Transactions that are not relevant are filtered out.
0 commit comments