Selaa lähdekoodia

syn: Fix IDL constant seeds parsing (#2699)

John Anthos 1 vuosi sitten
vanhempi
sitoutus
a9c423ef24

+ 1 - 0
CHANGELOG.md

@@ -19,6 +19,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 - syn: Add missing `new_from_array` method to `Hash` ([#2682](https://github.com/coral-xyz/anchor/pull/2682)).
 - cli: Switch to Cargo feature resolver(`resolver = "2"`) ([#2676](https://github.com/coral-xyz/anchor/pull/2676)).
 - cli: Fix using user specific path for `provider.wallet` in `Anchor.toml` ([#2696](https://github.com/coral-xyz/anchor/pull/2696)).
+- syn: Fix IDL constant seeds parsing ([#2699](https://github.com/coral-xyz/anchor/pull/2699)).
 - cli: Display errors if toolchain override restoration fails ([#2700](https://github.com/coral-xyz/anchor/pull/2700)).
 
 ### Breaking

+ 21 - 1
lang/syn/src/idl/parse/pda.rs

@@ -5,7 +5,7 @@ use crate::ConstraintSeedsGroup;
 use crate::{AccountsStruct, Field};
 use std::collections::HashMap;
 use std::str::FromStr;
-use syn::{Expr, ExprLit, Lit};
+use syn::{Expr, ExprLit, Lit, Path};
 
 // Parses a seeds constraint, extracting the IdlSeed types.
 //
@@ -135,6 +135,7 @@ impl<'a> PdaParser<'a> {
                 let seed_path: SeedPath = SeedPath(lit_byte_str.token().to_string(), Vec::new());
                 self.parse_str_literal(&seed_path)
             }
+            Expr::Path(expr_path) => self.parse_const_path(&expr_path.path),
             // Unknown type. Please file an issue.
             _ => {
                 println!("WARNING: unexpected seed: {seed:?}");
@@ -151,6 +152,25 @@ impl<'a> PdaParser<'a> {
         }))
     }
 
+    fn parse_const_path(&self, path: &Path) -> Option<IdlSeed> {
+        let ident = &path.segments.first().unwrap().ident;
+
+        let const_item = self.ctx.consts().find(|c| c.ident == *ident).unwrap();
+        let idl_ty = IdlType::from_str(&parser::tts_to_string(&const_item.ty)).ok()?;
+
+        let idl_ty_value = parser::tts_to_string(&const_item.expr);
+        let idl_ty_value: String = str_lit_to_array(&idl_ty, &idl_ty_value);
+
+        let seed_path: SeedPath = SeedPath(idl_ty_value, Vec::new());
+
+        if self.is_str_literal(&seed_path) {
+            self.parse_str_literal(&seed_path)
+        } else {
+            println!("WARNING: unexpected constant path value: {seed_path:?}");
+            None
+        }
+    }
+
     fn parse_const(&self, seed_path: &SeedPath) -> Option<IdlSeed> {
         // Pull in the constant value directly into the IDL.
         assert!(seed_path.components().is_empty());

+ 20 - 0
tests/relations-derivation/programs/relations-derivation/src/lib.rs

@@ -5,6 +5,8 @@ use anchor_lang::prelude::*;
 
 declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
 
+pub const SEED: &[u8] = b"contant-seed";
+
 #[program]
 pub mod relations_derivation {
     use super::*;
@@ -17,6 +19,9 @@ pub mod relations_derivation {
     pub fn test_relation(_ctx: Context<TestRelation>) -> Result<()> {
         Ok(())
     }
+    pub fn test_seed_constant(_ctx: Context<TestSeedConstant>) -> Result<()> {
+        Ok(())
+    }
 }
 
 #[derive(Accounts)]
@@ -60,6 +65,21 @@ pub struct TestRelation<'info> {
     nested: Nested<'info>,
 }
 
+#[derive(Accounts)]
+pub struct TestSeedConstant<'info> {
+    #[account(mut)]
+    my_account: Signer<'info>,
+    #[account(
+      init,
+      payer = my_account,
+      seeds = [SEED],
+      space = 100,
+      bump,
+    )]
+    account: Account<'info, MyAccount>,
+    system_program: Program<'info, System>,
+}
+
 #[account]
 pub struct MyAccount {
     pub my_account: Pubkey,

+ 4 - 0
tests/relations-derivation/tests/typescript.spec.ts

@@ -40,4 +40,8 @@ describe("typescript", () => {
 
     await tx.rpc();
   });
+
+  it("Can use relations derivation with seed constant", async () => {
+    await program.methods.testSeedConstant().accounts({}).rpc();
+  });
 });