[bdk_chain_redesign] Add balance methods to IndexedTxGraph
				
					
				
			This commit is contained in:
		
							parent
							
								
									d0a2aa83be
								
							
						
					
					
						commit
						db7883d813
					
				| @ -14,6 +14,15 @@ pub enum ObservedIn<A> { | ||||
|     Mempool(u64), | ||||
| } | ||||
| 
 | ||||
| impl<A: Clone> ObservedIn<&A> { | ||||
|     pub fn into_owned(self) -> ObservedIn<A> { | ||||
|         match self { | ||||
|             ObservedIn::Block(a) => ObservedIn::Block(a.clone()), | ||||
|             ObservedIn::Mempool(last_seen) => ObservedIn::Mempool(last_seen), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ChainPosition for ObservedIn<BlockId> { | ||||
|     fn height(&self) -> TxHeight { | ||||
|         match self { | ||||
| @ -259,4 +268,16 @@ impl<I: ChainPosition> FullTxOut<I> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<A: Clone> FullTxOut<ObservedIn<&A>> { | ||||
|     pub fn into_owned(self) -> FullTxOut<ObservedIn<A>> { | ||||
|         FullTxOut { | ||||
|             outpoint: self.outpoint, | ||||
|             txout: self.txout, | ||||
|             chain_position: self.chain_position.into_owned(), | ||||
|             spent_by: self.spent_by.map(|(o, txid)| (o.into_owned(), txid)), | ||||
|             is_on_coinbase: self.is_on_coinbase, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // TODO: make test
 | ||||
|  | ||||
| @ -4,6 +4,7 @@ use alloc::collections::BTreeSet; | ||||
| use bitcoin::{OutPoint, Transaction, TxOut}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     keychain::Balance, | ||||
|     sparse_chain::ChainPosition, | ||||
|     tx_graph::{Additions, TxGraph, TxInGraph}, | ||||
|     BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions, | ||||
| @ -260,4 +261,86 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> { | ||||
|         self.try_list_chain_utxos(chain) | ||||
|             .map(|r| r.expect("error is infallible")) | ||||
|     } | ||||
| 
 | ||||
|     pub fn try_balance<C, F>( | ||||
|         &self, | ||||
|         chain: C, | ||||
|         tip: u32, | ||||
|         mut should_trust: F, | ||||
|     ) -> Result<Balance, C::Error> | ||||
|     where | ||||
|         C: ChainOracle, | ||||
|         ObservedIn<A>: ChainPosition + Clone, | ||||
|         F: FnMut(&I::SpkIndex) -> bool, | ||||
|     { | ||||
|         let mut immature = 0; | ||||
|         let mut trusted_pending = 0; | ||||
|         let mut untrusted_pending = 0; | ||||
|         let mut confirmed = 0; | ||||
| 
 | ||||
|         for res in self.try_list_chain_txouts(&chain) { | ||||
|             let TxOutInChain { spk_index, txout } = res?; | ||||
|             let txout = txout.into_owned(); | ||||
| 
 | ||||
|             match &txout.chain_position { | ||||
|                 ObservedIn::Block(_) => { | ||||
|                     if txout.is_on_coinbase { | ||||
|                         if txout.is_mature(tip) { | ||||
|                             confirmed += txout.txout.value; | ||||
|                         } else { | ||||
|                             immature += txout.txout.value; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 ObservedIn::Mempool(_) => { | ||||
|                     if should_trust(spk_index) { | ||||
|                         trusted_pending += txout.txout.value; | ||||
|                     } else { | ||||
|                         untrusted_pending += txout.txout.value; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Ok(Balance { | ||||
|             immature, | ||||
|             trusted_pending, | ||||
|             untrusted_pending, | ||||
|             confirmed, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn balance<C, F>(&self, chain: C, tip: u32, should_trust: F) -> Balance | ||||
|     where | ||||
|         C: ChainOracle<Error = Infallible>, | ||||
|         ObservedIn<A>: ChainPosition + Clone, | ||||
|         F: FnMut(&I::SpkIndex) -> bool, | ||||
|     { | ||||
|         self.try_balance(chain, tip, should_trust) | ||||
|             .expect("error is infallible") | ||||
|     } | ||||
| 
 | ||||
|     pub fn try_balance_at<C>(&self, chain: C, height: u32) -> Result<u64, C::Error> | ||||
|     where | ||||
|         C: ChainOracle, | ||||
|         ObservedIn<A>: ChainPosition + Clone, | ||||
|     { | ||||
|         let mut sum = 0; | ||||
|         for res in self.try_list_chain_txouts(chain) { | ||||
|             let txo = res?.txout.into_owned(); | ||||
|             if txo.is_spendable_at(height) { | ||||
|                 sum += txo.txout.value; | ||||
|             } | ||||
|         } | ||||
|         Ok(sum) | ||||
|     } | ||||
| 
 | ||||
|     pub fn balance_at<C>(&self, chain: C, height: u32) -> u64 | ||||
|     where | ||||
|         C: ChainOracle<Error = Infallible>, | ||||
|         ObservedIn<A>: ChainPosition + Clone, | ||||
|     { | ||||
|         self.try_balance_at(chain, height) | ||||
|             .expect("error is infallible") | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user