diff --git a/mev-programs/tip-distribution-cli/src/main.rs b/mev-programs/tip-distribution-cli/src/main.rs index 26db60c..b7dfb70 100644 --- a/mev-programs/tip-distribution-cli/src/main.rs +++ b/mev-programs/tip-distribution-cli/src/main.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use anchor_lang::AccountDeserialize; +use anchor_lang::{system_program, AccountDeserialize, InstructionData, ToAccountMetas}; use clap::{Parser, Subcommand}; use jito_tip_distribution::state::{ClaimStatus, Config, TipDistributionAccount}; use jito_tip_distribution_sdk::{ @@ -8,7 +8,10 @@ use jito_tip_distribution_sdk::{ instruction::{update_config_ix, UpdateConfigAccounts, UpdateConfigArgs}, }; use solana_client::rpc_client::RpcClient; -use solana_sdk::pubkey::Pubkey; +use solana_sdk::{ + instruction::Instruction, pubkey::Pubkey, signature::read_keypair_file, signer::Signer, + transaction::Transaction, +}; #[derive(Parser)] #[command(author, version, about, long_about = None)] @@ -25,15 +28,48 @@ struct Cli { )] program_id: String, + #[arg(short, long)] + keypair_path: String, + #[command(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { + /// Initialize the config account information + InitConfig { + /// Authority + authority: Pubkey, + + /// Expired funds account + expired_funds_account: Pubkey, + + /// Number of epochs is valid + num_epochs_valid: u64, + + /// Max validator commission BPS + max_validator_commission_bps: u16, + }, + /// Get the config account information GetConfig, + /// Get tip distribution account information for a specific validator and epoch + InitializeTipDistributionAccount { + /// Validator vote account pubkey + #[arg(long)] + vote_account: Pubkey, + + /// Merkle root upload authority + #[arg(long)] + merkle_root_upload_authority: Pubkey, + + /// Validator commission BPS + #[arg(long)] + validator_commission_bps: u16, + }, + /// Get tip distribution account information for a specific validator and epoch GetTipDistributionAccount { /// Validator vote account pubkey @@ -77,10 +113,14 @@ enum Commands { /// Max validator commission BPS #[arg(long)] max_validator_commission_bps: u16, + }, - /// Bump - #[arg(long)] - bump: u8, + /// Upload merkle root + UploadMerkleRoot { + vote_account: Pubkey, + root: Vec, + max_total_claim: u64, + max_num_nodes: u64, }, } @@ -91,7 +131,46 @@ fn main() -> anyhow::Result<()> { let client = RpcClient::new(cli.rpc_url); + let keypair = read_keypair_file(cli.keypair_path).expect("Failed to read keypair"); + + let (config_pda, config_bump) = derive_config_account_address(&program_id); + match cli.command { + Commands::InitConfig { + authority, + expired_funds_account, + num_epochs_valid, + max_validator_commission_bps, + } => { + let ix = Instruction { + program_id, + data: jito_tip_distribution::instruction::Initialize { + authority, + expired_funds_account, + num_epochs_valid, + max_validator_commission_bps, + bump: config_bump, + } + .data(), + accounts: jito_tip_distribution::accounts::Initialize { + config: config_pda, + system_program: system_program::ID, + initializer: keypair.pubkey(), + } + .to_account_metas(None), + }; + + let blockhash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&keypair.pubkey()), + &[keypair], + blockhash, + ); + + client.send_transaction(&tx)?; + } + Commands::GetConfig => { let (config_pda, _) = derive_config_account_address(&program_id); println!("Config Account Address: {}", config_pda); @@ -110,6 +189,44 @@ fn main() -> anyhow::Result<()> { println!(" Bump: {}", config.bump); } + Commands::InitializeTipDistributionAccount { + vote_account, + merkle_root_upload_authority, + validator_commission_bps, + } => { + let epoch = client.get_epoch_info()?.epoch; + let (tip_distribution_pubkey, tip_distribution_bump) = + derive_tip_distribution_account_address(&program_id, &vote_account, epoch); + + let ix = Instruction { + program_id, + data: jito_tip_distribution::instruction::InitializeTipDistributionAccount { + merkle_root_upload_authority, + validator_commission_bps, + bump: tip_distribution_bump, + } + .data(), + accounts: jito_tip_distribution::accounts::InitializeTipDistributionAccount { + config: config_pda, + tip_distribution_account: tip_distribution_pubkey, + validator_vote_account: vote_account, + signer: keypair.pubkey(), + system_program: system_program::ID, + } + .to_account_metas(None), + }; + + let blockhash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&keypair.pubkey()), + &[keypair], + blockhash, + ); + + client.send_transaction(&tx)?; + } + Commands::GetTipDistributionAccount { vote_account, epoch, @@ -194,7 +311,6 @@ fn main() -> anyhow::Result<()> { expired_funds_account, num_epochs_valid, max_validator_commission_bps, - bump, } => { let authority_pubkey = Pubkey::from_str(&authority)?; let expired_funds_account_pubkey = Pubkey::from_str(&expired_funds_account)?; @@ -204,7 +320,7 @@ fn main() -> anyhow::Result<()> { expired_funds_account: expired_funds_account_pubkey, num_epochs_valid, max_validator_commission_bps, - bump, + bump: config_bump, }; let accounts = UpdateConfigAccounts { @@ -218,9 +334,58 @@ fn main() -> anyhow::Result<()> { accounts, ); - let serialized_data = instruction.data; - let base58_data = bs58::encode(serialized_data).into_string(); - println!("Base58 Serialized Data: {}", base58_data); + let blockhash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &[instruction], + Some(&keypair.pubkey()), + &[keypair], + blockhash, + ); + + client.send_transaction(&tx)?; + + // let serialized_data = instruction.data; + // let base58_data = bs58::encode(serialized_data).into_string(); + // println!("Base58 Serialized Data: {}", base58_data); + } + Commands::UploadMerkleRoot { + vote_account, + root, + max_total_claim, + max_num_nodes, + } => { + let mut source: [u8; 32] = [0; 32]; + source.copy_from_slice(root.as_slice()); + + let epoch = client.get_epoch_info()?.epoch; + let (tip_distribution_pubkey, _tip_distribution_bump) = + derive_tip_distribution_account_address(&program_id, &vote_account, epoch); + + let ix = Instruction { + program_id, + data: jito_tip_distribution::instruction::UploadMerkleRoot { + root: source, + max_total_claim, + max_num_nodes, + } + .data(), + accounts: jito_tip_distribution::accounts::UploadMerkleRoot { + config: config_pda, + merkle_root_upload_authority: keypair.pubkey(), + tip_distribution_account: tip_distribution_pubkey, + } + .to_account_metas(None), + }; + + let blockhash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&keypair.pubkey()), + &[keypair], + blockhash, + ); + + client.send_transaction(&tx)?; } }