From 8fc3664cf266a321e87effb84a421bfefce718a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s?= <7888669+moisses89@users.noreply.github.com> Date: Thu, 2 Jan 2025 12:57:31 +0100 Subject: [PATCH] Refactor get_contract_metadata --- safe_eth/eth/clients/blockscout_client.py | 44 +++++++++++---------- safe_eth/eth/clients/etherscan_client.py | 4 +- safe_eth/eth/clients/etherscan_client_v2.py | 2 +- safe_eth/eth/clients/sourcify_client.py | 30 +++++++++----- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/safe_eth/eth/clients/blockscout_client.py b/safe_eth/eth/clients/blockscout_client.py index 096731736..8848c3132 100644 --- a/safe_eth/eth/clients/blockscout_client.py +++ b/safe_eth/eth/clients/blockscout_client.py @@ -178,23 +178,35 @@ def _do_request(self, url: str, query: str) -> Optional[Dict[str, Any]]: return response.json() - def get_contract_metadata( - self, address: ChecksumAddress + def _process_contract_metadata( + self, contract_data: dict[str, Any] ) -> Optional[ContractMetadata]: - query = '{address(hash: "%s") { hash, smartContract {name, abi} }}' % address - result = self._do_request(self.grahpql_url, query) + """ + Return a ContractMetadata from BlockScout response + + :param contract_data: + :return: + """ if ( - result - and "error" not in result - and result.get("data", {}).get("address", {}) - and result["data"]["address"]["smartContract"] + "error" not in contract_data + and contract_data.get("data", {}).get("address", {}) + and contract_data["data"]["address"]["smartContract"] ): - smart_contract = result["data"]["address"]["smartContract"] + smart_contract = contract_data["data"]["address"]["smartContract"] return ContractMetadata( smart_contract["name"], json.loads(smart_contract["abi"]), False ) return None + def get_contract_metadata( + self, address: ChecksumAddress + ) -> Optional[ContractMetadata]: + query = '{address(hash: "%s") { hash, smartContract {name, abi} }}' % address + contract_data = self._do_request(self.grahpql_url, query) + if contract_data: + return self._process_contract_metadata(contract_data) + return None + class AsyncBlockscoutClient(BlockscoutClient): def __init__( @@ -227,15 +239,7 @@ async def async_get_contract_metadata( self, address: ChecksumAddress ) -> Optional[ContractMetadata]: query = '{address(hash: "%s") { hash, smartContract {name, abi} }}' % address - result = await self._async_do_request(self.grahpql_url, query) - if ( - result - and "error" not in result - and result.get("data", {}).get("address", {}) - and result["data"]["address"]["smartContract"] - ): - smart_contract = result["data"]["address"]["smartContract"] - return ContractMetadata( - smart_contract["name"], json.loads(smart_contract["abi"]), False - ) + contract_data = await self._async_do_request(self.grahpql_url, query) + if contract_data: + return self._process_contract_metadata(contract_data) return None diff --git a/safe_eth/eth/clients/etherscan_client.py b/safe_eth/eth/clients/etherscan_client.py index 853856bc9..6ef01d3ea 100644 --- a/safe_eth/eth/clients/etherscan_client.py +++ b/safe_eth/eth/clients/etherscan_client.py @@ -367,7 +367,7 @@ def get_contract_metadata( return None @staticmethod - def _process_response(response): + def _process_get_contract_source_code_response(response): if response and isinstance(response, list): result = response[0] abi_str = result.get("ABI") @@ -406,7 +406,7 @@ def get_contract_source_code(self, contract_address: str, retry: bool = True): f"module=contract&action=getsourcecode&address={contract_address}" ) response = self._retry_request(url, retry=retry) # Returns a list - return self._process_response(response) + return self._process_get_contract_source_code_response(response) def get_contract_abi(self, contract_address: str, retry: bool = True): url = self.build_url( diff --git a/safe_eth/eth/clients/etherscan_client_v2.py b/safe_eth/eth/clients/etherscan_client_v2.py index 39bc09dcb..4cd7d9159 100644 --- a/safe_eth/eth/clients/etherscan_client_v2.py +++ b/safe_eth/eth/clients/etherscan_client_v2.py @@ -134,7 +134,7 @@ async def async_get_contract_source_code( f"module=contract&action=getsourcecode&address={contract_address}" ) response = await self._async_do_request(url) # Returns a list - return self._process_response(response) + return self._process_get_contract_source_code_response(response) async def async_get_contract_metadata( self, contract_address: str diff --git a/safe_eth/eth/clients/sourcify_client.py b/safe_eth/eth/clients/sourcify_client.py index 5bd34c393..7c53061fc 100644 --- a/safe_eth/eth/clients/sourcify_client.py +++ b/safe_eth/eth/clients/sourcify_client.py @@ -91,6 +91,20 @@ def get_chains(self) -> Dict[str, Any]: result = self._do_request(url) return result or {} + def _process_contract_metadata( + self, contract_data: dict[str, Any], match_type: str + ) -> ContractMetadata: + """ + Return a ContractMetadata from Sourcify response + + :param contract_data: + :param match_type: + :return: + """ + abi = self._get_abi_from_metadata(contract_data) + name = self._get_name_from_metadata(contract_data) + return ContractMetadata(name, abi, match_type == "partial_match") + def get_contract_metadata( self, contract_address: str ) -> Optional[ContractMetadata]: @@ -103,11 +117,9 @@ def get_contract_metadata( self.base_url_repo, f"/contracts/{match_type}/{self.network.value}/{contract_address}/metadata.json", ) - metadata = self._do_request(url) - if metadata: - abi = self._get_abi_from_metadata(metadata) - name = self._get_name_from_metadata(metadata) - return ContractMetadata(name, abi, match_type == "partial_match") + contract_data = self._do_request(url) + if contract_data: + return self._process_contract_metadata(contract_data, match_type) return None @@ -155,9 +167,7 @@ async def async_get_contract_metadata( self.base_url_repo, f"/contracts/{match_type}/{self.network.value}/{contract_address}/metadata.json", ) - metadata = await self._async_do_request(url) - if metadata: - abi = self._get_abi_from_metadata(metadata) - name = self._get_name_from_metadata(metadata) - return ContractMetadata(name, abi, match_type == "partial_match") + contract_data = await self._async_do_request(url) + if contract_data: + return self._process_contract_metadata(contract_data, match_type) return None