From b6b4f11a5c4b36e73dd13f9da1289af5ab242e95 Mon Sep 17 00:00:00 2001 From: acheron <98934430+acheroncrypto@users.noreply.github.com> Date: Mon, 24 Feb 2025 00:00:24 +0100 Subject: [PATCH] idl: Fix using account or arg values for `seeds::program` (#3570) --- CHANGELOG.md | 1 + lang/syn/src/idl/accounts.rs | 31 +++++++++++-------- .../programs/pda-derivation/src/lib.rs | 30 ++++++++++++++++++ tests/pda-derivation/tests/typescript.spec.ts | 8 +++++ 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcdd8c3e7c..668c83409a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -117,6 +117,7 @@ The minor version will be incremented upon a breaking change and the patch versi - client: Remove `std::process::exit` usage ([#3544](https://github.com/coral-xyz/anchor/pull/3544)). - idl: Fix using `Pubkey` constants with `seeds::program` ([#3559](https://github.com/coral-xyz/anchor/pull/3559)). - lang: Fix instructions with no accounts causing compilation errors when using `declare_program!` ([#3567](https://github.com/coral-xyz/anchor/pull/3567)). +- idl: Fix using account or arg values for `seeds::program` ([#3570](https://github.com/coral-xyz/anchor/pull/3570)). ### Breaking diff --git a/lang/syn/src/idl/accounts.rs b/lang/syn/src/idl/accounts.rs index 6a410d9d08..a66957bc71 100644 --- a/lang/syn/src/idl/accounts.rs +++ b/lang/syn/src/idl/accounts.rs @@ -351,29 +351,34 @@ fn parse_seed(seed: &syn::Expr, accounts: &AccountsStruct) -> Result { - let seed = path - .path - .get_ident() - .map(|ident| ident.to_string()) - .filter(|ident| args.contains_key(ident)) - .map(|path| { + let seed = match path.path.get_ident() { + Some(ident) if args.contains_key(&ident.to_string()) => { quote! { #idl::IdlSeed::Arg( #idl::IdlSeedArg { - path: #path.into(), + path: stringify!(#ident).into(), } ) } - }) - .unwrap_or_else(|| { + } + Some(ident) if accounts.field_names().contains(&ident.to_string()) => { quote! { - #idl::IdlSeed::Const( - #idl::IdlSeedConst { - value: AsRef::<[u8]>::as_ref(&#seed).into(), + #idl::IdlSeed::Account( + #idl::IdlSeedAccount { + path: stringify!(#ident).into(), + account: None, } ) } - }); + } + _ => quote! { + #idl::IdlSeed::Const( + #idl::IdlSeedConst { + value: AsRef::<[u8]>::as_ref(&#path).into(), + } + ) + }, + }; Ok(seed) } syn::Expr::Lit(_) => Ok(quote! { diff --git a/tests/pda-derivation/programs/pda-derivation/src/lib.rs b/tests/pda-derivation/programs/pda-derivation/src/lib.rs index d18154d2be..6d27afa42b 100644 --- a/tests/pda-derivation/programs/pda-derivation/src/lib.rs +++ b/tests/pda-derivation/programs/pda-derivation/src/lib.rs @@ -67,6 +67,14 @@ pub mod pda_derivation { pub fn pubkey_const(_ctx: Context) -> Result<()> { Ok(()) } + + pub fn seeds_program_account(_ctx: Context) -> Result<()> { + Ok(()) + } + + pub fn seeds_program_arg(_ctx: Context, _some_program: Pubkey) -> Result<()> { + Ok(()) + } } #[derive(Accounts)] @@ -240,6 +248,28 @@ pub struct PubkeyConst<'info> { pub acc: UncheckedAccount<'info>, } +#[derive(Accounts)] +pub struct SeedsProgramAccount<'info> { + #[account( + seeds = [b"*"], + seeds::program = some_program, + bump + )] + pub pda: UncheckedAccount<'info>, + pub some_program: Program<'info, System>, +} + +#[derive(Accounts)] +#[instruction(some_program: Pubkey)] +pub struct SeedsProgramArg<'info> { + #[account( + seeds = [b"*"], + seeds::program = some_program, + bump + )] + pub pda: UncheckedAccount<'info>, +} + #[account] pub struct MyAccount { data: u64, diff --git a/tests/pda-derivation/tests/typescript.spec.ts b/tests/pda-derivation/tests/typescript.spec.ts index a1f9fcf385..7ed45311d6 100644 --- a/tests/pda-derivation/tests/typescript.spec.ts +++ b/tests/pda-derivation/tests/typescript.spec.ts @@ -150,4 +150,12 @@ describe("typescript", () => { it("Can use `Pubkey` constants with `seeds::program`", async () => { await program.methods.pubkeyConst().rpc(); }); + + it("Can use accounts with `seeds::program`", async () => { + await program.methods.seedsProgramAccount().rpc(); + }); + + it("Can use arguments with `seeds::program`", async () => { + await program.methods.seedsProgramArg(anchor.web3.PublicKey.default).rpc(); + }); });