Skip to content

Commit 9eba5ed

Browse files
committed
Add --reconcile-no-sync-account-balances flag to account sync subcommand
1 parent f84764c commit 9eba5ed

File tree

1 file changed

+72
-6
lines changed

1 file changed

+72
-6
lines changed

src/main.rs

+72-6
Original file line numberDiff line numberDiff line change
@@ -3277,12 +3277,13 @@ async fn process_account_sync(
32773277
rpc_client: &RpcClient,
32783278
address: Option<Pubkey>,
32793279
max_epochs_to_process: Option<u64>,
3280+
reconcile_no_sync_account_balances: bool,
32803281
notifier: &Notifier,
32813282
) -> Result<(), Box<dyn std::error::Error>> {
32823283
process_account_sync_pending_transfers(db, rpc_client).await?;
32833284
process_account_sync_sweep(db, rpc_client, notifier).await?;
32843285

3285-
let mut accounts = match address {
3286+
let (mut accounts, mut no_sync_accounts): (_, Vec<_>) = match address {
32863287
Some(address) => {
32873288
// sync all tokens for the given address...
32883289
let accounts = db.get_account_tokens(address);
@@ -3294,8 +3295,56 @@ async fn process_account_sync(
32943295
None => db.get_accounts(),
32953296
}
32963297
.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+
"\nWarning: {} ({}) 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+
}
32993348

33003349
let current_sol_price = MaybeToken::SOL().get_current_price(rpc_client).await?;
33013350

@@ -4491,6 +4540,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
44914540
.validator(is_parsable::<u64>)
44924541
.help("Only process up to this number of epochs for account balance changes [default: all]"),
44934542
)
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+
)
44944549
)
44954550
.subcommand(
44964551
SubCommand::with_name("wrap")
@@ -5490,8 +5545,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
54905545
)
54915546
.await?
54925547
}
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?;
54955557
}
54965558
("db", Some(db_matches)) => match db_matches.subcommand() {
54975559
("import", Some(arg_matches)) => {
@@ -5611,7 +5673,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
56115673
ui_amount,
56125674
)
56135675
.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?;
56155678
}
56165679
("dispose", Some(arg_matches)) => {
56175680
let address = pubkey_of(arg_matches, "address").unwrap();
@@ -5858,13 +5921,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
58585921
}
58595922
("sync", Some(arg_matches)) => {
58605923
let address = pubkey_of(arg_matches, "address");
5924+
let reconcile_no_sync_account_balances =
5925+
arg_matches.is_present("reconcile_no_sync_account_balances");
58615926
let max_epochs_to_process =
58625927
value_t!(arg_matches, "max_epochs_to_process", u64).ok();
58635928
process_account_sync(
58645929
&mut db,
58655930
&rpc_client,
58665931
address,
58675932
max_epochs_to_process,
5933+
reconcile_no_sync_account_balances,
58685934
&notifier,
58695935
)
58705936
.await?;

0 commit comments

Comments
 (0)