Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Counter on duplicated event names #2124

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,22 @@ FieldSpec createBinaryDefinition(String binary) {
.build();
}

private FieldSpec createEventDefinition(String name, List<NamedTypeName> parameters) {
private FieldSpec createEventDefinition(
String name,
List<NamedTypeName> parameters,
Map<String, Integer> 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)
.initializer(initializer)
Expand All @@ -432,26 +444,50 @@ private String buildEventDefinitionName(String eventName) {
return eventName.toUpperCase() + "_EVENT";
}

private List<MethodSpec> buildFunctionDefinitions(
List<MethodSpec> buildFunctionDefinitions(
String className,
TypeSpec.Builder classBuilder,
List<AbiDefinition> functionDefinitions)
throws ClassNotFoundException {

Set<String> duplicateFunctionNames = getDuplicateFunctionNames(functionDefinitions);
Map<String, Integer> eventsCount = getDuplicatedEventNames(functionDefinitions);
List<MethodSpec> methodSpecs = new ArrayList<>();
for (AbiDefinition functionDefinition : functionDefinitions) {
if (functionDefinition.getType().equals(TYPE_FUNCTION)) {
String functionName = funcNameToConst(functionDefinition.getName(), true);
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;
}

Map<String, Integer> getDuplicatedEventNames(List<AbiDefinition> functionDefinitions) {
Map<String, Integer> countMap = new HashMap<>();

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);
countMap.put(functionName, count + 1);
} else {
countMap.put(functionName, 1);
}
});

return countMap;
}

private List<TypeSpec> buildStructTypes(final List<AbiDefinition> functionDefinitions)
throws ClassNotFoundException {
final List<AbiDefinition.NamedType> orderedKeys = extractStructs(functionDefinitions);
Expand Down Expand Up @@ -1917,11 +1953,12 @@ private static String getEventFromLogFunctionName(String functionName) {
}

List<MethodSpec> buildEventFunctions(
AbiDefinition functionDefinition, TypeSpec.Builder classBuilder)
AbiDefinition functionDefinition,
TypeSpec.Builder classBuilder,
Map<String, Integer> eventsCount
)
throws ClassNotFoundException {
String functionName = functionDefinition.getName();
List<AbiDefinition.NamedType> inputs = functionDefinition.getInputs();
String responseClassName = Strings.capitaliseFirstLetter(functionName) + "EventResponse";

List<NamedTypeName> parameters = new ArrayList<>();
List<NamedTypeName> indexedParameters = new ArrayList<>();
Expand All @@ -1946,7 +1983,15 @@ List<MethodSpec> buildEventFunctions(
parameters.add(parameter);
}

classBuilder.addField(createEventDefinition(functionName, parameters));
String functionName = functionDefinition.getName();

classBuilder.addField(createEventDefinition(
functionName, parameters, eventsCount, functionDefinition
));

functionName = functionDefinition.getName();

String responseClassName = Strings.capitaliseFirstLetter(functionName) + "EventResponse";

classBuilder.addType(
buildEventResponseObject(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,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"
Expand Down Expand Up @@ -773,7 +777,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"
Expand Down Expand Up @@ -853,7 +861,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"
Expand Down Expand Up @@ -926,6 +938,140 @@ 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 EVENTNAME1_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" +
" java.util.Arrays.<org.web3j.abi.TypeReference<?>>asList(new org.web3j.abi.TypeReference<org.web3j.abi.datatypes.Utf8String>() {}, new org.web3j.abi.TypeReference<org.web3j.abi.datatypes.Bool>() {}));\n" +
" ;\n" +
"\n" +
" public static final org.web3j.abi.datatypes.Event EVENTNAME_EVENT = new org.web3j.abi.datatypes.Event(\"eventName\", \n" +
" java.util.Arrays.<org.web3j.abi.TypeReference<?>>asList(new org.web3j.abi.TypeReference<org.web3j.abi.datatypes.Address>() {}, new org.web3j.abi.TypeReference<org.web3j.abi.datatypes.Utf8String>() {}, new org.web3j.abi.TypeReference<org.web3j.abi.datatypes.Bool>() {}));\n" +
" ;\n" +
"\n" +
" public static java.util.List<EventName1EventResponse> getEventName1Events(\n" +
" org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" +
" java.util.List<org.web3j.tx.Contract.EventValuesWithLog> valueList = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, transactionReceipt);\n" +
" java.util.ArrayList<EventName1EventResponse> responses = new java.util.ArrayList<EventName1EventResponse>(valueList.size());\n" +
" for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\n" +
" EventName1EventResponse typedResponse = new EventName1EventResponse();\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 static EventName1EventResponse getEventName1EventFromLog(\n" +
" org.web3j.protocol.core.methods.response.Log log) {\n" +
" org.web3j.tx.Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(EVENTNAME1_EVENT, log);\n" +
" EventName1EventResponse typedResponse = new EventName1EventResponse();\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" +
" public io.reactivex.Flowable<EventName1EventResponse> eventName1EventFlowable(\n" +
" org.web3j.protocol.core.methods.request.EthFilter filter) {\n" +
" return web3j.ethLogFlowable(filter).map(log -> getEventName1EventFromLog(log));\n" +
" }\n" +
"\n" +
" public io.reactivex.Flowable<EventName1EventResponse> eventName1EventFlowable(\n" +
" org.web3j.protocol.core.DefaultBlockParameter startBlock,\n" +
" 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 java.util.List<EventNameEventResponse> getEventNameEvents(\n" +
" org.web3j.protocol.core.methods.response.TransactionReceipt transactionReceipt) {\n" +
" java.util.List<org.web3j.tx.Contract.EventValuesWithLog> valueList = staticExtractEventParametersWithLog(EVENTNAME_EVENT, transactionReceipt);\n" +
" java.util.ArrayList<EventNameEventResponse> responses = new java.util.ArrayList<EventNameEventResponse>(valueList.size());\n" +
" for (org.web3j.tx.Contract.EventValuesWithLog eventValues : valueList) {\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" +
" typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" +
" responses.add(typedResponse);\n" +
" }\n" +
" return responses;\n" +
" }\n" +
"\n" +
" public static EventNameEventResponse getEventNameEventFromLog(\n" +
" org.web3j.protocol.core.methods.response.Log log) {\n" +
" org.web3j.tx.Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(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" +
" typedResponse.pauseState = (java.lang.Boolean) eventValues.getNonIndexedValues().get(2).getValue();\n" +
" return typedResponse;\n" +
" }\n" +
"\n" +
" public io.reactivex.Flowable<EventNameEventResponse> eventNameEventFlowable(\n" +
" org.web3j.protocol.core.methods.request.EthFilter filter) {\n" +
" return web3j.ethLogFlowable(filter).map(log -> getEventNameEventFromLog(log));\n" +
" }\n" +
"\n" +
" public io.reactivex.Flowable<EventNameEventResponse> eventNameEventFlowable(\n" +
" org.web3j.protocol.core.DefaultBlockParameter startBlock,\n" +
" 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 class EventName1EventResponse 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 EventNameEventResponse 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 =
Expand Down
Loading