Skip to content

Commit 5d516de

Browse files
committed
make cli more robust
1 parent a67d89b commit 5d516de

File tree

6 files changed

+119
-62
lines changed

6 files changed

+119
-62
lines changed

api/src/cache.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -286,15 +286,18 @@ impl Cache {
286286
let distributors_to_load = self.distributors.clone();
287287
let distributor_keys_vec = self.get_distributor_keys();
288288
let distributor_keys = distributor_keys_vec.as_slice();
289-
289+
290290
// Retry logic for network errors
291291
let mut retry_count = 0;
292292
const MAX_RETRIES: u32 = 3;
293293
const RETRY_DELAY: Duration = Duration::from_secs(2);
294-
294+
295295
loop {
296296
match rpc_client
297-
.get_multiple_accounts_with_commitment(&distributor_keys, CommitmentConfig::confirmed())
297+
.get_multiple_accounts_with_commitment(
298+
&distributor_keys,
299+
CommitmentConfig::confirmed(),
300+
)
298301
.await
299302
{
300303
Ok(accounts) => {
@@ -306,12 +309,15 @@ impl Cache {
306309
let distributor = distributors_to_load.get(index).unwrap();
307310
match account {
308311
Some(account) => {
309-
let distributor_data =
310-
MerkleDistributor::try_deserialize(&mut account.data.as_slice())
311-
.map_err(|err| ApiError::InternalError(Box::new(err)))
312-
.unwrap();
313-
distributor_cache
314-
.insert(distributor.distributor_pubkey.clone(), distributor_data);
312+
let distributor_data = MerkleDistributor::try_deserialize(
313+
&mut account.data.as_slice(),
314+
)
315+
.map_err(|err| ApiError::InternalError(Box::new(err)))
316+
.unwrap();
317+
distributor_cache.insert(
318+
distributor.distributor_pubkey.clone(),
319+
distributor_data,
320+
);
315321
}
316322
None => {
317323
println!(
@@ -325,18 +331,22 @@ impl Cache {
325331
}
326332
Err(e) => {
327333
retry_count += 1;
328-
println!("Error in distributor gma (attempt {}/{}): {:?}", retry_count, MAX_RETRIES, e);
329-
334+
println!(
335+
"Error in distributor gma (attempt {}/{}): {:?}",
336+
retry_count, MAX_RETRIES, e
337+
);
338+
330339
if retry_count >= MAX_RETRIES {
331340
println!("Max retries reached for distributor cache update. Skipping this cycle.");
332341
break;
333342
}
334-
343+
335344
// Check if it's a network error that's worth retrying
336345
let error_string = format!("{:?}", e);
337-
if error_string.contains("IncompleteMessage") ||
338-
error_string.contains("timeout") ||
339-
error_string.contains("connection") {
346+
if error_string.contains("IncompleteMessage")
347+
|| error_string.contains("timeout")
348+
|| error_string.contains("connection")
349+
{
340350
println!("Retrying after {} seconds...", RETRY_DELAY.as_secs());
341351
tokio::time::sleep(RETRY_DELAY).await;
342352
} else {
@@ -365,10 +375,16 @@ impl Cache {
365375
}
366376
// Allow polling updates (slot 0) to override if data is different
367377
// This fixes the bug where WebSocket misses updates but polling catches them
368-
if entry.get().slot <= data.slot || (data.slot == 0 && entry.get().data != data.data) {
378+
if entry.get().slot <= data.slot
379+
|| (data.slot == 0 && entry.get().data != data.data)
380+
{
369381
println!(
370382
"Updating cache with {} for claimant: {} ({}) on {} tree",
371-
if data.slot > 0 { "newer slot" } else { "polling data" },
383+
if data.slot > 0 {
384+
"newer slot"
385+
} else {
386+
"polling data"
387+
},
372388
data.data.claimant.to_string(),
373389
pubkey,
374390
data.data.distributor.to_string()

api/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,7 @@ async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
106106
info!("started rpc client at {}", args.rpc_url);
107107

108108
let mut paths: Vec<_> = match fs::read_dir(&args.merkle_tree_path) {
109-
Ok(entries) => entries
110-
.filter_map(|r| r.ok())
111-
.collect(),
109+
Ok(entries) => entries.filter_map(|r| r.ok()).collect(),
112110
Err(e) => {
113111
eprintln!(
114112
"Warning: Could not read merkle tree directory '{}': {}",

cli/src/bin/cli.rs

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ pub struct Args {
7272

7373
impl Args {
7474
fn get_program_client(&self) -> Program<Rc<Keypair>> {
75-
// let payer =
76-
// read_keypair_file(self.keypair_path.clone()).expect("Wallet keypair file not found");
77-
let payer = Keypair::new();
75+
let payer = read_keypair_file(self.keypair_path.clone().unwrap())
76+
.expect("Wallet keypair file not found");
77+
// let payer = Keypair::new();
7878
let client = AnchorClient::new_with_options(
7979
Cluster::Custom(self.rpc_url.clone(), self.rpc_url.clone()),
8080
Rc::new(Keypair::from_bytes(&payer.to_bytes()).unwrap()),
@@ -530,29 +530,43 @@ fn check_distributor_onchain_matches(
530530

531531
fn get_pre_list() -> Vec<String> {
532532
let list = vec![
533-
"DHLXnJdACTY83yKwnUkeoDjqi4QBbsYGa1v8tJL76ViX",
534-
"BULRqL3U2jPgwvz6HYCyBVq9BMtK94Y1Nz98KQop23aD",
535-
"7w32LzRsJrQiE7S3ZSdkz9TSFGey1XNsonPmdm9xDUch",
536-
"55pPhcCcp8gEKvKWr1JUkAcdwMeemmNhTHmkWNR9sJib",
537-
"62ucxc2gd5TBCwzToEEWVV4M5drVK7Fi7aYozniqWtac",
538-
"5unTfT2kssBuNvHPY6LbJfJpLqEcdMxGYLWHwShaeTLi",
539-
"9zg3seAh4Er1Nz8GAuiciH437apxtzgUWBT8frhudevR",
540-
"AjefJWRfjRCVNSQ1pHnTW8F7szLV7xFZftiB3yM5vnTa",
541-
"8SEFruHjgNrnV8ak2Ff11wg9em8Nh72RWTwk359bRyzE",
542-
"7jBypy9HX1dyLHPnmRnRubibNUaBPrShnERGnoE7rc3C",
543-
"XWpxVfYTeKmmp18DPxqPvWFL7P1C2vbdegDPAbXkV1n",
544-
"AuTFdqo4GsxpDgtag87pDaHE259cE94Z82kdpFozVBhC",
545-
"6h43GsVT3TjtLa5nRpsXp15GDpAY4smWCYHgcq58dSPM",
546-
"2mAax9cNqDXDg9eDJDby1tBh9Q8N3TS7qLhX9rMp8EVc",
547-
"JBeYA7dmBGCNgaEdtqdoUnESwKJho5YvgXVNLgo4n3MM",
548-
"HeTpE5BnNinzNv92MzVAGyVT5LjAwTWuk5qQcPURmi2L",
549-
"Bidku3jkJUxiTzBJZroEfwPcUWueNUst9LrMbZQLhrtG",
550-
"HUQytvb7WCCqbHnpQrVgXhmXSw4XfWMnmqCiKz6T1vsU",
551-
"4zvTjdpyr3SAgLeSpCnq4KaHvX2j5SbkwxYydzbfqhRQ",
552-
"EVfUfs9XNwJmfNvoazDbZVb6ecnGCxgQrJzsCQHoQ4q7",
553-
"GMtwcuktJfrRcnyGktWW4Vab8cfjPcBy3xbuZgRegw6E",
554-
"HAPdsaZFfQDG4bD8vzBbPCUawUWKSJxvhQ7TGg1BeAxZ",
533+
// "DHLXnJdACTY83yKwnUkeoDjqi4QBbsYGa1v8tJL76ViX",
534+
// "BULRqL3U2jPgwvz6HYCyBVq9BMtK94Y1Nz98KQop23aD",
535+
// "7w32LzRsJrQiE7S3ZSdkz9TSFGey1XNsonPmdm9xDUch",
536+
// "55pPhcCcp8gEKvKWr1JUkAcdwMeemmNhTHmkWNR9sJib",
537+
// "62ucxc2gd5TBCwzToEEWVV4M5drVK7Fi7aYozniqWtac",
538+
// "5unTfT2kssBuNvHPY6LbJfJpLqEcdMxGYLWHwShaeTLi",
539+
// "9zg3seAh4Er1Nz8GAuiciH437apxtzgUWBT8frhudevR",
540+
// "AjefJWRfjRCVNSQ1pHnTW8F7szLV7xFZftiB3yM5vnTa",
541+
// "8SEFruHjgNrnV8ak2Ff11wg9em8Nh72RWTwk359bRyzE",
542+
// "7jBypy9HX1dyLHPnmRnRubibNUaBPrShnERGnoE7rc3C",
543+
// "XWpxVfYTeKmmp18DPxqPvWFL7P1C2vbdegDPAbXkV1n",
544+
// "AuTFdqo4GsxpDgtag87pDaHE259cE94Z82kdpFozVBhC",
545+
// "6h43GsVT3TjtLa5nRpsXp15GDpAY4smWCYHgcq58dSPM",
546+
// "2mAax9cNqDXDg9eDJDby1tBh9Q8N3TS7qLhX9rMp8EVc",
547+
// "JBeYA7dmBGCNgaEdtqdoUnESwKJho5YvgXVNLgo4n3MM",
548+
// "HeTpE5BnNinzNv92MzVAGyVT5LjAwTWuk5qQcPURmi2L",
549+
// "Bidku3jkJUxiTzBJZroEfwPcUWueNUst9LrMbZQLhrtG",
550+
// "HUQytvb7WCCqbHnpQrVgXhmXSw4XfWMnmqCiKz6T1vsU",
551+
// "4zvTjdpyr3SAgLeSpCnq4KaHvX2j5SbkwxYydzbfqhRQ",
552+
// "EVfUfs9XNwJmfNvoazDbZVb6ecnGCxgQrJzsCQHoQ4q7",
553+
// "GMtwcuktJfrRcnyGktWW4Vab8cfjPcBy3xbuZgRegw6E",
554+
// "HAPdsaZFfQDG4bD8vzBbPCUawUWKSJxvhQ7TGg1BeAxZ",
555+
"4FED9aSQhGfX43FrSUa6GgmNjBsy76GTe9UHig7r2nK6",
556+
"6PAG5Le18uDrwkWWyuMFF3N3G74ksShVbUR5L7uDJtFR",
557+
"HZ1g3FXyvDt4pC1p7mUFnA44UtPkXghGJUtoxw5TDi42",
558+
"7gcjNCwGKhFsfDgHwH6Ja4pM2xBJj47hJpexxMFDyBpM",
559+
"8LWr1b9bXN7vRAgSL1Gg8U36ZB7oHGDupRQYVcw4FiQ9",
560+
"9qkVBGAgPzixW8Fky7sTjAoAv6ZAZEymVGvmYvqVwFmR",
561+
"FtfVWjnft13vKCGHGj6QaZcHWP8GcvJKanXQY3JL3zd3",
562+
"6gS27oW41tRD4GHW5QXe3vQN9SkC7TyFFQmtuRtJRT9Q",
563+
"dRiaT3YueNdfkhRBkLnzE6TDf4b35uESgL3Boopzxj6",
564+
"DRiL3JgMc8Hdxv6TBkxDcan9qEm2JoBhFiWViQxupPo",
565+
"DriQrk2v2HsLigaqH2qJtpCQ3MrNLGvq8GTB6jtXC2F",
566+
"DriEp7U5awPuc6p4ZM8gFWWxS79Go7VQstkKaMiGwJb",
567+
"DriM2HACfSFeh5tHum2aRgfgFeRGy72qpbc4UsMkvLm",
555568
];
569+
556570
let list: Vec<String> = list.iter().map(|x| x.to_string()).collect();
557571
list
558572
}

cli/src/bin/instructions/process_claim.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use solana_sdk::compute_budget::ComputeBudgetInstruction;
21
use crate::*;
2+
use solana_sdk::compute_budget::ComputeBudgetInstruction;
33

44
pub fn process_claim(args: &Args, claim_args: &ClaimArgs) {
55
let keypair = read_keypair_file(&args.keypair_path.clone().unwrap())
@@ -62,12 +62,8 @@ pub fn process_claim(args: &Args, claim_args: &ClaimArgs) {
6262
ixs.push(claim_ix);
6363

6464
let blockhash = client.get_latest_blockhash().unwrap();
65-
let tx = Transaction::new_signed_with_payer(
66-
&ixs,
67-
Some(&claimant.key()),
68-
&[&keypair],
69-
blockhash,
70-
);
65+
let tx =
66+
Transaction::new_signed_with_payer(&ixs, Some(&claimant.key()), &[&keypair], blockhash);
7167

7268
let signature = client
7369
.send_and_confirm_transaction_with_spinner(&tx)

cli/src/bin/instructions/process_fund_all.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use solana_sdk::compute_budget::ComputeBudgetInstruction;
21
use crate::*;
2+
use solana_sdk::compute_budget::ComputeBudgetInstruction;
33

44
pub fn process_fund_all(args: &Args, fund_all_args: &FundAllArgs) {
55
let program = args.get_program_client();
@@ -17,6 +17,29 @@ pub fn process_fund_all(args: &Args, fund_all_args: &FundAllArgs) {
1717
for file in paths {
1818
let single_tree_path = file.path();
1919

20+
// Skip directories
21+
if single_tree_path.is_dir() {
22+
continue;
23+
}
24+
25+
// Skip non-JSON files
26+
match single_tree_path.extension() {
27+
Some(ext) if ext == "json" => {
28+
// Continue processing JSON files
29+
}
30+
Some(ext) => {
31+
println!("skipping non-json file: {}", single_tree_path.display());
32+
continue;
33+
}
34+
None => {
35+
println!(
36+
"skipping file without extension: {}",
37+
single_tree_path.display()
38+
);
39+
continue;
40+
}
41+
}
42+
2043
let merkle_tree =
2144
AirdropMerkleTree::new_from_file(&single_tree_path).expect("failed to read");
2245
let (distributor_pubkey, _bump) =
@@ -45,14 +68,17 @@ pub fn process_fund_all(args: &Args, fund_all_args: &FundAllArgs) {
4568
);
4669
}
4770

48-
ixs.push(spl_token::instruction::transfer(
49-
&spl_token::id(),
50-
&source_vault,
51-
&token_vault,
52-
&keypair.pubkey(),
53-
&[],
54-
merkle_tree.max_total_claim,
55-
).unwrap());
71+
ixs.push(
72+
spl_token::instruction::transfer(
73+
&spl_token::id(),
74+
&source_vault,
75+
&token_vault,
76+
&keypair.pubkey(),
77+
&[],
78+
merkle_tree.max_total_claim,
79+
)
80+
.unwrap(),
81+
);
5682

5783
let tx = Transaction::new_signed_with_payer(
5884
&ixs,

cli/src/bin/instructions/process_new_distributor.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use solana_sdk::compute_budget::ComputeBudgetInstruction;
21
use crate::*;
2+
use solana_sdk::compute_budget::ComputeBudgetInstruction;
33

44
pub fn process_new_distributor(args: &Args, new_distributor_args: &NewDistributorArgs) {
55
let client = RpcClient::new_with_commitment(&args.rpc_url, CommitmentConfig::finalized());
@@ -75,6 +75,13 @@ pub fn process_new_distributor(args: &Args, new_distributor_args: &NewDistributo
7575
),
7676
);
7777
}
78+
println!("clawback_receiver: ");
79+
println!("keypair: {}", keypair.pubkey());
80+
println!(
81+
"keypair balance: {}",
82+
client.get_balance(&keypair.pubkey()).unwrap()
83+
);
84+
println!("program payer: {}", program.payer());
7885
let clawback_receiver = get_or_create_ata(&program, args.mint, keypair.pubkey()).unwrap();
7986

8087
ixs.push(Instruction {

0 commit comments

Comments
 (0)