<commit_before>package org.adridadou.ethereum;

import com.google.common.collect.Sets;
import org.adridadou.ethereum.blockchain.BlockchainProxy;
import org.adridadou.ethereum.converters.input.*;
import org.adridadou.ethereum.converters.output.*;
import org.adridadou.ethereum.smartcontract.SmartContract;
import org.adridadou.ethereum.values.*;
import org.adridadou.exception.ContractNotFoundException;
import org.adridadou.exception.EthereumApiException;
import org.ethereum.core.CallTransaction;
import org.ethereum.solidity.compiler.CompilationResult;
import org.ethereum.solidity.compiler.SolidityCompiler;

import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * Created by davidroon on 31.03.16.
 * This code is released under Apache 2 license
 */
public class EthereumContractInvocationHandler implements InvocationHandler {

    private final Map<EthAddress, Map<EthAccount, SmartContract>> contracts = new HashMap<>();
    private final BlockchainProxy blockchainProxy;
    private final InputTypeHandler inputTypeHandler;
    private final OutputTypeHandler outputTypeHandler;
    private final Map<ProxyWrapper, SmartContractInfo> info = new HashMap<>();


    EthereumContractInvocationHandler(BlockchainProxy blockchainProxy, InputTypeHandler inputTypeHandler, OutputTypeHandler outputTypeHandler) {
        this.blockchainProxy = blockchainProxy;
        this.inputTypeHandler = inputTypeHandler;
        this.outputTypeHandler = outputTypeHandler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        final String methodName = method.getName();
        SmartContractInfo contractInfo = info.get(new ProxyWrapper(proxy));
        SmartContract contract = contracts.get(contractInfo.getAddress()).get(contractInfo.getSender());
        Object[] arguments = Optional.ofNullable(args).map(this::prepareArguments).orElse(new Object[0]);
        if (method.getReturnType().equals(Void.TYPE)) {
            contract.callFunction(methodName, arguments).get();
            return Void.TYPE;
        } else if (method.getReturnType().equals(CompletableFuture.class)) {
                return contract.callFunction(methodName, arguments).thenApply(result -> convertResult(result, method));
        } else {
            return convertResult(contract.callConstFunction(methodName, arguments), method);
        }
    }

    private Object[] prepareArguments(Object[] args) {
<commit_msg>Unwrap ExecutionException when calling a void-typed contract method<commit_after>package org.adridadou.ethereum;

import com.google.common.collect.Sets;
import org.adridadou.ethereum.blockchain.BlockchainProxy;
import org.adridadou.ethereum.converters.input.*;
import org.adridadou.ethereum.converters.output.*;
import org.adridadou.ethereum.smartcontract.SmartContract;
import org.adridadou.ethereum.values.*;
import org.adridadou.exception.ContractNotFoundException;
import org.adridadou.exception.EthereumApiException;
import org.ethereum.core.CallTransaction;
import org.ethereum.solidity.compiler.CompilationResult;
import org.ethereum.solidity.compiler.SolidityCompiler;

import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * Created by davidroon on 31.03.16.
 * This code is released under Apache 2 license
 */
public class EthereumContractInvocationHandler implements InvocationHandler {

    private final Map<EthAddress, Map<EthAccount, SmartContract>> contracts = new HashMap<>();
    private final BlockchainProxy blockchainProxy;
    private final InputTypeHandler inputTypeHandler;
    private final OutputTypeHandler outputTypeHandler;
    private final Map<ProxyWrapper, SmartContractInfo> info = new HashMap<>();


    EthereumContractInvocationHandler(BlockchainProxy blockchainProxy, InputTypeHandler inputTypeHandler, OutputTypeHandler outputTypeHandler) {
        this.blockchainProxy = blockchainProxy;
        this.inputTypeHandler = inputTypeHandler;
        this.outputTypeHandler = outputTypeHandler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        final String methodName = method.getName();
        SmartContractInfo contractInfo = info.get(new ProxyWrapper(proxy));
        SmartContract contract = contracts.get(contractInfo.getAddress()).get(contractInfo.getSender());
        Object[] arguments = Optional.ofNullable(args).map(this::prepareArguments).orElse(new Object[0]);
        if (method.getReturnType().equals(Void.TYPE)) {
            try {
                contract.callFunction(methodName, arguments).get();
            }
            catch (ExecutionException e) {
                throw e.getCause();
            }

            return Void.TYPE;
        } else if (method.getReturnType().equals(CompletableFuture.class)) {
                return contract.callFunction(methodName, arguments).thenApply(result -> convertResult(result, method));
        } else {
            return convertResult(contract.callConstFunction(methodName, arguments), method);
        }
    }

    private Object[] prepareArguments(Object[] args) {

{'fraction_non_alphanumeric': 0.09517673048600883, 'fraction_numerical': 0.0029455081001472753, 'mean_word_length': 4.411354581673307, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7662612', 'n_tokens_mistral': 1461, 'n_tokens_neox': 1407, 'n_words': 299}