Example #1
0
    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)
Example #2
0
    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)
Example #3
0
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
Example #4
0
 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
Example #5
0
 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
Example #6
0
 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
Example #7
0
    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)
Example #8
0
 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)
Example #9
0
 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)
Example #10
0
 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)