@@ -39,6 +39,7 @@ use core::fmt;
3939use  core:: ops:: Deref ; 
4040use  miniscript:: psbt:: { PsbtExt ,  PsbtInputExt ,  PsbtInputSatisfier } ; 
4141
42+ use  bdk_chain:: indexed_tx_graph:: Indexer ; 
4243#[ allow( unused_imports) ]  
4344use  log:: { debug,  error,  info,  trace} ; 
4445
@@ -427,27 +428,97 @@ impl<D> Wallet<D> {
427428            . next ( ) 
428429    } 
429430
430-     /// Return a single transactions made and received by the wallet 
431-      /// 
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 >  { 
431+     /// Returns a `TxOut` known by this wallet corresponding to `outpoint` if it exists in the 
432+      /// wallet's database whether spent or not. 
433+      pub  fn  get_txout ( & self ,  outpoint :  & OutPoint )  -> Option < TxOut >  { 
434+         self . indexed_graph 
435+             . graph ( ) 
436+             . all_txouts ( ) 
437+             . filter_map ( |( op,  txo) | { 
438+                 if  op. eq ( outpoint)  { 
439+                     Some ( txo. clone ( ) ) 
440+                 }  else  { 
441+                     None 
442+                 } 
443+             } ) 
444+             . next ( ) 
445+     } 
446+ 
447+     /// The total transaction fee amount, sum of input amounts minus sum of output amounts, in sats. 
448+      /// If the `Wallet` is missing a TxOut for an input returns None. 
449+      pub  fn  fee_amount ( & self ,  tx :  & Transaction )  -> Option < u64 >  { 
450+         let  txouts:  Option < Vec < TxOut > >  = tx
451+             . input 
452+             . iter ( ) 
453+             . map ( |txin| self . get_txout ( & txin. previous_output ) ) 
454+             . collect ( ) ; 
455+ 
456+         txouts. map ( |inputs| { 
457+             let  input_amount:  u64  = inputs. iter ( ) . map ( |i| i. value ) . sum ( ) ; 
458+             let  output_amount:  u64  = tx. output . iter ( ) . map ( |o| o. value ) . sum ( ) ; 
459+             input_amount
460+                 . checked_sub ( output_amount) 
461+                 . expect ( "input amount must be greater than output amount" ) 
462+         } ) 
463+     } 
464+ 
465+     /// The transaction's `FeeRate`. If the `Wallet` is missing a `TxOut` for an input returns None. 
466+      pub  fn  fee_rate ( & self ,  tx :  & Transaction )  -> Option < FeeRate >  { 
467+         let  fee_amount = self . fee_amount ( tx) ; 
468+         fee_amount. map ( |fee| { 
469+             let  weight = tx. weight ( ) ; 
470+             FeeRate :: from_wu ( fee,  weight) 
471+         } ) 
472+     } 
473+ 
474+     /// Return `TransactionAmounts` for a `Transaction` in relation to the `Wallet` and it's 
475+      /// descriptors. 
476+      pub  fn  sent_and_received ( & self ,  tx :  & Transaction )  -> TransactionAmounts  { 
477+         let  index = & self . indexed_graph . index ; 
478+ 
479+         let  received = tx
480+             . output 
481+             . iter ( ) 
482+             . map ( |txout| { 
483+                 if  index. index_of_spk ( & txout. script_pubkey ) . is_some ( )  { 
484+                     txout. value 
485+                 }  else  { 
486+                     0 
487+                 } 
488+             } ) 
489+             . sum ( ) ; 
490+ 
491+         let  sent = tx
492+             . input 
493+             . iter ( ) 
494+             . map ( |txin| { 
495+                 if  let  Some ( ( _,  txout) )  = index. txout ( txin. previous_output )  { 
496+                     txout. value 
497+                 }  else  { 
498+                     0 
499+                 } 
500+             } ) 
501+             . sum ( ) ; 
502+ 
503+         TransactionAmounts  {  sent,  received } 
504+     } 
505+ 
506+     /// Return a single `CanonicalTx` made and received by the wallet or `None` if it doesn't 
507+      /// exist in the wallet 
508+      pub  fn  get_tx ( 
509+         & self , 
510+         txid :  Txid , 
511+     )  -> Option < CanonicalTx < ' _ ,  Transaction ,  ConfirmationTimeAnchor > >  { 
435512        let  graph = self . indexed_graph . graph ( ) ; 
436513
437-         let  canonical_tx =  CanonicalTx  { 
514+         Some ( CanonicalTx  { 
438515            observed_as :  graph. get_chain_position ( 
439516                & self . chain , 
440517                self . chain . tip ( ) . unwrap_or_default ( ) , 
441518                txid, 
442519            ) ?, 
443520            node :  graph. get_tx_node ( txid) ?, 
444-         } ; 
445- 
446-         Some ( new_tx_details ( 
447-             & self . indexed_graph , 
448-             canonical_tx, 
449-             include_raw, 
450-         ) ) 
521+         } ) 
451522    } 
452523
453524    /// Add a new checkpoint to the wallet's internal view of the chain. 
@@ -524,6 +595,10 @@ impl<D> Wallet<D> {
524595        let  changeset:  ChangeSet  = self . indexed_graph . insert_tx ( & tx,  anchor,  last_seen) . into ( ) ; 
525596        let  changed = !changeset. is_empty ( ) ; 
526597        self . persist . stage ( changeset) ; 
598+ 
599+         let  additions = self . indexed_graph . index . index_tx ( & tx) ; 
600+         self . indexed_graph . index . apply_additions ( additions) ; 
601+ 
527602        Ok ( changed) 
528603    } 
529604
@@ -599,7 +674,7 @@ impl<D> Wallet<D> {
599674     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; 
600675     /// # let mut wallet = doctest_wallet!(); 
601676     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); 
602-      /// let ( psbt, details)  = { 
677+      /// let psbt = { 
603678     ///    let mut builder =  wallet.build_tx(); 
604679     ///    builder 
605680     ///        .add_recipient(to_address.script_pubkey(), 50_000); 
@@ -624,7 +699,7 @@ impl<D> Wallet<D> {
624699        & mut  self , 
625700        coin_selection :  Cs , 
626701        params :  TxParams , 
627-     )  -> Result < ( psbt:: PartiallySignedTransaction ,   TransactionDetails ) ,  Error > 
702+     )  -> Result < psbt:: PartiallySignedTransaction ,  Error > 
628703    where 
629704        D :  PersistBackend < ChangeSet > , 
630705    { 
@@ -969,20 +1044,8 @@ impl<D> Wallet<D> {
9691044        // sort input/outputs according to the chosen algorithm 
9701045        params. ordering . sort_tx ( & mut  tx) ; 
9711046
972-         let  txid = tx. txid ( ) ; 
973-         let  sent = coin_selection. local_selected_amount ( ) ; 
9741047        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) ) 
1048+         Ok ( psbt) 
9861049    } 
9871050
9881051    /// Bump the fee of a transaction previously created with this wallet. 
@@ -1001,7 +1064,7 @@ impl<D> Wallet<D> {
10011064     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; 
10021065     /// # let mut wallet = doctest_wallet!(); 
10031066     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); 
1004-      /// let ( mut psbt, _)  = { 
1067+      /// let mut psbt = { 
10051068     ///     let mut builder = wallet.build_tx(); 
10061069     ///     builder 
10071070     ///         .add_recipient(to_address.script_pubkey(), 50_000) 
@@ -1011,7 +1074,7 @@ impl<D> Wallet<D> {
10111074     /// let _ = wallet.sign(&mut psbt, SignOptions::default())?; 
10121075     /// let tx = psbt.extract_tx(); 
10131076     /// // broadcast tx but it's taking too long to confirm so we want to bump the fee 
1014-      /// let ( mut psbt, _)  =  { 
1077+      /// let mut psbt =  { 
10151078     ///     let mut builder = wallet.build_fee_bump(tx.txid())?; 
10161079     ///     builder 
10171080     ///         .fee_rate(FeeRate::from_sat_per_vb(5.0)); 
@@ -1171,7 +1234,7 @@ impl<D> Wallet<D> {
11711234     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; 
11721235     /// # let mut wallet = doctest_wallet!(); 
11731236     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); 
1174-      /// let ( mut psbt, _)  = { 
1237+      /// let mut psbt = { 
11751238     ///     let mut builder = wallet.build_tx(); 
11761239     ///     builder.add_recipient(to_address.script_pubkey(), 50_000); 
11771240     ///     builder.finish()? 
@@ -1721,7 +1784,7 @@ impl<D> Wallet<D> {
17211784        Ok ( changed) 
17221785    } 
17231786
1724-     /// Commits all curently  [`staged`] changed to the persistence backend returning and error when 
1787+     /// Commits all currently  [`staged`] changed to the persistence backend returning and error when 
17251788     /// this fails. 
17261789     /// 
17271790     /// This returns whether the `update` resulted in any changes. 
@@ -1812,61 +1875,6 @@ fn new_local_utxo(
18121875    } 
18131876} 
18141877
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- 
18701878#[ macro_export]  
18711879#[ doc( hidden) ]  
18721880/// Macro for getting a wallet for use in a doctest 
0 commit comments