events.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import * as anchor from "@coral-xyz/anchor";
  2. import { assert } from "chai";
  3. import { Events } from "../target/types/events";
  4. describe("Events", () => {
  5. // Configure the client to use the local cluster.
  6. anchor.setProvider(anchor.AnchorProvider.env());
  7. const program = anchor.workspace.Events as anchor.Program<Events>;
  8. type Event = anchor.IdlEvents<typeof program["idl"]>;
  9. const getEvent = async <E extends keyof Event>(
  10. eventName: E,
  11. methodName: keyof typeof program["methods"]
  12. ) => {
  13. let listenerId: number;
  14. const event = await new Promise<Event[E]>((res) => {
  15. listenerId = program.addEventListener(eventName, (event) => {
  16. res(event);
  17. });
  18. program.methods[methodName]().rpc();
  19. });
  20. await program.removeEventListener(listenerId);
  21. return event;
  22. };
  23. describe("Normal event", () => {
  24. it("Single event works", async () => {
  25. const event = await getEvent("myEvent", "initialize");
  26. assert.strictEqual(event.data.toNumber(), 5);
  27. assert.strictEqual(event.label, "hello");
  28. });
  29. it("Multiple events work", async () => {
  30. const eventOne = await getEvent("myEvent", "initialize");
  31. const eventTwo = await getEvent("myOtherEvent", "testEvent");
  32. assert.strictEqual(eventOne.data.toNumber(), 5);
  33. assert.strictEqual(eventOne.label, "hello");
  34. assert.strictEqual(eventTwo.data.toNumber(), 6);
  35. assert.strictEqual(eventTwo.label, "bye");
  36. });
  37. });
  38. describe("CPI event", () => {
  39. it("Works without accounts being specified", async () => {
  40. const tx = await program.methods.testEventCpi().transaction();
  41. const config = { commitment: "confirmed" } as const;
  42. const txHash = await program.provider.sendAndConfirm(tx, [], config);
  43. const txResult = await program.provider.connection.getTransaction(
  44. txHash,
  45. config
  46. );
  47. const ixData = anchor.utils.bytes.bs58.decode(
  48. txResult.meta.innerInstructions[0].instructions[0].data
  49. );
  50. const eventData = anchor.utils.bytes.base64.encode(ixData.slice(8));
  51. const event = program.coder.events.decode(eventData);
  52. assert.strictEqual(event.name, "myOtherEvent");
  53. assert.strictEqual(event.data.label, "cpi");
  54. assert.strictEqual((event.data.data as anchor.BN).toNumber(), 7);
  55. });
  56. it("Throws on unauthorized invocation", async () => {
  57. const tx = new anchor.web3.Transaction();
  58. tx.add(
  59. new anchor.web3.TransactionInstruction({
  60. programId: program.programId,
  61. keys: [
  62. {
  63. pubkey: anchor.web3.PublicKey.findProgramAddressSync(
  64. [Buffer.from("__event_authority")],
  65. program.programId
  66. )[0],
  67. isSigner: false,
  68. isWritable: false,
  69. },
  70. {
  71. pubkey: program.programId,
  72. isSigner: false,
  73. isWritable: false,
  74. },
  75. ],
  76. data: Buffer.from([0xe4, 0x45, 0xa5, 0x2e, 0x51, 0xcb, 0x9a, 0x1d]),
  77. })
  78. );
  79. try {
  80. await program.provider.sendAndConfirm(tx, []);
  81. } catch (e) {
  82. if (e.logs.some((log) => log.includes("ConstraintSigner"))) return;
  83. console.log(e);
  84. }
  85. throw new Error("Was able to invoke the self-CPI instruction");
  86. });
  87. });
  88. });