diff --git a/README.md b/README.md index 7d47df8..8f60a78 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,12 @@ foundry: Now, instead of launching a local process, it will attempt to connect to the remote anvil node and use this plugin as the ape interface. +To connect to a remote anvil node using an environment variable, set `APE_FOUNDRY_HOST`: + +```bash +export APE_FOUNDRY_HOST=https://your-anvil.example.com` +``` + ## Impersonate Accounts You can impersonate accounts using the `ape-foundry` plugin. diff --git a/ape_foundry/provider.py b/ape_foundry/provider.py index a57b961..b37570d 100644 --- a/ape_foundry/provider.py +++ b/ape_foundry/provider.py @@ -1,3 +1,4 @@ +import os import random import shutil from bisect import bisect_right @@ -144,7 +145,11 @@ def timeout(self) -> int: @property def _clean_uri(self) -> str: - return str(URL(self.uri).with_user(None).with_password(None)) + try: + return str(URL(self.uri).with_user(None).with_password(None)) + except ValueError: + # Likely isn't a real URI. + return self.uri @property def _port(self) -> Optional[int]: @@ -271,6 +276,9 @@ def connect(self): elif "host" in self.provider_settings: self._host = self.provider_settings["host"] + elif "APE_FOUNDRY_HOST" in os.environ: + self._host = os.environ["APE_FOUNDRY_HOST"] + elif self._host is None: self._host = self.uri @@ -278,8 +286,11 @@ def connect(self): # Connects to already running process self._start() - elif self.config.manage_process: + elif self.config.manage_process and ( + "localhost" in self._host or "127.0.0.1" in self._host or self._host == "auto" + ): # Only do base-process setup if not connecting to already-running process + # and is running on localhost. super().connect() if self._host: self._set_web3() diff --git a/tests/test_provider.py b/tests/test_provider.py index 7166615..4c7fd8d 100644 --- a/tests/test_provider.py +++ b/tests/test_provider.py @@ -1,3 +1,4 @@ +import os import tempfile from pathlib import Path @@ -301,7 +302,25 @@ def test_remote_host(temp_config, networks, no_anvil_bin): with temp_config(data): with pytest.raises( FoundryProviderError, - match=r"Failed to connect to Anvil node at 'https://example.com'\.", + match=r"Failed to connect to remote Anvil node at 'https://example.com'\.", ): with networks.ethereum.local.use_provider("foundry"): assert True + + +def test_remote_host_using_env_var(temp_config, networks, no_anvil_bin): + original = os.environ.get("APE_FOUNDRY_HOST") + os.environ["APE_FOUNDRY_HOST"] = "https://example2.com" + try: + with pytest.raises( + FoundryProviderError, + match=r"Failed to connect to remote Anvil node at 'https://example2.com'\.", + ): + with networks.ethereum.local.use_provider("foundry"): + assert True + + finally: + if original is None: + del os.environ["APE_FOUNDRY_HOST"] + else: + os.environ["APE_FOUNDRY_HOST"] = original