program.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { PublicKey } from "@solana/web3.js";
  2. import { inflate } from "pako";
  3. import Provider from "./provider";
  4. import { RpcFactory } from "./rpc";
  5. import { Idl, idlAddress, decodeIdlAccount } from "./idl";
  6. import Coder from "./coder";
  7. import { Rpcs, Ixs, Txs, Accounts, State } from "./rpc";
  8. import { getProvider } from "./";
  9. /**
  10. * Program is the IDL deserialized representation of a Solana program.
  11. */
  12. export class Program {
  13. /**
  14. * Address of the program.
  15. */
  16. readonly programId: PublicKey;
  17. /**
  18. * IDL describing this program's interface.
  19. */
  20. readonly idl: Idl;
  21. /**
  22. * Async functions to invoke instructions against a Solana priogram running
  23. * on a cluster.
  24. */
  25. readonly rpc: Rpcs;
  26. /**
  27. * Async functions to fetch deserialized program accounts from a cluster.
  28. */
  29. readonly account: Accounts;
  30. /**
  31. * Functions to build `TransactionInstruction` objects.
  32. */
  33. readonly instruction: Ixs;
  34. /**
  35. * Functions to build `Transaction` objects.
  36. */
  37. readonly transaction: Txs;
  38. /**
  39. * Coder for serializing rpc requests.
  40. */
  41. readonly coder: Coder;
  42. /**
  43. * Object with state account accessors and rpcs.
  44. */
  45. readonly state: State;
  46. /**
  47. * Wallet and network provider.
  48. */
  49. readonly provider: Provider;
  50. public constructor(idl: Idl, programId: PublicKey, provider?: Provider) {
  51. this.idl = idl;
  52. this.programId = programId;
  53. this.provider = provider ?? getProvider();
  54. // Build the serializer.
  55. const coder = new Coder(idl);
  56. // Build the dynamic RPC functions.
  57. const [rpcs, ixs, txs, accounts, state] = RpcFactory.build(
  58. idl,
  59. coder,
  60. programId,
  61. this.provider
  62. );
  63. this.rpc = rpcs;
  64. this.instruction = ixs;
  65. this.transaction = txs;
  66. this.account = accounts;
  67. this.coder = coder;
  68. this.state = state;
  69. }
  70. /**
  71. * Generates a Program client by fetching the IDL from chain.
  72. */
  73. public static async at(programId: PublicKey, provider?: Provider) {
  74. const idl = await Program.fetchIdl(programId, provider);
  75. return new Program(idl, programId, provider);
  76. }
  77. /**
  78. * Fetches an idl from the blockchain.
  79. */
  80. public static async fetchIdl(programId: PublicKey, provider?: Provider) {
  81. provider = provider ?? getProvider();
  82. const address = await idlAddress(programId);
  83. const accountInfo = await provider.connection.getAccountInfo(address);
  84. // Chop off account discriminator.
  85. let idlAccount = decodeIdlAccount(accountInfo.data.slice(8));
  86. const inflatedIdl = inflate(idlAccount.data);
  87. return JSON.parse(decodeUtf8(inflatedIdl));
  88. }
  89. }
  90. function decodeUtf8(array: Uint8Array): string {
  91. const decoder =
  92. typeof TextDecoder === "undefined"
  93. ? new (require("util").TextDecoder)("utf-8") // Node.
  94. : new TextDecoder("utf-8"); // Browser.
  95. return decoder.decode(array);
  96. }