def _ens_lookup(self, web3: Optional[Web3], name: str) -> Optional[ChecksumEthAddress]: """Performs an ENS lookup and returns address if found else None May raise: - RemoteError if Etherscan is used and there is a problem querying it or parsing its response """ if web3 is not None: return web3.ens.resolve(name) # else we gotta manually query contracts via etherscan normal_name = normalize_name(name) resolver_addr = self._call_contract_etherscan( ENS_MAINNET_ADDR, abi=ENS_ABI, method_name='resolver', arguments=[normal_name_to_hash(normal_name)], ) if is_none_or_zero_address(resolver_addr): return None address = self._call_contract_etherscan( to_checksum_address(resolver_addr), abi=ENS_RESOLVER_ABI, method_name='addr', arguments=[normal_name_to_hash(normal_name)], ) if is_none_or_zero_address(address): return None return to_checksum_address(address)
def _ens_lookup( self, web3: Optional[Web3], name: str, blockchain: SupportedBlockchain = SupportedBlockchain.ETHEREUM, ) -> Optional[Union[ChecksumEthAddress, HexStr]]: """Performs an ENS lookup and returns address if found else None TODO: currently web3.py 5.15.0 does not support multichain ENS domains (EIP-2304), therefore requesting a non-Ethereum address won't use the web3 ens library and will require to extend the library resolver ABI. An issue in their repo (#1839) reporting the lack of support has been created. This function will require refactoring once they include support for EIP-2304. https://github.com/ethereum/web3.py/issues/1839 May raise: - RemoteError if Etherscan is used and there is a problem querying it or parsing its response """ normal_name = normalize_name(name) resolver_addr = self._call_contract( web3=web3, contract_address=ENS_MAINNET_ADDR, abi=ENS_ABI, method_name='resolver', arguments=[normal_name_to_hash(normal_name)], ) if is_none_or_zero_address(resolver_addr): return None ens_resolver_abi = ENS_RESOLVER_ABI.copy() arguments = [normal_name_to_hash(normal_name)] if blockchain != SupportedBlockchain.ETHEREUM: ens_resolver_abi.extend(ENS_RESOLVER_ABI_MULTICHAIN_ADDRESS) arguments.append(blockchain.ens_coin_type()) address = self._call_contract( web3=web3, contract_address=to_checksum_address(resolver_addr), abi=ens_resolver_abi, method_name='addr', arguments=arguments, ) if is_none_or_zero_address(address): return None if blockchain != SupportedBlockchain.ETHEREUM: return HexStr(address.hex()) return to_checksum_address(address)
def _prepare_ens_call_arguments(addr: ChecksumEthAddress) -> List[Any]: try: reversed_domain = address_to_reverse_domain(addr) except (TypeError, ValueError) as e: raise InputError(f'Address {addr} has incorrect format or type. {str(e)}') from e normalized_domain_name = normalize_name(reversed_domain) arguments = [normal_name_to_hash(normalized_domain_name)] return arguments
def resolve(self, name, get='addr'): normal_name = normalize_name(name) resolver = self.resolver(normal_name) if resolver: lookup_function = getattr(resolver, get) namehash = normal_name_to_hash(normal_name) return lookup_function(namehash) else: return None
def resolve(self, name: str, get: str='addr') -> Optional[Union[ChecksumAddress, str]]: normal_name = normalize_name(name) resolver = self.resolver(normal_name) if resolver: lookup_function = getattr(resolver.functions, get) namehash = normal_name_to_hash(normal_name) address = lookup_function(namehash).call() if is_none_or_zero_address(address): return None return lookup_function(namehash).call() else: return None
def resolve(self, name, get='addr'): normal_name = normalize_name(name) resolver = self.resolver(normal_name) if resolver: lookup_function = getattr(resolver.functions, get) namehash = normal_name_to_hash(normal_name) address = lookup_function(namehash).call() if is_none_or_zero_address(address): return None return lookup_function(namehash).call() else: return None
def _get_resolver( self, normal_name: str, fn_name: str = 'addr' ) -> Tuple[Optional[Union['Contract', 'AsyncContract']], str]: current_name = normal_name # look for a resolver, starting at the full name and taking the parent each time that no # resolver is found while True: if is_empty_name(current_name): # if no resolver found across all iterations, current_name will eventually be the # empty string '' which returns here return None, current_name resolver_addr = self.ens.caller.resolver(normal_name_to_hash(current_name)) if not is_none_or_zero_address(resolver_addr): # if resolver found, return it return self._type_aware_resolver(resolver_addr, fn_name), current_name # set current_name to parent and try again current_name = self.parent(current_name)
def _reverse_registrar(self) -> 'Contract': addr = self.ens.caller.owner( normal_name_to_hash(REVERSE_REGISTRAR_DOMAIN)) return self.web3.eth.contract(address=addr, abi=abis.REVERSE_REGISTRAR)
def resolver(self, normal_name: str) -> Optional['Contract']: resolver_addr = self.ens.caller.resolver( normal_name_to_hash(normal_name)) if is_none_or_zero_address(resolver_addr): return None return self._resolverContract(address=resolver_addr)
def resolver(self, normal_name): resolver_addr = self.ens.resolver(normal_name_to_hash(normal_name)) if not resolver_addr: return None return self._resolverContract(address=resolver_addr)