瀏覽代碼

idl: Fix using account or arg values for `seeds::program` (#3570)

acheron 7 月之前
父節點
當前提交
b6b4f11a5c

+ 1 - 0
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
 

+ 18 - 13
lang/syn/src/idl/accounts.rs

@@ -351,29 +351,34 @@ fn parse_seed(seed: &syn::Expr, accounts: &AccountsStruct) -> Result<TokenStream
             )
         }),
         syn::Expr::Path(path) => {
-            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! {

+ 30 - 0
tests/pda-derivation/programs/pda-derivation/src/lib.rs

@@ -67,6 +67,14 @@ pub mod pda_derivation {
     pub fn pubkey_const(_ctx: Context<PubkeyConst>) -> Result<()> {
         Ok(())
     }
+
+    pub fn seeds_program_account(_ctx: Context<SeedsProgramAccount>) -> Result<()> {
+        Ok(())
+    }
+
+    pub fn seeds_program_arg(_ctx: Context<SeedsProgramArg>, _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,

+ 8 - 0
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();
+  });
 });