Browse Source

ts: Add postInstructions (#1007)

SolanaMonkeyBusiness 3 years ago
parent
commit
c188846a4b
4 changed files with 90 additions and 0 deletions
  1. 1 0
      CHANGELOG.md
  2. 13 0
      ts/src/program/context.ts
  3. 5 0
      ts/src/program/namespace/transaction.ts
  4. 71 0
      ts/tests/transaction.spec.ts

+ 1 - 0
CHANGELOG.md

@@ -18,6 +18,7 @@ incremented for features.
 ### Features
 
 * lang: Add `SystemAccount<'info>` account type for generic wallet addresses or accounts owned by the system program ([#954](https://github.com/project-serum/anchor/pull/954))
+* ts: Add inputs `postInstructions` and `preInstructions` as a replacement for (the now deprecated) `instructions`
 
 ### Fixes
 

+ 13 - 0
ts/src/program/context.ts

@@ -28,11 +28,24 @@ export type Context<A extends Accounts = Accounts> = {
   signers?: Array<Signer>;
 
   /**
+   * @deprecated use preInstructions instead.
    * Instructions to run *before* a given method. Often this is used, for
    * example to create accounts prior to executing a method.
    */
   instructions?: TransactionInstruction[];
 
+  /**
+   * Instructions to run *before* a given method. Often this is used, for
+   * example to create accounts prior to executing a method.
+   */
+  preInstructions?: TransactionInstruction[];
+
+  /**
+   * Instructions to run *after* a given method. Often this is used, for
+   * example to close accounts after executing a method.
+   */
+  postInstructions?: TransactionInstruction[];
+
   /**
    * Commitment parameters to use for a transaction.
    */

+ 5 - 0
ts/src/program/namespace/transaction.ts

@@ -16,8 +16,13 @@ export default class TransactionFactory {
     const txFn: TransactionFn<IDL, I> = (...args): Transaction => {
       const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
       const tx = new Transaction();
+      if (ctx.preInstructions && ctx.instructions) {
+        throw new Error("instructions is deprecated, use preInstructions");
+      }
+      ctx.preInstructions?.forEach((ix) => tx.add(ix));
       ctx.instructions?.forEach((ix) => tx.add(ix));
       tx.add(ixFn(...args));
+      ctx.postInstructions?.forEach((ix) => tx.add(ix));
       return tx;
     };
 

+ 71 - 0
ts/tests/transaction.spec.ts

@@ -0,0 +1,71 @@
+import TransactionFactory from "../src/program/namespace/transaction";
+import InstructionFactory from "../src/program/namespace/instruction";
+import { Coder } from "../src";
+import { PublicKey, TransactionInstruction } from "@solana/web3.js";
+
+describe("Transaction", () => {
+  const preIx = new TransactionInstruction({
+    keys: [],
+    programId: PublicKey.default,
+    data: Buffer.from("pre"),
+  });
+  const postIx = new TransactionInstruction({
+    keys: [],
+    programId: PublicKey.default,
+    data: Buffer.from("post"),
+  });
+  const idl = {
+    version: "0.0.0",
+    name: "basic_0",
+    instructions: [
+      {
+        name: "initialize",
+        accounts: [],
+        args: [],
+      },
+    ],
+  };
+
+  it("should add pre instructions before method ix", async () => {
+    const coder = new Coder(idl);
+    const programId = PublicKey.default;
+    const ixItem = InstructionFactory.build(
+      idl.instructions[0],
+      (ixName, ix) => coder.instruction.encode(ixName, ix),
+      programId
+    );
+    const txItem = TransactionFactory.build(idl.instructions[0], ixItem);
+    const tx = txItem({ accounts: {}, preInstructions: [preIx] });
+    expect(tx.instructions.length).toBe(2);
+    expect(tx.instructions[0]).toMatchObject(preIx);
+  });
+
+  it("should add post instructions after method ix", async () => {
+    const coder = new Coder(idl);
+    const programId = PublicKey.default;
+    const ixItem = InstructionFactory.build(
+      idl.instructions[0],
+      (ixName, ix) => coder.instruction.encode(ixName, ix),
+      programId
+    );
+    const txItem = TransactionFactory.build(idl.instructions[0], ixItem);
+    const tx = txItem({ accounts: {}, postInstructions: [postIx] });
+    expect(tx.instructions.length).toBe(2);
+    expect(tx.instructions[1]).toMatchObject(postIx);
+  });
+
+  it("should throw error if both preInstructions and instructions are used", async () => {
+    const coder = new Coder(idl);
+    const programId = PublicKey.default;
+    const ixItem = InstructionFactory.build(
+      idl.instructions[0],
+      (ixName, ix) => coder.instruction.encode(ixName, ix),
+      programId
+    );
+    const txItem = TransactionFactory.build(idl.instructions[0], ixItem);
+
+    expect(() =>
+      txItem({ accounts: {}, preInstructions: [preIx], instructions: [preIx] })
+    ).toThrow(new Error("instructions is deprecated, use preInstructions"));
+  });
+});