@@ -3277,12 +3277,13 @@ async fn process_account_sync(
3277
3277
rpc_client : & RpcClient ,
3278
3278
address : Option < Pubkey > ,
3279
3279
max_epochs_to_process : Option < u64 > ,
3280
+ reconcile_no_sync_account_balances : bool ,
3280
3281
notifier : & Notifier ,
3281
3282
) -> Result < ( ) , Box < dyn std:: error:: Error > > {
3282
3283
process_account_sync_pending_transfers ( db, rpc_client) . await ?;
3283
3284
process_account_sync_sweep ( db, rpc_client, notifier) . await ?;
3284
3285
3285
- let mut accounts = match address {
3286
+ let ( mut accounts, mut no_sync_accounts ) : ( _ , Vec < _ > ) = match address {
3286
3287
Some ( address) => {
3287
3288
// sync all tokens for the given address...
3288
3289
let accounts = db. get_account_tokens ( address) ;
@@ -3294,8 +3295,56 @@ async fn process_account_sync(
3294
3295
None => db. get_accounts ( ) ,
3295
3296
}
3296
3297
. into_iter ( )
3297
- . filter ( |account| !account. no_sync . unwrap_or_default ( ) )
3298
- . collect :: < Vec < _ > > ( ) ;
3298
+ . partition ( |account| !account. no_sync . unwrap_or_default ( ) ) ;
3299
+
3300
+ if reconcile_no_sync_account_balances {
3301
+ println ! ( "{} no sync accounts" , no_sync_accounts. len( ) ) ;
3302
+ for account in no_sync_accounts. iter_mut ( ) {
3303
+ if account. lots . is_empty ( ) {
3304
+ continue ;
3305
+ }
3306
+
3307
+ let current_balance = account. token . balance ( rpc_client, & account. address ) ?;
3308
+
3309
+ match current_balance. cmp ( & account. last_update_balance ) {
3310
+ std:: cmp:: Ordering :: Less => {
3311
+ println ! (
3312
+ "\n Warning: {} ({}) balance is less than expected. Actual: {}{}, expected: {}{}\n " ,
3313
+ account. address,
3314
+ account. token,
3315
+ account. token. symbol( ) ,
3316
+ account. token. ui_amount( current_balance) ,
3317
+ account. token. symbol( ) ,
3318
+ account. token. ui_amount( account. last_update_balance)
3319
+ ) ;
3320
+ }
3321
+ std:: cmp:: Ordering :: Greater => {
3322
+ // sort by lowest basis
3323
+ account
3324
+ . lots
3325
+ . sort_by ( |a, b| a. acquisition . price ( ) . cmp ( & b. acquisition . price ( ) ) ) ;
3326
+
3327
+ let lowest_basis_lot = & mut account. lots [ 0 ] ;
3328
+ let additional_balance = current_balance - account. last_update_balance ;
3329
+ lowest_basis_lot. amount += additional_balance;
3330
+
3331
+ let msg = format ! (
3332
+ "{} ({}): Additional {}{} added" ,
3333
+ account. address,
3334
+ account. token,
3335
+ account. token. symbol( ) ,
3336
+ account. token. ui_amount( additional_balance)
3337
+ ) ;
3338
+ notifier. send ( & msg) . await ;
3339
+ println ! ( "{msg}" ) ;
3340
+
3341
+ account. last_update_balance = current_balance;
3342
+ db. update_account ( account. clone ( ) ) ?;
3343
+ }
3344
+ _ => { }
3345
+ }
3346
+ }
3347
+ }
3299
3348
3300
3349
let current_sol_price = MaybeToken :: SOL ( ) . get_current_price ( rpc_client) . await ?;
3301
3350
@@ -4491,6 +4540,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4491
4540
. validator ( is_parsable :: < u64 > )
4492
4541
. help ( "Only process up to this number of epochs for account balance changes [default: all]" ) ,
4493
4542
)
4543
+ . arg (
4544
+ Arg :: with_name ( "reconcile_no_sync_account_balances" )
4545
+ . long ( "reconcile-no-sync-account-balances" )
4546
+ . takes_value ( false )
4547
+ . help ( "Reconcile local account balances with on-chain state for --no-sync accounts (advanced; uncommon)" ) ,
4548
+ )
4494
4549
)
4495
4550
. subcommand (
4496
4551
SubCommand :: with_name ( "wrap" )
@@ -5490,8 +5545,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5490
5545
)
5491
5546
. await ?
5492
5547
}
5493
- process_account_sync ( & mut db, & rpc_client, None , max_epochs_to_process, & notifier)
5494
- . await ?;
5548
+ process_account_sync (
5549
+ & mut db,
5550
+ & rpc_client,
5551
+ None ,
5552
+ max_epochs_to_process,
5553
+ false ,
5554
+ & notifier,
5555
+ )
5556
+ . await ?;
5495
5557
}
5496
5558
( "db" , Some ( db_matches) ) => match db_matches. subcommand ( ) {
5497
5559
( "import" , Some ( arg_matches) ) => {
@@ -5611,7 +5673,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5611
5673
ui_amount,
5612
5674
)
5613
5675
. await ?;
5614
- process_account_sync ( & mut db, & rpc_client, Some ( address) , None , & notifier) . await ?;
5676
+ process_account_sync ( & mut db, & rpc_client, Some ( address) , None , false , & notifier)
5677
+ . await ?;
5615
5678
}
5616
5679
( "dispose" , Some ( arg_matches) ) => {
5617
5680
let address = pubkey_of ( arg_matches, "address" ) . unwrap ( ) ;
@@ -5858,13 +5921,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5858
5921
}
5859
5922
( "sync" , Some ( arg_matches) ) => {
5860
5923
let address = pubkey_of ( arg_matches, "address" ) ;
5924
+ let reconcile_no_sync_account_balances =
5925
+ arg_matches. is_present ( "reconcile_no_sync_account_balances" ) ;
5861
5926
let max_epochs_to_process =
5862
5927
value_t ! ( arg_matches, "max_epochs_to_process" , u64 ) . ok ( ) ;
5863
5928
process_account_sync (
5864
5929
& mut db,
5865
5930
& rpc_client,
5866
5931
address,
5867
5932
max_epochs_to_process,
5933
+ reconcile_no_sync_account_balances,
5868
5934
& notifier,
5869
5935
)
5870
5936
. await ?;
0 commit comments