@@ -427,27 +427,97 @@ impl<D> Wallet<D> {
427427 . next ( )
428428 }
429429
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 > {
430+ /// Returns a `TxOut` known by this wallet corresponding to `outpoint` if it exists in the
431+ /// wallet's database whether spent or not.
432+ pub fn get_txout ( & self , outpoint : & OutPoint ) -> Option < TxOut > {
433+ self . indexed_graph
434+ . graph ( )
435+ . all_txouts ( )
436+ . filter_map ( |( op, txo) | {
437+ if op. eq ( outpoint) {
438+ Some ( txo. clone ( ) )
439+ } else {
440+ None
441+ }
442+ } )
443+ . next ( )
444+ }
445+
446+ /// The total transaction fee amount, sum of input amounts minus sum of output amounts, in sats.
447+ /// If the `Wallet` is missing a TxOut for an input returns None.
448+ pub fn fee_amount ( & self , tx : & Transaction ) -> Option < u64 > {
449+ let txouts: Option < Vec < TxOut > > = tx
450+ . input
451+ . iter ( )
452+ . map ( |txin| self . get_txout ( & txin. previous_output ) )
453+ . collect ( ) ;
454+
455+ txouts. map ( |inputs| {
456+ let input_amount: u64 = inputs. iter ( ) . map ( |i| i. value ) . sum ( ) ;
457+ let output_amount: u64 = tx. output . iter ( ) . map ( |o| o. value ) . sum ( ) ;
458+ input_amount
459+ . checked_sub ( output_amount)
460+ . expect ( "input amount must be greater than output amount" )
461+ } )
462+ }
463+
464+ /// The transaction's `FeeRate`. If the `Wallet` is missing a `TxOut` for an input returns None.
465+ pub fn fee_rate ( & self , tx : & Transaction ) -> Option < FeeRate > {
466+ let fee_amount = self . fee_amount ( tx) ;
467+ fee_amount. map ( |fee| {
468+ let weight = tx. weight ( ) ;
469+ FeeRate :: from_wu ( fee, weight)
470+ } )
471+ }
472+
473+ /// Return `TransactionAmounts` for a `Transaction` in relation to the `Wallet` and it's
474+ /// descriptors.
475+ pub fn sent_and_received ( & self , tx : & Transaction ) -> TransactionAmounts {
476+ let index = & self . indexed_graph . index ;
477+
478+ let received = tx
479+ . output
480+ . iter ( )
481+ . map ( |txout| {
482+ if index. index_of_spk ( & txout. script_pubkey ) . is_some ( ) {
483+ txout. value
484+ } else {
485+ 0
486+ }
487+ } )
488+ . sum ( ) ;
489+
490+ let sent = tx
491+ . input
492+ . iter ( )
493+ . map ( |txin| {
494+ if let Some ( ( _, txout) ) = index. txout ( txin. previous_output ) {
495+ txout. value
496+ } else {
497+ 0
498+ }
499+ } )
500+ . sum ( ) ;
501+
502+ TransactionAmounts { sent, received }
503+ }
504+
505+ /// Return a single `CanonicalTx` made and received by the wallet or `None` if it doesn't
506+ /// exist in the wallet
507+ pub fn get_tx (
508+ & self ,
509+ txid : Txid ,
510+ ) -> Option < CanonicalTx < ' _ , Transaction , ConfirmationTimeAnchor > > {
435511 let graph = self . indexed_graph . graph ( ) ;
436512
437- let canonical_tx = CanonicalTx {
513+ Some ( CanonicalTx {
438514 observed_as : graph. get_chain_position (
439515 & self . chain ,
440516 self . chain . tip ( ) . unwrap_or_default ( ) ,
441517 txid,
442518 ) ?,
443519 node : graph. get_tx_node ( txid) ?,
444- } ;
445-
446- Some ( new_tx_details (
447- & self . indexed_graph ,
448- canonical_tx,
449- include_raw,
450- ) )
520+ } )
451521 }
452522
453523 /// Add a new checkpoint to the wallet's internal view of the chain.
@@ -599,7 +669,7 @@ impl<D> Wallet<D> {
599669 /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
600670 /// # let mut wallet = doctest_wallet!();
601671 /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
602- /// let ( psbt, details) = {
672+ /// let psbt = {
603673 /// let mut builder = wallet.build_tx();
604674 /// builder
605675 /// .add_recipient(to_address.script_pubkey(), 50_000);
@@ -624,7 +694,7 @@ impl<D> Wallet<D> {
624694 & mut self ,
625695 coin_selection : Cs ,
626696 params : TxParams ,
627- ) -> Result < ( psbt:: PartiallySignedTransaction , TransactionDetails ) , Error >
697+ ) -> Result < psbt:: PartiallySignedTransaction , Error >
628698 where
629699 D : PersistBackend < ChangeSet > ,
630700 {
@@ -969,20 +1039,8 @@ impl<D> Wallet<D> {
9691039 // sort input/outputs according to the chosen algorithm
9701040 params. ordering . sort_tx ( & mut tx) ;
9711041
972- let txid = tx. txid ( ) ;
973- let sent = coin_selection. local_selected_amount ( ) ;
9741042 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) )
1043+ Ok ( psbt)
9861044 }
9871045
9881046 /// Bump the fee of a transaction previously created with this wallet.
@@ -1001,7 +1059,7 @@ impl<D> Wallet<D> {
10011059 /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
10021060 /// # let mut wallet = doctest_wallet!();
10031061 /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
1004- /// let ( mut psbt, _) = {
1062+ /// let mut psbt = {
10051063 /// let mut builder = wallet.build_tx();
10061064 /// builder
10071065 /// .add_recipient(to_address.script_pubkey(), 50_000)
@@ -1011,7 +1069,7 @@ impl<D> Wallet<D> {
10111069 /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
10121070 /// let tx = psbt.extract_tx();
10131071 /// // broadcast tx but it's taking too long to confirm so we want to bump the fee
1014- /// let ( mut psbt, _) = {
1072+ /// let mut psbt = {
10151073 /// let mut builder = wallet.build_fee_bump(tx.txid())?;
10161074 /// builder
10171075 /// .fee_rate(FeeRate::from_sat_per_vb(5.0));
@@ -1171,7 +1229,7 @@ impl<D> Wallet<D> {
11711229 /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
11721230 /// # let mut wallet = doctest_wallet!();
11731231 /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
1174- /// let ( mut psbt, _) = {
1232+ /// let mut psbt = {
11751233 /// let mut builder = wallet.build_tx();
11761234 /// builder.add_recipient(to_address.script_pubkey(), 50_000);
11771235 /// builder.finish()?
@@ -1721,7 +1779,7 @@ impl<D> Wallet<D> {
17211779 Ok ( changed)
17221780 }
17231781
1724- /// Commits all curently [`staged`] changed to the persistence backend returning and error when
1782+ /// Commits all currently [`staged`] changed to the persistence backend returning and error when
17251783 /// this fails.
17261784 ///
17271785 /// This returns whether the `update` resulted in any changes.
@@ -1812,61 +1870,6 @@ fn new_local_utxo(
18121870 }
18131871}
18141872
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-
18701873#[ macro_export]
18711874#[ doc( hidden) ]
18721875/// Macro for getting a wallet for use in a doctest
0 commit comments