package org.matthiaszimmermann.web3j.demo; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.Charset; import java.util.Map.Entry; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.matthiaszimmermann.web3j.util.Web3jConstants; import org.matthiaszimmermann.web3j.util.Web3jUtils; import org.web3j.codegen.SolidityFunctionWrapperGenerator; import org.web3j.protocol.core.Request; import org.web3j.protocol.core.methods.response.EthCompileSolidity; import org.web3j.protocol.core.methods.response.EthGetCompilers; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; public class CompileDemo extends AbstractDemo { static final String CONTRACT = "Greeter"; static final String BASE_PACKAGE = "org.matthiaszimmermann.web3j.demo.contract"; static final String FOLDER_BASE = System.getProperty("user.home") + "/Desktop/private/github/web3j_demo"; static final String FOLDER_SOURCE = FOLDER_BASE + "/src/main/resources"; static final String FOLDER_TARGET = FOLDER_BASE + "/src/main/java"; public static void main(String args []) throws Exception { new CompileDemo(args).run(); } public CompileDemo(String [] args) { super(args); } @Override public void run() throws Exception { super.run(); // get and print installed compilers EthGetCompilers compilers = web3j .ethGetCompilers() .sendAsync() .get(); System.out.println("Available compilers:"); for(String compiler: compilers.getResult()) { System.out.println("- " + compiler); } System.out.println(); // compile solidity code String sourceFile = String.format("%s/%s.%s", FOLDER_SOURCE, CONTRACT, Web3jConstants.EXT_SOLIDITY); String sourceCode = Web3jUtils.readSolidityFile(sourceFile); compileSolidity(sourceCode, CONTRACT, FOLDER_SOURCE); // generate java wrapper class String binaryFile = getBinaryFileName(CONTRACT, FOLDER_SOURCE); String abiFile = getAbiFileName(CONTRACT, FOLDER_SOURCE); String [] cmdLine = {binaryFile, abiFile, "-p", BASE_PACKAGE, "-o", FOLDER_TARGET}; System.out.printf("Running SolidityFunctionWrapperGenerator " + String.join(" ", cmdLine) + " ... "); SolidityFunctionWrapperGenerator.main(cmdLine); } /** * Compiles solidity source code using web3j. * Currently not working for testrpc see {@link https://github.com/web3j/web3j/issues/53}. */ public void compileNotWorkding(String source) { Request<?, EthCompileSolidity> result = web3j.ethCompileSolidity(source); System.out.println(result.toString()); } /** * Compiles solidity source code using JSON-RPC API directly. */ private JsonObject compileSolidity(String source, String contractName, String path) throws Exception { String compileCommandTemplate = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_compileSolidity\",\"params\":[\"%s\"],\"id\":1}"; String compileCommand = String.format(compileCommandTemplate, source); System.out.println("Compile command " + compileCommand); System.out.printf("Sending compile request to " + clientUrl + " ... "); StringEntity requestEntity = new StringEntity(compileCommand, ContentType.create("text/plain").withCharset(Charset.forName("UTF-8"))); HttpUriRequest request = RequestBuilder .post(clientUrl) .setEntity(requestEntity) .build(); ResponseHandler<JsonObject> rh = new ResponseHandler<JsonObject>() { @Override public JsonObject handleResponse(final HttpResponse response) throws IOException { StatusLine statusLine = response.getStatusLine(); HttpEntity entity = response.getEntity(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException( statusLine.getStatusCode(), statusLine.getReasonPhrase()); } if (entity == null) { throw new ClientProtocolException("Response contains no content"); } Gson gson = new GsonBuilder().create(); Reader reader = new InputStreamReader(entity.getContent(), Charset.forName("UTF-8")); return gson.fromJson(reader, JsonObject.class); } }; JsonObject response = HttpClients.createDefault().execute(request, rh); System.out.println(" done"); checkForErrors(response); checkForResult(response, contractName, path); return response; } private void checkForErrors(JsonObject response) { String ERROR = "error"; if(response.has(ERROR)) { JsonObject error = response.get(ERROR).getAsJsonObject(); System.out.println("Error code: " + error.get("code").toString()); System.out.println("Error message:\n" + error.get("message").getAsString()); } } private void checkForResult(JsonObject response, String contractName, String path) throws Exception { String RESULT = "result"; if(response.has(RESULT)) { printJsonElement("JSON-RPC response\n", response, "", contractName, path); } } /** * prints content to console * for abiDefinition and code elements the value is written to the file system. */ private void printJsonElement(String id, JsonElement e, String ident, String contractName, String path) throws Exception { if(id.equals("abiDefinition:") || id.equals("code:")) { File file = null; String value = e.toString(); verifyValue(id, value); if(id.equals("abiDefinition:")) { file = new File(getAbiFileName(contractName, path)); } else { // strip initial '"' if(value.startsWith("\"")) { value = value.substring(1); } // strip tailing '"' if(value.endsWith("\"")) { value = value.substring(0, value.length() - 1); } file = new File(getBinaryFileName(contractName, path)); } // System.out.printf("-- writing " + id + "value output to '" + file.getAbsolutePath() + "' ... "); BufferedWriter bw = new BufferedWriter(new FileWriter(file)); bw.write(value); bw.close(); if(value.length() >= 3000) { System.out.println(ident + id + value.substring(0, 3000) + " ..."); } else { System.out.println(ident + id + value); } } else if(e.isJsonPrimitive()) { String value = e.getAsString(); value = verifyValue(id, value); System.out.println(ident + id + value); } else if(e.isJsonObject()) { System.out.println(ident + id + " {"); JsonObject o = (JsonObject)e; for(Entry<String, JsonElement> entry: o.entrySet()) { String key = entry.getKey(); printJsonElement(key + ":", entry.getValue(), ident + " ", contractName, path); } System.out.println(ident + "}"); } else if(e.isJsonArray()) { System.out.println(ident + id + " ["); JsonArray a= (JsonArray)e; a.forEach(child -> { try { printJsonElement("", child, ident + " ", contractName, path); } catch (Exception e1) { e1.printStackTrace(); } }); System.out.println(ident + "}"); } else { System.out.println(ident + id + "<!!!> " + e.toString()); } } private String getAbiFileName(String contractName, String path) { return String.format("%s\\%s.%s", path, contractName, Web3jConstants.EXT_ABI); } private String getBinaryFileName(String contractName, String path) { return String.format("%s\\%s.%s", path, contractName, Web3jConstants.EXT_BINARY); } private String verifyValue(String id, String s) { if(s.startsWith("0x")) { String allowedChars = "0123456789abcdefg"; int unexpectedChars = 0; for(int i = 2; i < s.length(); i++) { if(allowedChars.indexOf(s.charAt(i)) < 0) { unexpectedChars++; } } if(unexpectedChars != 0) { System.out.println("// " + unexpectedChars + " unexpected chars found"); } } if(id.equals("code:") || id.equals("abiDefinition:")) { try { File tmp = null; if(id.equals("code:")) { tmp = File.createTempFile("contract", ".bin");} else { tmp = File.createTempFile("contract", ".abi");} BufferedWriter bw = new BufferedWriter(new FileWriter(tmp)); bw.write(s); bw.close(); // System.out.println("// wrote content of '" + id + "' to file " + tmp.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } } return s.length() <= 3000 ? s : s.substring(0, 3000); } }