Преглед на файлове

rename to transactionInstructions everywhere; still lots to fix in provider

henrye преди 2 години
родител
ревизия
b20b5dabb1

+ 9 - 5
ts/packages/anchor/src/nodewallet.ts

@@ -1,5 +1,5 @@
 import { Buffer } from "buffer";
-import { Keypair, PublicKey, Transaction } from "@solana/web3.js";
+import { Keypair, PublicKey, VersionedTransaction } from "@solana/web3.js";
 import { Wallet } from "./provider";
 
 /**
@@ -30,14 +30,18 @@ export default class NodeWallet implements Wallet {
     return new NodeWallet(payer);
   }
 
-  async signTransaction(tx: Transaction): Promise<Transaction> {
-    tx.partialSign(this.payer);
+  async signTransaction(
+    tx: VersionedTransaction
+  ): Promise<VersionedTransaction> {
+    tx.sign([this.payer]);
     return tx;
   }
 
-  async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
+  async signAllTransactions(
+    txs: VersionedTransaction[]
+  ): Promise<VersionedTransaction[]> {
     return txs.map((t) => {
-      t.partialSign(this.payer);
+      t.sign([this.payer]);
       return t;
     });
   }

+ 21 - 14
ts/packages/anchor/src/program/index.ts

@@ -6,7 +6,7 @@ import { Coder, BorshCoder } from "../coder/index.js";
 import NamespaceFactory, {
   RpcNamespace,
   InstructionNamespace,
-  TransactionNamespace,
+  TransactionInstructionsNamespace,
   AccountNamespace,
   SimulateNamespace,
   MethodsNamespace,
@@ -138,13 +138,13 @@ export class Program<IDL extends Idl = Idl> {
   readonly instruction: InstructionNamespace<IDL>;
 
   /**
-   * The namespace provides functions to build [[Transaction]] objects for each
+   * The namespace provides functions to build [[TransactionInstruction\[\]]] objects for each
    * method of a program.
    *
    * ## Usage
    *
    * ```javascript
-   * program.transaction.<method>(...args, ctx);
+   * program.transactionInstructions.<method>(...args, ctx);
    * ```
    *
    * ## Parameters
@@ -159,7 +159,7 @@ export class Program<IDL extends Idl = Idl> {
    * To create an instruction for the `increment` method above,
    *
    * ```javascript
-   * const tx = await program.transaction.increment({
+   * const tx = await program.transactionInstructions.increment({
    *   accounts: {
    *     counter,
    *   },
@@ -167,7 +167,7 @@ export class Program<IDL extends Idl = Idl> {
    * ```
    * @deprecated
    */
-  readonly transaction: TransactionNamespace<IDL>;
+  readonly transactionInstructions: TransactionInstructionsNamespace<IDL>;
 
   /**
    * The namespace provides functions to simulate transactions for each method
@@ -283,17 +283,24 @@ export class Program<IDL extends Idl = Idl> {
     this._events = new EventManager(this._programId, provider, this._coder);
 
     // Dynamic namespaces.
-    const [rpc, instruction, transaction, account, simulate, methods, views] =
-      NamespaceFactory.build(
-        idl,
-        this._coder,
-        programId,
-        provider,
-        getCustomResolver ?? (() => undefined)
-      );
+    const [
+      rpc,
+      instruction,
+      transactionInstructions,
+      account,
+      simulate,
+      methods,
+      views,
+    ] = NamespaceFactory.build(
+      idl,
+      this._coder,
+      programId,
+      provider,
+      getCustomResolver ?? (() => undefined)
+    );
     this.rpc = rpc;
     this.instruction = instruction;
-    this.transaction = transaction;
+    this.transactionInstructions = transactionInstructions;
     this.account = account;
     this.simulate = simulate;
     this.methods = methods;

+ 15 - 10
ts/packages/anchor/src/program/namespace/index.ts

@@ -4,7 +4,9 @@ import { Coder } from "../../coder/index.js";
 import Provider from "../../provider.js";
 import { Idl, IdlInstruction } from "../../idl.js";
 import InstructionFactory, { InstructionNamespace } from "./instruction.js";
-import TransactionFactory, { TransactionNamespace } from "./transaction.js";
+import TransactionInstructionsFactory, {
+  TransactionInstructionsNamespace,
+} from "./transaction-instructions.js";
 import RpcFactory, { RpcNamespace } from "./rpc.js";
 import AccountFactory, { AccountNamespace } from "./account.js";
 import SimulateFactory, { SimulateNamespace } from "./simulate.js";
@@ -15,7 +17,10 @@ import { CustomAccountResolver } from "../accounts-resolver.js";
 
 // Re-exports.
 export { InstructionNamespace, InstructionFn } from "./instruction.js";
-export { TransactionNamespace, TransactionFn } from "./transaction.js";
+export {
+  TransactionInstructionsNamespace,
+  TransactionInstructionsFn,
+} from "./transaction-instructions.js";
 export { RpcNamespace, RpcFn } from "./rpc.js";
 export { AccountNamespace, AccountClient, ProgramAccount } from "./account.js";
 export { SimulateNamespace, SimulateFn } from "./simulate.js";
@@ -38,7 +43,7 @@ export default class NamespaceFactory {
   ): [
     RpcNamespace<IDL>,
     InstructionNamespace<IDL>,
-    TransactionNamespace<IDL>,
+    TransactionInstructionsNamespace<IDL>,
     AccountNamespace<IDL>,
     SimulateNamespace<IDL>,
     MethodsNamespace<IDL>,
@@ -46,7 +51,7 @@ export default class NamespaceFactory {
   ] {
     const rpc: RpcNamespace = {};
     const instruction: InstructionNamespace = {};
-    const transaction: TransactionNamespace = {};
+    const transactionInstructions: TransactionInstructionsNamespace = {};
     const simulate: SimulateNamespace = {};
     const methods: MethodsNamespace = {};
     const view: ViewNamespace = {};
@@ -63,11 +68,11 @@ export default class NamespaceFactory {
         (ixName, ix) => coder.instruction.encode(ixName, ix),
         programId
       );
-      const txItem = TransactionFactory.build(idlIx, ixItem);
-      const rpcItem = RpcFactory.build(idlIx, txItem, idlErrors, provider);
+      const txIxsItem = TransactionInstructionsFactory.build(idlIx, ixItem);
+      const rpcItem = RpcFactory.build(idlIx, txIxsItem, idlErrors, provider);
       const simulateItem = SimulateFactory.build(
         idlIx,
-        txItem,
+        txIxsItem,
         idlErrors,
         provider,
         coder,
@@ -80,7 +85,7 @@ export default class NamespaceFactory {
         programId,
         idlIx,
         ixItem,
-        txItem,
+        txIxsItem,
         rpcItem,
         simulateItem,
         viewItem,
@@ -91,7 +96,7 @@ export default class NamespaceFactory {
       const name = camelCase(idlIx.name);
 
       instruction[name] = ixItem;
-      transaction[name] = txItem;
+      transactionInstructions[name] = txIxsItem;
       rpc[name] = rpcItem;
       simulate[name] = simulateItem;
       methods[name] = methodItem;
@@ -103,7 +108,7 @@ export default class NamespaceFactory {
     return [
       rpc as RpcNamespace<IDL>,
       instruction as InstructionNamespace<IDL>,
-      transaction as TransactionNamespace<IDL>,
+      transactionInstructions as TransactionInstructionsNamespace<IDL>,
       account,
       simulate as SimulateNamespace<IDL>,
       methods as MethodsNamespace<IDL>,

+ 6 - 7
ts/packages/anchor/src/program/namespace/methods.ts

@@ -3,7 +3,6 @@ import {
   ConfirmOptions,
   PublicKey,
   Signer,
-  Transaction,
   TransactionInstruction,
   TransactionSignature,
 } from "@solana/web3.js";
@@ -20,7 +19,7 @@ import { AccountNamespace } from "./account.js";
 import { InstructionFn } from "./instruction.js";
 import { RpcFn } from "./rpc.js";
 import { SimulateFn, SimulateResponse } from "./simulate.js";
-import { TransactionFn } from "./transaction.js";
+import { TransactionInstructionsFn } from "./transaction-instructions.js";
 import {
   AllInstructions,
   InstructionAccountAddresses,
@@ -40,7 +39,7 @@ export class MethodsBuilderFactory {
     programId: PublicKey,
     idlIx: AllInstructions<IDL>,
     ixFn: InstructionFn<IDL>,
-    txFn: TransactionFn<IDL>,
+    txIxsFn: TransactionInstructionsFn<IDL>,
     rpcFn: RpcFn<IDL>,
     simulateFn: SimulateFn<IDL>,
     viewFn: ViewFn<IDL> | undefined,
@@ -52,7 +51,7 @@ export class MethodsBuilderFactory {
       new MethodsBuilder(
         args,
         ixFn,
-        txFn,
+        txIxsFn,
         rpcFn,
         simulateFn,
         viewFn,
@@ -121,7 +120,7 @@ export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
   constructor(
     _args: Array<any>,
     private _ixFn: InstructionFn<IDL>,
-    private _txFn: TransactionFn<IDL>,
+    private _txIxsFn: TransactionInstructionsFn<IDL>,
     private _rpcFn: RpcFn<IDL>,
     private _simulateFn: SimulateFn<IDL>,
     private _viewFn: ViewFn<IDL> | undefined,
@@ -299,13 +298,13 @@ export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
     };
   }
 
-  public async transaction(): Promise<Transaction> {
+  public async transactionInstructions(): Promise<TransactionInstruction[]> {
     if (this._autoResolveAccounts) {
       await this._accountsResolver.resolve();
     }
 
     // @ts-ignore
-    return this._txFn(...this._args, {
+    return this._txIxsFn(...this._args, {
       accounts: this._accounts,
       signers: this._signers,
       remainingAccounts: this._remainingAccounts,

+ 4 - 4
ts/packages/anchor/src/program/namespace/rpc.ts

@@ -2,7 +2,7 @@ import { TransactionSignature } from "@solana/web3.js";
 import Provider from "../../provider.js";
 import { Idl } from "../../idl.js";
 import { splitArgsAndCtx } from "../context.js";
-import { TransactionFn } from "./transaction.js";
+import { TransactionInstructionsFn } from "./transaction-instructions.js";
 import { translateError } from "../../error.js";
 import {
   AllInstructions,
@@ -13,12 +13,12 @@ import {
 export default class RpcFactory {
   public static build<IDL extends Idl, I extends AllInstructions<IDL>>(
     idlIx: I,
-    txFn: TransactionFn<IDL, I>,
+    txIxsFn: TransactionInstructionsFn<IDL, I>,
     idlErrors: Map<number, string>,
     provider: Provider
   ): RpcFn {
     const rpc: RpcFn<IDL, I> = async (...args) => {
-      const tx = txFn(...args);
+      const txIxs = txIxsFn(...args);
       const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
       if (provider.sendAndConfirm === undefined) {
         throw new Error(
@@ -27,7 +27,7 @@ export default class RpcFactory {
       }
       try {
         return await provider.sendAndConfirm(
-          tx,
+          txIxs,
           ctx.signers ?? [],
           ctx.options
         );

+ 3 - 3
ts/packages/anchor/src/program/namespace/simulate.ts

@@ -2,7 +2,7 @@ import { PublicKey } from "@solana/web3.js";
 import Provider from "../../provider.js";
 import { SuccessfulTxSimulationResponse } from "src/utils/rpc.js";
 import { splitArgsAndCtx } from "../context.js";
-import { TransactionFn } from "./transaction.js";
+import { TransactionInstructionsFn } from "./transaction-instructions.js";
 import { EventParser, Event } from "../event.js";
 import { Coder } from "../../coder/index.js";
 import { Idl, IdlEvent } from "../../idl.js";
@@ -17,7 +17,7 @@ import {
 export default class SimulateFactory {
   public static build<IDL extends Idl, I extends AllInstructions<IDL>>(
     idlIx: AllInstructions<IDL>,
-    txFn: TransactionFn<IDL>,
+    txIxsFn: TransactionInstructionsFn<IDL>,
     idlErrors: Map<number, string>,
     provider: Provider,
     coder: Coder,
@@ -25,7 +25,7 @@ export default class SimulateFactory {
     idl: IDL
   ): SimulateFn<IDL, I> {
     const simulate: SimulateFn<IDL> = async (...args) => {
-      const tx = txFn(...args);
+      const tx = txIxsFn(...args);
       const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
       let resp: SuccessfulTxSimulationResponse | undefined = undefined;
       if (provider.simulate === undefined) {

+ 13 - 11
ts/packages/anchor/src/program/namespace/transaction.ts → ts/packages/anchor/src/program/namespace/transaction-instructions.ts

@@ -1,4 +1,4 @@
-import { Transaction, TransactionInstruction } from "@solana/web3.js";
+import { TransactionInstruction } from "@solana/web3.js";
 import { Idl, IdlInstruction } from "../../idl.js";
 import { splitArgsAndCtx } from "../context.js";
 import { InstructionFn } from "./instruction.js";
@@ -8,12 +8,14 @@ import {
   MakeInstructionsNamespace,
 } from "./types.js";
 
-export default class TransactionFactory {
+export default class TransactionInstructionsFactory {
   public static build<IDL extends Idl, I extends AllInstructions<IDL>>(
     idlIx: I,
     ixFn: InstructionFn<IDL, I>
-  ): TransactionFn<IDL, I> {
-    const txFn: TransactionFn<IDL, I> = (...args): TransactionInstruction[] => {
+  ): TransactionInstructionsFn<IDL, I> {
+    const txIxsFn: TransactionInstructionsFn<IDL, I> = (
+      ...args
+    ): TransactionInstruction[] => {
       const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
       const tx: TransactionInstruction[] = [];
       if (ctx.preInstructions && ctx.instructions) {
@@ -26,18 +28,18 @@ export default class TransactionFactory {
       return tx;
     };
 
-    return txFn;
+    return txIxsFn;
   }
 }
 
 /**
- * The namespace provides functions to build [[Transaction]] objects for each
+ * The namespace provides functions to build [[TransactionInstruction\[\]]] objects for each
  * method of a program.
  *
  * ## Usage
  *
  * ```javascript
- * program.transaction.<method>(...args, ctx);
+ * program.transactionInstructions.<method>(...args, ctx);
  * ```
  *
  * ## Parameters
@@ -52,22 +54,22 @@ export default class TransactionFactory {
  * To create an instruction for the `increment` method above,
  *
  * ```javascript
- * const tx = await program.transaction.increment({
+ * const tx = await program.transactionInstructions.increment({
  *   accounts: {
  *     counter,
  *   },
  * });
  * ```
  */
-export type TransactionNamespace<
+export type TransactionInstructionsNamespace<
   IDL extends Idl = Idl,
   I extends AllInstructions<IDL> = AllInstructions<IDL>
 > = MakeInstructionsNamespace<IDL, I, TransactionInstruction[]>;
 
 /**
- * Tx is a function to create a `TransactionInstruction[]` for a given program instruction.
+ * TxIxs is a function to create a `TransactionInstruction[]` for a given program instruction.
  */
-export type TransactionFn<
+export type TransactionInstructionsFn<
   IDL extends Idl = Idl,
   I extends AllInstructions<IDL> = AllInstructions<IDL>
 > = InstructionContextFn<IDL, I, TransactionInstruction[]>;

+ 9 - 10
ts/packages/anchor/src/provider.ts

@@ -15,31 +15,28 @@ import {
 } from "@solana/web3.js";
 import { bs58 } from "./utils/bytes/index.js";
 import { isBrowser } from "./utils/common.js";
-import {
-  simulateTransaction,
-  SuccessfulTxSimulationResponse,
-} from "./utils/rpc.js";
+import { SuccessfulTxSimulationResponse } from "./utils/rpc.js";
 
 export default interface Provider {
   readonly connection: Connection;
   readonly publicKey?: PublicKey;
 
   send?(
-    tx: TransactionInstruction[],
+    txIxs: TransactionInstruction[],
     signers?: Signer[],
     opts?: SendOptions
   ): Promise<TransactionSignature>;
   sendAndConfirm?(
-    tx: TransactionInstruction[],
+    txIxs: TransactionInstruction[],
     signers?: Signer[],
     opts?: ConfirmOptions
   ): Promise<TransactionSignature>;
   sendAll?(
-    txWithSigners: { tx: TransactionInstruction[]; signers?: Signer[] }[],
+    txWithSigners: { txIxs: TransactionInstruction[]; signers?: Signer[] }[],
     opts?: ConfirmOptions
   ): Promise<Array<TransactionSignature>>;
   simulate?(
-    tx: TransactionInstruction[],
+    txIxs: TransactionInstruction[],
     signers?: Signer[],
     commitment?: Commitment,
     includeAccounts?: boolean | PublicKey[]
@@ -278,8 +275,10 @@ export class AnchorProvider implements Provider {
     if (signers) {
       tx = await this.wallet.signTransaction(tx);
     }
-    const result = await simulateTransaction(
-      this.connection,
+    // TODO: update to the latest version that passes in versioned transactions
+    // We have to figure out how to update all of the things above as well.
+    // Since it has to go txIxs -> TxMsg -> VersionedTransaction
+    const result = await this.connection.simulateTransaction(
       tx,
       signers,
       commitment,

+ 4 - 137
ts/packages/anchor/src/utils/rpc.ts

@@ -5,7 +5,6 @@ import {
   Connection,
   PublicKey,
   TransactionSignature,
-  Transaction,
   TransactionInstruction,
   Commitment,
   Signer,
@@ -13,6 +12,7 @@ import {
   SimulatedTransactionResponse,
   SendTransactionError,
   Context,
+  VersionedTransaction,
 } from "@solana/web3.js";
 import { chunks } from "../utils/common.js";
 import { Address, translateAddress } from "../program/common.js";
@@ -49,8 +49,8 @@ export async function invoke(
     provider = getProvider();
   }
 
-  const tx = new Transaction();
-  tx.add(
+  const txInstructions: TransactionInstruction[] = [];
+  txInstructions.push(
     new TransactionInstruction({
       programId,
       keys: accounts ?? [],
@@ -64,7 +64,7 @@ export async function invoke(
     );
   }
 
-  return await provider.sendAndConfirm(tx, []);
+  return await provider.sendAndConfirm(txInstructions, []);
 }
 
 const GET_MULTIPLE_ACCOUNTS_LIMIT: number = 99;
@@ -150,139 +150,6 @@ async function getMultipleAccountsAndContextCore(
   return accounts;
 }
 
-// copy from @solana/web3.js that has a commitment param
-export async function simulateTransaction(
-  connection: Connection,
-  transaction: Transaction,
-  signers?: Array<Signer>,
-  commitment?: Commitment,
-  includeAccounts?: boolean | Array<PublicKey>
-): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
-  if (signers && signers.length > 0) {
-    transaction.sign(...signers);
-  }
-
-  // @ts-expect-error
-  const message = transaction._compile();
-  const signData = message.serialize();
-  // @ts-expect-error
-  const wireTransaction = transaction._serialize(signData);
-  const encodedTransaction = wireTransaction.toString("base64");
-  const config: any = {
-    encoding: "base64",
-    commitment: commitment ?? connection.commitment,
-  };
-
-  if (includeAccounts) {
-    const addresses = (
-      Array.isArray(includeAccounts) ? includeAccounts : message.nonProgramIds()
-    ).map((key) => key.toBase58());
-
-    config["accounts"] = {
-      encoding: "base64",
-      addresses,
-    };
-  }
-
-  if (signers) {
-    config.sigVerify = true;
-  }
-
-  const args = [encodedTransaction, config];
-  // @ts-expect-error
-  const unsafeRes = await connection._rpcRequest("simulateTransaction", args);
-  const res = create(unsafeRes, SimulatedTransactionResponseStruct);
-  if ("error" in res) {
-    let logs;
-    if ("data" in res.error) {
-      logs = res.error.data.logs;
-      if (logs && Array.isArray(logs)) {
-        const traceIndent = "\n    ";
-        const logTrace = traceIndent + logs.join(traceIndent);
-        console.error(res.error.message, logTrace);
-      }
-    }
-    throw new SendTransactionError(
-      "failed to simulate transaction: " + res.error.message,
-      logs
-    );
-  }
-  return res.result;
-}
-
-// copy from @solana/web3.js
-function jsonRpcResult<T, U>(schema: Struct<T, U>) {
-  return coerce(createRpcResult(schema), UnknownRpcResult, (value) => {
-    if ("error" in value) {
-      return value;
-    } else {
-      return {
-        ...value,
-        result: create(value.result, schema),
-      };
-    }
-  });
-}
-
-// copy from @solana/web3.js
-const UnknownRpcResult = createRpcResult(unknown());
-
-// copy from @solana/web3.js
-function createRpcResult<T, U>(result: Struct<T, U>) {
-  return union([
-    pick({
-      jsonrpc: literal("2.0"),
-      id: string(),
-      result,
-    }),
-    pick({
-      jsonrpc: literal("2.0"),
-      id: string(),
-      error: pick({
-        code: unknown(),
-        message: string(),
-        data: optional(any()),
-      }),
-    }),
-  ]);
-}
-
-// copy from @solana/web3.js
-function jsonRpcResultAndContext<T, U>(value: Struct<T, U>) {
-  return jsonRpcResult(
-    pick({
-      context: pick({
-        slot: number(),
-      }),
-      value,
-    })
-  );
-}
-
-// copy from @solana/web3.js
-const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(
-  pick({
-    err: nullable(union([pick({}), string()])),
-    logs: nullable(array(string())),
-    accounts: optional(
-      nullable(
-        array(
-          nullable(
-            pick({
-              executable: boolean(),
-              owner: string(),
-              lamports: number(),
-              data: array(string()),
-              rentEpoch: optional(number()),
-            })
-          )
-        )
-      )
-    ),
-    unitsConsumed: optional(number()),
-  })
-);
-
 export type SuccessfulTxSimulationResponse = Omit<
   SimulatedTransactionResponse,
   "err"

+ 25 - 12
ts/packages/anchor/tests/transaction.spec.ts

@@ -1,9 +1,9 @@
-import TransactionFactory from "../src/program/namespace/transaction";
+import TransactionInstructionsFactory from "../src/program/namespace/transaction-instructions";
 import InstructionFactory from "../src/program/namespace/instruction";
 import { BorshCoder } from "../src";
 import { PublicKey, TransactionInstruction } from "@solana/web3.js";
 
-describe("Transaction", () => {
+describe("Transaction Instructions", () => {
   const preIx = new TransactionInstruction({
     keys: [],
     programId: PublicKey.default,
@@ -34,10 +34,13 @@ describe("Transaction", () => {
       (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);
+    const txIxsItem = TransactionInstructionsFactory.build(
+      idl.instructions[0],
+      ixItem
+    );
+    const txIxs = txIxsItem({ accounts: {}, preInstructions: [preIx] });
+    expect(txIxs.length).toBe(2);
+    expect(txIxs[0]).toMatchObject(preIx);
   });
 
   it("should add post instructions after method ix", async () => {
@@ -48,10 +51,13 @@ describe("Transaction", () => {
       (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);
+    const txIxsItem = TransactionInstructionsFactory.build(
+      idl.instructions[0],
+      ixItem
+    );
+    const txIxs = txIxsItem({ accounts: {}, postInstructions: [postIx] });
+    expect(txIxs.length).toBe(2);
+    expect(txIxs[1]).toMatchObject(postIx);
   });
 
   it("should throw error if both preInstructions and instructions are used", async () => {
@@ -62,10 +68,17 @@ describe("Transaction", () => {
       (ixName, ix) => coder.instruction.encode(ixName, ix),
       programId
     );
-    const txItem = TransactionFactory.build(idl.instructions[0], ixItem);
+    const txIxsItem = TransactionInstructionsFactory.build(
+      idl.instructions[0],
+      ixItem
+    );
 
     expect(() =>
-      txItem({ accounts: {}, preInstructions: [preIx], instructions: [preIx] })
+      txIxsItem({
+        accounts: {},
+        preInstructions: [preIx],
+        instructions: [preIx],
+      })
     ).toThrow(new Error("instructions is deprecated, use preInstructions"));
   });
 });