@@ -26,7 +26,7 @@ use bdk_chain::{
2626    local_chain:: { self ,  LocalChain ,  UpdateNotConnectedError } , 
2727    tx_graph:: { CanonicalTx ,  TxGraph } , 
2828    Append ,  BlockId ,  ChainPosition ,  ConfirmationTime ,  ConfirmationTimeAnchor ,  FullTxOut , 
29-     IndexedTxGraph ,  Persist ,  PersistBackend , 
29+     IndexedTxGraph ,  Persist ,  PersistBackend ,   TotalSentReceived , 
3030} ; 
3131use  bitcoin:: consensus:: encode:: serialize; 
3232use  bitcoin:: secp256k1:: Secp256k1 ; 
@@ -65,7 +65,7 @@ use crate::descriptor::{
6565    calc_checksum,  into_wallet_descriptor_checked,  DerivedDescriptor ,  DescriptorMeta , 
6666    ExtendedDescriptor ,  ExtractPolicy ,  IntoWalletDescriptor ,  Policy ,  XKeyUtils , 
6767} ; 
68- use  crate :: error:: { Error ,  MiniscriptPsbtError } ; 
68+ use  crate :: error:: { CalculateFeeError ,   Error ,  MiniscriptPsbtError } ; 
6969use  crate :: psbt:: PsbtUtils ; 
7070use  crate :: signer:: SignerError ; 
7171use  crate :: types:: * ; 
@@ -427,27 +427,49 @@ impl<D> Wallet<D> {
427427            . next ( ) 
428428    } 
429429
430-     /// Return a single transactions made and received by the wallet  
430+     /// Calculates the fee of a given transaction. Returns 0 if `tx` is a coinbase transaction.  
431431     /// 
432-      /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if 
433-      /// `include_raw` is `true`. 
434-      pub  fn  get_tx ( & self ,  txid :  Txid ,  include_raw :  bool )  -> Option < TransactionDetails >  { 
432+      /// Note `tx` does not have to be in the graph for this to work. 
433+      pub  fn  calculate_fee ( & self ,  tx :  & Transaction )  -> Result < u64 ,  CalculateFeeError >  { 
434+         match  self . indexed_graph . graph ( ) . calculate_fee ( tx)  { 
435+             None  => Err ( CalculateFeeError :: MissingTxOut ) , 
436+             Some ( fee)  if  fee < 0  => Err ( CalculateFeeError :: NegativeFee ( fee) ) , 
437+             Some ( fee)  => Ok ( u64:: try_from ( fee) . unwrap ( ) ) , 
438+         } 
439+     } 
440+ 
441+     /// Calculate the `FeeRate` for a given transaction. 
442+      /// 
443+      /// Note `tx` does not have to be in the graph for this to work. 
444+      pub  fn  calculate_fee_rate ( & self ,  tx :  & Transaction )  -> Result < FeeRate ,  CalculateFeeError >  { 
445+         self . calculate_fee ( tx) . map ( |fee| { 
446+             let  weight = tx. weight ( ) ; 
447+             FeeRate :: from_wu ( fee,  weight) 
448+         } ) 
449+     } 
450+ 
451+     /// Return `TotalSentReceived` for a `Transaction` in relation to the `Wallet` and it's 
452+      /// descriptors. 
453+      pub  fn  total_sent_received ( & self ,  tx :  & Transaction )  -> TotalSentReceived  { 
454+         self . indexed_graph . index . total_sent_received ( tx) 
455+     } 
456+ 
457+     /// Return a single `CanonicalTx` made and received by the wallet or `None` if it doesn't 
458+      /// exist in the wallet 
459+      pub  fn  get_tx ( 
460+         & self , 
461+         txid :  Txid , 
462+     )  -> Option < CanonicalTx < ' _ ,  Transaction ,  ConfirmationTimeAnchor > >  { 
435463        let  graph = self . indexed_graph . graph ( ) ; 
436464
437-         let  canonical_tx =  CanonicalTx  { 
465+         Some ( CanonicalTx  { 
438466            observed_as :  graph. get_chain_position ( 
439467                & self . chain , 
440468                self . chain . tip ( ) . unwrap_or_default ( ) , 
441469                txid, 
442470            ) ?, 
443471            node :  graph. get_tx_node ( txid) ?, 
444-         } ; 
445- 
446-         Some ( new_tx_details ( 
447-             & self . indexed_graph , 
448-             canonical_tx, 
449-             include_raw, 
450-         ) ) 
472+         } ) 
451473    } 
452474
453475    /// Add a new checkpoint to the wallet's internal view of the chain. 
@@ -599,7 +621,7 @@ impl<D> Wallet<D> {
599621     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; 
600622     /// # let mut wallet = doctest_wallet!(); 
601623     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); 
602-      /// let ( psbt, details)  = { 
624+      /// let psbt = { 
603625     ///    let mut builder =  wallet.build_tx(); 
604626     ///    builder 
605627     ///        .add_recipient(to_address.script_pubkey(), 50_000); 
@@ -624,7 +646,7 @@ impl<D> Wallet<D> {
624646        & mut  self , 
625647        coin_selection :  Cs , 
626648        params :  TxParams , 
627-     )  -> Result < ( psbt:: PartiallySignedTransaction ,   TransactionDetails ) ,  Error > 
649+     )  -> Result < psbt:: PartiallySignedTransaction ,  Error > 
628650    where 
629651        D :  PersistBackend < ChangeSet > , 
630652    { 
@@ -969,20 +991,8 @@ impl<D> Wallet<D> {
969991        // sort input/outputs according to the chosen algorithm 
970992        params. ordering . sort_tx ( & mut  tx) ; 
971993
972-         let  txid = tx. txid ( ) ; 
973-         let  sent = coin_selection. local_selected_amount ( ) ; 
974994        let  psbt = self . complete_transaction ( tx,  coin_selection. selected ,  params) ?; 
975- 
976-         let  transaction_details = TransactionDetails  { 
977-             transaction :  None , 
978-             txid, 
979-             confirmation_time :  ConfirmationTime :: Unconfirmed  {  last_seen :  0  } , 
980-             received, 
981-             sent, 
982-             fee :  Some ( fee_amount) , 
983-         } ; 
984- 
985-         Ok ( ( psbt,  transaction_details) ) 
995+         Ok ( psbt) 
986996    } 
987997
988998    /// Bump the fee of a transaction previously created with this wallet. 
@@ -1001,7 +1011,7 @@ impl<D> Wallet<D> {
10011011     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; 
10021012     /// # let mut wallet = doctest_wallet!(); 
10031013     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); 
1004-      /// let ( mut psbt, _)  = { 
1014+      /// let mut psbt = { 
10051015     ///     let mut builder = wallet.build_tx(); 
10061016     ///     builder 
10071017     ///         .add_recipient(to_address.script_pubkey(), 50_000) 
@@ -1011,7 +1021,7 @@ impl<D> Wallet<D> {
10111021     /// let _ = wallet.sign(&mut psbt, SignOptions::default())?; 
10121022     /// let tx = psbt.extract_tx(); 
10131023     /// // broadcast tx but it's taking too long to confirm so we want to bump the fee 
1014-      /// let ( mut psbt, _)  =  { 
1024+      /// let mut psbt =  { 
10151025     ///     let mut builder = wallet.build_fee_bump(tx.txid())?; 
10161026     ///     builder 
10171027     ///         .fee_rate(FeeRate::from_sat_per_vb(5.0)); 
@@ -1171,7 +1181,7 @@ impl<D> Wallet<D> {
11711181     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; 
11721182     /// # let mut wallet = doctest_wallet!(); 
11731183     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); 
1174-      /// let ( mut psbt, _)  = { 
1184+      /// let mut psbt = { 
11751185     ///     let mut builder = wallet.build_tx(); 
11761186     ///     builder.add_recipient(to_address.script_pubkey(), 50_000); 
11771187     ///     builder.finish()? 
@@ -1721,7 +1731,7 @@ impl<D> Wallet<D> {
17211731        Ok ( changed) 
17221732    } 
17231733
1724-     /// Commits all curently  [`staged`] changed to the persistence backend returning and error when 
1734+     /// Commits all currently  [`staged`] changed to the persistence backend returning and error when 
17251735     /// this fails. 
17261736     /// 
17271737     /// This returns whether the `update` resulted in any changes. 
@@ -1812,61 +1822,6 @@ fn new_local_utxo(
18121822    } 
18131823} 
18141824
1815- fn  new_tx_details ( 
1816-     indexed_graph :  & IndexedTxGraph < ConfirmationTimeAnchor ,  KeychainTxOutIndex < KeychainKind > > , 
1817-     canonical_tx :  CanonicalTx < ' _ ,  Transaction ,  ConfirmationTimeAnchor > , 
1818-     include_raw :  bool , 
1819- )  -> TransactionDetails  { 
1820-     let  graph = indexed_graph. graph ( ) ; 
1821-     let  index = & indexed_graph. index ; 
1822-     let  tx = canonical_tx. node . tx ; 
1823- 
1824-     let  received = tx
1825-         . output 
1826-         . iter ( ) 
1827-         . map ( |txout| { 
1828-             if  index. index_of_spk ( & txout. script_pubkey ) . is_some ( )  { 
1829-                 txout. value 
1830-             }  else  { 
1831-                 0 
1832-             } 
1833-         } ) 
1834-         . sum ( ) ; 
1835- 
1836-     let  sent = tx
1837-         . input 
1838-         . iter ( ) 
1839-         . map ( |txin| { 
1840-             if  let  Some ( ( _,  txout) )  = index. txout ( txin. previous_output )  { 
1841-                 txout. value 
1842-             }  else  { 
1843-                 0 
1844-             } 
1845-         } ) 
1846-         . sum ( ) ; 
1847- 
1848-     let  inputs = tx
1849-         . input 
1850-         . iter ( ) 
1851-         . map ( |txin| { 
1852-             graph
1853-                 . get_txout ( txin. previous_output ) 
1854-                 . map ( |txout| txout. value ) 
1855-         } ) 
1856-         . sum :: < Option < u64 > > ( ) ; 
1857-     let  outputs = tx. output . iter ( ) . map ( |txout| txout. value ) . sum ( ) ; 
1858-     let  fee = inputs. map ( |inputs| inputs. saturating_sub ( outputs) ) ; 
1859- 
1860-     TransactionDetails  { 
1861-         transaction :  if  include_raw {  Some ( tx. clone ( ) )  }  else  {  None  } , 
1862-         txid :  canonical_tx. node . txid , 
1863-         received, 
1864-         sent, 
1865-         fee, 
1866-         confirmation_time :  canonical_tx. observed_as . cloned ( ) . into ( ) , 
1867-     } 
1868- } 
1869- 
18701825#[ macro_export]  
18711826#[ doc( hidden) ]  
18721827/// Macro for getting a wallet for use in a doctest 
0 commit comments