<commit_before>package org.adridadou.ethereum.propeller;

import org.adridadou.ethereum.propeller.converters.future.FutureConverter;
import org.adridadou.ethereum.propeller.event.EthereumEventHandler;
import org.adridadou.ethereum.propeller.exception.EthereumApiException;
import org.adridadou.ethereum.propeller.solidity.*;
import org.adridadou.ethereum.propeller.solidity.abi.AbiParam;
import org.adridadou.ethereum.propeller.solidity.converters.decoders.SolidityTypeDecoder;
import org.adridadou.ethereum.propeller.solidity.converters.encoders.SolidityTypeEncoder;
import org.adridadou.ethereum.propeller.swarm.SwarmHash;
import org.adridadou.ethereum.propeller.swarm.SwarmService;
import org.adridadou.ethereum.propeller.values.*;
import rx.Observable;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static java.lang.reflect.Proxy.newProxyInstance;

/**
 * Created by davidroon on 31.03.16.
 * This code is released under Apache 2 license
 */
public class EthereumFacade {
    public static final Charset CHARSET = StandardCharsets.UTF_8;
    private final EthereumContractInvocationHandler handler;
    private final EthereumProxy ethereumProxy;
    private final SwarmService swarmService;
    private final SolidityCompiler solidityCompiler;

    EthereumFacade(EthereumProxy ethereumProxy, SwarmService swarmService, SolidityCompiler solidityCompiler) {
        this.swarmService = swarmService;
        this.solidityCompiler = solidityCompiler;
        this.handler = new EthereumContractInvocationHandler(ethereumProxy);
        this.ethereumProxy = ethereumProxy;
    }

    /**
     * This method defines a new type as void. This means that for this type, no decoder will be used and null will be returned.
     * This is used usually by wrapper projects to define language specific void types, for example Unit in Scala
     *
     * @param cls the class that needs to be seen as Void
     * @return the EthereumFacade object itself
     */
    public EthereumFacade addVoidType(Class<?> cls) {
        ethereumProxy.addVoidClass(cls);
        return this;
    }

    /**
     * This method adds a converter from CompletableFuture to another future type. This is useful if you wnat to integrate a library with its own
     * Future type or for a wrapper project that wants to convert CompletableFuture to another Future type. for example scala Future
     * @param futureConverter the future converter to add
     * @return the EthereumFacade object itself
     */
    public EthereumFacade addFutureConverter(FutureConverter futureConverter) {
        handler.addFutureConverter(futureConverter);
        return this;
    }

    /**
     * Creates a proxy object representing the interface with the smart contract.
     * This method reads the swarm url from the deployed code and then tries to download the smart contract metadata from Swarm.
     * It then reads the ABI from the smart contract's metadata to create the proxy.
     * @param address the address of the smart contract
     * @param account the account to use to send transactions
     * @param contractInterface The interface representing the smart contract
     * @return the contract proxy object
     */
    public <T> T createContractProxy(EthAddress address, EthAccount account, Class<T> contractInterface) {
        return createContractProxy(getDetails(address), address, account, contractInterface);
    }

    /**
     * Creates a proxy object representing the interface with the smart contract.
     * @param abi The ABI of the smart contract
     * @param address The address of the smart contract
     * @param account The account to use to send transactions
     * @param contractInterface The interface representing the smart contract
     * @return the contract proxy object
     */
    public <T> T createContractProxy(EthAbi abi, EthAddress address, EthAccount account, Class<T> contractInterface) {
        T proxy = (T) newProxyInstance(contractInterface.getClassLoader(), new Class[]{contractInterface}, handler);
        handler.register(proxy, contractInterface, new SolidityContractDetails(abi.getAbi(), null, null), address, account);
        return proxy;
    }

    /**
     * Creates a proxy object representing the interface with the smart contract.
     * @param details The compiled smart contract
     * @param address The address of the smart contract
     * @param account The account to use to send transactions
     * @param contractInterface The interface representing the smart contract
     * @return the contract proxy object
     */
    public <T> T createContractProxy(SolidityContractDetails details, EthAddress address, EthAccount account, Class<T> contractInterface) {
        T proxy = (T) newProxyInstance(contractInterface.getClassLoader(), new Class[]{contractInterface}, handler);
        handler.register(proxy, contractInterface, details, address, account);
        return proxy;
    }

    /**
     * Publishes the contract
     * @param contract The compiled contract to publish<commit_msg>fix javadocs<commit_after>package org.adridadou.ethereum.propeller;

import org.adridadou.ethereum.propeller.converters.future.FutureConverter;
import org.adridadou.ethereum.propeller.event.EthereumEventHandler;
import org.adridadou.ethereum.propeller.exception.EthereumApiException;
import org.adridadou.ethereum.propeller.solidity.*;
import org.adridadou.ethereum.propeller.solidity.abi.AbiParam;
import org.adridadou.ethereum.propeller.solidity.converters.decoders.SolidityTypeDecoder;
import org.adridadou.ethereum.propeller.solidity.converters.encoders.SolidityTypeEncoder;
import org.adridadou.ethereum.propeller.swarm.SwarmHash;
import org.adridadou.ethereum.propeller.swarm.SwarmService;
import org.adridadou.ethereum.propeller.values.*;
import rx.Observable;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static java.lang.reflect.Proxy.newProxyInstance;

/**
 * Created by davidroon on 31.03.16.
 * This code is released under Apache 2 license
 */
public class EthereumFacade {
    public static final Charset CHARSET = StandardCharsets.UTF_8;
    private final EthereumContractInvocationHandler handler;
    private final EthereumProxy ethereumProxy;
    private final SwarmService swarmService;
    private final SolidityCompiler solidityCompiler;

    EthereumFacade(EthereumProxy ethereumProxy, SwarmService swarmService, SolidityCompiler solidityCompiler) {
        this.swarmService = swarmService;
        this.solidityCompiler = solidityCompiler;
        this.handler = new EthereumContractInvocationHandler(ethereumProxy);
        this.ethereumProxy = ethereumProxy;
    }

    /**
     * This method defines a new type as void. This means that for this type, no decoder will be used and null will be returned.
     * This is used usually by wrapper projects to define language specific void types, for example Unit in Scala
     *
     * @param cls the class that needs to be seen as Void
     * @return the EthereumFacade object itself
     */
    public EthereumFacade addVoidType(Class<?> cls) {
        ethereumProxy.addVoidClass(cls);
        return this;
    }

    /**
     * This method adds a converter from CompletableFuture to another future type. This is useful if you wnat to integrate a library with its own
     * Future type or for a wrapper project that wants to convert CompletableFuture to another Future type. for example scala Future
     * @param futureConverter the future converter to add
     * @return the EthereumFacade object itself
     */
    public EthereumFacade addFutureConverter(FutureConverter futureConverter) {
        handler.addFutureConverter(futureConverter);
        return this;
    }

    /**
     * Creates a proxy object representing the interface with the smart contract.
     * This method reads the swarm url from the deployed code and then tries to download the smart contract metadata from Swarm.
     * It then reads the ABI from the smart contract's metadata to create the proxy.
     * @param address the address of the smart contract
     * @param account the account to use to send transactions
     * @param contractInterface The interface representing the smart contract
     * @param <T> the proxy object type
     * @return the contract proxy object
     */
    public <T> T createContractProxy(EthAddress address, EthAccount account, Class<T> contractInterface) {
        return createContractProxy(getDetails(address), address, account, contractInterface);
    }

    /**
     * Creates a proxy object representing the interface with the smart contract.
     * @param abi The ABI of the smart contract
     * @param address The address of the smart contract
     * @param account The account to use to send transactions
     * @param contractInterface The interface representing the smart contract
     * @param <T> the proxy object type
     * @return the contract proxy object
     */
    public <T> T createContractProxy(EthAbi abi, EthAddress address, EthAccount account, Class<T> contractInterface) {
        T proxy = (T) newProxyInstance(contractInterface.getClassLoader(), new Class[]{contractInterface}, handler);
        handler.register(proxy, contractInterface, new SolidityContractDetails(abi.getAbi(), null, null), address, account);
        return proxy;
    }

    /**
     * Creates a proxy object representing the interface with the smart contract.
     * @param details The compiled smart contract
     * @param address The address of the smart contract
     * @param account The account to use to send transactions
     * @param contractInterface The interface representing the smart contract
     * @param <T> the proxy object type
     * @return the contract proxy object
     */
    public <T> T createContractProxy(SolidityContractDetails details, EthAddress address, EthAccount account, Class<T> contractInterface) {
        T proxy = (T) newProxyInstance(contractInterface.getClassLoader(), new Class[]{contractInterface}, handler);
        handler.register(proxy, contractInterface, details, address, account);
        return proxy;
    }

    /**
     * Publishes the contract
     * @param contract The compiled contract to publish
{'fraction_non_alphanumeric': 0.06740509325002367, 'fraction_numerical': 0.0015147211966297454, 'mean_word_length': 3.9180633147113593, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4740617', 'n_tokens_mistral': 2782, 'n_tokens_neox': 2693, 'n_words': 960}