Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions sdk-libs/macros/src/light_pdas/account/seed_extraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub fn extract_from_accounts_struct(
}

// Check for #[light_account(token, ...)] attribute
let token_attr = extract_light_token_attr(&field.attrs, instruction_args);
let token_attr = extract_light_token_attr(&field.attrs, instruction_args)?;

if has_light_account_pda {
// Extract inner type from Account<'info, T> or Box<Account<'info, T>>
Expand Down Expand Up @@ -314,10 +314,11 @@ struct LightTokenAttr {

/// Extract #[light_account(token, authority = [...])] attribute
/// Variant name is derived from field name, not specified in attribute
/// Returns Err if the attribute exists but has malformed syntax
fn extract_light_token_attr(
attrs: &[syn::Attribute],
instruction_args: &InstructionArgSet,
) -> Option<LightTokenAttr> {
) -> syn::Result<Option<LightTokenAttr>> {
for attr in attrs {
if attr.path().is_ident("light_account") {
let tokens = match &attr.meta {
Expand All @@ -332,18 +333,13 @@ fn extract_light_token_attr(
.any(|t| matches!(&t, proc_macro2::TokenTree::Ident(ident) if ident == "token"));

if has_token {
// Parse authority = [...] if present
if let Ok(parsed) = parse_light_token_list(&tokens, instruction_args) {
return Some(parsed);
}
return Some(LightTokenAttr {
variant_name: None,
authority_seeds: None,
});
// Parse authority = [...] - propagate errors instead of swallowing them
let parsed = parse_light_token_list(&tokens, instruction_args)?;
return Ok(Some(parsed));
}
}
}
None
Ok(None)
}

/// Parse light_account(token, authority = [...]) content
Expand Down
35 changes: 25 additions & 10 deletions sdk-libs/macros/src/light_pdas/accounts/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ impl LightAccountsBuilder {
})
}

/// Get the expression to access CreateAccountsProof.
///
/// Returns either:
/// - `proof_ident` (direct) if CreateAccountsProof is passed as a direct argument
/// - `params.create_accounts_proof` (nested) if nested inside a params struct
fn get_proof_access(&self) -> Result<TokenStream, syn::Error> {
if let Some(ref proof_ident) = self.parsed.direct_proof_arg {
Ok(quote! { #proof_ident })
} else {
let first_arg = self.get_first_instruction_arg()?;
let params_ident = &first_arg.name;
Ok(quote! { #params_ident.create_accounts_proof })
}
}

/// Validate constraints (e.g., account count < 255).
pub fn validate(&self) -> Result<(), syn::Error> {
let total = self.parsed.rentfree_fields.len()
Expand Down Expand Up @@ -317,13 +332,13 @@ impl LightAccountsBuilder {
let rentfree_count = self.parsed.rentfree_fields.len() as u8;
let pda_count = self.parsed.rentfree_fields.len();

let first_arg = self.get_first_instruction_arg()?;
let params_ident = &first_arg.name;
// Get proof access expression (direct arg or nested in params)
let proof_access = self.get_proof_access()?;

let first_pda_output_tree = &self.parsed.rentfree_fields[0].output_tree;

let mints = &self.parsed.light_mint_fields;
let mint_invocation = LightMintsBuilder::new(mints, params_ident, &self.infra)
let mint_invocation = LightMintsBuilder::new(mints, &proof_access, &self.infra)
.with_pda_context(pda_count, quote! { #first_pda_output_tree })
.generate_invocation();

Expand Down Expand Up @@ -356,7 +371,7 @@ impl LightAccountsBuilder {
use light_sdk::cpi::{InvokeLightSystemProgram, LightCpiInstruction};
light_sdk::cpi::v2::LightSystemProgramCpi::new_cpi(
crate::LIGHT_CPI_SIGNER,
#params_ident.create_accounts_proof.proof.clone()
#proof_access.proof.clone()
)
.with_new_addresses(&[#(#new_addr_idents),*])
.with_account_infos(&all_compressed_infos)
Expand All @@ -373,8 +388,8 @@ impl LightAccountsBuilder {
generate_pda_compress_blocks(&self.parsed.rentfree_fields);
let rentfree_count = self.parsed.rentfree_fields.len() as u8;

let first_arg = self.get_first_instruction_arg()?;
let params_ident = &first_arg.name;
// Get proof access expression (direct arg or nested in params)
let proof_access = self.get_proof_access()?;

let fee_payer = &self.infra.fee_payer;
let compression_config = &self.infra.compression_config;
Expand All @@ -397,7 +412,7 @@ impl LightAccountsBuilder {
use light_sdk::cpi::{InvokeLightSystemProgram, LightCpiInstruction};
light_sdk::cpi::v2::LightSystemProgramCpi::new_cpi(
crate::LIGHT_CPI_SIGNER,
#params_ident.create_accounts_proof.proof.clone()
#proof_access.proof.clone()
)
.with_new_addresses(&[#(#new_addr_idents),*])
.with_account_infos(&all_compressed_infos)
Expand All @@ -407,12 +422,12 @@ impl LightAccountsBuilder {

/// Generate mints-only body WITHOUT the Ok(true) return.
fn generate_pre_init_mints_only_body(&self) -> Result<TokenStream, syn::Error> {
let first_arg = self.get_first_instruction_arg()?;
let params_ident = &first_arg.name;
// Get proof access expression (direct arg or nested in params)
let proof_access = self.get_proof_access()?;

let mints = &self.parsed.light_mint_fields;
let mint_invocation =
LightMintsBuilder::new(mints, params_ident, &self.infra).generate_invocation();
LightMintsBuilder::new(mints, &proof_access, &self.infra).generate_invocation();

let fee_payer = &self.infra.fee_payer;

Expand Down
Loading
Loading