diff --git a/clients/rust/marginfi-cli/src/entrypoint.rs b/clients/rust/marginfi-cli/src/entrypoint.rs index 7f03230d7..f31ba5d60 100644 --- a/clients/rust/marginfi-cli/src/entrypoint.rs +++ b/clients/rust/marginfi-cli/src/entrypoint.rs @@ -19,7 +19,7 @@ use marginfi::{ prelude::{GroupConfig, MarginfiGroup}, state::{ marginfi_account::{Balance, LendingAccount, MarginfiAccount}, - marginfi_group::{BankConfig, InterestRateConfig, OracleConfig, WrappedI80F48}, + marginfi_group::{Bank, BankConfig, InterestRateConfig, OracleConfig, WrappedI80F48}, }, }; use solana_sdk::{commitment_config::CommitmentLevel, pubkey::Pubkey}; @@ -55,6 +55,8 @@ pub enum Command { #[cfg(feature = "dev")] InspectPadding {}, #[cfg(feature = "dev")] + PatchIdl { idl_path: String }, + #[cfg(feature = "dev")] InspectSize {}, Account { #[clap(subcommand)] @@ -366,6 +368,8 @@ pub fn entry(opts: Opts) -> Result<()> { Command::Profile { subcmd } => profile(subcmd), #[cfg(feature = "dev")] Command::InspectPadding {} => inspect_padding(), + #[cfg(feature = "dev")] + Command::PatchIdl { idl_path } => patch_idl(idl_path), Command::Account { subcmd } => process_account_subcmd(subcmd, &opts.cfg_override), #[cfg(feature = "lip")] Command::Lip { subcmd } => process_lip_subcmd(subcmd, &opts.cfg_override), @@ -676,6 +680,26 @@ fn inspect_size() -> Result<()> { Ok(()) } +#[cfg(feature = "dev")] +fn patch_idl(idl_path: String) -> Result<()> { + use crate::patch_type_layout; + + let file = std::fs::File::open(&idl_path)?; + let reader = std::io::BufReader::new(file); + let mut idl: serde_json::Value = serde_json::from_reader(reader)?; + + patch_type_layout!(idl, "Bank", Bank, "accounts"); + patch_type_layout!(idl, "Balance", Balance, "types"); + patch_type_layout!(idl, "BankConfig", BankConfig, "types"); + + let idl_patched_path = idl_path.replace(".json", "_patched.json"); + let file = std::fs::File::create(&idl_patched_path)?; + let writer = std::io::BufWriter::new(file); + serde_json::to_writer_pretty(writer, &idl)?; + + Ok(()) +} + fn process_account_subcmd(subcmd: AccountCommand, global_options: &GlobalOptions) -> Result<()> { let profile = load_profile()?; let config = profile.get_config(Some(global_options))?; diff --git a/clients/rust/marginfi-cli/src/macros.rs b/clients/rust/marginfi-cli/src/macros.rs index 61981cf2c..da37c9e91 100644 --- a/clients/rust/marginfi-cli/src/macros.rs +++ b/clients/rust/marginfi-cli/src/macros.rs @@ -34,3 +34,37 @@ macro_rules! home_path { } }; } + +#[macro_export] +macro_rules! patch_type_layout { + ($idl:expr, $typename:expr, $struct:ty, $category:expr) => { + let target_type = $idl[$category] + .as_array_mut() + .unwrap() + .iter_mut() + .find(|el| el["name"] == $typename) + .unwrap(); + + let target_type_layout = <$struct>::type_layout(); + let idl_fields = target_type["type"]["fields"].as_array_mut().unwrap(); + + let mut padding_field_counter = 0; + for (index, field) in target_type_layout.fields.iter().enumerate() { + match field { + type_layout::Field::Field { .. } => {} + type_layout::Field::Padding { size } => { + let padding_field = serde_json::json!( + { + "name": format!("auto_padding_{}", padding_field_counter), + "type": { + "array": ["u8", size] + } + } + ); + idl_fields.insert(index, padding_field); + padding_field_counter += 1; + } + } + } + }; +}