def build_transaction_for_function(address,
                                   web3,
                                   function_name=None,
                                   transaction=None,
                                   contract_abi=None,
                                   fn_abi=None,
                                   *args,
                                   **kwargs):
    """Builds a dictionary with the fields required to make the given transaction

    Don't call this directly, instead use :meth:`Contract.buildTransaction`
    on your contract instance.
    """
    prepared_transaction = prepare_transaction(
        address,
        web3,
        fn_identifier=function_name,
        contract_abi=contract_abi,
        fn_abi=fn_abi,
        transaction=transaction,
        fn_args=args,
        fn_kwargs=kwargs,
    )

    prepared_transaction = fill_transaction_defaults(web3,
                                                     prepared_transaction)

    return prepared_transaction
def transact_with_contract_function(address,
                                    web3,
                                    function_name=None,
                                    transaction=None,
                                    contract_abi=None,
                                    fn_abi=None,
                                    *args,
                                    **kwargs):
    """
    Helper function for interacting with a contract function by sending a
    transaction.
    """
    transact_transaction = prepare_transaction(
        address,
        web3,
        fn_identifier=function_name,
        contract_abi=contract_abi,
        transaction=transaction,
        fn_abi=fn_abi,
        fn_args=args,
        fn_kwargs=kwargs,
    )

    txn_hash = web3.eth.sendTransaction(transact_transaction)
    return txn_hash
def estimate_gas_for_function(address,
                              web3,
                              fn_identifier=None,
                              transaction=None,
                              contract_abi=None,
                              fn_abi=None,
                              *args,
                              **kwargs):
    """Estimates gas cost a function call would take.

    Don't call this directly, instead use :meth:`Contract.estimateGas`
    on your contract instance.
    """
    estimate_transaction = prepare_transaction(
        address,
        web3,
        fn_identifier=fn_identifier,
        contract_abi=contract_abi,
        fn_abi=fn_abi,
        transaction=transaction,
        fn_args=args,
        fn_kwargs=kwargs,
    )

    gas_estimate = web3.eth.estimateGas(estimate_transaction)
    return gas_estimate
    def _prepare_transaction(cls,
                             fn_name,
                             fn_args=None,
                             fn_kwargs=None,
                             transaction=None):

        return prepare_transaction(
            cls.address,
            cls.web3,
            fn_identifier=fn_name,
            contract_abi=cls.abi,
            transaction=transaction,
            fn_args=fn_args,
            fn_kwargs=fn_kwargs,
        )
def call_contract_function(web3,
                           address,
                           normalizers,
                           function_identifier,
                           transaction,
                           block_id=None,
                           contract_abi=None,
                           fn_abi=None,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = prepare_transaction(
        address,
        web3,
        fn_identifier=function_identifier,
        contract_abi=contract_abi,
        fn_abi=fn_abi,
        transaction=transaction,
        fn_args=args,
        fn_kwargs=kwargs,
    )

    if block_id is None:
        return_data = web3.eth.call(call_transaction)
    else:
        return_data = web3.eth.call(call_transaction,
                                    block_identifier=block_id)

    if fn_abi is None:
        fn_abi = find_matching_fn_abi(contract_abi, function_identifier, args,
                                      kwargs)

    output_types = get_abi_output_types(fn_abi)

    try:
        output_data = decode_abi(output_types, return_data)
    except DecodingError as e:
        # Provide a more helpful error message than the one provided by
        # eth-abi-utils
        is_missing_code_error = (return_data in ACCEPTABLE_EMPTY_STRINGS
                                 and web3.eth.getCode(address)
                                 in ACCEPTABLE_EMPTY_STRINGS)
        if is_missing_code_error:
            msg = (
                "Could not transact with/call contract function, is contract "
                "deployed correctly and chain synced?")
        else:
            msg = (
                "Could not decode contract function call {} return data {} for "
                "output_types {}".format(function_identifier, return_data,
                                         output_types))
        raise BadFunctionCallOutput(msg) from e

    _normalizers = itertools.chain(
        BASE_RETURN_NORMALIZERS,
        normalizers,
    )
    normalized_data = map_abi_data(_normalizers, output_types, output_data)

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data