From dbd488d3b4e5beff291ddaaea311034dabe9082e Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Fri, 1 Oct 2021 16:03:43 -0700 Subject: [PATCH 1/3] Output function selector as part of ContractFunctionObj --- .../templates/TypeScript/contract.handlebars | 2 + .../output/typescript/abi_gen_dummy.ts | 64 +++++++++++++++++++ .../output/typescript/test_lib_dummy.ts | 4 ++ base-contract/src/types.ts | 1 + 4 files changed, 71 insertions(+) diff --git a/abi-gen/templates/TypeScript/contract.handlebars b/abi-gen/templates/TypeScript/contract.handlebars index 61ff3701a..62f0b2106 100644 --- a/abi-gen/templates/TypeScript/contract.handlebars +++ b/abi-gen/templates/TypeScript/contract.handlebars @@ -296,8 +296,10 @@ export class {{contractName}}Contract extends BaseContract { {{#assertionType name type}}{{/assertionType}} {{/each}} const functionSignature = '{{this.functionSignature}}'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, {{^this.constant}} {{> method_tx}} {{/this.constant}} diff --git a/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts b/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts index 060c1d62d..31526a188 100644 --- a/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts +++ b/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts @@ -981,8 +981,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isArray('a', a); const functionSignature = 'acceptsAnArrayOfBytes(bytes[])'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1007,8 +1009,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isString('a', a); const functionSignature = 'acceptsBytes(bytes)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1045,8 +1049,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'complexInputComplexOutput((uint256,bytes,string))'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, @@ -1098,8 +1104,10 @@ export class AbiGenDummyContract extends BaseContract { assert.isString('r', r); assert.isString('s', s); const functionSignature = 'ecrecoverFn(bytes32,uint8,bytes32,bytes32)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1123,8 +1131,10 @@ export class AbiGenDummyContract extends BaseContract { public emitSimpleEvent(): ContractTxFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'emitSimpleEvent()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async sendTransactionAsync( txData?: Partial | undefined, opts: SendTransactionOpts = { shouldValidate: true }, @@ -1187,8 +1197,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isArray('index_0', index_0); const functionSignature = 'methodAcceptingArrayOfArrayOfStructs((bytes,uint32,bytes[],string)[][])'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1220,8 +1232,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isArray('index_0', index_0); const functionSignature = 'methodAcceptingArrayOfStructs((bytes,uint32,bytes[],string)[])'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1247,8 +1261,10 @@ export class AbiGenDummyContract extends BaseContract { > { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'methodReturningArrayOfStructs()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, @@ -1279,8 +1295,10 @@ export class AbiGenDummyContract extends BaseContract { public methodReturningMultipleValues(): ContractFunctionObj<[BigNumber, string]> { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'methodReturningMultipleValues()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[BigNumber, string]> { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1306,8 +1324,10 @@ export class AbiGenDummyContract extends BaseContract { }> { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'methodUsingNestedStructWithInnerStructNotUsedElsewhere()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, @@ -1344,8 +1364,10 @@ export class AbiGenDummyContract extends BaseContract { assert.isString('index_1', index_1); assert.isString('index_2', index_2); const functionSignature = 'multiInputMultiOutput(uint256,bytes,string)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, @@ -1381,8 +1403,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'nestedStructInput(((bytes,uint32,bytes[],string),string))'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1409,8 +1433,10 @@ export class AbiGenDummyContract extends BaseContract { }> { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'nestedStructOutput()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, @@ -1451,8 +1477,10 @@ export class AbiGenDummyContract extends BaseContract { public noInputNoOutput(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'noInputNoOutput()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1479,8 +1507,10 @@ export class AbiGenDummyContract extends BaseContract { public noInputSimpleOutput(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'noInputSimpleOutput()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1504,8 +1534,10 @@ export class AbiGenDummyContract extends BaseContract { public nonPureMethod(): ContractTxFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'nonPureMethod()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async sendTransactionAsync( txData?: Partial | undefined, opts: SendTransactionOpts = { shouldValidate: true }, @@ -1560,8 +1592,10 @@ export class AbiGenDummyContract extends BaseContract { public nonPureMethodThatReturnsNothing(): ContractTxFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'nonPureMethodThatReturnsNothing()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async sendTransactionAsync( txData?: Partial | undefined, opts: SendTransactionOpts = { shouldValidate: true }, @@ -1617,8 +1651,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isString('a', a); const functionSignature = 'overloadedMethod(string)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1643,8 +1679,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isBigNumber('a', a); const functionSignature = 'overloadedMethod(int256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1668,8 +1706,10 @@ export class AbiGenDummyContract extends BaseContract { public pureFunctionWithConstant(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'pureFunctionWithConstant()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1693,8 +1733,10 @@ export class AbiGenDummyContract extends BaseContract { public requireWithConstant(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'requireWithConstant()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1718,8 +1760,10 @@ export class AbiGenDummyContract extends BaseContract { public revertWithConstant(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'revertWithConstant()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1747,8 +1791,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isBigNumber('index_0', index_0); const functionSignature = 'simpleInputNoOutput(uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1776,8 +1822,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isBigNumber('index_0', index_0); const functionSignature = 'simpleInputSimpleOutput(uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1801,8 +1849,10 @@ export class AbiGenDummyContract extends BaseContract { public simplePureFunction(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'simplePureFunction()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1827,8 +1877,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isBigNumber('x', x); const functionSignature = 'simplePureFunctionWithInput(uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1852,8 +1904,10 @@ export class AbiGenDummyContract extends BaseContract { public simpleRequire(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'simpleRequire()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1877,8 +1931,10 @@ export class AbiGenDummyContract extends BaseContract { public simpleRevert(): ContractFunctionObj { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'simpleRevert()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1908,8 +1964,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'structInput((bytes,uint32,bytes[],string))'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -1942,8 +2000,10 @@ export class AbiGenDummyContract extends BaseContract { }> { const self = (this as any) as AbiGenDummyContract; const functionSignature = 'structOutput()'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, @@ -1986,8 +2046,10 @@ export class AbiGenDummyContract extends BaseContract { assert.isString('y', y); assert.isBigNumber('c', c); const functionSignature = 'withAddressInput(address,uint256,uint256,address,uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -2012,8 +2074,10 @@ export class AbiGenDummyContract extends BaseContract { const self = (this as any) as AbiGenDummyContract; assert.isBigNumber('wad', wad); const functionSignature = 'withdraw(uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async sendTransactionAsync( txData?: Partial | undefined, opts: SendTransactionOpts = { shouldValidate: true }, diff --git a/abi-gen/test-cli/output/typescript/test_lib_dummy.ts b/abi-gen/test-cli/output/typescript/test_lib_dummy.ts index 2991833d2..b96fb31c4 100644 --- a/abi-gen/test-cli/output/typescript/test_lib_dummy.ts +++ b/abi-gen/test-cli/output/typescript/test_lib_dummy.ts @@ -264,8 +264,10 @@ export class TestLibDummyContract extends BaseContract { const self = (this as any) as TestLibDummyContract; assert.isBigNumber('x', x); const functionSignature = 'publicAddConstant(uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; @@ -290,8 +292,10 @@ export class TestLibDummyContract extends BaseContract { const self = (this as any) as TestLibDummyContract; assert.isBigNumber('x', x); const functionSignature = 'publicAddOne(uint256)'; + const selector = self._lookupAbiEncoder(functionSignature).getSelector(); return { + selector, async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); let rawCallResult; diff --git a/base-contract/src/types.ts b/base-contract/src/types.ts index a2857a08e..2f44cc12b 100644 --- a/base-contract/src/types.ts +++ b/base-contract/src/types.ts @@ -48,6 +48,7 @@ export interface AwaitTransactionSuccessOpts extends SendTransactionOpts { } export interface ContractFunctionObj { + selector: string; callAsync(callData?: Partial, defaultBlock?: BlockParam): Promise; getABIEncodedTransactionData(): string; } From 911a065edd63b4a9e279d5a9392c89e08179a06a Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Fri, 1 Oct 2021 16:11:26 -0700 Subject: [PATCH 2/3] add selector unit test --- abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts b/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts index 5dfc7eb50..0d7dc1c15 100644 --- a/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts +++ b/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts @@ -67,6 +67,10 @@ describe('AbiGenDummy Contract', () => { await blockchainLifecycle.revertAsync(); }); describe('simplePureFunction', () => { + it('can get the function selector', () => { + const selector = abiGenDummy.simplePureFunction().selector; + expect(selector).to.equal('0xa3c2f6b6'); + }); it('should call simplePureFunction', async () => { const result = await abiGenDummy.simplePureFunction().callAsync(); expect(result).to.deep.equal(new BigNumber(1)); From 76c4f7b75550e3027e7c8edd163f5a6c025fedc4 Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Mon, 4 Oct 2021 14:53:23 -0700 Subject: [PATCH 3/3] Update changelog --- abi-gen/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/abi-gen/CHANGELOG.json b/abi-gen/CHANGELOG.json index 3b7886ac6..6e44f1f89 100644 --- a/abi-gen/CHANGELOG.json +++ b/abi-gen/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "5.7.0", + "changes": [ + { + "note": "Add selector to ContractFunctionObj", + "pr": 48 + } + ] + }, { "timestamp": 1632416472, "version": "5.6.3",