From 1ed7098e8e338b70514ec80fb38f4da7e85d4702 Mon Sep 17 00:00:00 2001 From: Mattia Monari Date: Fri, 3 Mar 2023 11:55:04 +0100 Subject: [PATCH 1/6] Add a check on the duplicated event names #1781 --- .../codegen/SolidityFunctionWrapper.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java index a4d20b73d..8d328e2d9 100644 --- a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java +++ b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java @@ -423,6 +423,7 @@ private List buildFunctionDefinitions( throws ClassNotFoundException { Set duplicateFunctionNames = getDuplicateFunctionNames(functionDefinitions); + changeEventsName(functionDefinitions); List methodSpecs = new ArrayList<>(); for (AbiDefinition functionDefinition : functionDefinitions) { if (functionDefinition.getType().equals(TYPE_FUNCTION)) { @@ -436,6 +437,25 @@ private List buildFunctionDefinitions( return methodSpecs; } + private void changeEventsName(List functionDefinitions) { + + Map countMap = new HashMap<>(); + + for (AbiDefinition functionDefinition : functionDefinitions) { + if (TYPE_EVENT.equals(functionDefinition.getType()) + && functionDefinition.getName() != null) { + String s = functionDefinition.getName(); + if (countMap.containsKey(s)) { + int count = countMap.get(s); + functionDefinition.setName(s + count); + countMap.put(s, count + 1); + } else { + countMap.put(s, 1); + } + } + } + } + private List buildStructTypes(final List functionDefinitions) throws ClassNotFoundException { final List orderedKeys = extractStructs(functionDefinitions); @@ -723,6 +743,7 @@ Iterable buildFuncNameConstants(List functionDefinitio Set fieldNames = new HashSet<>(); fieldNames.add(Contract.FUNC_DEPLOY); Set duplicateFunctionNames = getDuplicateFunctionNames(functionDefinitions); + changeEventsName(functionDefinitions); if (!duplicateFunctionNames.isEmpty()) { System.out.println( "\nWarning: Duplicate field(s) found: " From 40b76a87c393474d88c8d7bc590fa1d2ace0b8df Mon Sep 17 00:00:00 2001 From: Mattia Monari Date: Fri, 3 Mar 2023 15:35:43 +0100 Subject: [PATCH 2/6] Rename changeDuplicateEventsName, replace stream to for loop --- .../codegen/SolidityFunctionWrapper.java | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java index 8d328e2d9..d56d84fef 100644 --- a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java +++ b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java @@ -416,14 +416,14 @@ private String buildEventDefinitionName(String eventName) { return eventName.toUpperCase() + "_EVENT"; } - private List buildFunctionDefinitions( + List buildFunctionDefinitions( String className, TypeSpec.Builder classBuilder, List functionDefinitions) throws ClassNotFoundException { Set duplicateFunctionNames = getDuplicateFunctionNames(functionDefinitions); - changeEventsName(functionDefinitions); + changeDuplicateEventsName(functionDefinitions); List methodSpecs = new ArrayList<>(); for (AbiDefinition functionDefinition : functionDefinitions) { if (functionDefinition.getType().equals(TYPE_FUNCTION)) { @@ -437,23 +437,25 @@ private List buildFunctionDefinitions( return methodSpecs; } - private void changeEventsName(List functionDefinitions) { + private void changeDuplicateEventsName(List functionDefinitions) { Map countMap = new HashMap<>(); - for (AbiDefinition functionDefinition : functionDefinitions) { - if (TYPE_EVENT.equals(functionDefinition.getType()) - && functionDefinition.getName() != null) { - String s = functionDefinition.getName(); - if (countMap.containsKey(s)) { - int count = countMap.get(s); - functionDefinition.setName(s + count); - countMap.put(s, count + 1); - } else { - countMap.put(s, 1); - } - } - } + functionDefinitions.stream() + .filter( + function -> + TYPE_EVENT.equals(function.getType()) && function.getName() != null) + .forEach( + function -> { + String functionName = function.getName(); + if (countMap.containsKey(functionName)) { + int count = countMap.get(functionName); + function.setName(functionName + count); + countMap.put(functionName, count + 1); + } else { + countMap.put(functionName, 1); + } + }); } private List buildStructTypes(final List functionDefinitions) @@ -743,7 +745,6 @@ Iterable buildFuncNameConstants(List functionDefinitio Set fieldNames = new HashSet<>(); fieldNames.add(Contract.FUNC_DEPLOY); Set duplicateFunctionNames = getDuplicateFunctionNames(functionDefinitions); - changeEventsName(functionDefinitions); if (!duplicateFunctionNames.isEmpty()) { System.out.println( "\nWarning: Duplicate field(s) found: " From c04218b1a1ed7a25b351240010feebde746ac71b Mon Sep 17 00:00:00 2001 From: Mattia Monari Date: Fri, 3 Mar 2023 15:36:33 +0100 Subject: [PATCH 3/6] Add testing unit for the duplicated events --- .../codegen/SolidityFunctionWrapperTest.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java index 257a51f04..59b6d5bbb 100644 --- a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java +++ b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java @@ -902,6 +902,124 @@ public void testBuildFuncNameConstants() throws Exception { assertEquals(builder.build().toString(), (expected)); } + @Test + public void testBuildFunctionDuplicatedEventNames() throws Exception { + + AbiDefinition firstEventDefinition = + new AbiDefinition( + false, + Arrays.asList(new NamedType("action", "string", false), new NamedType("pauseState", "bool", false)), + "eventName", + Collections.emptyList(), + "event", + false); + AbiDefinition secondEventDefinition = + new AbiDefinition( + false, + Arrays.asList(new NamedType("cToken", "address", false), new NamedType("action", "string", false), new NamedType("pauseState", "bool", false)), + "eventName", + Collections.emptyList(), + "event", + false); + TypeSpec.Builder builder = TypeSpec.classBuilder("testClass"); + builder.addMethods(solidityFunctionWrapper.buildFunctionDefinitions("testClass", builder, Arrays.asList(firstEventDefinition, secondEventDefinition))); + + String expected = + "class testClass {\n" + + " public static final org.web3j.abi.datatypes.Event EVENTNAME_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" + + " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + + " ;\n" + + "\n" + + " public static final org.web3j.abi.datatypes.Event EVENTNAME1_EVENT = new org.web3j.abi.datatypes.Event(\"eventName1\", \n" + + " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + + " ;\n" + + "\n" + + " public static java.util.List getEventNameEvents(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME_EVENT, transactionReceipt);\n" + + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + + " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + + " typedResponse.log = eventValues.getLog();\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " responses.add(typedResponse);\n" + + " }\n" + + " return responses;\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + + " @java.lang.Override\n" + + " public EventNameEventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME_EVENT, log);\n" + + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + + " typedResponse.log = log;\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " return typedResponse;\n" + + " }\n" + + " });\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + + " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" + + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME_EVENT));\n" + + " return eventNameEventFlowable(filter);\n" + + " }\n" + + "\n" + + " public static java.util.List getEventName1Events(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, transactionReceipt);\n" + + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + + " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + + " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + + " typedResponse.log = eventValues.getLog();\n" + + " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" + + " responses.add(typedResponse);\n" + + " }\n" + + " return responses;\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + + " @java.lang.Override\n" + + " public EventName1EventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME1_EVENT, log);\n" + + " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + + " typedResponse.log = log;\n" + + " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" + + " return typedResponse;\n" + + " }\n" + + " });\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + + " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" + + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME1_EVENT));\n" + + " return eventName1EventFlowable(filter);\n" + + " }\n" + + "\n" + + " public static class EventNameEventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + + " public java.lang.String action;\n" + + "\n" + + " public java.lang.Boolean pauseState;\n" + + " }\n" + + "\n" + + " public static class EventName1EventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + + " public java.lang.String cToken;\n" + + "\n" + + " public java.lang.String action;\n" + + "\n" + + " public java.lang.Boolean pauseState;\n" + + " }\n" + + "}\n"; + + assertEquals(builder.build().toString(), (expected)); + } + @Test public void testBuildFunctionTransactionAndCall() throws Exception { AbiDefinition functionDefinition = From 2cce3dde02721c2c19152e1eca9ff93ba5ad757c Mon Sep 17 00:00:00 2001 From: Mattia Monari Date: Fri, 3 Mar 2023 15:39:23 +0100 Subject: [PATCH 4/6] Apply spotless formatting --- .../codegen/SolidityFunctionWrapperTest.java | 197 +++++++++--------- 1 file changed, 103 insertions(+), 94 deletions(-) diff --git a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java index 59b6d5bbb..5bcc4d4df 100644 --- a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java +++ b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java @@ -908,7 +908,9 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { AbiDefinition firstEventDefinition = new AbiDefinition( false, - Arrays.asList(new NamedType("action", "string", false), new NamedType("pauseState", "bool", false)), + Arrays.asList( + new NamedType("action", "string", false), + new NamedType("pauseState", "bool", false)), "eventName", Collections.emptyList(), "event", @@ -916,106 +918,113 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { AbiDefinition secondEventDefinition = new AbiDefinition( false, - Arrays.asList(new NamedType("cToken", "address", false), new NamedType("action", "string", false), new NamedType("pauseState", "bool", false)), + Arrays.asList( + new NamedType("cToken", "address", false), + new NamedType("action", "string", false), + new NamedType("pauseState", "bool", false)), "eventName", Collections.emptyList(), "event", false); TypeSpec.Builder builder = TypeSpec.classBuilder("testClass"); - builder.addMethods(solidityFunctionWrapper.buildFunctionDefinitions("testClass", builder, Arrays.asList(firstEventDefinition, secondEventDefinition))); + builder.addMethods( + solidityFunctionWrapper.buildFunctionDefinitions( + "testClass", + builder, + Arrays.asList(firstEventDefinition, secondEventDefinition))); String expected = - "class testClass {\n" + - " public static final org.web3j.abi.datatypes.Event EVENTNAME_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" + - " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + - " ;\n" + - "\n" + - " public static final org.web3j.abi.datatypes.Event EVENTNAME1_EVENT = new org.web3j.abi.datatypes.Event(\"eventName1\", \n" + - " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + - " ;\n" + - "\n" + - " public static java.util.List getEventNameEvents(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + - " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME_EVENT, transactionReceipt);\n" + - " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + - " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + - " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + - " typedResponse.log = eventValues.getLog();\n" + - " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + - " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(1).getValue();\n" + - " responses.add(typedResponse);\n" + - " }\n" + - " return responses;\n" + - " }\n" + - "\n" + - " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + - " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + - " @java.lang.Override\n" + - " public EventNameEventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + - " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME_EVENT, log);\n" + - " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + - " typedResponse.log = log;\n" + - " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + - " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(1).getValue();\n" + - " return typedResponse;\n" + - " }\n" + - " });\n" + - " }\n" + - "\n" + - " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + - " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" + - " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME_EVENT));\n" + - " return eventNameEventFlowable(filter);\n" + - " }\n" + - "\n" + - " public static java.util.List getEventName1Events(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + - " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, transactionReceipt);\n" + - " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + - " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + - " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + - " typedResponse.log = eventValues.getLog();\n" + - " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + - " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" + - " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" + - " responses.add(typedResponse);\n" + - " }\n" + - " return responses;\n" + - " }\n" + - "\n" + - " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + - " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + - " @java.lang.Override\n" + - " public EventName1EventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + - " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME1_EVENT, log);\n" + - " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + - " typedResponse.log = log;\n" + - " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + - " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" + - " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" + - " return typedResponse;\n" + - " }\n" + - " });\n" + - " }\n" + - "\n" + - " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + - " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" + - " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME1_EVENT));\n" + - " return eventName1EventFlowable(filter);\n" + - " }\n" + - "\n" + - " public static class EventNameEventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + - " public java.lang.String action;\n" + - "\n" + - " public java.lang.Boolean pauseState;\n" + - " }\n" + - "\n" + - " public static class EventName1EventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + - " public java.lang.String cToken;\n" + - "\n" + - " public java.lang.String action;\n" + - "\n" + - " public java.lang.Boolean pauseState;\n" + - " }\n" + - "}\n"; + "class testClass {\n" + + " public static final org.web3j.abi.datatypes.Event EVENTNAME_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" + + " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + + " ;\n" + + "\n" + + " public static final org.web3j.abi.datatypes.Event EVENTNAME1_EVENT = new org.web3j.abi.datatypes.Event(\"eventName1\", \n" + + " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + + " ;\n" + + "\n" + + " public static java.util.List getEventNameEvents(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME_EVENT, transactionReceipt);\n" + + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + + " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + + " typedResponse.log = eventValues.getLog();\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " responses.add(typedResponse);\n" + + " }\n" + + " return responses;\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + + " @java.lang.Override\n" + + " public EventNameEventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME_EVENT, log);\n" + + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + + " typedResponse.log = log;\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " return typedResponse;\n" + + " }\n" + + " });\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + + " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" + + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME_EVENT));\n" + + " return eventNameEventFlowable(filter);\n" + + " }\n" + + "\n" + + " public static java.util.List getEventName1Events(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, transactionReceipt);\n" + + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + + " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + + " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + + " typedResponse.log = eventValues.getLog();\n" + + " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" + + " responses.add(typedResponse);\n" + + " }\n" + + " return responses;\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + + " @java.lang.Override\n" + + " public EventName1EventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME1_EVENT, log);\n" + + " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + + " typedResponse.log = log;\n" + + " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" + + " typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" + + " return typedResponse;\n" + + " }\n" + + " });\n" + + " }\n" + + "\n" + + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + + " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" + + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME1_EVENT));\n" + + " return eventName1EventFlowable(filter);\n" + + " }\n" + + "\n" + + " public static class EventNameEventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + + " public java.lang.String action;\n" + + "\n" + + " public java.lang.Boolean pauseState;\n" + + " }\n" + + "\n" + + " public static class EventName1EventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + + " public java.lang.String cToken;\n" + + "\n" + + " public java.lang.String action;\n" + + "\n" + + " public java.lang.Boolean pauseState;\n" + + " }\n" + + "}\n"; assertEquals(builder.build().toString(), (expected)); } From e7ec19b72c9769d3a6de4515b8fbd2b56b9331fe Mon Sep 17 00:00:00 2001 From: Mattia Monari Date: Wed, 22 Mar 2023 11:40:00 +0100 Subject: [PATCH 5/6] Change handling of duplicate event names --- .../codegen/SolidityFunctionWrapper.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java index d56d84fef..acefa0d92 100644 --- a/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java +++ b/codegen/src/main/java/org/web3j/codegen/SolidityFunctionWrapper.java @@ -402,9 +402,19 @@ private FieldSpec createBinaryDefinition(String binary) { .build(); } - private FieldSpec createEventDefinition(String name, List parameters) { + private FieldSpec createEventDefinition( + String name, + List parameters, + Map eventsCount, + AbiDefinition event) { CodeBlock initializer = buildVariableLengthEventInitializer(name, parameters); + Integer occurrences = eventsCount.get(name); + if (occurrences > 1) { + event.setName(name + (occurrences - 1)); + eventsCount.replace(name, occurrences - 1); + name = event.getName(); + } return FieldSpec.builder(Event.class, buildEventDefinitionName(name)) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) @@ -423,7 +433,7 @@ List buildFunctionDefinitions( throws ClassNotFoundException { Set duplicateFunctionNames = getDuplicateFunctionNames(functionDefinitions); - changeDuplicateEventsName(functionDefinitions); + Map eventsCount = getDuplicatedEventNames(functionDefinitions); List methodSpecs = new ArrayList<>(); for (AbiDefinition functionDefinition : functionDefinitions) { if (functionDefinition.getType().equals(TYPE_FUNCTION)) { @@ -431,13 +441,14 @@ List buildFunctionDefinitions( boolean useUpperCase = !duplicateFunctionNames.contains(functionName); methodSpecs.addAll(buildFunctions(functionDefinition, useUpperCase)); } else if (functionDefinition.getType().equals(TYPE_EVENT)) { - methodSpecs.addAll(buildEventFunctions(functionDefinition, classBuilder)); + methodSpecs.addAll( + buildEventFunctions(functionDefinition, classBuilder, eventsCount)); } } return methodSpecs; } - private void changeDuplicateEventsName(List functionDefinitions) { + Map getDuplicatedEventNames(List functionDefinitions) { Map countMap = new HashMap<>(); @@ -450,12 +461,13 @@ private void changeDuplicateEventsName(List functionDefinitions) String functionName = function.getName(); if (countMap.containsKey(functionName)) { int count = countMap.get(functionName); - function.setName(functionName + count); countMap.put(functionName, count + 1); } else { countMap.put(functionName, 1); } }); + + return countMap; } private List buildStructTypes(final List functionDefinitions) @@ -1836,7 +1848,9 @@ MethodSpec buildEventTransactionReceiptFunction( } List buildEventFunctions( - AbiDefinition functionDefinition, TypeSpec.Builder classBuilder) + AbiDefinition functionDefinition, + TypeSpec.Builder classBuilder, + Map eventsCount) throws ClassNotFoundException { String functionName = functionDefinition.getName(); List inputs = functionDefinition.getInputs(); @@ -1865,7 +1879,10 @@ List buildEventFunctions( parameters.add(parameter); } - classBuilder.addField(createEventDefinition(functionName, parameters)); + classBuilder.addField( + createEventDefinition(functionName, parameters, eventsCount, functionDefinition)); + + functionName = functionDefinition.getName(); classBuilder.addType( buildEventResponseObject( From de224fd7b59611b447b305aa036535e4e49e349b Mon Sep 17 00:00:00 2001 From: Mattia Monari Date: Wed, 22 Mar 2023 11:40:28 +0100 Subject: [PATCH 6/6] Update the unit test for duplicate event names --- .../codegen/SolidityFunctionWrapperTest.java | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java index 5bcc4d4df..1426f582f 100644 --- a/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java +++ b/codegen/src/test/java/org/web3j/codegen/SolidityFunctionWrapperTest.java @@ -673,7 +673,11 @@ public void testBuildEventConstantMultipleValueReturn() throws Exception { TypeSpec.Builder builder = TypeSpec.classBuilder("testClass"); builder.addMethods( - solidityFunctionWrapper.buildEventFunctions(functionDefinition, builder)); + solidityFunctionWrapper.buildEventFunctions( + functionDefinition, + builder, + solidityFunctionWrapper.getDuplicatedEventNames( + Collections.singletonList(functionDefinition)))); String expected = "class testClass {\n" @@ -757,7 +761,11 @@ public void testBuildEventWithNamedAndNoNamedParameters() throws Exception { TypeSpec.Builder builder = TypeSpec.classBuilder("testClass"); builder.addMethods( - solidityFunctionWrapper.buildEventFunctions(functionDefinition, builder)); + solidityFunctionWrapper.buildEventFunctions( + functionDefinition, + builder, + solidityFunctionWrapper.getDuplicatedEventNames( + Collections.singletonList(functionDefinition)))); String expected = "class testClass {\n" @@ -833,7 +841,11 @@ public void testBuildEventWithNativeList() throws Exception { TypeSpec.Builder builder = TypeSpec.classBuilder("testClass"); builder.addMethods( - solidityFunctionWrapper.buildEventFunctions(functionDefinition, builder)); + solidityFunctionWrapper.buildEventFunctions( + functionDefinition, + builder, + solidityFunctionWrapper.getDuplicatedEventNames( + Collections.singletonList(functionDefinition)))); String expected = "class testClass {\n" @@ -935,16 +947,16 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { String expected = "class testClass {\n" - + " public static final org.web3j.abi.datatypes.Event EVENTNAME_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" + + " public static final org.web3j.abi.datatypes.Event EVENTNAME1_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" + " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + " ;\n" + "\n" - + " public static final org.web3j.abi.datatypes.Event EVENTNAME1_EVENT = new org.web3j.abi.datatypes.Event(\"eventName1\", \n" + + " public static final org.web3j.abi.datatypes.Event EVENTNAME_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" + " java.util.Arrays.>asList(new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}, new org.web3j.abi.TypeReference() {}));\n" + " ;\n" + "\n" - + " public static java.util.List getEventNameEvents(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" - + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME_EVENT, transactionReceipt);\n" + + " public static java.util.List getEventName1Events(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, transactionReceipt);\n" + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" @@ -956,11 +968,11 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { + " return responses;\n" + " }\n" + "\n" - + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + " @java.lang.Override\n" + " public EventNameEventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" - + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME_EVENT, log);\n" + + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME1_EVENT, log);\n" + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + " typedResponse.log = log;\n" + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" @@ -970,17 +982,17 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { + " });\n" + " }\n" + "\n" - + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" - + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME_EVENT));\n" - + " return eventNameEventFlowable(filter);\n" + + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME1_EVENT));\n" + + " return eventName1EventFlowable(filter);\n" + " }\n" + "\n" - + " public static java.util.List getEventName1Events(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" - + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, transactionReceipt);\n" - + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + + " public static java.util.List getEventNameEvents(org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" + + " java.util.List valueList = staticExtractEventParametersWithLog(EVENTNAME_EVENT, transactionReceipt);\n" + + " java.util.ArrayList responses = new java.util.ArrayList(valueList.size());\n" + " for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" - + " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + " typedResponse.log = eventValues.getLog();\n" + " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" @@ -990,12 +1002,12 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { + " return responses;\n" + " }\n" + "\n" - + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" - + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.methods.request.EthFilter filter) {\n" + + " return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function() {\n" + " @java.lang.Override\n" - + " public EventName1EventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" - + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME1_EVENT, log);\n" - + " EventName1EventResponse typedResponse = new EventName1EventResponse();\n" + + " public EventNameEventResponse apply(org.web3j.protocol.core.methods.response.Log log) {\n" + + " org.web3j.tx.Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(EVENTNAME_EVENT, log);\n" + + " EventNameEventResponse typedResponse = new EventNameEventResponse();\n" + " typedResponse.log = log;\n" + " typedResponse.cToken = (java.lang.String) eventValues.getNonIndexedValues().get(0).getValue();\n" + " typedResponse.action = (java.lang.String) eventValues.getNonIndexedValues().get(1).getValue();\n" @@ -1005,10 +1017,10 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { + " });\n" + " }\n" + "\n" - + " public io.reactivex.Flowable eventName1EventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + + " public io.reactivex.Flowable eventNameEventFlowable(org.web3j.protocol.core.DefaultBlockParameter startBlock, org.web3j.protocol.core.DefaultBlockParameter endBlock) {\n" + " org.web3j.protocol.core.methods.request.EthFilter filter = new org.web3j.protocol.core.methods.request.EthFilter(startBlock, endBlock, getContractAddress());\n" - + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME1_EVENT));\n" - + " return eventName1EventFlowable(filter);\n" + + " filter.addSingleTopic(org.web3j.abi.EventEncoder.encode(EVENTNAME_EVENT));\n" + + " return eventNameEventFlowable(filter);\n" + " }\n" + "\n" + " public static class EventNameEventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" @@ -1017,7 +1029,7 @@ public void testBuildFunctionDuplicatedEventNames() throws Exception { + " public java.lang.Boolean pauseState;\n" + " }\n" + "\n" - + " public static class EventName1EventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + + " public static class EventNameEventResponse extends org.web3j.protocol.core.methods.response.BaseEventResponse {\n" + " public java.lang.String cToken;\n" + "\n" + " public java.lang.String action;\n"