diff --git a/setup.py b/setup.py index 8733e9717f..4d1dd9bd73 100644 --- a/setup.py +++ b/setup.py @@ -77,6 +77,7 @@ "click>=8.0.0", "eth-account==0.5.7", "ethpm-types>=0.1.0b7", + "evm-trace>=0.1.0.a2", "hexbytes>=0.2.2,<1.0.0", "packaging>=20.9,<21.0", "pandas>=1.3.0,<2.0", diff --git a/src/ape/api/providers.py b/src/ape/api/providers.py index a66e61c8ff..d3f663da36 100644 --- a/src/ape/api/providers.py +++ b/src/ape/api/providers.py @@ -14,6 +14,7 @@ from eth_typing import HexStr from eth_utils import add_0x_prefix, keccak from ethpm_types.abi import EventABI +from evm_trace import TraceFrame from hexbytes import HexBytes from pydantic import Field, validator from web3 import Web3 @@ -32,17 +33,7 @@ ) from ape.logging import logger from ape.types import AddressType, BlockID, ContractLog, SnapshotID -from ape.utils import BaseInterfaceModel, abstractmethod, cached_property - - -def raises_not_implemented(fn): - def inner(*args, **kwargs): - raise NotImplementedError( - f"Attempted to call method '{fn.__name__}' in 'ProviderAPI', " - f"which is only available in 'TestProviderAPI'." - ) - - return inner +from ape.utils import BaseInterfaceModel, abstractmethod, cached_property, raises_not_implemented class BlockGasAPI(BaseInterfaceModel): @@ -371,6 +362,18 @@ def unlock_account(self, address: AddressType) -> bool: bool: ``True`` if successfully unlocked account and ``False`` otherwise. """ + @raises_not_implemented + def get_transaction_trace(self, txn_hash: str) -> Iterator[TraceFrame]: + """ + Provide a detailed description of opcodes. + + Args: + txn_hash (str): The hash of a transaction to trace. + + Returns: + Iterator(EvmTrace): Transaction execution trace object. + """ + def prepare_transaction(self, txn: TransactionAPI) -> TransactionAPI: """ Set default values on the transaction. diff --git a/src/ape/utils.py b/src/ape/utils.py index ef7d3be9aa..1e62b54c3d 100644 --- a/src/ape/utils.py +++ b/src/ape/utils.py @@ -727,6 +727,19 @@ def json(self, *args, **kwargs) -> str: return super().json(*args, **kwargs) +def raises_not_implemented(fn): + """ + Decorator for raising helpful not implemented error. + """ + + def inner(*args, **kwargs): + raise NotImplementedError( + f"Attempted to call method '{fn.__qualname__}', method not supported." + ) + + return inner + + __all__ = [ "abstractmethod", "BaseInterfaceModel", @@ -742,6 +755,7 @@ def json(self, *args, **kwargs) -> str: "get_all_files_in_directory", "injected_before_use", "load_config", + "raises_not_implemented", "singledispatchmethod", "stream_response", "to_address",