From fe99c42591cb219af3bc9b54093f05d565e852ce Mon Sep 17 00:00:00 2001 From: andrejlukacovic <37964423+lukacan@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:07:47 +0100 Subject: [PATCH] Fix/program client custom types (#117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * obtain full path for custom types (Struct/Enum), provide good UX if types are private and cannot be used within program_client * ✅ add cargo test for program_client * 🔥 removed duplicate code * 🐛 Fixed malformed program name. --------- Co-authored-by: lukacan Co-authored-by: Ikrk --- crates/client/src/idl.rs | 368 +++++++++++++----- .../expanded_source_codes/expanded_escrow.rs | 276 +++++++++++-- ...ode.rs => expected_program_client_code.rs} | 12 + crates/client/tests/test_program_client.rs | 2 +- 4 files changed, 536 insertions(+), 122 deletions(-) rename crates/client/tests/test_data/expected_source_codes/{expected_client_code.rs => expected_program_client_code.rs} (90%) diff --git a/crates/client/src/idl.rs b/crates/client/src/idl.rs index 8d37c9d6..f2831dcf 100644 --- a/crates/client/src/idl.rs +++ b/crates/client/src/idl.rs @@ -96,9 +96,15 @@ use heck::{ToSnakeCase, ToUpperCamelCase}; use quote::ToTokens; +use syn::{visit::Visit, File}; use thiserror::Error; -static ACCOUNT_MOD_PREFIX: &str = "__client_accounts_"; +const ACCOUNT_MOD_PREFIX: &str = "__client_accounts_"; +const MOD_PRIVATE: &str = "__private"; +const MOD_INSTRUCTION: &str = "instruction"; +const MOD_GLOBAL: &str = "__global"; +const ID_IDENT: &str = "ID"; +const ACCOUNTS_IDENT: &str = "__accounts"; #[derive(Error, Debug)] pub enum Error { @@ -108,6 +114,75 @@ pub enum Error { MissingOrInvalidProgramItems(&'static str), } +struct ModPub { + pub mod_name: String, + pub is_pub: bool, +} + +struct FullPathFinder { + target_item_name: String, + current_module: String, + found_path: Option, + module_pub: Vec, +} + +fn find_item_path(target_item_name: &str, syn_file: &File) -> Option { + let mut finder = FullPathFinder { + target_item_name: target_item_name.to_string(), + current_module: "".to_string(), + found_path: None, + module_pub: vec![], + }; + finder.visit_file(syn_file); + finder.found_path +} + +impl<'ast> syn::visit::Visit<'ast> for FullPathFinder { + fn visit_item(&mut self, item: &'ast syn::Item) { + if let Some(_found_path) = &self.found_path { + return; + } + + // INFO this will only look for enum or struct + match item { + syn::Item::Enum(syn::ItemEnum { ident, .. }) + | syn::Item::Struct(syn::ItemStruct { ident, .. }) => { + if *ident == self.target_item_name { + // Found the target item, construct the full path. + self.found_path = Some(format!("{}::{}", self.current_module, ident)); + for x in &self.module_pub { + if !x.is_pub { + println!("\nMod: \x1b[91m{}\x1b[0m is private!! \n- modify visibility to \x1b[93mpub\x1b[0m in order to use the custom type inside program_client.", x.mod_name) + } + } + return; + } + } + + _ => {} + } + + syn::visit::visit_item(self, item); + } + + fn visit_item_mod(&mut self, module: &'ast syn::ItemMod) { + let old_module = self.current_module.clone(); + self.current_module = format!("{}::{}", self.current_module, module.ident); + + let is_pub = matches!(module.vis, syn::Visibility::Public(_)); + + self.module_pub.push(ModPub { + mod_name: module.ident.to_string(), + is_pub, + }); + + syn::visit::visit_item_mod(self, module); + + self.module_pub.pop(); + self.current_module = old_module; + } +} + #[derive(Debug)] pub struct Idl { pub programs: Vec, @@ -144,14 +219,16 @@ pub async fn parse_to_idl_program(name: String, code: &str) -> Result; let mut account_mods = Vec::::new(); - for item in syn::parse_file(code)?.items.into_iter() { + let syn_file = syn::parse_file(code)?; + + for item in syn_file.items.iter() { match item { - syn::Item::Static(item_static) if item_static.ident == "ID" => { - static_program_id = Some(item_static); + syn::Item::Static(item_static) if item_static.ident == ID_IDENT => { + static_program_id = Some(item_static.clone()); } syn::Item::Mod(item_mod) => match item_mod.ident.to_string().as_str() { - "__private" => mod_private = Some(item_mod), - "instruction" => mod_instruction = Some(item_mod), + MOD_PRIVATE => mod_private = Some(item_mod.clone()), + MOD_INSTRUCTION => mod_instruction = Some(item_mod.clone()), _ => set_account_modules(&mut account_mods, item_mod), }, _ => (), @@ -167,27 +244,19 @@ pub async fn parse_to_idl_program(name: String, code: &str) -> Result Result ProgramResult { - // let ix = - // instruction::Initialize::deserialize(&mut &ix_data[..]).map_err(|_| - // anchor_lang::__private::ErrorCode::InstructionDidNotDeserialize)?; - // let instruction::Initialize = ix; - // let mut remaining_accounts: &[AccountInfo] = accounts; - // let mut accounts = - // Initialize::try_accounts(program_id, &mut remaining_accounts, - // ix_data)?; - // turnstile::initialize(Context::new(program_id, &mut accounts, - // remaining_accounts))?; - // accounts.exit(program_id) + // pub fn init_vesting( + // __program_id: &Pubkey, + // __accounts: &[AccountInfo], + // __ix_data: &[u8], + // ) -> anchor_lang::Result<()> { + // ::solana_program::log::sol_log("Instruction: InitVesting"); + // let ix = instruction::InitVesting::deserialize(&mut &__ix_data[..]) + // .map_err(|_| anchor_lang::error::ErrorCode::InstructionDidNotDeserialize)?; + // let instruction::InitVesting { + // recipient, + // amount, + // start_at, + // end_at, + // interval, + // input_option, + // } = ix; + // let mut __bumps = std::collections::BTreeMap::new(); + // let mut __reallocs = std::collections::BTreeSet::new(); + // let mut __remaining_accounts: &[AccountInfo] = __accounts; + // let mut __accounts = InitVesting::try_accounts( + // __program_id, + // &mut __remaining_accounts, + // __ix_data, + // &mut __bumps, + // &mut __reallocs, + // )?; + // let result = fuzz_example3::init_vesting( + // anchor_lang::context::Context::new( + // __program_id, + // &mut __accounts, + // __remaining_accounts, + // __bumps, + // ), + // recipient, + // amount, + // start_at, + // end_at, + // interval, + // input_option, + // )?; + // __accounts.exit(__program_id) // } + // } + // } + // // ``` let instruction_item_fns = { @@ -241,7 +346,7 @@ pub async fn parse_to_idl_program(name: String, code: &str) -> Result Some(item_mod), + syn::Item::Mod(item_mod) if item_mod.ident == MOD_GLOBAL => Some(item_mod), _ => None?, }) .ok_or(Error::MissingOrInvalidProgramItems( @@ -258,23 +363,64 @@ pub async fn parse_to_idl_program(name: String, code: &str) -> Result ProgramResult { - // let ix = - // instruction::Initialize::deserialize(&mut &ix_data[..]).map_err(|_| - // anchor_lang::__private::ErrorCode::InstructionDidNotDeserialize)?; - // let instruction::Initialize = ix; - // let mut remaining_accounts: &[AccountInfo] = accounts; - // let mut accounts = - // Initialize::try_accounts(program_id, &mut remaining_accounts, - // ix_data)?; - // turnstile::initialize(Context::new(program_id, &mut accounts, - // remaining_accounts))?; - // accounts.exit(program_id) + // + // pub fn init_vesting( + // __program_id: &Pubkey, + // __accounts: &[AccountInfo], + // __ix_data: &[u8], + // ) -> anchor_lang::Result<()> { + // ::solana_program::log::sol_log("Instruction: InitVesting"); + // let ix = instruction::InitVesting::deserialize(&mut &__ix_data[..]) + // .map_err(|_| anchor_lang::error::ErrorCode::InstructionDidNotDeserialize)?; + // let instruction::InitVesting { + // recipient, + // amount, + // start_at, + // end_at, + // interval, + // input_option, + // } = ix; + // let mut __bumps = std::collections::BTreeMap::new(); + // let mut __reallocs = std::collections::BTreeSet::new(); + // let mut __remaining_accounts: &[AccountInfo] = __accounts; + // + // *** we are looking for this part *** + // + // let mut __accounts = InitVesting::try_accounts( + // __program_id, + // &mut __remaining_accounts, + // __ix_data, + // &mut __bumps, + // &mut __reallocs, + // )?; + // ************************************* + // let result = fuzz_example3::init_vesting( + // anchor_lang::context::Context::new( + // __program_id, + // &mut __accounts, + // __remaining_accounts, + // __bumps, + // ), + // recipient, + // amount, + // start_at, + // end_at, + // interval, + // input_option, + // )?; + // __accounts.exit(__program_id) // } + // // ``` let mut instruction_account_pairs = Vec::new(); @@ -283,29 +429,29 @@ pub async fn parse_to_idl_program(name: String, code: &str) -> Result *expr_try.expr, - _ => None? - }; - let expr_call_func = match expr_try_expr { - syn::Expr::Call(expr_call) => *expr_call.func, - _ => None? - }; - let account_group_name = match expr_call_func { - syn::Expr::Path(expr_path) => expr_path.path.segments.into_iter().next()?.ident, - _ => None? - }; - Some(account_group_name.to_string()) - })?; + let local = if let syn::Stmt::Local(local) = stmt { + local + } else { + None? + }; + if !matches!(&local.pat, syn::Pat::Ident(pat_ident) if pat_ident.ident == ACCOUNTS_IDENT) { + None? + } + let init_expr = *local.init?.1; + let expr_try_expr = match init_expr { + syn::Expr::Try(expr_try) => *expr_try.expr, + _ => None?, + }; + let expr_call_func = match expr_try_expr { + syn::Expr::Call(expr_call) => *expr_call.func, + _ => None?, + }; + let account_group_name = match expr_call_func { + syn::Expr::Path(expr_path) => expr_path.path.segments.into_iter().next()?.ident, + _ => None?, + }; + Some(account_group_name.to_string()) + })?; let instruction_name = item_fn.sig.ident.to_string(); let idl_instruction = IdlInstruction { @@ -336,20 +482,35 @@ pub async fn parse_to_idl_program(name: String, code: &str) -> Result Result Result, item_module: syn::ItemMod) { +fn set_account_modules(account_modules: &mut Vec, item_module: &syn::ItemMod) { if item_module .ident .to_string() .starts_with(ACCOUNT_MOD_PREFIX) { - account_modules.push(item_module); + account_modules.push(item_module.clone()); return; } - let modules = item_module + let modules = &item_module .content + .as_ref() .ok_or(Error::MissingOrInvalidProgramItems( "account mod: empty content", )) .unwrap() .1; - for module in modules { + for module in modules.iter() { if let syn::Item::Mod(nested_module) = module { set_account_modules(account_modules, nested_module); } diff --git a/crates/client/tests/test_data/expanded_source_codes/expanded_escrow.rs b/crates/client/tests/test_data/expanded_source_codes/expanded_escrow.rs index af6e3781..9102df22 100644 --- a/crates/client/tests/test_data/expanded_source_codes/expanded_escrow.rs +++ b/crates/client/tests/test_data/expanded_source_codes/expanded_escrow.rs @@ -26,21 +26,40 @@ use anchor_spl::token::{ TokenAccount, Transfer, }; -#[doc = r" The static program ID"] -pub static ID: anchor_lang::solana_program::pubkey::Pubkey = - anchor_lang::solana_program::pubkey::Pubkey::new_from_array([5u8, 214u8, - 204u8, 101u8, 166u8, 163u8, 239u8, 244u8, 13u8, 110u8, 64u8, - 106u8, 230u8, 81u8, 141u8, 186u8, 208u8, 155u8, 78u8, 83u8, - 194u8, 215u8, 103u8, 17u8, 94u8, 15u8, 137u8, 68u8, 170u8, - 153u8, 74u8, 59u8]); -#[doc = r" Confirms that a given pubkey is equivalent to the program ID"] -pub fn check_id(id: &anchor_lang::solana_program::pubkey::Pubkey) -> bool { - id == &ID -} -#[doc = r" Returns the program ID"] -pub fn id() -> anchor_lang::solana_program::pubkey::Pubkey { ID } +pub mod innerstate { + use super::*; + + pub enum EnumInputInner { + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + } + impl borsh::de::BorshDeserialize for EnumInputInner { + fn deserialize_reader(reader: &mut R) + -> ::core::result::Result { + let tag = + ::deserialize_reader(reader)?; + ::deserialize_variant(reader, tag) + } + } + impl borsh::de::EnumExt for EnumInputInner { + fn deserialize_variant(reader: &mut R, + variant_idx: u8) + -> ::core::result::Result { + let mut return_value = + match variant_idx { + 0u8 => EnumInputInner::Variant1, + 1u8 => EnumInputInner::Variant2, + 2u8 => EnumInputInner::Variant3, + 3u8 => EnumInputInner::Variant4, + 4u8 => EnumInputInner::Variant5, + _ => + return Err(borsh::maybestd::io::Error::new(borsh::maybestd::io::ErrorKind::InvalidInput, + -use self::escrow::*; @@ -48,8 +67,8 @@ use self::escrow::*; -// Transferring from initializer to taker + // Transferring from initializer to taker @@ -63,6 +82,187 @@ use self::escrow::*; + + { + let res = + ::alloc::fmt::format(format_args!("Unexpected variant index: {0:?}", + variant_idx)); + res + })), + }; + Ok(return_value) + } + } + impl borsh::ser::BorshSerialize for EnumInputInner { + fn serialize(&self, writer: &mut W) + -> ::core::result::Result<(), borsh::maybestd::io::Error> { + let variant_idx: u8 = + match self { + EnumInputInner::Variant1 => 0u8, + EnumInputInner::Variant2 => 1u8, + EnumInputInner::Variant3 => 2u8, + EnumInputInner::Variant4 => 3u8, + EnumInputInner::Variant5 => 4u8, + }; + writer.write_all(&variant_idx.to_le_bytes())?; + match self { + EnumInputInner::Variant1 => {} + EnumInputInner::Variant2 => {} + EnumInputInner::Variant3 => {} + EnumInputInner::Variant4 => {} + EnumInputInner::Variant5 => {} + } + Ok(()) + } + } +} +pub use crate::innerstate::*; +pub mod state { + use anchor_lang::prelude::*; + pub enum EnumInput { Variant1, Variant2, Variant3, Variant4, Variant5, } + impl borsh::de::BorshDeserialize for EnumInput { + fn deserialize_reader(reader: &mut R) + -> ::core::result::Result { + let tag = + ::deserialize_reader(reader)?; + ::deserialize_variant(reader, tag) + } + } + impl borsh::de::EnumExt for EnumInput { + fn deserialize_variant(reader: &mut R, + variant_idx: u8) + -> ::core::result::Result { + let mut return_value = + match variant_idx { + 0u8 => EnumInput::Variant1, + 1u8 => EnumInput::Variant2, + 2u8 => EnumInput::Variant3, + 3u8 => EnumInput::Variant4, + 4u8 => EnumInput::Variant5, + _ => + return Err(borsh::maybestd::io::Error::new(borsh::maybestd::io::ErrorKind::InvalidInput, + { + let res = + ::alloc::fmt::format(format_args!("Unexpected variant index: {0:?}", + variant_idx)); + res + })), + }; + Ok(return_value) + } + } + impl borsh::ser::BorshSerialize for EnumInput { + fn serialize(&self, writer: &mut W) + -> ::core::result::Result<(), borsh::maybestd::io::Error> { + let variant_idx: u8 = + match self { + EnumInput::Variant1 => 0u8, + EnumInput::Variant2 => 1u8, + EnumInput::Variant3 => 2u8, + EnumInput::Variant4 => 3u8, + EnumInput::Variant5 => 4u8, + }; + writer.write_all(&variant_idx.to_le_bytes())?; + match self { + EnumInput::Variant1 => {} + EnumInput::Variant2 => {} + EnumInput::Variant3 => {} + EnumInput::Variant4 => {} + EnumInput::Variant5 => {} + } + Ok(()) + } + } + pub struct StructInput { + pub field1: u8, + pub field2: String, + pub field3: StructInputInner, + } + impl borsh::de::BorshDeserialize for StructInput where + u8: borsh::BorshDeserialize, String: borsh::BorshDeserialize, + StructInputInner: borsh::BorshDeserialize { + fn deserialize_reader(reader: &mut R) + -> ::core::result::Result { + Ok(Self { + field1: borsh::BorshDeserialize::deserialize_reader(reader)?, + field2: borsh::BorshDeserialize::deserialize_reader(reader)?, + field3: borsh::BorshDeserialize::deserialize_reader(reader)?, + }) + } + } + impl borsh::ser::BorshSerialize for StructInput where + u8: borsh::ser::BorshSerialize, String: borsh::ser::BorshSerialize, + StructInputInner: borsh::ser::BorshSerialize { + fn serialize(&self, writer: &mut W) + -> ::core::result::Result<(), borsh::maybestd::io::Error> { + borsh::BorshSerialize::serialize(&self.field1, writer)?; + borsh::BorshSerialize::serialize(&self.field2, writer)?; + borsh::BorshSerialize::serialize(&self.field3, writer)?; + Ok(()) + } + } + #[automatically_derived] + impl ::core::default::Default for StructInput { + #[inline] + fn default() -> StructInput { + StructInput { + field1: ::core::default::Default::default(), + field2: ::core::default::Default::default(), + field3: ::core::default::Default::default(), + } + } + } + pub struct StructInputInner { + pub field1: Pubkey, + pub field2: String, + } + impl borsh::de::BorshDeserialize for StructInputInner where + Pubkey: borsh::BorshDeserialize, String: borsh::BorshDeserialize { + fn deserialize_reader(reader: &mut R) + -> ::core::result::Result { + Ok(Self { + field1: borsh::BorshDeserialize::deserialize_reader(reader)?, + field2: borsh::BorshDeserialize::deserialize_reader(reader)?, + }) + } + } + impl borsh::ser::BorshSerialize for StructInputInner where + Pubkey: borsh::ser::BorshSerialize, String: borsh::ser::BorshSerialize + { + fn serialize(&self, writer: &mut W) + -> ::core::result::Result<(), borsh::maybestd::io::Error> { + borsh::BorshSerialize::serialize(&self.field1, writer)?; + borsh::BorshSerialize::serialize(&self.field2, writer)?; + Ok(()) + } + } + #[automatically_derived] + impl ::core::default::Default for StructInputInner { + #[inline] + fn default() -> StructInputInner { + StructInputInner { + field1: ::core::default::Default::default(), + field2: ::core::default::Default::default(), + } + } + } +} +pub use crate::state::*; +#[doc = r" The static program ID"] +pub static ID: anchor_lang::solana_program::pubkey::Pubkey = + anchor_lang::solana_program::pubkey::Pubkey::new_from_array([5u8, 214u8, + 204u8, 101u8, 166u8, 163u8, 239u8, 244u8, 13u8, 110u8, 64u8, + 106u8, 230u8, 81u8, 141u8, 186u8, 208u8, 155u8, 78u8, 83u8, + 194u8, 215u8, 103u8, 17u8, 94u8, 15u8, 137u8, 68u8, 170u8, + 153u8, 74u8, 59u8]); +#[doc = r" Confirms that a given pubkey is equivalent to the program ID"] +pub fn check_id(id: &anchor_lang::solana_program::pubkey::Pubkey) -> bool { + id == &ID +} +#[doc = r" Returns the program ID"] +pub fn id() -> anchor_lang::solana_program::pubkey::Pubkey { ID } +use self::escrow::*; /// # Safety #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { @@ -358,7 +558,7 @@ mod __private { error_msg: anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.to_string(), error_origin: Some(anchor_lang::error::ErrorOrigin::Source(anchor_lang::error::Source { filename: "programs/escrow/src/lib.rs", - line: 25u32, + line: 42u32, })), compared_values: None, }).with_account_name("IdlAccount")); @@ -1697,7 +1897,7 @@ mod __private { error_msg: anchor_lang::error::ErrorCode::RequireEqViolated.to_string(), error_origin: Some(anchor_lang::error::ErrorOrigin::Source(anchor_lang::error::Source { filename: "programs/escrow/src/lib.rs", - line: 25u32, + line: 42u32, })), compared_values: None, }).with_values((idl_expansion.len(), idl_data.len()))); @@ -1730,7 +1930,7 @@ mod __private { error_msg: anchor_lang::error::ErrorCode::RequireGteViolated.to_string(), error_origin: Some(anchor_lang::error::ErrorOrigin::Source(anchor_lang::error::Source { filename: "programs/escrow/src/lib.rs", - line: 25u32, + line: 42u32, })), compared_values: None, }).with_values((target.len(), buffer_len))); @@ -1752,7 +1952,11 @@ mod __private { instruction::InitializeEscrow::deserialize(&mut &__ix_data[..]).map_err(|_| anchor_lang::error::ErrorCode::InstructionDidNotDeserialize)?; let instruction::InitializeEscrow { - initializer_amount, taker_amount } = ix; + initializer_amount, + taker_amount, + _enum_variant, + _enum_variant_inner, + _struct_variant_inner } = ix; let mut __bumps = std::collections::BTreeMap::new(); let mut __reallocs = std::collections::BTreeSet::new(); let mut __remaining_accounts: &[AccountInfo] = __accounts; @@ -1763,7 +1967,8 @@ mod __private { let result = escrow::initialize_escrow(anchor_lang::context::Context::new(__program_id, &mut __accounts, __remaining_accounts, __bumps), - initializer_amount, taker_amount)?; + initializer_amount, taker_amount, _enum_variant, + _enum_variant_inner, _struct_variant_inner)?; __accounts.exit(__program_id) } #[inline(never)] @@ -1813,7 +2018,9 @@ pub mod escrow { use super::*; const ESCROW_PDA_SEED: &[u8] = b"escrow"; pub fn initialize_escrow(ctx: Context, - initializer_amount: u64, taker_amount: u64) -> Result<()> { + initializer_amount: u64, taker_amount: u64, _enum_variant: EnumInput, + _enum_variant_inner: EnumInputInner, + _struct_variant_inner: StructInput) -> Result<()> { ctx.accounts.escrow_account.initializer_key = *ctx.accounts.initializer.key; ctx.accounts.escrow_account.initializer_deposit_token_account = @@ -1865,24 +2072,41 @@ pub mod instruction { pub struct InitializeEscrow { pub initializer_amount: u64, pub taker_amount: u64, + pub _enum_variant: EnumInput, + pub _enum_variant_inner: EnumInputInner, + pub _struct_variant_inner: StructInput, } impl borsh::ser::BorshSerialize for InitializeEscrow where - u64: borsh::ser::BorshSerialize, u64: borsh::ser::BorshSerialize { + u64: borsh::ser::BorshSerialize, u64: borsh::ser::BorshSerialize, + EnumInput: borsh::ser::BorshSerialize, + EnumInputInner: borsh::ser::BorshSerialize, + StructInput: borsh::ser::BorshSerialize { fn serialize(&self, writer: &mut W) -> ::core::result::Result<(), borsh::maybestd::io::Error> { borsh::BorshSerialize::serialize(&self.initializer_amount, writer)?; borsh::BorshSerialize::serialize(&self.taker_amount, writer)?; + borsh::BorshSerialize::serialize(&self._enum_variant, writer)?; + borsh::BorshSerialize::serialize(&self._enum_variant_inner, + writer)?; + borsh::BorshSerialize::serialize(&self._struct_variant_inner, + writer)?; Ok(()) } } impl borsh::de::BorshDeserialize for InitializeEscrow where - u64: borsh::BorshDeserialize, u64: borsh::BorshDeserialize { + u64: borsh::BorshDeserialize, u64: borsh::BorshDeserialize, + EnumInput: borsh::BorshDeserialize, + EnumInputInner: borsh::BorshDeserialize, + StructInput: borsh::BorshDeserialize { fn deserialize_reader(reader: &mut R) -> ::core::result::Result { Ok(Self { initializer_amount: borsh::BorshDeserialize::deserialize_reader(reader)?, taker_amount: borsh::BorshDeserialize::deserialize_reader(reader)?, + _enum_variant: borsh::BorshDeserialize::deserialize_reader(reader)?, + _enum_variant_inner: borsh::BorshDeserialize::deserialize_reader(reader)?, + _struct_variant_inner: borsh::BorshDeserialize::deserialize_reader(reader)?, }) } } @@ -1940,9 +2164,9 @@ pub mod instruction { #[doc = r" mirroring the structs deriving `Accounts`, where each field is"] #[doc = r" a `Pubkey`. This is useful for specifying accounts for a client."] pub mod accounts { + pub use crate::__client_accounts_initialize_escrow::*; pub use crate::__client_accounts_exchange::*; pub use crate::__client_accounts_cancel_escrow::*; - pub use crate::__client_accounts_initialize_escrow::*; } #[instruction(initializer_amount : u64)] pub struct InitializeEscrow<'info> { @@ -2061,7 +2285,7 @@ impl<'info> anchor_lang::Accounts<'info> for InitializeEscrow<'info> where error_msg: anchor_lang::error::ErrorCode::TryingToInitPayerAsProgramAccount.to_string(), error_origin: Some(anchor_lang::error::ErrorOrigin::Source(anchor_lang::error::Source { filename: "programs/escrow/src/lib.rs", - line: 103u32, + line: 123u32, })), compared_values: None, }).with_pubkeys((initializer.key(), escrow_account.key()))); @@ -3002,7 +3226,7 @@ impl anchor_lang::AccountDeserialize for EscrowAccount { error_msg: anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.to_string(), error_origin: Some(anchor_lang::error::ErrorOrigin::Source(anchor_lang::error::Source { filename: "programs/escrow/src/lib.rs", - line: 169u32, + line: 189u32, })), compared_values: None, }).with_account_name("EscrowAccount")); diff --git a/crates/client/tests/test_data/expected_source_codes/expected_client_code.rs b/crates/client/tests/test_data/expected_source_codes/expected_program_client_code.rs similarity index 90% rename from crates/client/tests/test_data/expected_source_codes/expected_client_code.rs rename to crates/client/tests/test_data/expected_source_codes/expected_program_client_code.rs index 741b0b16..c7c23bf8 100644 --- a/crates/client/tests/test_data/expected_source_codes/expected_client_code.rs +++ b/crates/client/tests/test_data/expected_source_codes/expected_program_client_code.rs @@ -10,6 +10,9 @@ pub mod escrow_instruction { client: &Client, i_initializer_amount: u64, i_taker_amount: u64, + i__enum_variant: escrow::state::EnumInput, + i__enum_variant_inner: escrow::innerstate::EnumInputInner, + i__struct_variant_inner: escrow::state::StructInput, a_initializer: Pubkey, a_initializer_deposit_token_account: Pubkey, a_initializer_receive_token_account: Pubkey, @@ -24,6 +27,9 @@ pub mod escrow_instruction { escrow::instruction::InitializeEscrow { initializer_amount: i_initializer_amount, taker_amount: i_taker_amount, + _enum_variant: i__enum_variant, + _enum_variant_inner: i__enum_variant_inner, + _struct_variant_inner: i__struct_variant_inner, }, escrow::accounts::InitializeEscrow { initializer: a_initializer, @@ -40,6 +46,9 @@ pub mod escrow_instruction { pub fn initialize_escrow_ix( i_initializer_amount: u64, i_taker_amount: u64, + i__enum_variant: escrow::state::EnumInput, + i__enum_variant_inner: escrow::innerstate::EnumInputInner, + i__struct_variant_inner: escrow::state::StructInput, a_initializer: Pubkey, a_initializer_deposit_token_account: Pubkey, a_initializer_receive_token_account: Pubkey, @@ -52,6 +61,9 @@ pub mod escrow_instruction { data: escrow::instruction::InitializeEscrow { initializer_amount: i_initializer_amount, taker_amount: i_taker_amount, + _enum_variant: i__enum_variant, + _enum_variant_inner: i__enum_variant_inner, + _struct_variant_inner: i__struct_variant_inner, } .data(), accounts: escrow::accounts::InitializeEscrow { diff --git a/crates/client/tests/test_program_client.rs b/crates/client/tests/test_program_client.rs index caa224ed..74ae4d7e 100644 --- a/crates/client/tests/test_program_client.rs +++ b/crates/client/tests/test_program_client.rs @@ -17,7 +17,7 @@ pub async fn generate_program_client() { // after you've called `makers trdelnik test`. let expected_client_code = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/tests/test_data/expected_source_codes/expected_client_code.rs" + "/tests/test_data/expected_source_codes/expected_program_client_code.rs" )); let program_idl =