@@ -2341,101 +2341,121 @@ impl Wallet {
23412341 . to_string ( )
23422342 }
23432343
2344- /// Applies an update to the wallet, stages the changes, and returns events.
2344+ /// Applies an update to the wallet, stages changes, and returns events describing what changed .
23452345 ///
2346- /// Usually you create an `update` by interacting with some blockchain data source and inserting
2347- /// transactions related to your wallet into it. Staged changes are NOT persisted.
2346+ /// This is the primary method for updating wallet state with new blockchain data. It accepts
2347+ /// an [`Update`]
23482348 ///
2349- /// After applying updates, you should process the events in your app before persisting the
2350- /// staged wallet changes. For an example of how to persist staged wallet changes, see
2351- /// [`Wallet::reveal_next_address`].
2349+ /// **IMPORTANT**: Changes are staged but **NOT automatically persisted**. You must:
2350+ ///
2351+ /// 1. Process the returned events in your application
2352+ /// 2. Call [`take_staged`] to retrieve the [`ChangeSet`]
2353+ /// 3. Persist the changeset to your database/storage
2354+ ///
2355+ /// Failing to persist changes means they will be lost when the wallet is reloaded.
2356+ ///
2357+ /// # Example
2358+ ///
2359+ /// ## Basic usage with event handling
23522360 ///
23532361 /// ```rust,no_run
23542362 /// # use bitcoin::*;
23552363 /// # use bdk_wallet::*;
23562364 /// use bdk_wallet::event::WalletEvent;
23572365 /// # let wallet_update = Update::default();
23582366 /// # let mut wallet = doctest_wallet!();
2367+ ///
2368+ /// // Apply the update and get events
23592369 /// let events = wallet.apply_update(wallet_update)?;
2360- /// // Handle wallet relevant events from this update.
2361- /// events.iter().for_each(|event| {
2370+ ///
2371+ /// // Handle each event
2372+ /// for event in events {
23622373 /// match event {
2363- /// // The chain tip changed.
23642374 /// WalletEvent::ChainTipChanged { old_tip, new_tip } => {
2365- /// todo!() // handle event
2375+ /// println!(
2376+ /// "Chain advanced from {} to {}",
2377+ /// old_tip.height, new_tip.height
2378+ /// );
23662379 /// }
2367- /// // An unconfirmed tx is now confirmed in a block.
23682380 /// WalletEvent::TxConfirmed {
23692381 /// txid,
2370- /// tx,
23712382 /// block_time,
23722383 /// old_block_time: None,
2384+ /// ..
23732385 /// } => {
2374- /// todo!() // handle event
2386+ /// println!(
2387+ /// "Transaction {} confirmed at height {}",
2388+ /// txid, block_time.block_id.height
2389+ /// );
23752390 /// }
2376- /// // A confirmed tx is now confirmed in a new block (reorg).
23772391 /// WalletEvent::TxConfirmed {
23782392 /// txid,
2379- /// tx,
23802393 /// block_time,
2381- /// old_block_time: Some(old_block_time),
2394+ /// old_block_time: Some(old),
2395+ /// ..
23822396 /// } => {
2383- /// todo!() // handle event
2397+ /// println!(
2398+ /// "Transaction {} re-confirmed due to reorg: {} -> {}",
2399+ /// txid, old.block_id.height, block_time.block_id.height
2400+ /// );
23842401 /// }
2385- /// // A new unconfirmed tx was seen in the mempool.
23862402 /// WalletEvent::TxUnconfirmed {
23872403 /// txid,
2388- /// tx,
23892404 /// old_block_time: None,
2405+ /// ..
23902406 /// } => {
2391- /// todo!() // handle event
2407+ /// println!("New mempool transaction: {}", txid);
23922408 /// }
2393- /// // A previously confirmed tx in now unconfirmed in the mempool (reorg).
23942409 /// WalletEvent::TxUnconfirmed {
23952410 /// txid,
2396- /// tx ,
2397- /// old_block_time: Some(old_block_time),
2411+ /// old_block_time: Some(old) ,
2412+ /// ..
23982413 /// } => {
2399- /// todo!() // handle event
2414+ /// println!(
2415+ /// "Transaction {} unconfirmed due to reorg from height {}",
2416+ /// txid, old.block_id.height
2417+ /// );
24002418 /// }
2401- /// // An unconfirmed tx was replaced in the mempool (RBF or double spent input).
24022419 /// WalletEvent::TxReplaced {
2403- /// txid,
2404- /// tx,
2405- /// conflicts,
2420+ /// txid, conflicts, ..
24062421 /// } => {
2407- /// todo!() // handle event
2422+ /// println!("Transaction {} replaced: {:?}", txid, conflicts);
24082423 /// }
2409- /// // An unconfirmed tx was dropped from the mempool (fee too low).
2410- /// WalletEvent::TxDropped { txid, tx } => {
2411- /// todo!() // handle event
2424+ /// WalletEvent::TxDropped { txid, .. } => {
2425+ /// println!("Transaction {} dropped from mempool", txid);
24122426 /// }
24132427 /// _ => {
2414- /// // unexpected event, do nothing
2428+ /// debug_assert!(false, " unexpected event")
24152429 /// }
24162430 /// }
2417- /// // take staged wallet changes
2418- /// let staged = wallet.take_staged();
2419- /// // persist staged changes
2420- /// });
2431+ /// }
2432+ ///
2433+ /// // IMPORTANT: Persist the changes
2434+ /// if let Some(changeset) = wallet.take_staged() {
2435+ /// // Save changeset to your database
2436+ /// // e.g., db.persist(&changeset)?;
2437+ /// }
24212438 /// # Ok::<(), anyhow::Error>(())
24222439 /// ```
2423- /// [`TxBuilder`]: crate::TxBuilder
2440+ ///
2441+ /// # See Also
2442+ ///
2443+ /// - [`apply_block`] - Apply a single block to the wallet
2444+ /// - [`apply_block_connected_to`] - Apply a block with explicit connection point
2445+ /// - [`take_staged`] - Retrieve staged changes for persistence
2446+ /// - [`WalletEvent`] - Documentation for all event types
2447+ /// - [`Update`] - The update structure accepted by this method
2448+ ///
2449+ /// [`apply_block`]: Wallet::apply_block
2450+ /// [`apply_block_connected_to`]: Wallet::apply_block_connected_to
2451+ /// [`take_staged`]: Wallet::take_staged
24242452 pub fn apply_update (
24252453 & mut self ,
24262454 update : impl Into < Update > ,
24272455 ) -> Result < Vec < WalletEvent > , CannotConnectError > {
24282456 // snapshot of chain tip and transactions before update
24292457 let chain_tip1 = self . chain . tip ( ) . block_id ( ) ;
2430- let wallet_txs1 = self
2431- . transactions ( )
2432- . map ( |wtx| {
2433- (
2434- wtx. tx_node . txid ,
2435- ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2436- )
2437- } )
2438- . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2458+ let wallet_txs1 = self . collect_wallet_txs ( ) ;
24392459
24402460 // apply update
24412461 let update = update. into ( ) ;
@@ -2454,15 +2474,7 @@ impl Wallet {
24542474
24552475 // chain tip and transactions after update
24562476 let chain_tip2 = self . chain . tip ( ) . block_id ( ) ;
2457- let wallet_txs2 = self
2458- . transactions ( )
2459- . map ( |wtx| {
2460- (
2461- wtx. tx_node . txid ,
2462- ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2463- )
2464- } )
2465- . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2477+ let wallet_txs2 = self . collect_wallet_txs ( ) ;
24662478
24672479 Ok ( wallet_events (
24682480 self ,
@@ -2557,7 +2569,9 @@ impl Wallet {
25572569 /// if you need the inserted block data to be reloaded after closing the wallet.
25582570 /// See [`Wallet::reveal_next_address`].
25592571 ///
2560- /// See [`apply_update_events`] for more information on the returned [`WalletEvent`]s.
2572+ /// See [`apply_update`] for more information on the returned [`WalletEvent`]s.
2573+ ///
2574+ /// [`apply_update`]: Wallet::apply_update
25612575 pub fn apply_block_connected_to (
25622576 & mut self ,
25632577 block : & Block ,
@@ -2566,15 +2580,7 @@ impl Wallet {
25662580 ) -> Result < Vec < WalletEvent > , ApplyHeaderError > {
25672581 // snapshot of chain tip and transactions before update
25682582 let chain_tip1 = self . chain . tip ( ) . block_id ( ) ;
2569- let wallet_txs1 = self
2570- . transactions ( )
2571- . map ( |wtx| {
2572- (
2573- wtx. tx_node . txid ,
2574- ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2575- )
2576- } )
2577- . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2583+ let wallet_txs1 = self . collect_wallet_txs ( ) ;
25782584
25792585 // apply block to wallet
25802586 let mut changeset = ChangeSet :: default ( ) ;
@@ -2592,15 +2598,7 @@ impl Wallet {
25922598
25932599 // chain tip and transactions after update
25942600 let chain_tip2 = self . chain . tip ( ) . block_id ( ) ;
2595- let wallet_txs2 = self
2596- . transactions ( )
2597- . map ( |wtx| {
2598- (
2599- wtx. tx_node . txid ,
2600- ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2601- )
2602- } )
2603- . collect :: < BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > > ( ) ;
2601+ let wallet_txs2 = self . collect_wallet_txs ( ) ;
26042602
26052603 Ok ( wallet_events (
26062604 self ,
@@ -2611,13 +2609,30 @@ impl Wallet {
26112609 ) )
26122610 }
26132611
2612+ /// Collects all canonical wallet transactions into a map.
2613+ ///
2614+ /// This method is primarily used internally to create before/after snapshots when applying
2615+ /// updates or blocks to the wallet.
2616+ fn collect_wallet_txs (
2617+ & self ,
2618+ ) -> BTreeMap < Txid , ( Arc < Transaction > , ChainPosition < ConfirmationBlockTime > ) > {
2619+ self . transactions ( )
2620+ . map ( |wtx| {
2621+ (
2622+ wtx. tx_node . txid ,
2623+ ( wtx. tx_node . tx . clone ( ) , wtx. chain_position ) ,
2624+ )
2625+ } )
2626+ . collect ( )
2627+ }
2628+
26142629 /// Apply relevant unconfirmed transactions to the wallet.
26152630 ///
26162631 /// Transactions that are not relevant are filtered out.
26172632 ///
26182633 /// This method takes in an iterator of `(tx, last_seen)` where `last_seen` is the timestamp of
26192634 /// when the transaction was last seen in the mempool. This is used for conflict resolution
2620- /// when there is conflicting unconfirmed transactions. The transaction with the later
2635+ /// when there are conflicting unconfirmed transactions. The transaction with the later
26212636 /// `last_seen` is prioritized.
26222637 ///
26232638 /// **WARNING**: You must persist the changes resulting from one or more calls to this method
0 commit comments