예제 #1
0
파일: contract.py 프로젝트: euri10/web3.py
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #2
0
def call_contract_function(contract, function_name, transaction, *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #3
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_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
            contract.web3.eth.getCode(contract.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_name,
                    return_data,
                    output_types
                )
            )
        raise BadFunctionCallOutput(msg) from e

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

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #4
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_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
            contract.web3.eth.getCode(contract.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_name,
                    return_data,
                    output_types
                )
            )
        raise BadFunctionCallOutput(msg) from e

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

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #5
0
 def call(self, *args, **kwargs):
     kwargs.pop('private_key', None)
     from_address = None
     if len(args) == 1:
         from_address = args[0].pop('from', None)
     tx = self._call.buildTransaction(*args, **kwargs)
     if from_address is not None:
         tx['from'] = from_address
     output_types = get_abi_output_types(self._call.abi)
     return_data = self._call.web3.eth.call(tx)
     decoded = decode_abi(output_types, return_data)
     return decoded[0] if len(decoded) == 1 else decoded
예제 #6
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_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
        msg = (
            "Could not decode contract function call {} return data {} for "
            "output_types {}".format(
                function_name,
                return_data,
                output_types
            )
        )
        raise_from(BadFunctionCallOutput(msg), e)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #7
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_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
        msg = (
            "Could not decode contract function call {} return data {} for "
            "output_types {}".format(
                function_name,
                return_data,
                output_types
            )
        )
        raise_from(BadFunctionCallOutput(msg), e)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #8
0
def call_contract_function(contract, function_name, transaction, *args,
                           **kwargs):
    """Calls a contract constant or function.

    The function must not have state changing effects.
    For those see :func:`transact_with_contract_function`

    For usual cases, you do not want to call this directly,
    but interact with your contract through :meth:`Contract.call` method.

    :param contract: :class:`web3.contract.Contract` object instance
    :param function_name: Contract function name to call
    :param transaction: Transaction parameters to pass to underlying ``web3.eth.call``
    :param *arguments: Arguments to be passed to contract function. Automatically encoded
    :return: Function call results, encoded to Python object
    """
    if transaction is None:
        call_transaction = {}
    else:
        call_transaction = dict(**transaction)

    function_abi = contract.find_matching_fn_abi(function_name, args, kwargs)
    function_selector = function_abi_to_4byte_selector(function_abi)

    arguments = merge_args_and_kwargs(function_abi, args, kwargs)

    call_transaction['data'] = contract.encodeABI(
        function_name,
        arguments,
        data=function_selector,
    )

    return_data = contract.web3.eth.call(call_transaction)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
예제 #9
0
    def call(self, function_name: str, *args, **kargs):
        self._check_function_name_and_kargs(function_name, kargs)
        data = self.get_transaction_data(self.abi, function_name, args)

        res = self.call_function(sender=self.sender,
                                 to=self.contract_address,
                                 value=kargs.pop('value', 0),
                                 data=decode_hex(data),
                                 **kargs)

        if res:
            fn_abi = find_matching_fn_abi(self.abi, function_name, args)
            output_types = get_abi_output_types(fn_abi)
            res = decode_abi(output_types, res)
            if len(res) == 1:
                res = res[0]

        return res
예제 #10
0
파일: contract.py 프로젝트: XertroV/web3.py
def call_contract_function(contract=None,
                           function_name=None,
                           transaction=None,
                           *arguments):
    if not arguments:
        arguments = []

    function_abi = contract.find_matching_abi(function_name, arguments)
    function_selector = function_abi_to_4byte_selector(function_abi)

    transaction['data'] = contract.encodeABI(
        function_name,
        arguments,
        data=function_selector,
    )

    return_data = contract.web3.eth.call(transaction)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)
    if len(output_data) == 1:
        return output_data[0]
    else:
        return output_data