From 4ba6ec259b7f1e1629c0c05779576eed532b0432 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Mon, 25 Nov 2024 18:22:31 -0600 Subject: [PATCH] feat: add support for API secret --- README.md | 7 +++++++ ape_infura/provider.py | 24 ++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d3032b9..04dc897 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,13 @@ export WEB3_INFURA_PROJECT_ID=MY_API_TOKEN export WEB3_INFURA_PROJECT_ID=MY_API_TOKEN1, MY_API_TOKEN2 ``` +Additionally, if your app requires an API secret as well, use either of the following environment variables: + +- WEB3_INFURA_PROJECT_ID +- WEB3_INFURA_API_KEY + +And each request will use the secret as a form of authentication. + To use the Infura provider plugin in most commands, set it via the `--network` option: ```bash diff --git a/ape_infura/provider.py b/ape_infura/provider.py index ca5515c..5fc47f0 100644 --- a/ape_infura/provider.py +++ b/ape_infura/provider.py @@ -6,12 +6,15 @@ from ape.api import UpstreamProvider from ape.exceptions import ContractLogicError, ProviderError, VirtualMachineError from ape_ethereum.provider import Web3Provider +from requests import Session from web3 import HTTPProvider, Web3 from web3.exceptions import ContractLogicError as Web3ContractLogicError from web3.gas_strategies.rpc import rpc_gas_price_strategy from web3.middleware import geth_poa_middleware -_ENVIRONMENT_VARIABLE_NAMES = ("WEB3_INFURA_PROJECT_ID", "WEB3_INFURA_API_KEY") +_API_KEY_ENVIRONMENT_VARIABLE_NAMES = ("WEB3_INFURA_PROJECT_ID", "WEB3_INFURA_API_KEY") +_API_SECRET_ENVIRONMENT_VARIABLE_NAMES = ("WEB3_INFURA_PROJECT_SECRET", "WEB3_INFURA_API_SECRET") + # NOTE: https://docs.infura.io/learn/websockets#supported-networks _WEBSOCKET_CAPABLE_ECOSYSTEMS = { "ethereum", @@ -30,10 +33,18 @@ class InfuraProviderError(ProviderError): class MissingProjectKeyError(InfuraProviderError): def __init__(self): - env_var_str = ", ".join([f"${n}" for n in _ENVIRONMENT_VARIABLE_NAMES]) + env_var_str = ", ".join([f"${n}" for n in _API_KEY_ENVIRONMENT_VARIABLE_NAMES]) super().__init__(f"Must set one of {env_var_str}") +def _get_api_key_secret() -> Optional[str]: + for name in _API_SECRET_ENVIRONMENT_VARIABLE_NAMES: + if secret := os.environ.get(name): + return secret + + return None + + class Infura(Web3Provider, UpstreamProvider): network_uris: dict[tuple[str, str], str] = {} @@ -52,7 +63,7 @@ def __get_random_api_key(self) -> str: @cached_property def _api_keys(self) -> set[str]: api_keys = set() - for env_var_name in _ENVIRONMENT_VARIABLE_NAMES: + for env_var_name in _API_KEY_ENVIRONMENT_VARIABLE_NAMES: if env_var := os.environ.get(env_var_name): api_keys.update(set(key.strip() for key in env_var.split(","))) @@ -94,7 +105,12 @@ def connection_str(self) -> str: return self.uri def connect(self): - self._web3 = Web3(HTTPProvider(self.uri)) + session = Session() + if api_secret := _get_api_key_secret(): + session.auth = ("", api_secret) + + http_provider = HTTPProvider(self.uri, session=session) + self._web3 = Web3(http_provider) # Any chain that *began* as PoA needs the middleware for pre-merge blocks optimism = (10, 420)