diff --git a/docs/userguides/networks.md b/docs/userguides/networks.md index e685bbac44..aa00b2553a 100644 --- a/docs/userguides/networks.md +++ b/docs/userguides/networks.md @@ -123,3 +123,15 @@ To use a different network, such as `hardhat` or Anvil nodes, use the `--network ```shell ape networks run --network ethereum:local:foundry ``` + +## Provider Interaction + +Once you are connected to a network, you now have access to a `.provider`. +The provider class is what higher level Manager classes in Ape use to interface with the blockchain. +You can call methods directly from the provider, like this: + +```python +from ape import chain + +block = chain.provider.get_block("latest") +``` diff --git a/src/ape/api/providers.py b/src/ape/api/providers.py index 6f8f37a11b..e2d473ed27 100644 --- a/src/ape/api/providers.py +++ b/src/ape/api/providers.py @@ -1106,6 +1106,7 @@ def _prepare_call(self, txn: TransactionAPI, **kwargs) -> List: block_identifier = kwargs.pop("block_identifier", kwargs.pop("block_id", "latest")) if isinstance(block_identifier, int): block_identifier = to_hex(block_identifier) + arguments = [txn_dict, block_identifier] if "state_override" in kwargs: arguments.append(kwargs["state_override"]) @@ -1154,6 +1155,7 @@ def get_receipt( network_config: Dict = self.network.config.dict().get(self.network.name, {}) max_retries = network_config.get("max_get_transaction_retries", DEFAULT_MAX_RETRIES_TX) + txn = {} for attempt in range(max_retries): try: txn = dict(self.web3.eth.get_transaction(HexStr(txn_hash))) @@ -1491,13 +1493,14 @@ def _handle_execution_reverted( if isinstance(exception, Web3ContractLogicError) and no_reason: # Check for custom exception data and use that as the message instead. # This allows compiler exception enrichment to function. + err_trace = None try: if trace: trace, err_trace = tee(trace) elif txn: err_trace = self.provider.get_transaction_trace(txn.txn_hash.hex()) - data = list(err_trace)[-1].raw + data = list(err_trace)[-1].raw if err_trace else {} memory = data.get("memory", []) return_value = "".join([x[2:] for x in memory[4:]]) if return_value: diff --git a/src/ape_test/provider.py b/src/ape_test/provider.py index e81747bf11..b4bd2b81a7 100644 --- a/src/ape_test/provider.py +++ b/src/ape_test/provider.py @@ -77,7 +77,7 @@ def estimate_gas_cost(self, txn: TransactionAPI, **kwargs) -> int: block = self.web3.eth.get_block("latest") return block["gasLimit"] - block_id = kwargs.pop("block_identifier", None) + block_id = kwargs.pop("block_identifier", kwargs.pop("block_id", None)) estimate_gas = self.web3.eth.estimate_gas txn_dict = txn.dict() if txn_dict.get("gas") == "auto": @@ -139,7 +139,7 @@ def base_fee(self) -> int: def send_call(self, txn: TransactionAPI, **kwargs) -> bytes: data = txn.dict(exclude_none=True) - block_id = kwargs.pop("block_identifier", None) + block_id = kwargs.pop("block_identifier", kwargs.pop("block_id", None)) state = kwargs.pop("state_override", None) call_kwargs = {"block_identifier": block_id, "state_override": state} diff --git a/tests/functional/test_contract_instance.py b/tests/functional/test_contract_instance.py index 360a41cc7f..d3082936b0 100644 --- a/tests/functional/test_contract_instance.py +++ b/tests/functional/test_contract_instance.py @@ -112,11 +112,19 @@ def test_call_use_block_identifier(contract_instance, owner, chain): actual = contract_instance.myNumber(block_identifier=block_id) assert actual == expected + # Ensure alias "block_id" works + actual = contract_instance.myNumber(block_id=block_id) + assert actual == expected + # Ensure works with hex block_id = to_hex(block_id) actual = contract_instance.myNumber(block_identifier=block_id) assert actual == expected + # Ensure alias "block_id" works. + actual = contract_instance.myNumber(block_id=block_id) + assert actual == expected + # Ensure works keywords like "latest" actual = contract_instance.myNumber(block_identifier="latest") assert actual == 3 @@ -182,8 +190,9 @@ def test_call_using_block_identifier( contract.setNumber(1, sender=owner) height = chain.blocks.height contract.setNumber(33, sender=owner) - actual = contract.myNumber(block_identifier=height) - assert actual == 1 + actual_0 = contract.myNumber(block_identifier=height) + actual_1 = contract.myNumber(block_id=height) + assert actual_0 == actual_1 == 1 def test_repr(vyper_contract_instance):