Skip to content

Commit

Permalink
CLI commands for managing fee state (#257)
Browse files Browse the repository at this point in the history
Adds commands for:

* init_fee_state
* edit_fee_state
* config_group_fee
* propagate_fee (but you should probably use a script instead of updating one group at a time)
  • Loading branch information
jgur-psyops authored Nov 21, 2024
1 parent f51c25a commit 063a5de
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 3 deletions.
66 changes: 65 additions & 1 deletion clients/rust/marginfi-cli/src/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,36 @@ pub enum GroupCommand {
#[clap(short = 't', long)]
existing_token_lookup_tables: Vec<Pubkey>,
},
InitFeeState {
#[clap(long)]
admin: Pubkey,
#[clap(long)]
fee_wallet: Pubkey,
#[clap(long)]
bank_init_flat_sol_fee: u32,
#[clap(long)]
program_fee_fixed: f64,
#[clap(long)]
program_fee_rate: f64,
},
EditFeeState {
#[clap(long)]
fee_wallet: Pubkey,
#[clap(long)]
bank_init_flat_sol_fee: u32,
#[clap(long)]
program_fee_fixed: f64,
#[clap(long)]
program_fee_rate: f64,
},
ConfigGroupFee {
#[clap(long)]
flag: u64,
},
PropagateFee {
#[clap(long)]
marginfi_group: Pubkey,
},
}

#[derive(Clone, Copy, Debug, Parser, ArgEnum)]
Expand Down Expand Up @@ -309,6 +339,8 @@ pub enum BankCommand {
},
CollectFees {
bank: Pubkey,
#[clap(help = "The ATA for fee_state.global_fee_wallet and the bank's mint")]
fee_ata: Pubkey,
},
WithdrawFees {
bank: Pubkey,
Expand Down Expand Up @@ -635,6 +667,36 @@ fn group(subcmd: GroupCommand, global_options: &GlobalOptions) -> Result<()> {
&profile,
existing_token_lookup_tables,
),
GroupCommand::InitFeeState {
admin,
fee_wallet,
bank_init_flat_sol_fee,
program_fee_fixed,
program_fee_rate,
} => processor::initialize_fee_state(
config,
admin,
fee_wallet,
bank_init_flat_sol_fee,
program_fee_fixed,
program_fee_rate,
),
GroupCommand::EditFeeState {
fee_wallet,
bank_init_flat_sol_fee,
program_fee_fixed,
program_fee_rate,
} => processor::edit_fee_state(
config,
fee_wallet,
bank_init_flat_sol_fee,
program_fee_fixed,
program_fee_rate,
),
GroupCommand::ConfigGroupFee { flag } => processor::config_group_fee(config, profile, flag),
GroupCommand::PropagateFee { marginfi_group } => {
processor::propagate_fee(config, marginfi_group)
}
}
}

Expand Down Expand Up @@ -763,7 +825,9 @@ fn bank(subcmd: BankCommand, global_options: &GlobalOptions) -> Result<()> {
BankCommand::SettleAllEmissions { bank } => {
processor::emissions::claim_all_emissions_for_bank(&config, &profile, bank)
}
BankCommand::CollectFees { bank } => processor::admin::process_collect_fees(config, bank),
BankCommand::CollectFees { bank, fee_ata } => {
processor::admin::process_collect_fees(config, bank, fee_ata)
}
BankCommand::WithdrawFees {
bank,
amount,
Expand Down
4 changes: 2 additions & 2 deletions clients/rust/marginfi-cli/src/processor/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use solana_sdk::{
instruction::Instruction, message::Message, pubkey::Pubkey, transaction::Transaction,
};

pub fn process_collect_fees(config: Config, bank_pk: Pubkey) -> Result<()> {
pub fn process_collect_fees(config: Config, bank_pk: Pubkey, fee_ata: Pubkey) -> Result<()> {
let bank = config.mfi_program.account::<Bank>(bank_pk)?;
let rpc_client = config.mfi_program.rpc();

Expand All @@ -33,7 +33,7 @@ pub fn process_collect_fees(config: Config, bank_pk: Pubkey) -> Result<()> {
liquidity_vault: bank.liquidity_vault,
insurance_vault: bank.insurance_vault,
fee_state: find_fee_state_pda(&marginfi::id()).0,
fee_ata: find_fee_state_pda(&marginfi::id()).0, // TODO
fee_ata,
}
.to_account_metas(Some(true)),
data: marginfi::instruction::LendingPoolCollectBankFees {}.data(),
Expand Down
164 changes: 164 additions & 0 deletions clients/rust/marginfi-cli/src/processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,170 @@ pub fn process_set_user_flag(
Ok(())
}

pub fn initialize_fee_state(
config: Config,
admin: Pubkey,
fee_wallet: Pubkey,
bank_init_flat_sol_fee: u32,
program_fee_fixed: f64,
program_fee_rate: f64,
) -> Result<()> {
let program_fee_fixed: WrappedI80F48 = I80F48::from_num(program_fee_fixed).into();
let program_fee_rate: WrappedI80F48 = I80F48::from_num(program_fee_rate).into();

let rpc_client = config.mfi_program.rpc();

let fee_state_pubkey = find_fee_state_pda(&config.program_id).0;

let initialize_fee_state_ixs_builder = config.mfi_program.request();

let initialize_fee_state_ixs = initialize_fee_state_ixs_builder
.accounts(marginfi::accounts::InitFeeState {
payer: config.authority(),
fee_state: fee_state_pubkey,
rent: sysvar::rent::id(),
system_program: system_program::id(),
})
.args(marginfi::instruction::InitGlobalFeeState {
admin,
fee_wallet,
bank_init_flat_sol_fee,
program_fee_fixed,
program_fee_rate,
})
.instructions()?;

let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
let message = Message::new(&initialize_fee_state_ixs, Some(&config.authority()));
let mut transaction = Transaction::new_unsigned(message);
transaction.partial_sign(&config.get_signers(false), recent_blockhash);

match process_transaction(&transaction, &rpc_client, config.get_tx_mode()) {
Ok(sig) => println!("Fee state initialized (sig: {})", sig),
Err(err) => {
println!("Error during fee state initialization:\n{:#?}", err);
return Err(anyhow!("Error during fee state initialization"));
}
};

Ok(())
}

pub fn edit_fee_state(
config: Config,
fee_wallet: Pubkey,
bank_init_flat_sol_fee: u32,
program_fee_fixed: f64,
program_fee_rate: f64,
) -> Result<()> {
let program_fee_fixed: WrappedI80F48 = I80F48::from_num(program_fee_fixed).into();
let program_fee_rate: WrappedI80F48 = I80F48::from_num(program_fee_rate).into();

let rpc_client = config.mfi_program.rpc();

let fee_state_pubkey = find_fee_state_pda(&config.program_id).0;

let edit_fee_state_ixs_builder = config.mfi_program.request();

let edit_fee_state_ixs = edit_fee_state_ixs_builder
.accounts(marginfi::accounts::EditFeeState {
global_fee_admin: config.authority(),
fee_state: fee_state_pubkey,
})
.args(marginfi::instruction::EditGlobalFeeState {
fee_wallet,
bank_init_flat_sol_fee,
program_fee_fixed,
program_fee_rate,
})
.instructions()?;

let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
let message = Message::new(&edit_fee_state_ixs, Some(&config.authority()));
let mut transaction = Transaction::new_unsigned(message);
transaction.partial_sign(&config.get_signers(false), recent_blockhash);

match process_transaction(&transaction, &rpc_client, config.get_tx_mode()) {
Ok(sig) => println!("Fee state edited (sig: {})", sig),
Err(err) => {
println!("Error during fee state edit:\n{:#?}", err);
return Err(anyhow!("Error during fee state edit"));
}
};

Ok(())
}

pub fn config_group_fee(config: Config, profile: Profile, flag: u64) -> Result<()> {
let rpc_client = config.mfi_program.rpc();
let marginfi_group_pubkey = profile.marginfi_group.ok_or_else(|| {
anyhow!(
"Marginfi group does not exist for profile [{}]",
profile.name
)
})?;

let fee_state_pubkey = find_fee_state_pda(&profile.program_id.unwrap()).0;

let config_group_fee_ixs_builder = config.mfi_program.request();

let config_group_fee_ixs = config_group_fee_ixs_builder
.accounts(marginfi::accounts::ConfigGroupFee {
marginfi_group: marginfi_group_pubkey,
global_fee_admin: config.authority(),
fee_state: fee_state_pubkey,
})
.args(marginfi::instruction::ConfigGroupFee { flag })
.instructions()?;

let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
let message = Message::new(&config_group_fee_ixs, Some(&config.authority()));
let mut transaction = Transaction::new_unsigned(message);
transaction.partial_sign(&config.get_signers(false), recent_blockhash);

match process_transaction(&transaction, &rpc_client, config.get_tx_mode()) {
Ok(sig) => println!("Config group fee updated (sig: {})", sig),
Err(err) => {
println!("Error during config group fee update:\n{:#?}", err);
return Err(anyhow!("Error during config group fee update"));
}
};

Ok(())
}

/// Note: doing this one group at a time is tedious, consider running the script instead.
pub fn propagate_fee(config: Config, marginfi_group: Pubkey) -> Result<()> {
let rpc_client = config.mfi_program.rpc();

let fee_state_pubkey = find_fee_state_pda(&config.program_id).0;

let propagate_fee_ixs_builder = config.mfi_program.request();

let propagate_fee_ixs = propagate_fee_ixs_builder
.accounts(marginfi::accounts::PropagateFee {
fee_state: fee_state_pubkey,
marginfi_group,
})
.args(marginfi::instruction::PropagateFeeState {})
.instructions()?;

let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
let message = Message::new(&propagate_fee_ixs, None);
let mut transaction = Transaction::new_unsigned(message);
transaction.partial_sign(&config.get_signers(false), recent_blockhash);

match process_transaction(&transaction, &rpc_client, config.get_tx_mode()) {
Ok(sig) => println!("Fee propagated (sig: {})", sig),
Err(err) => {
println!("Error during fee propagation:\n{:#?}", err);
return Err(anyhow!("Error during fee propagation"));
}
};

Ok(())
}

// --------------------------------------------------------------------------------------------------------------------
// bank
// --------------------------------------------------------------------------------------------------------------------
Expand Down

0 comments on commit 063a5de

Please sign in to comment.