2
2
use orchard:: note_encryption:: OrchardDomain ;
3
3
4
4
use sapling_crypto:: note_encryption:: SaplingDomain ;
5
+ use zcash_primitives:: transaction:: fees:: zip317:: MARGINAL_FEE ;
5
6
6
7
use std:: { cmp, sync:: Arc } ;
7
8
use tokio:: sync:: RwLock ;
@@ -82,6 +83,7 @@ impl LightWallet {
82
83
}
83
84
84
85
/// TODO: Add Doc Comment Here!
86
+ // TODO: this should minus the fee of sending the confirmed balance!
85
87
pub async fn spendable_orchard_balance ( & self , target_addr : Option < String > ) -> Option < u64 > {
86
88
if let Capability :: Spend ( _) = self . wallet_capability ( ) . orchard {
87
89
self . verified_balance :: < OrchardDomain > ( target_addr) . await
@@ -91,6 +93,7 @@ impl LightWallet {
91
93
}
92
94
93
95
/// TODO: Add Doc Comment Here!
96
+ // TODO: this should minus the fee of sending the confirmed balance!
94
97
pub async fn spendable_sapling_balance ( & self , target_addr : Option < String > ) -> Option < u64 > {
95
98
if let Capability :: Spend ( _) = self . wallet_capability ( ) . sapling {
96
99
self . verified_balance :: < SaplingDomain > ( target_addr) . await
@@ -161,12 +164,33 @@ impl LightWallet {
161
164
self . shielded_balance :: < D > ( target_addr, filters) . await
162
165
}
163
166
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" ) ]
165
188
pub async fn maybe_verified_orchard_balance ( & self , addr : Option < String > ) -> Option < u64 > {
166
189
self . shielded_balance :: < OrchardDomain > ( addr, & [ ] ) . await
167
190
}
168
191
169
- /// TODO: Add Doc Comment Here!
192
+ /// Deprecated for `shielded_balance`
193
+ #[ deprecated( note = "deprecated for `shielded_balance` as incorrectly named and unnecessary" ) ]
170
194
pub async fn maybe_verified_sapling_balance ( & self , addr : Option < String > ) -> Option < u64 > {
171
195
self . shielded_balance :: < SaplingDomain > ( addr, & [ ] ) . await
172
196
}
@@ -203,7 +227,7 @@ impl LightWallet {
203
227
/// Get the height of the anchor block
204
228
pub async fn get_anchor_height ( & self ) -> u32 {
205
229
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 ?
207
231
None => 0 ,
208
232
}
209
233
}
@@ -290,3 +314,101 @@ impl LightWallet {
290
314
self . transaction_context . transaction_metadata_set . clone ( )
291
315
}
292
316
}
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