events.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. const anchor = require("@coral-xyz/anchor");
  2. const { assert } = require("chai");
  3. describe("Events", () => {
  4. // Configure the client to use the local cluster.
  5. anchor.setProvider(anchor.AnchorProvider.env());
  6. const program = anchor.workspace.Events;
  7. describe("Normal event", () => {
  8. it("Single event works", async () => {
  9. let listener = null;
  10. let [event, slot] = await new Promise((resolve, _reject) => {
  11. listener = program.addEventListener("MyEvent", (event, slot) => {
  12. resolve([event, slot]);
  13. });
  14. program.rpc.initialize();
  15. });
  16. await program.removeEventListener(listener);
  17. assert.isAbove(slot, 0);
  18. assert.strictEqual(event.data.toNumber(), 5);
  19. assert.strictEqual(event.label, "hello");
  20. });
  21. it("Multiple events work", async () => {
  22. let listenerOne = null;
  23. let listenerTwo = null;
  24. let [eventOne, slotOne] = await new Promise((resolve, _reject) => {
  25. listenerOne = program.addEventListener("MyEvent", (event, slot) => {
  26. resolve([event, slot]);
  27. });
  28. program.rpc.initialize();
  29. });
  30. let [eventTwo, slotTwo] = await new Promise((resolve, _reject) => {
  31. listenerTwo = program.addEventListener(
  32. "MyOtherEvent",
  33. (event, slot) => {
  34. resolve([event, slot]);
  35. }
  36. );
  37. program.rpc.testEvent();
  38. });
  39. await program.removeEventListener(listenerOne);
  40. await program.removeEventListener(listenerTwo);
  41. assert.isAbove(slotOne, 0);
  42. assert.strictEqual(eventOne.data.toNumber(), 5);
  43. assert.strictEqual(eventOne.label, "hello");
  44. assert.isAbove(slotTwo, 0);
  45. assert.strictEqual(eventTwo.data.toNumber(), 6);
  46. assert.strictEqual(eventTwo.label, "bye");
  47. });
  48. });
  49. describe("Self-CPI event", () => {
  50. it("Works without accounts being specified", async () => {
  51. const tx = await program.methods.testEventCpi().transaction();
  52. const config = {
  53. commitment: "confirmed",
  54. };
  55. const txHash = await program.provider.sendAndConfirm(tx, [], config);
  56. const txResult = await program.provider.connection.getTransaction(
  57. txHash,
  58. config
  59. );
  60. const ixData = anchor.utils.bytes.bs58.decode(
  61. txResult.meta.innerInstructions[0].instructions[0].data
  62. );
  63. const eventData = anchor.utils.bytes.base64.encode(ixData.slice(8));
  64. const event = program.coder.events.decode(eventData);
  65. assert.strictEqual(event.name, "MyOtherEvent");
  66. assert.strictEqual(event.data.label, "cpi");
  67. assert.strictEqual(event.data.data.toNumber(), 7);
  68. });
  69. it("Malicious invocation throws", async () => {
  70. const tx = new anchor.web3.Transaction();
  71. tx.add(
  72. new anchor.web3.TransactionInstruction({
  73. programId: program.programId,
  74. keys: [
  75. {
  76. pubkey: anchor.web3.PublicKey.findProgramAddressSync(
  77. [Buffer.from("__event_authority")],
  78. program.programId
  79. )[0],
  80. isSigner: false,
  81. isWritable: false,
  82. },
  83. {
  84. pubkey: program.programId,
  85. isSigner: false,
  86. isWritable: false,
  87. },
  88. ],
  89. data: Buffer.from([0xe4, 0x45, 0xa5, 0x2e, 0x51, 0xcb, 0x9a, 0x1d]),
  90. })
  91. );
  92. try {
  93. await program.provider.sendAndConfirm(tx, []);
  94. } catch (e) {
  95. if (e.logs.some((log) => log.includes("ConstraintSigner"))) return;
  96. console.log(e);
  97. }
  98. throw new Error("Was able to invoke the self-CPI instruction");
  99. });
  100. });
  101. });