Skip to content

Commit

Permalink
Merge pull request hyperledger-web3j#1537 from drinkcoffee/changes-wi…
Browse files Browse the repository at this point in the history
…thout-codegen-application

Generate functions to get the ABI encoding of function selector and parameters
  • Loading branch information
mohamedelshami authored Nov 10, 2021
2 parents fd6c27f + 37f4847 commit 63857cb
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 11 deletions.
12 changes: 9 additions & 3 deletions abi/src/main/java/org/web3j/abi/datatypes/DynamicArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,16 @@ public DynamicArray(Class<T> type, T... values) {
@Override
public String getTypeAsString() {
String type;
if (!value.isEmpty() && StructType.class.isAssignableFrom(value.get(0).getClass())) {
type = value.get(0).getTypeAsString();
} else {
// Handle dynamic array of zero length. This will fail if the dynamic array
// is an array of structs.
if (value.isEmpty()) {
type = AbiTypes.getTypeAString(getComponentType());
} else {
if (StructType.class.isAssignableFrom(value.get(0).getClass())) {
type = value.get(0).getTypeAsString();
} else {
type = AbiTypes.getTypeAString(getComponentType());
}
}
return type + "[]";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,42 @@ abstract class FunctionWrapperGenerator {
static final String JAVA_TYPES_ARG = "--javaTypes";
static final String SOLIDITY_TYPES_ARG = "--solidityTypes";
static final String PRIMITIVE_TYPES_ARG = "--primitiveTypes";
static final String ABI_FUNCS = "--abiFuncs";

final File destinationDirLocation;
final String basePackageName;
final boolean useJavaNativeTypes;
final boolean useJavaPrimitiveTypes;
final boolean abiFuncs;

final Class<? extends Contract> contractClass;

FunctionWrapperGenerator(
File destinationDirLocation, String basePackageName, boolean useJavaNativeTypes) {

this(Contract.class, destinationDirLocation, basePackageName, useJavaNativeTypes, false);
this(
Contract.class,
destinationDirLocation,
basePackageName,
useJavaNativeTypes,
false,
false);
}

FunctionWrapperGenerator(
Class<? extends Contract> contractClass,
File destinationDirLocation,
String basePackageName,
boolean useJavaNativeTypes,
boolean useJavaPrimitiveTypes) {
boolean useJavaPrimitiveTypes,
boolean abiFuncs) {

this.destinationDirLocation = destinationDirLocation;
this.basePackageName = basePackageName;
this.useJavaNativeTypes = useJavaNativeTypes;
this.useJavaPrimitiveTypes = useJavaPrimitiveTypes;
this.contractClass = contractClass;
this.abiFuncs = abiFuncs;
}

public abstract void generate() throws IOException, ClassNotFoundException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public class SolidityFunctionWrapper extends Generator {
private final boolean useNativeJavaTypes;
private final boolean useJavaPrimitiveTypes;
private final boolean generateBothCallAndSend;

private final boolean abiFuncs;
private final int addressLength;

private final HashMap<Integer, ClassName> structClassNameMap = new HashMap<>();
Expand Down Expand Up @@ -156,6 +156,22 @@ public SolidityFunctionWrapper(
useNativeJavaTypes,
useJavaPrimitiveTypes,
generateBothCallAndSend,
false,
addressLength,
new LogGenerationReporter(LOGGER));
}

public SolidityFunctionWrapper(
boolean useNativeJavaTypes,
boolean useJavaPrimitiveTypes,
boolean generateBothCallAndSend,
boolean abiFuncs,
int addressLength) {
this(
useNativeJavaTypes,
useJavaPrimitiveTypes,
generateBothCallAndSend,
abiFuncs,
addressLength,
new LogGenerationReporter(LOGGER));
}
Expand All @@ -166,8 +182,25 @@ public SolidityFunctionWrapper(
boolean generateBothCallAndSend,
int addressLength,
GenerationReporter reporter) {
this(
useNativeJavaTypes,
useJavaPrimitiveTypes,
generateBothCallAndSend,
false,
addressLength,
reporter);
}

public SolidityFunctionWrapper(
boolean useNativeJavaTypes,
boolean useJavaPrimitiveTypes,
boolean generateBothCallAndSend,
boolean abiFuncs,
int addressLength,
GenerationReporter reporter) {
this.useNativeJavaTypes = useNativeJavaTypes;
this.useJavaPrimitiveTypes = useJavaPrimitiveTypes;
this.abiFuncs = abiFuncs;
this.addressLength = addressLength;
this.reporter = reporter;
this.generateBothCallAndSend = generateBothCallAndSend;
Expand Down Expand Up @@ -1347,6 +1380,15 @@ List<MethodSpec> buildFunctions(
results.addAll(buildFunctions(functionDefinition, useUpperCase, true));
}

// Create function that returns the ABI encoding of the Solidity function call.
if (abiFuncs) {
functionName = "getABI_" + functionName;
methodBuilder = MethodSpec.methodBuilder(functionName).addModifiers(Modifier.PUBLIC);
addParameters(methodBuilder, functionDefinition.getInputs());
buildAbiFunction(functionDefinition, methodBuilder, inputParams, useUpperCase);
results.add(methodBuilder.build());
}

return results;
}

Expand Down Expand Up @@ -1530,6 +1572,35 @@ private void buildTransactionFunction(
}
}

private void buildAbiFunction(
AbiDefinition functionDefinition,
MethodSpec.Builder methodBuilder,
String inputParams,
boolean useUpperCase)
throws ClassNotFoundException {

if (functionDefinition.isPayable()) {
methodBuilder.addParameter(BigInteger.class, WEI_VALUE);
}

String functionName = functionDefinition.getName();

methodBuilder.returns(TypeName.get(String.class));

methodBuilder.addStatement(
"final $T function = new $T(\n$N, \n$T.<$T>asList($L), \n$T"
+ ".<$T<?>>emptyList())",
Function.class,
Function.class,
funcNameToConst(functionName, useUpperCase),
Arrays.class,
Type.class,
inputParams,
Collections.class,
TypeReference.class);
methodBuilder.addStatement("return org.web3j.abi.FunctionEncoder.encode(function)");
}

TypeSpec buildEventResponseObject(
String className,
List<org.web3j.codegen.SolidityFunctionWrapper.NamedTypeName> indexedParameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class SolidityFunctionWrapperGenerator extends FunctionWrapperGenerator {
public static final String COMMAND_PREFIX = COMMAND_SOLIDITY + " " + COMMAND_GENERATE;

/*
* Usage: solidity generate [-hV] [-jt] [-st] [-B] -a=<abiFile> [-b=<binFile>]
* Usage: solidity generate [-hV] [-jt] [-st] [-B] [-r] -a=<abiFile> [-b=<binFile>]
* -o=<destinationFileDir> -p=<packageName>
* -h, --help Show this help message and exit.
* -V, --version Print version information and exit.
Expand All @@ -55,6 +55,7 @@ public class SolidityFunctionWrapperGenerator extends FunctionWrapperGenerator {
* Default: true
* -st, --solidityTypes use solidity types.
* -B, --generateBoth generate both call and send functions.
* -r, --abiFuncs ABI encoded function call getters.
*/

private final File binFile;
Expand Down Expand Up @@ -86,7 +87,33 @@ public SolidityFunctionWrapperGenerator(
useJavaPrimitiveTypes,
false,
Contract.class,
addressLength);
addressLength,
false);
}

public SolidityFunctionWrapperGenerator(
File binFile,
File abiFile,
File destinationDir,
String contractName,
String basePackageName,
boolean useJavaNativeTypes,
boolean useJavaPrimitiveTypes,
int addressLength,
boolean abiFuncs) {

this(
binFile,
abiFile,
destinationDir,
contractName,
basePackageName,
useJavaNativeTypes,
useJavaPrimitiveTypes,
false,
Contract.class,
addressLength,
abiFuncs);
}

protected SolidityFunctionWrapperGenerator(
Expand All @@ -99,14 +126,16 @@ protected SolidityFunctionWrapperGenerator(
boolean useJavaPrimitiveTypes,
boolean generateBothCallAndSend,
Class<? extends Contract> contractClass,
int addressLength) {
int addressLength,
boolean abiFuncs) {

super(
contractClass,
destinationDir,
basePackageName,
useJavaNativeTypes,
useJavaPrimitiveTypes);
useJavaPrimitiveTypes,
abiFuncs);

this.binFile = binFile;
this.abiFile = abiFile;
Expand Down Expand Up @@ -138,6 +167,7 @@ public final void generate() throws IOException, ClassNotFoundException {
useJavaNativeTypes,
useJavaPrimitiveTypes,
generateBothCallAndSend,
abiFuncs,
addressLength)
.generateJavaFiles(
contractClass,
Expand Down Expand Up @@ -235,6 +265,12 @@ private static class PicocliRunner implements Runnable {
required = false)
private boolean generateBothCallAndSend;

@Option(
names = {"-r", ABI_FUNCS},
description = "ABI encoded function call getters.",
required = false)
private boolean abiFuncs = false;

@Override
public void run() {
try {
Expand All @@ -256,7 +292,8 @@ public void run() {
primitiveTypes,
generateBothCallAndSend,
Contract.class,
addressLength)
addressLength,
abiFuncs)
.generate();
} catch (Exception e) {
exitError(e);
Expand Down

0 comments on commit 63857cb

Please sign in to comment.