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

com.citahub.cita.protocol.account.CompiledContract Maven / Gradle / Ivy

The newest version!
package com.citahub.cita.protocol.account;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.citahub.cita.protocol.ObjectMapperFactory;
import com.citahub.cita.utils.CallCmd;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.citahub.cita.protocol.core.methods.response.AbiDefinition;

public class CompiledContract {
    public static class ContractCompileError extends Exception {
        private String errorMessage;

        public ContractCompileError(String error) {
            errorMessage = error;
        }

        @Override
        public String toString() {
            return "complie contract failed because of " + errorMessage;
        }
    }

    public static class ContractFuncNotFound extends Exception {
        private String funcName;
        private int numOfArgs;

        public ContractFuncNotFound(String func, int num) {
            this.funcName = func;
            this.numOfArgs = num;
        }

        @Override
        public String toString() {
            return "contract method " + funcName + " with " + numOfArgs + " args " + " not found";
        }
    }

    private String bin;
    private String abi;
    private List typedABI;

    /// NOTE: the file name must be same with contract name
    public CompiledContract(File contractFile)
            throws IOException, InterruptedException, ContractCompileError {
        String fileName = contractFile.getName();
        if (fileName.indexOf(".") > 0) {
            fileName = fileName.substring(0, fileName.indexOf("."));
        }
        generateAbiAndBin(contractFile);

        String binPath = "/tmp/" + fileName + ".bin";
        String abiPath = "/tmp/" + fileName + ".abi";
        this.bin = new String(Files.readAllBytes(Paths.get(binPath)));
        this.abi = new String(Files.readAllBytes(Paths.get(abiPath)));
        this.typedABI = generateTypedABI();
    }

    public CompiledContract(String abi) throws IOException {
        this.abi = abi;
        this.typedABI = generateTypedABI();
    }

    /// TODO: support windows OS
    private void generateAbiAndBin(File contractFile)
            throws IOException, InterruptedException, ContractCompileError {
        String callSolcCmd = String.format(
                "solc %s --abi --bin --optimize --overwrite -o /tmp/",
                contractFile.getAbsolutePath());

        CallCmd.ExecutedResult result = CallCmd.callCmd(callSolcCmd);
        if (result.exitCode != 0) {
            throw new ContractCompileError(result.output);
        }
    }

    private List generateTypedABI() throws IOException {
        ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
        AbiDefinition[] typedABI = objectMapper.readValue(this.abi, AbiDefinition[].class);
        return Arrays.asList(typedABI);
    }

    public List getTypedABI() {
        return this.typedABI;
    }

    public String getBin() {
        return this.bin;
    }

    public String getAbi() {
        return this.abi;
    }

    /// TODO: how to distinguish overload function which the num of args are same???
    public AbiDefinition getFunctionAbi(String funcName, int numOfArgs)
            throws ContractFuncNotFound {
        List definitionList = new ArrayList<>();
        for (AbiDefinition abiDefinition : this.typedABI) {
            if (abiDefinition.getType().equals("function")
                    && abiDefinition.getName().equals(funcName)
                    && abiDefinition.getInputs().size() == numOfArgs) {
                definitionList.add(abiDefinition);
            }
        }
        if (definitionList.size() == 0) {
            throw new ContractFuncNotFound(funcName, numOfArgs);
        } else {
            return definitionList.get(0);
        }
    }

    public AbiDefinition getEventAbi(String eventName) {
        List definitionList = new ArrayList<>();
        for (AbiDefinition abiDefinition : this.typedABI) {
            if (abiDefinition.getType().equals("event")
                    && abiDefinition.getName().equals(eventName)) {
                definitionList.add(abiDefinition);
            }
        }
        return definitionList.get(0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy