Skip to content

Commit 9c7f30b

Browse files
committed
update create-merkle-tree to discover next airdrop version for mint
1 parent 45f0685 commit 9c7f30b

File tree

5 files changed

+100
-11
lines changed

5 files changed

+100
-11
lines changed

cli/src/bin/cli.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ pub enum Commands {
124124
TotalClaim(TotalClaimAgrs),
125125

126126
SetClawbackReceiver(ClawbackReceiverArgs),
127+
128+
/// Iteratively find airdrop version (PDA that don't exist yet)
129+
FindAirdropVersion(FindAirdropVersionArgs),
127130
}
128131

129132
#[derive(Parser, Debug)]
@@ -177,6 +180,13 @@ pub struct VerifyArgs {
177180
pub skip_verify_amount: bool,
178181
}
179182

183+
// NewDistributor subcommand args
184+
#[derive(Parser, Debug)]
185+
pub struct FindAirdropVersionArgs {
186+
#[clap(long, env)]
187+
pub start_airdrop_version: Option<u64>,
188+
}
189+
180190
// NewDistributor subcommand args
181191
#[derive(Parser, Debug)]
182192
pub struct NewDistributorArgs {
@@ -236,6 +246,10 @@ pub struct CreateMerkleTreeArgs {
236246
pub amount: u64,
237247
#[clap(long, env)]
238248
pub decimals: u32,
249+
250+
/// Optional starting airdrop version. If not provided, will auto-detect next available version
251+
#[clap(long, env)]
252+
pub start_airdrop_version: Option<u64>,
239253
}
240254

241255
#[derive(Parser, Debug)]
@@ -423,7 +437,7 @@ fn main() {
423437
}
424438
Commands::Clawback(clawback_args) => process_clawback(&args, clawback_args),
425439
Commands::CreateMerkleTree(merkle_tree_args) => {
426-
process_create_merkle_tree(merkle_tree_args);
440+
process_create_merkle_tree(&args, merkle_tree_args);
427441
}
428442
Commands::SetAdmin(set_admin_args) => {
429443
process_set_admin(&args, set_admin_args);
@@ -473,6 +487,9 @@ fn main() {
473487
Commands::SetClawbackReceiver(set_clawback_receiver_argrs) => {
474488
process_set_clawback_receiver(&args, set_clawback_receiver_argrs)
475489
}
490+
Commands::FindAirdropVersion(find_airdrop_version_args) => {
491+
process_find_airdrop_version(&args, find_airdrop_version_args);
492+
}
476493
}
477494
}
478495

cli/src/bin/instructions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ pub mod verify_kv_proof;
4242
pub use verify_kv_proof::*;
4343
pub mod process_set_clawback_receiver;
4444
pub use process_set_clawback_receiver::*;
45+
pub mod process_find_airdrop_version;
46+
pub use process_find_airdrop_version::*;

cli/src/bin/instructions/process_create_merkle_tree.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,42 @@ use std::collections::HashMap;
22

33
use crate::*;
44

5-
pub fn process_create_merkle_tree(merkle_tree_args: &CreateMerkleTreeArgs) {
5+
pub fn process_create_merkle_tree(args: &Args, merkle_tree_args: &CreateMerkleTreeArgs) {
6+
// Find the next available airdrop version
7+
let mut start_airdrop_version = 0;
8+
if args.mint == Pubkey::default() {
9+
println!("Mint is not set, will start creating merkle trees from version 0");
10+
}
11+
if args.mint != Pubkey::default() && merkle_tree_args.start_airdrop_version.is_none() {
12+
println!("Finding next available airdrop version for mint: {}", args.mint);
13+
14+
let program_client = args.get_program_client();
15+
let rpc_client = program_client.rpc();
16+
17+
let mut current_version = 0;
18+
while current_version < 1000000000000000000 {
19+
let (distributor_pubkey, _bump) =
20+
get_merkle_distributor_pda(&args.program_id, &args.mint, current_version);
21+
match rpc_client.get_account_data(&distributor_pubkey) {
22+
Ok(_) => {
23+
println!("Airdrop version {} exists", current_version);
24+
}
25+
Err(e) => {
26+
if e.to_string().contains("AccountNotFound") {
27+
println!("Found next available airdrop version: {}", current_version);
28+
start_airdrop_version = current_version;
29+
break;
30+
} else {
31+
println!("Failed to get PDA, Error: {}", e.to_string());
32+
}
33+
}
34+
}
35+
current_version += 1;
36+
}
37+
} else if let Some(version) = merkle_tree_args.start_airdrop_version {
38+
start_airdrop_version = version;
39+
println!("Using provided start airdrop version: {}", start_airdrop_version);
40+
}
641
let mut csv_entries = CsvEntry::new_from_file(&merkle_tree_args.csv_path).unwrap();
742

843
// exclude test address if have
@@ -30,28 +65,28 @@ pub fn process_create_merkle_tree(merkle_tree_args: &CreateMerkleTreeArgs) {
3065
let max_nodes_per_tree = merkle_tree_args.max_nodes_per_tree as usize;
3166

3267
let base_path = &merkle_tree_args.merkle_tree_path;
33-
let mut index = 0;
68+
let mut airdrop_version = start_airdrop_version;
3469
while csv_entries.len() > 0 {
3570
let last_index = max_nodes_per_tree.min(csv_entries.len());
3671
let sub_tree = csv_entries[0..last_index].to_vec();
3772
csv_entries = csv_entries[last_index..csv_entries.len()].to_vec();
3873

39-
// use index as version
74+
// use airdrop_version as version
4075
let merkle_tree =
41-
AirdropMerkleTree::new_from_entries(sub_tree, index, merkle_tree_args.decimals)
76+
AirdropMerkleTree::new_from_entries(sub_tree, airdrop_version, merkle_tree_args.decimals)
4277
.unwrap();
4378

4479
let base_path_clone = base_path.clone();
4580
let path = base_path_clone
4681
.as_path()
47-
.join(format!("tree_{}.json", index));
82+
.join(format!("tree_{}.json", airdrop_version));
4883

4984
merkle_tree.write_to_file(&path);
50-
index += 1;
85+
airdrop_version += 1;
5186
}
5287

5388
if merkle_tree_args.should_include_test_list {
54-
println!("create merkle tree for test claming index {}", index);
89+
println!("create merkle tree for test claming version {}", airdrop_version);
5590
let test_list = get_test_list()
5691
.into_iter()
5792
.map(|x| CsvEntry {
@@ -62,13 +97,17 @@ pub fn process_create_merkle_tree(merkle_tree_args: &CreateMerkleTreeArgs) {
6297
.collect::<Vec<CsvEntry>>();
6398

6499
let merkle_tree =
65-
AirdropMerkleTree::new_from_entries(test_list, index, merkle_tree_args.decimals as u32)
100+
AirdropMerkleTree::new_from_entries(test_list, airdrop_version, merkle_tree_args.decimals as u32)
66101
.unwrap();
67102
let base_path_clone = base_path.clone();
68103
let path = base_path_clone
69104
.as_path()
70-
.join(format!("tree_{}.json", index));
105+
.join(format!("tree_{}.json", airdrop_version));
71106

72107
merkle_tree.write_to_file(&path);
108+
airdrop_version += 1;
73109
}
110+
111+
// Output the last airdrop version used
112+
println!("Last airdrop version created: {}", airdrop_version - 1);
74113
}

cli/src/bin/instructions/process_create_test_list.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub fn process_create_test_list(args: &Args, create_test_list_args: &CreateTestL
1818
should_include_test_list: false,
1919
amount: create_test_list_args.amount,
2020
decimals: create_test_list_args.decimals,
21+
start_airdrop_version: None,
2122
};
22-
process_create_merkle_tree(merkle_tree_args);
23+
process_create_merkle_tree(args, merkle_tree_args);
2324
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::*;
2+
3+
pub fn process_find_airdrop_version(args: &Args, new_distributor_args: &FindAirdropVersionArgs) {
4+
let program_client = args.get_program_client();
5+
let rpc_client = program_client.rpc();
6+
7+
let start_version_check = new_distributor_args.start_airdrop_version.unwrap_or(0);
8+
let mut current_version = start_version_check;
9+
10+
println!("Starting to find airdrop version for mint: {}, starting from: {}", args.mint, start_version_check);
11+
12+
while current_version < 1000000000000000000 {
13+
let (distributor_pubkey, _bump) =
14+
get_merkle_distributor_pda(&args.program_id, &args.mint, current_version);
15+
match rpc_client.get_account_data(&distributor_pubkey) {
16+
Ok(_) => {
17+
println!("Airdrop version {} exists, account: {}", current_version, distributor_pubkey);
18+
}
19+
Err(e) => {
20+
if e.to_string().contains("AccountNotFound") {
21+
println!("Airdrop version does not exist: {} <- next airdrop_version", current_version);
22+
break;
23+
} else {
24+
println!("Failed to get PDA, Error: {}", e.to_string());
25+
}
26+
}
27+
}
28+
current_version += 1;
29+
}
30+
}

0 commit comments

Comments
 (0)