views.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { PublicKey } from "@solana/web3.js";
  2. import { Idl, IdlAccount } from "../../idl.js";
  3. import { SimulateFn } from "./simulate.js";
  4. import {
  5. AllInstructions,
  6. InstructionContextFn,
  7. MakeInstructionsNamespace,
  8. } from "./types";
  9. import { IdlCoder } from "../../coder/borsh/idl";
  10. import { decode } from "../../utils/bytes/base64";
  11. export default class ViewFactory {
  12. public static build<IDL extends Idl, I extends AllInstructions<IDL>>(
  13. programId: PublicKey,
  14. idlIx: AllInstructions<IDL>,
  15. simulateFn: SimulateFn<IDL>,
  16. idl: IDL
  17. ): ViewFn<IDL, I> | undefined {
  18. const isMut = idlIx.accounts.find((a: IdlAccount) => a.isMut);
  19. const hasReturn = !!idlIx.returns;
  20. if (isMut || !hasReturn) return;
  21. const view: ViewFn<IDL> = async (...args) => {
  22. let simulationResult = await simulateFn(...args);
  23. const returnPrefix = `Program return: ${programId} `;
  24. let returnLog = simulationResult.raw.find((l) =>
  25. l.startsWith(returnPrefix)
  26. );
  27. if (!returnLog) {
  28. throw new Error("View expected return log");
  29. }
  30. let returnData = decode(returnLog.slice(returnPrefix.length));
  31. let returnType = idlIx.returns;
  32. if (!returnType) {
  33. throw new Error("View expected return type");
  34. }
  35. const coder = IdlCoder.fieldLayout(
  36. { type: returnType },
  37. Array.from([...(idl.accounts ?? []), ...(idl.types ?? [])])
  38. );
  39. return coder.decode(returnData);
  40. };
  41. return view;
  42. }
  43. }
  44. export type ViewNamespace<
  45. IDL extends Idl = Idl,
  46. I extends AllInstructions<IDL> = AllInstructions<IDL>
  47. > = MakeInstructionsNamespace<IDL, I, Promise<any>>;
  48. /**
  49. * ViewFn is a single method generated from an IDL. It simulates a method
  50. * against a cluster configured by the provider, and then parses the events
  51. * and extracts return data from the raw logs emitted during the simulation.
  52. */
  53. export type ViewFn<
  54. IDL extends Idl = Idl,
  55. I extends AllInstructions<IDL> = AllInstructions<IDL>
  56. > = InstructionContextFn<IDL, I, Promise<any>>;