Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
 async def _async_call(self, func, *args, **kwargs):
     tx = prepare_transaction(self.__contract.address, None, func.function_identifier,
                              func.contract_abi, func.abi, {}, args, kwargs)
     if self.__block is None:
         return_data = await self.__contract.web3.eth.call(tx)
     else:
         return_data = await self.__contract.web3.eth.call(tx, self.__block)
     output_types = get_abi_output_types(func.abi)
     result = decode_abi(output_types, hexstr_if_str(to_bytes, return_data))
     return result if len(func.abi['outputs']) > 1 else result[0]
Exemplo n.º 8
0
    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,
        )
Exemplo n.º 9
0
    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,
        )
Exemplo n.º 10
0
 async def _async_send(self, func, *args, **kwargs):
     contract = self.__contract
     web3 = self.__contract.web3
     tx = prepare_transaction(contract.address, None, func.function_identifier,
                              func.contract_abi, func.abi, {}, args, kwargs)
     tx.update({
         'gas': 0,
         'gasPrice': await web3.eth.gasPrice,
         'nonce': await web3.eth.getTransactionCount(contract.signer.address)
     })
     tx['gas'] = await web3.eth.estimateGas(tx)
     if tx['gas'] > await contract.signer.balance:
         raise ValueError('Need gas over account balance')
     signed_tx = contract.signer.sign_transaction(tx)
     tx_hash = await web3.eth.sendRawTransaction(signed_tx.rawTransaction)
     deadline = time() + 300
     while True:
         receipt = await web3.eth.getTransactionReceipt(tx_hash)
         if receipt is not None:
             break
         await asyncio.sleep(0.01)
         if time() > deadline:
             raise TimeoutError("Timeout while awaiting transaction receipt")
Exemplo n.º 11
0
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
Exemplo n.º 12
0
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