Browse Source

ts: Fix using IDLs that have defined types as generic arguments (#3016)

cryptopapi997 1 năm trước cách đây
mục cha
commit
29a6558d08

+ 1 - 0
CHANGELOG.md

@@ -44,6 +44,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 - lang: Make tuple struct fields public in `declare_program!` ([#2994](https://github.com/coral-xyz/anchor/pull/2994)).
 - Remove `rust-version` from crate manifests ([#3000](https://github.com/coral-xyz/anchor/pull/3000)).
 - cli: Fix upgradeable program clones ([#3010](https://github.com/coral-xyz/anchor/pull/3010)).
+- ts: Fix using IDLs that have defined types as generic arguments ([#3016](https://github.com/coral-xyz/anchor/pull/3016)).
 
 ### Breaking
 

+ 33 - 0
tests/idl/programs/new-idl/src/lib.rs

@@ -112,6 +112,14 @@ pub mod new_idl {
         Ok(())
     }
 
+    pub fn generic_custom_struct(
+        ctx: Context<GenericCustomStruct>,
+        generic_arg: GenericStruct<SomeStruct, 4>,
+    ) -> Result<()> {
+        ctx.accounts.my_account.field = generic_arg;
+        Ok(())
+    }
+
     pub fn full_path(
         ctx: Context<FullPath>,
         named_struct: NamedStruct,
@@ -315,11 +323,36 @@ pub struct Generic<'info> {
     pub system_program: Program<'info, System>,
 }
 
+#[derive(Accounts)]
+pub struct GenericCustomStruct<'info> {
+    #[account(mut)]
+    pub signer: Signer<'info>,
+    #[account(
+        init,
+        payer = signer,
+        space = 1024,
+        seeds = [b"genericCustomStruct", signer.key.as_ref()],
+        bump
+    )]
+    pub my_account: Account<'info, GenericAccountCustomStruct>,
+    pub system_program: Program<'info, System>,
+}
+
 #[account]
 pub struct GenericAccount {
     pub field: GenericStruct<u16, 4>,
 }
 
+#[account]
+pub struct GenericAccountCustomStruct {
+    pub field: GenericStruct<SomeStruct, 4>,
+}
+
+#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
+pub struct SomeStruct {
+    pub field: u16,
+}
+
 #[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug)]
 pub struct GenericStruct<T, const N: usize> {
     arr: [T; N],

+ 22 - 0
tests/idl/tests/new-idl.ts

@@ -347,6 +347,28 @@ describe("New IDL", () => {
       assert.deepEqual(myAccount.field, arg);
     });
 
+    it("Can use generics populated with custom struct", async () => {
+      const arg = {
+        arr: [{ field: 1 }, { field: 2 }, { field: 3 }, { field: 4 }],
+        subField: {
+          subArr: new Array(8).fill(null).map((_, i) => ({ field: i })),
+          another: [
+            { field: 42 },
+            { field: 420 },
+            { field: 4_200 },
+            { field: 42_000 },
+          ],
+        },
+      };
+      const { pubkeys } = await program.methods
+        .genericCustomStruct(arg)
+        .rpcAndKeys();
+      const myAccount = await program.account.genericAccountCustomStruct.fetch(
+        pubkeys.myAccount
+      );
+      assert.deepEqual(myAccount.field, arg);
+    });
+
     it("Can use full module path types", async () => {
       const kp = anchor.web3.Keypair.generate();
 

+ 4 - 1
ts/packages/anchor/src/coder/borsh/idl.ts

@@ -126,7 +126,10 @@ export class IdlCoder {
             throw new IdlError(`Invalid generic field: ${field.name}`);
           }
 
-          return IdlCoder.fieldLayout({ ...field, type: genericArg.type });
+          return IdlCoder.fieldLayout(
+            { ...field, type: genericArg.type },
+            types
+          );
         }
 
         throw new IdlError(