From e04367e78568998ff85696b61a49373681d8c8bb Mon Sep 17 00:00:00 2001 From: farwayer Date: Wed, 15 Mar 2023 01:32:48 +0100 Subject: [PATCH] contract/interface: add `hasEvent` and `hasFunction` methods, `has` trap to contract and filters proxy --- src.ts/_tests/test-contract.ts | 26 ++++++++++++++++++++++++++ src.ts/abi/interface.ts | 16 ++++++++++++++++ src.ts/contract/contract.ts | 22 ++++++++++++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src.ts/_tests/test-contract.ts b/src.ts/_tests/test-contract.ts index 6f894abe1d..0abe305665 100644 --- a/src.ts/_tests/test-contract.ts +++ b/src.ts/_tests/test-contract.ts @@ -177,6 +177,32 @@ describe("Test Contract", function() { await specificEvent; await allEvents; }); + + it("tests hasFunction", async function() { + const contract = new Contract(addr, abi); + + assert.equal(contract.hasFunction('testCallAdd'), true); + assert.equal(contract.hasFunction('notExistFn'), false); + assert.equal(contract.hasFunction('function testCallAdd(uint256 a, uint256 b) pure returns (uint256 result)'), true); + assert.equal(contract.hasFunction('function testCallAdd(uint256 a) pure returns (uint256 result)'), false); + assert('testCallAdd' in contract); + assert(!('notExistFn' in contract)); + assert('function testCallAdd(uint256 a, uint256 b) pure returns (uint256 result)' in contract); + assert(!('function testCallAdd(uint256 a) pure returns (uint256 result)' in contract)); + }); + + it("tests hasEvent", async function() { + const contract = new Contract(addr, abi); + + assert.equal(contract.hasEvent('EventUint256'), true); + assert.equal(contract.hasEvent('NotExistEvent'), false); + assert.equal(contract.hasEvent('event EventUint256(uint256 indexed value)'), true); + assert.equal(contract.hasEvent('event EventUint256()'), false); + assert('EventUint256' in contract.filters); + assert(!('NotExistEvent' in contract.filters)); + assert('event EventUint256(uint256 indexed value)' in contract.filters); + assert(!('event EventUint256()' in contract.filters)); + }); }); describe("Test Typed Contract Interaction", function() { diff --git a/src.ts/abi/interface.ts b/src.ts/abi/interface.ts index f266e9f253..dce8d55f52 100644 --- a/src.ts/abi/interface.ts +++ b/src.ts/abi/interface.ts @@ -407,6 +407,14 @@ export class Interface { return null; } + /** + * Check if interface has function %%key%%, which may be a function + * selector, function name or function signature that belongs to the ABI. + */ + hasFunction(key: string): boolean { + return !!this.#getFunction(key, null, false); + } + /** * Get the function name for %%key%%, which may be a function selector, * function name or function signature that belongs to the ABI. @@ -504,6 +512,14 @@ export class Interface { return null; } + /** + * Check if interface has event %%key%%, which may be a topic hash, + * event name or event signature that belongs to the ABI. + */ + hasEvent(key: string): boolean { + return !!this.#getEvent(key, null, false); + } + /** * Get the event name for %%key%%, which may be a topic hash, * event name or event signature that belongs to the ABI. diff --git a/src.ts/contract/contract.ts b/src.ts/contract/contract.ts index 627e61ad8e..3dc872a69b 100644 --- a/src.ts/contract/contract.ts +++ b/src.ts/contract/contract.ts @@ -685,7 +685,11 @@ export class BaseContract implements Addressable, EventEmitterable ( + Reflect.has(target, _prop) || + this.hasEvent(String(_prop)) + ), }); defineProperties(this, { filters }); @@ -706,7 +710,11 @@ export class BaseContract implements Addressable, EventEmitterable ( + Reflect.has(target, _prop) || + this.hasFunction(String(_prop)) + ), }); } @@ -762,11 +770,21 @@ export class BaseContract implements Addressable, EventEmitterable(key: string | FunctionFragment): T { if (typeof(key) !== "string") { key = key.format(); } return (new WrappedMethod(this, key)); } + hasEvent(key: string | EventFragment): boolean { + if (typeof(key) !== "string") { key = key.format(); } + return this.interface.hasEvent(key); + } + getEvent(key: string | EventFragment): ContractEvent { if (typeof(key) !== "string") { key = key.format(); } return (new WrappedEvent(this, key));