@@ -541,14 +541,77 @@ impl<A: Clone + Ord> TxGraph<A> {
541541
542542 /// Inserts the given `seen_at` for `txid` into [`TxGraph`].
543543 ///
544- /// Note that [`TxGraph`] only keeps track of the latest `seen_at`.
544+ /// Note that [`TxGraph`] only keeps track of the latest `seen_at`. To batch
545+ /// update all unconfirmed transactions with the latest `seen_at`, see
546+ /// [`update_last_seen_unconfirmed`].
547+ ///
548+ /// [`update_last_seen_unconfirmed`]: Self::update_last_seen_unconfirmed
545549 pub fn insert_seen_at ( & mut self , txid : Txid , seen_at : u64 ) -> ChangeSet < A > {
546550 let mut update = Self :: default ( ) ;
547551 let ( _, _, update_last_seen) = update. txs . entry ( txid) . or_default ( ) ;
548552 * update_last_seen = seen_at;
549553 self . apply_update ( update)
550554 }
551555
556+ /// Update the last seen time for all unconfirmed transactions.
557+ ///
558+ /// This method updates the last seen unconfirmed time for this [`TxGraph`] by inserting
559+ /// the given `seen_at` for every transaction not yet anchored to a confirmed block,
560+ /// and returns the [`ChangeSet`] after applying all updates to `self`.
561+ ///
562+ /// This is useful for keeping track of the latest time a transaction was seen
563+ /// unconfirmed, which is important for evaluating transaction conflicts in the same
564+ /// [`TxGraph`]. For details of how [`TxGraph`] resolves conflicts, see the docs for
565+ /// [`try_get_chain_position`].
566+ ///
567+ /// A normal use of this method is to call it with the current system time. Although
568+ /// block headers contain a timestamp, using the header time would be less effective
569+ /// at tracking mempool transactions, because it can drift from actual clock time, plus
570+ /// we may want to update a transaction's last seen time repeatedly between blocks.
571+ ///
572+ /// # Example
573+ ///
574+ /// ```rust
575+ /// # use bdk_chain::example_utils::*;
576+ /// # use std::time::UNIX_EPOCH;
577+ /// # let tx = tx_from_hex(RAW_TX_1);
578+ /// # let mut tx_graph = bdk_chain::TxGraph::<()>::new([tx]);
579+ /// let now = std::time::SystemTime::now()
580+ /// .duration_since(UNIX_EPOCH)
581+ /// .expect("valid duration")
582+ /// .as_secs();
583+ /// let changeset = tx_graph.update_last_seen_unconfirmed(now);
584+ /// assert!(!changeset.last_seen.is_empty());
585+ /// ```
586+ ///
587+ /// Note that [`TxGraph`] only keeps track of the latest `seen_at`, so the given time must
588+ /// by strictly greater than what is currently stored for a transaction to have an effect.
589+ /// To insert a last seen time for a single txid, see [`insert_seen_at`].
590+ ///
591+ /// [`insert_seen_at`]: Self::insert_seen_at
592+ /// [`try_get_chain_position`]: Self::try_get_chain_position
593+ pub fn update_last_seen_unconfirmed ( & mut self , seen_at : u64 ) -> ChangeSet < A > {
594+ let mut changeset = ChangeSet :: default ( ) ;
595+ let unanchored_txs: Vec < Txid > = self
596+ . txs
597+ . iter ( )
598+ . filter_map (
599+ |( & txid, ( _, anchors, _) ) | {
600+ if anchors. is_empty ( ) {
601+ Some ( txid)
602+ } else {
603+ None
604+ }
605+ } ,
606+ )
607+ . collect ( ) ;
608+
609+ for txid in unanchored_txs {
610+ changeset. append ( self . insert_seen_at ( txid, seen_at) ) ;
611+ }
612+ changeset
613+ }
614+
552615 /// Extends this graph with another so that `self` becomes the union of the two sets of
553616 /// transactions.
554617 ///
0 commit comments