All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fisco.bcos.web3j.codegen.TruffleJsonFunctionWrapperGenerator Maven / Gradle / Ivy

package org.fisco.bcos.web3j.codegen;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import org.fisco.bcos.web3j.protocol.ObjectMapperFactory;
import org.fisco.bcos.web3j.protocol.core.methods.response.AbiDefinition;
import org.fisco.bcos.web3j.tx.ChainId;
import org.fisco.bcos.web3j.utils.Collection;
import org.fisco.bcos.web3j.utils.Strings;

/**
 * Java wrapper source code generator for Truffle JSON format. Truffle embeds the Solidity ABI
 * formatted JSON in its own format. That format also gives access to the binary code. It also
 * contains information about deployment addresses. This should make integration with Truffle
 * easier.
 */
public class TruffleJsonFunctionWrapperGenerator extends FunctionWrapperGenerator {

  private static final String USAGE =
      "truffle generate "
          + "[--javaTypes|--solidityTypes] "
          + ".json "
          + "-p|--package  "
          + "-o|--outputDir ";

  private String jsonFileLocation;

  private TruffleJsonFunctionWrapperGenerator(
      String jsonFileLocation,
      String destinationDirLocation,
      String basePackageName,
      boolean useJavaNativeTypes) {

    super(new File(destinationDirLocation), basePackageName, useJavaNativeTypes);
    this.jsonFileLocation = jsonFileLocation;
  }

  public static void run(String[] args) throws Exception {
    if (args.length < 1 || !"generate".equals(args[0])) {
      Console.exitError(USAGE);
    } else {
      main(Collection.tail(args));
    }
  }

  public static void main(String[] args) throws Exception {

    String[] fullArgs;
    if (args.length == 5) {
      fullArgs = new String[args.length + 1];
      fullArgs[0] = JAVA_TYPES_ARG;
      System.arraycopy(args, 0, fullArgs, 1, args.length);
    } else {
      fullArgs = args;
    }

    if (fullArgs.length != 6) {
      Console.exitError(USAGE);
    }

    boolean useJavaNativeTypes = useJavaNativeTypes(fullArgs[0], USAGE);

    String jsonFileLocation = parsePositionalArg(fullArgs, 1);
    String destinationDirLocation = parseParameterArgument(fullArgs, "-o", "--outputDir");
    String basePackageName = parseParameterArgument(fullArgs, "-p", "--package");

    if (Strings.isEmpty(jsonFileLocation)
        || Strings.isEmpty(destinationDirLocation)
        || Strings.isEmpty(basePackageName)) {
      Console.exitError(USAGE);
    }

    new TruffleJsonFunctionWrapperGenerator(
            jsonFileLocation, destinationDirLocation, basePackageName, useJavaNativeTypes)
        .generate();
  }

  static Contract loadContractDefinition(File jsonFile) throws IOException {
    ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
    return objectMapper.readValue(jsonFile, Contract.class);
  }

  @SuppressWarnings("unchecked")
  private void generate() throws IOException, ClassNotFoundException {

    File truffleJsonFile = new File(jsonFileLocation);
    if (!truffleJsonFile.exists() || !truffleJsonFile.canRead()) {
      Console.exitError("Invalid input json file specified: " + jsonFileLocation);
    }

    String fileName = truffleJsonFile.getName();
    String contractName = getFileNameNoExtension(fileName);

    Contract c = loadContractDefinition(truffleJsonFile);
    if (c == null) {
      Console.exitError("Unable to parse input json file");
    } else {
      String className = Strings.capitaliseFirstLetter(contractName);
      System.out.printf("Generating " + basePackageName + "." + className + " ... ");
      Map addresses;
      if (c.networks != null && !c.networks.isEmpty()) {
        addresses =
            c.networks
                .entrySet()
                .stream()
                .filter(e -> (e.getValue() != null && e.getValue().getAddress() != null))
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getAddress()));
      } else {
        addresses = Collections.EMPTY_MAP;
      }
      new SolidityFunctionWrapper(useJavaNativeTypes)
          .generateJavaFiles(
              contractName,
              c.getBytecode(),
              c.getAbi(),
              destinationDirLocation.toString(),
              basePackageName,
              addresses);
      System.out.println("File written to " + destinationDirLocation.toString() + "\n");
    }
  }

  /**
   * Truffle Contract
   *
   * 

Describes a contract exported by and consumable by Truffle, which may include information * about deployed instances on networks. */ @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "contractName", "abi", "bytecode", "deployedBytecode", "sourceMap", "deployedSourceMap", "source", "sourcePath", "ast", "compiler", "networks", "schemaVersion", "updatedAt" }) public static class Contract { @JsonProperty("contractName") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^[a-zA-Z_][a-zA-Z0-9_]*$") public String contractName; @JsonProperty(value = "abi", required = true) public List abi; @JsonProperty("bytecode") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$") public String bytecode; @JsonProperty("deployedBytecode") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$") public String deployedBytecode; @JsonProperty("sourceMap") public String sourceMap; @JsonProperty("deployedSourceMap") public String deployedSourceMap; @JsonProperty("source") public String source; @JsonProperty("sourcePath") public String sourcePath; @JsonProperty("ast") public JsonNode ast; @JsonProperty("compiler") public Compiler compiler; @JsonProperty("networks") public Map networks; @JsonProperty("schemaVersion") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "[0-9]+\\.[0-9]+\\.[0-9]+") public String schemaVersion; @JsonProperty("updatedAt") @JsonFormat( shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "GMT") public Date updatedAt; public Contract() {} public Contract( String contractName, List abi, String bytecode, String deployedBytecode, String sourceMap, String deployedSourceMap, String source, String sourcePath, JsonNode ast, Compiler compiler, Map networks, String schemaVersion, Date updatedAt) { super(); this.contractName = contractName; this.abi = abi; this.bytecode = bytecode; this.deployedBytecode = deployedBytecode; this.sourceMap = sourceMap; this.deployedSourceMap = deployedSourceMap; this.source = source; this.sourcePath = sourcePath; this.ast = ast; this.compiler = compiler; this.networks = networks; this.schemaVersion = schemaVersion; this.updatedAt = updatedAt; } public String getContractName() { return contractName; } public List getAbi() { return abi; } public String getBytecode() { return bytecode; } public NetworkInfo getNetwork(String networkId) { return networks == null ? null : networks.get(networkId); } public String getAddress(String networkId) { NetworkInfo network = getNetwork(networkId); return network == null ? null : network.getAddress(); } /** * Convenience method to get the deployed address of the contract. * * @param network the contract's address on this Ethereum network * @return the contract's address or null if there isn't one known. */ public String getAddress(Network network) { return getAddress(Long.toString(network.id)); } /* * c.f., ChainId * * This should be updated with https://github.com/web3j/web3j/issues/234 */ enum Network { olympic(0), mainnet(ChainId.MAINNET), morden(ChainId.EXPANSE_MAINNET), ropsten(ChainId.ROPSTEN), rinkeby(ChainId.RINKEBY), kovan(ChainId.KOVAN); public final long id; Network(long id) { this.id = id; } } } @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({"name", "version"}) public static class Compiler { @JsonProperty("name") public String name; @JsonProperty("version") public String version; @JsonIgnore private Map additionalProperties = new HashMap(); public Compiler() {} public Compiler(String name, String version) { super(); this.name = name; this.version = version; } @JsonAnyGetter public Map getAdditionalProperties() { return this.additionalProperties; } @JsonAnySetter public void setAdditionalProperty(String name, JsonNode value) { this.additionalProperties.put(name, value); } public Compiler withAdditionalProperty(String name, JsonNode value) { this.additionalProperties.put(name, value); return this; } } // For now we just ignore "events" @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({"events", "links", "address"}) public static class NetworkInfo { @JsonProperty("events") public Map events; @JsonProperty("links") public Map links; @JsonProperty("address") public String address; public NetworkInfo() {} public NetworkInfo(Map events, Map links, String address) { super(); this.events = events; this.links = links; this.address = address; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy