22use orchard:: note_encryption:: OrchardDomain ;
33
44use sapling_crypto:: note_encryption:: SaplingDomain ;
5+ use zcash_primitives:: transaction:: fees:: zip317:: MARGINAL_FEE ;
56
67use std:: { cmp, sync:: Arc } ;
78use tokio:: sync:: RwLock ;
@@ -82,6 +83,7 @@ impl LightWallet {
8283 }
8384
8485 /// TODO: Add Doc Comment Here!
86+ // TODO: this should minus the fee of sending the confirmed balance!
8587 pub async fn spendable_orchard_balance ( & self , target_addr : Option < String > ) -> Option < u64 > {
8688 if let Capability :: Spend ( _) = self . wallet_capability ( ) . orchard {
8789 self . verified_balance :: < OrchardDomain > ( target_addr) . await
@@ -91,6 +93,7 @@ impl LightWallet {
9193 }
9294
9395 /// TODO: Add Doc Comment Here!
96+ // TODO: this should minus the fee of sending the confirmed balance!
9497 pub async fn spendable_sapling_balance ( & self , target_addr : Option < String > ) -> Option < u64 > {
9598 if let Capability :: Spend ( _) = self . wallet_capability ( ) . sapling {
9699 self . verified_balance :: < SaplingDomain > ( target_addr) . await
@@ -161,12 +164,33 @@ impl LightWallet {
161164 self . shielded_balance :: < D > ( target_addr, filters) . await
162165 }
163166
164- /// TODO: Add Doc Comment Here!
167+ /// Returns balance for a given shielded pool excluding any notes with value less than marginal fee
168+ /// that are confirmed on the block chain (the block has at least 1 confirmation)
169+ pub async fn confirmed_balance_excluding_dust < D : DomainWalletExt > (
170+ & self ,
171+ target_addr : Option < String > ,
172+ ) -> Option < u64 >
173+ where
174+ <D as Domain >:: Recipient : Recipient ,
175+ <D as Domain >:: Note : PartialEq + Clone ,
176+ {
177+ #[ allow( clippy:: type_complexity) ]
178+ let filters: & [ Box < dyn Fn ( & & D :: WalletNote , & TransactionRecord ) -> bool > ] = & [
179+ Box :: new ( |_, transaction| transaction. status . is_confirmed ( ) ) ,
180+ Box :: new ( |note, _| !note. pending_receipt ( ) ) ,
181+ Box :: new ( |note, _| note. value ( ) >= MARGINAL_FEE . into_u64 ( ) ) ,
182+ ] ;
183+ self . shielded_balance :: < D > ( target_addr, filters) . await
184+ }
185+
186+ /// Deprecated for `shielded_balance`
187+ #[ deprecated( note = "deprecated for `shielded_balance` as incorrectly named and unnecessary" ) ]
165188 pub async fn maybe_verified_orchard_balance ( & self , addr : Option < String > ) -> Option < u64 > {
166189 self . shielded_balance :: < OrchardDomain > ( addr, & [ ] ) . await
167190 }
168191
169- /// TODO: Add Doc Comment Here!
192+ /// Deprecated for `shielded_balance`
193+ #[ deprecated( note = "deprecated for `shielded_balance` as incorrectly named and unnecessary" ) ]
170194 pub async fn maybe_verified_sapling_balance ( & self , addr : Option < String > ) -> Option < u64 > {
171195 self . shielded_balance :: < SaplingDomain > ( addr, & [ ] ) . await
172196 }
@@ -203,7 +227,7 @@ impl LightWallet {
203227 /// Get the height of the anchor block
204228 pub async fn get_anchor_height ( & self ) -> u32 {
205229 match self . get_target_height_and_anchor_offset ( ) . await {
206- Some ( ( height, anchor_offset) ) => height - anchor_offset as u32 - 1 ,
230+ Some ( ( height, anchor_offset) ) => height - anchor_offset as u32 - 1 , // what is the purpose of this -1 ?
207231 None => 0 ,
208232 }
209233 }
@@ -290,3 +314,101 @@ impl LightWallet {
290314 self . transaction_context . transaction_metadata_set . clone ( )
291315 }
292316}
317+
318+ #[ cfg( test) ]
319+ mod tests {
320+ use orchard:: note_encryption:: OrchardDomain ;
321+ use sapling_crypto:: note_encryption:: SaplingDomain ;
322+
323+ use zingo_status:: confirmation_status:: ConfirmationStatus ;
324+ use zingoconfig:: ZingoConfigBuilder ;
325+
326+ use crate :: {
327+ mocks:: { orchard_note:: OrchardCryptoNoteBuilder , SaplingCryptoNoteBuilder } ,
328+ wallet:: {
329+ notes:: {
330+ orchard:: mocks:: OrchardNoteBuilder , sapling:: mocks:: SaplingNoteBuilder ,
331+ transparent:: mocks:: TransparentOutputBuilder ,
332+ } ,
333+ transaction_record:: mocks:: TransactionRecordBuilder ,
334+ LightWallet , WalletBase ,
335+ } ,
336+ } ;
337+
338+ #[ tokio:: test]
339+ async fn confirmed_balance_excluding_dust ( ) {
340+ let wallet = LightWallet :: new (
341+ ZingoConfigBuilder :: default ( ) . create ( ) ,
342+ WalletBase :: FreshEntropy ,
343+ 1 ,
344+ )
345+ . unwrap ( ) ;
346+ let confirmed_tx_record = TransactionRecordBuilder :: default ( )
347+ . status ( ConfirmationStatus :: Confirmed ( 80 . into ( ) ) )
348+ . transparent_outputs ( TransparentOutputBuilder :: default ( ) )
349+ . sapling_notes ( SaplingNoteBuilder :: default ( ) )
350+ . sapling_notes ( SaplingNoteBuilder :: default ( ) )
351+ . sapling_notes (
352+ SaplingNoteBuilder :: default ( )
353+ . note (
354+ SaplingCryptoNoteBuilder :: default ( )
355+ . value ( sapling_crypto:: value:: NoteValue :: from_raw ( 3_000 ) )
356+ . clone ( ) ,
357+ )
358+ . clone ( ) ,
359+ )
360+ . orchard_notes ( OrchardNoteBuilder :: default ( ) )
361+ . orchard_notes ( OrchardNoteBuilder :: default ( ) )
362+ . orchard_notes (
363+ OrchardNoteBuilder :: default ( )
364+ . note (
365+ OrchardCryptoNoteBuilder :: default ( )
366+ . value ( orchard:: value:: NoteValue :: from_raw ( 5_000 ) )
367+ . clone ( ) ,
368+ )
369+ . clone ( ) ,
370+ )
371+ . orchard_notes (
372+ OrchardNoteBuilder :: default ( )
373+ . note (
374+ OrchardCryptoNoteBuilder :: default ( )
375+ . value ( orchard:: value:: NoteValue :: from_raw ( 2_000 ) )
376+ . clone ( ) ,
377+ )
378+ . clone ( ) ,
379+ )
380+ . build ( ) ;
381+ let pending_tx_record = TransactionRecordBuilder :: default ( )
382+ . status ( ConfirmationStatus :: Pending ( 95 . into ( ) ) )
383+ . transparent_outputs ( TransparentOutputBuilder :: default ( ) )
384+ . sapling_notes ( SaplingNoteBuilder :: default ( ) )
385+ . orchard_notes ( OrchardNoteBuilder :: default ( ) )
386+ . build ( ) ;
387+ {
388+ let mut tx_map = wallet
389+ . transaction_context
390+ . transaction_metadata_set
391+ . write ( )
392+ . await ;
393+ tx_map
394+ . transaction_records_by_id
395+ . insert_transaction_record ( confirmed_tx_record) ;
396+ tx_map
397+ . transaction_records_by_id
398+ . insert_transaction_record ( pending_tx_record) ;
399+ }
400+
401+ assert_eq ! (
402+ wallet
403+ . confirmed_balance_excluding_dust:: <SaplingDomain >( None )
404+ . await ,
405+ Some ( 400_000 )
406+ ) ;
407+ assert_eq ! (
408+ wallet
409+ . confirmed_balance_excluding_dust:: <OrchardDomain >( None )
410+ . await ,
411+ Some ( 1_605_000 )
412+ ) ;
413+ }
414+ }
0 commit comments