瀏覽代碼

ts: add `pubkeys` method builder function to view all instruction account addresses (#1733)

Co-authored-by: Paul Schaaf <paulsimonschaaf@gmail.com>
Matthew Callens 3 年之前
父節點
當前提交
d1ddf8ee24

+ 1 - 0
CHANGELOG.md

@@ -18,6 +18,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 * avm: New `avm update` command to update the Anchor CLI to the latest version ([#1670](https://github.com/project-serum/anchor/pull/1670)).
 * cli: Update js/ts templates to use new `program.methods` syntax ([#1732](https://github.com/project-serum/anchor/pull/1732)).
 * cli: Workspaces created with `anchor init` now come with the `prettier` formatter and scripts included ([#1741](https://github.com/project-serum/anchor/pull/1741)).
+* ts: Add `pubkeys` function to methods builder to get all instruction account addresses ([#1733](https://github.com/project-serum/anchor/pull/1733)).
 
 ### Fixes
 

+ 2 - 1
tests/pda-derivation/programs/pda-derivation/src/lib.rs

@@ -22,7 +22,8 @@ pub mod pda_derivation {
         Ok(())
     }
 
-    pub fn init_my_account(ctx: Context<InitMyAccount>, seed_a: u8) -> Result<()> {
+    pub fn init_my_account(ctx: Context<InitMyAccount>, _seed_a: u8) -> Result<()> {
+        ctx.accounts.account.data = 1337;
         Ok(())
     }
 }

+ 42 - 8
tests/pda-derivation/tests/typescript.spec.ts

@@ -1,12 +1,17 @@
 import * as anchor from "@project-serum/anchor";
 import BN from "bn.js";
 import { Keypair } from "@solana/web3.js";
+import { findProgramAddressSync } from "@project-serum/anchor/dist/cjs/utils/pubkey";
+import { Program } from "@project-serum/anchor";
+import { PdaDerivation } from "../target/types/pda_derivation";
+import { expect } from "chai";
+const encode = anchor.utils.bytes.utf8.encode;
 
 describe("typescript", () => {
   // Configure the client to use the local cluster.
   anchor.setProvider(anchor.Provider.env());
 
-  const program = anchor.workspace.PdaDerivation;
+  const program = anchor.workspace.PdaDerivation as Program<PdaDerivation>;
   const base = Keypair.generate();
   const dataKey = Keypair.generate();
   const data = new BN(1);
@@ -23,12 +28,41 @@ describe("typescript", () => {
   });
 
   it("Inits the derived accounts", async () => {
-    await program.methods
-      .initMyAccount(seedA)
-      .accounts({
-        base: base.publicKey,
-        base2: base.publicKey,
-      })
-      .rpc();
+    const MY_SEED = "hi";
+    const MY_SEED_STR = "hi";
+    const MY_SEED_U8 = 1;
+    const MY_SEED_U32 = 2;
+    const MY_SEED_U64 = 3;
+    const expectedPDAKey = findProgramAddressSync(
+      [
+        Buffer.from([seedA]),
+        encode("another-seed"),
+        encode("test"),
+        base.publicKey.toBuffer(),
+        base.publicKey.toBuffer(),
+        encode(MY_SEED),
+        encode(MY_SEED_STR),
+        Buffer.from([MY_SEED_U8]),
+        new anchor.BN(MY_SEED_U32).toArrayLike(Buffer, "le", 4),
+        new anchor.BN(MY_SEED_U64).toArrayLike(Buffer, "le", 8),
+        new anchor.BN(data).toArrayLike(Buffer, "le", 8),
+        dataKey.publicKey.toBuffer(),
+      ],
+      program.programId
+    )[0];
+
+    const tx = program.methods.initMyAccount(seedA).accounts({
+      base: base.publicKey,
+      base2: base.publicKey,
+    });
+
+    const keys = await tx.pubkeys();
+    expect(keys.account.equals(expectedPDAKey)).is.true;
+
+    await tx.rpc();
+
+    const actualData = (await program.account.myAccount.fetch(expectedPDAKey))
+      .data;
+    expect(actualData.toNumber()).is.equal(1337);
   });
 });

+ 13 - 1
ts/src/program/namespace/methods.ts

@@ -10,7 +10,12 @@ import {
 import { SimulateResponse } from "./simulate.js";
 import { TransactionFn } from "./transaction.js";
 import { Idl } from "../../idl.js";
-import { AllInstructions, MethodsFn, MakeMethodsNamespace } from "./types.js";
+import {
+  AllInstructions,
+  MethodsFn,
+  MakeMethodsNamespace,
+  InstructionAccountAddresses,
+} from "./types.js";
 import { InstructionFn } from "./instruction.js";
 import { RpcFn } from "./rpc.js";
 import { SimulateFn } from "./simulate.js";
@@ -83,6 +88,13 @@ export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
     );
   }
 
+  public async pubkeys(): Promise<
+    Partial<InstructionAccountAddresses<IDL, I>>
+  > {
+    await this._accountsResolver.resolve();
+    return this._accounts as Partial<InstructionAccountAddresses<IDL, I>>;
+  }
+
   public accounts(
     accounts: Partial<Accounts<I["accounts"][number]>>
   ): MethodsBuilder<IDL, I> {

+ 7 - 0
ts/src/program/namespace/types.ts

@@ -88,6 +88,13 @@ export type InstructionContextFnArgs<
   Context<Accounts<I["accounts"][number]>>
 ];
 
+export type InstructionAccountAddresses<
+  IDL extends Idl,
+  I extends AllInstructions<IDL>
+> = {
+  [N in keyof Accounts<I["accounts"][number]>]: PublicKey;
+};
+
 export type MethodsFn<
   IDL extends Idl,
   I extends IDL["instructions"][number],