ts: Add strong type support for `addEventListener` (#2627)
This commit is contained in:
parent
cec9946111
commit
fdda604d41
|
@ -23,6 +23,7 @@ The minor version will be incremented upon a breaking change and the patch versi
|
|||
- ts: Add support for unnamed(tuple) enum in accounts ([#2601](https://github.com/coral-xyz/anchor/pull/2601)).
|
||||
- cli: Add program template with multiple files for instructions, state... ([#2602](https://github.com/coral-xyz/anchor/pull/2602)).
|
||||
- lang: `Box` the inner enums of `anchor_lang::error::Error` to optimize `anchor_lang::Result` ([#2600](https://github.com/coral-xyz/anchor/pull/2600)).
|
||||
- ts: Add strong type support for `Program.addEventListener` method ([#2627](https://github.com/coral-xyz/anchor/pull/2627)).
|
||||
|
||||
### Fixes
|
||||
|
||||
|
|
|
@ -6,4 +6,4 @@ wallet = "~/.config/solana/id.json"
|
|||
events = "2dhGsWUzy5YKUsjZdLHLmkNpUDAXkNa9MYWsPc4Ziqzy"
|
||||
|
||||
[scripts]
|
||||
test = "yarn run mocha -t 1000000 tests/"
|
||||
test = "yarn run ts-mocha -t 1000000 -p ./tsconfig.json tests/**/*.ts"
|
||||
|
|
|
@ -1,68 +1,54 @@
|
|||
const anchor = require("@coral-xyz/anchor");
|
||||
const { assert } = require("chai");
|
||||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { assert } from "chai";
|
||||
|
||||
import { Events } from "../target/types/events";
|
||||
|
||||
describe("Events", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.Events;
|
||||
const program = anchor.workspace.Events as anchor.Program<Events>;
|
||||
|
||||
type Event = anchor.IdlEvents<typeof program["idl"]>;
|
||||
const getEvent = async <E extends keyof Event>(
|
||||
eventName: E,
|
||||
methodName: keyof typeof program["methods"]
|
||||
) => {
|
||||
let listenerId: number;
|
||||
const event = await new Promise<Event[E]>((res) => {
|
||||
listenerId = program.addEventListener(eventName, (event) => {
|
||||
res(event);
|
||||
});
|
||||
program.methods[methodName]().rpc();
|
||||
});
|
||||
await program.removeEventListener(listenerId);
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
describe("Normal event", () => {
|
||||
it("Single event works", async () => {
|
||||
let listener = null;
|
||||
const event = await getEvent("MyEvent", "initialize");
|
||||
|
||||
let [event, slot] = await new Promise((resolve, _reject) => {
|
||||
listener = program.addEventListener("MyEvent", (event, slot) => {
|
||||
resolve([event, slot]);
|
||||
});
|
||||
program.rpc.initialize();
|
||||
});
|
||||
await program.removeEventListener(listener);
|
||||
|
||||
assert.isAbove(slot, 0);
|
||||
assert.strictEqual(event.data.toNumber(), 5);
|
||||
assert.strictEqual(event.label, "hello");
|
||||
});
|
||||
|
||||
it("Multiple events work", async () => {
|
||||
let listenerOne = null;
|
||||
let listenerTwo = null;
|
||||
const eventOne = await getEvent("MyEvent", "initialize");
|
||||
const eventTwo = await getEvent("MyOtherEvent", "testEvent");
|
||||
|
||||
let [eventOne, slotOne] = await new Promise((resolve, _reject) => {
|
||||
listenerOne = program.addEventListener("MyEvent", (event, slot) => {
|
||||
resolve([event, slot]);
|
||||
});
|
||||
program.rpc.initialize();
|
||||
});
|
||||
|
||||
let [eventTwo, slotTwo] = await new Promise((resolve, _reject) => {
|
||||
listenerTwo = program.addEventListener(
|
||||
"MyOtherEvent",
|
||||
(event, slot) => {
|
||||
resolve([event, slot]);
|
||||
}
|
||||
);
|
||||
program.rpc.testEvent();
|
||||
});
|
||||
|
||||
await program.removeEventListener(listenerOne);
|
||||
await program.removeEventListener(listenerTwo);
|
||||
|
||||
assert.isAbove(slotOne, 0);
|
||||
assert.strictEqual(eventOne.data.toNumber(), 5);
|
||||
assert.strictEqual(eventOne.label, "hello");
|
||||
|
||||
assert.isAbove(slotTwo, 0);
|
||||
assert.strictEqual(eventTwo.data.toNumber(), 6);
|
||||
assert.strictEqual(eventTwo.label, "bye");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Self-CPI event", () => {
|
||||
describe("CPI event", () => {
|
||||
it("Works without accounts being specified", async () => {
|
||||
const tx = await program.methods.testEventCpi().transaction();
|
||||
const config = {
|
||||
commitment: "confirmed",
|
||||
};
|
||||
const config = { commitment: "confirmed" } as const;
|
||||
const txHash = await program.provider.sendAndConfirm(tx, [], config);
|
||||
const txResult = await program.provider.connection.getTransaction(
|
||||
txHash,
|
||||
|
@ -77,10 +63,10 @@ describe("Events", () => {
|
|||
|
||||
assert.strictEqual(event.name, "MyOtherEvent");
|
||||
assert.strictEqual(event.data.label, "cpi");
|
||||
assert.strictEqual(event.data.data.toNumber(), 7);
|
||||
assert.strictEqual((event.data.data as anchor.BN).toNumber(), 7);
|
||||
});
|
||||
|
||||
it("Malicious invocation throws", async () => {
|
||||
it("Throws on unauthorized invocation", async () => {
|
||||
const tx = new anchor.web3.Transaction();
|
||||
tx.add(
|
||||
new anchor.web3.TransactionInstruction({
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"types": ["mocha", "chai"],
|
||||
"lib": ["es2015"],
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import NamespaceFactory, {
|
|||
SimulateNamespace,
|
||||
MethodsNamespace,
|
||||
ViewNamespace,
|
||||
IdlEvents,
|
||||
} from "./namespace/index.js";
|
||||
import { utf8 } from "../utils/bytes/index.js";
|
||||
import { EventManager } from "./event.js";
|
||||
|
@ -357,9 +358,13 @@ export class Program<IDL extends Idl = Idl> {
|
|||
* @param callback The function to invoke whenever the event is emitted from
|
||||
* program logs.
|
||||
*/
|
||||
public addEventListener(
|
||||
eventName: string,
|
||||
callback: (event: any, slot: number, signature: string) => void
|
||||
public addEventListener<E extends keyof IdlEvents<IDL>>(
|
||||
eventName: E,
|
||||
callback: (
|
||||
event: IdlEvents<IDL>[E],
|
||||
slot: number,
|
||||
signature: string
|
||||
) => void
|
||||
): number {
|
||||
return this._events.addEventListener(eventName, callback);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue