diff --git a/apps/api.nameai.io/README.md b/apps/api.nameai.io/README.md
index 607e9c08f..95bc77673 100644
--- a/apps/api.nameai.io/README.md
+++ b/apps/api.nameai.io/README.md
@@ -78,8 +78,6 @@ Ensure that Docker and the AWS CLI are installed and configured on your machine.
You need to set up the following environment variables before running the script:
-- `PROVIDER_URI_MAINNET`
-- `PROVIDER_URI_SEPOLIA`
- `ALCHEMY_URI_MAINNET`
- `ALCHEMY_URI_SEPOLIA`
- `ENS_SUBGRAPH_URL_MAINNET`
@@ -93,7 +91,7 @@ If you are using GitHub Actions for deployment, you need to configure the follow
- `AWS_ROLE` - The IAM role to assume for AWS actions.
- `AWS_REGION` - The AWS region where your resources are located.
-- `PROVIDER_URI_MAINNET`, `PROVIDER_URI_SEPOLIA`, `ALCHEMY_URI_MAINNET`, `ALCHEMY_URI_SEPOLIA`, `ENS_SUBGRAPH_URL_MAINNET`, `ENS_SUBGRAPH_URL_SEPOLIA` - The respective URIs for your application.
+- `ALCHEMY_URI_MAINNET`, `ALCHEMY_URI_SEPOLIA`, `ENS_SUBGRAPH_URL_MAINNET`, `ENS_SUBGRAPH_URL_SEPOLIA` - The respective URIs for your application.
- `CERTIFICATE_NAME` - The name of the ACM certificate.
- `HOSTED_ZONE_NAME` - The name of your Route 53 hosted zone.
- `PROD_DOMAIN_NAME` - The production domain name.
diff --git a/packages/nameguard-python/.env.example b/packages/nameguard-python/.env.example
index 2545a203f..5fad07537 100644
--- a/packages/nameguard-python/.env.example
+++ b/packages/nameguard-python/.env.example
@@ -19,3 +19,6 @@ ALCHEMY_URI_SEPOLIA=https://eth-sepolia.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY]
# - https://thegraph.com/explorer/subgraphs/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH?view=Query&chain=arbitrum-one
ENS_SUBGRAPH_URL_MAINNET=https://api.thegraph.com/subgraphs/name/ensdomains/ens
ENS_SUBGRAPH_URL_SEPOLIA=https://api.studio.thegraph.com/query/49574/enssepolia/version/latest
+
+# Use ENSNode API (default is true)
+USE_ENSNODE_API=true
\ No newline at end of file
diff --git a/packages/nameguard-python/README.md b/packages/nameguard-python/README.md
index ad0e8fe4d..0ee6d1d29 100644
--- a/packages/nameguard-python/README.md
+++ b/packages/nameguard-python/README.md
@@ -75,11 +75,11 @@ See the [NameGuard Python README](./apps/api.nameguard.io/README.md) for more de
### Environment Variables
-NameGuard uses the specified Provider endpoints (e.g. Alchemy, Infura, your own Ethereum node, etc...) for `secure-primary-name/`. Provider endpoints have to be set by environment variables, e.g.:
+NameGuard uses the ENSNode API for primary name lookups in `secure-primary-name`. The ENSNode API only returns normalized primary names, so unnormalized primary names are treated as having no primary name.
+
+For `fake-eth-name-check`, NameGuard uses Alchemy endpoints. Alchemy endpoints have to be set by environment variables, e.g.:
```bash
-export PROVIDER_URI_MAINNET=https://eth-mainnet.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY]
-export PROVIDER_URI_SEPOLIA=https://eth-sepolia.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY]
export ALCHEMY_URI_MAINNET=https://eth-mainnet.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY]
export ALCHEMY_URI_SEPOLIA=https://eth-sepolia.g.alchemy.com/v2/[YOUR_ALCHEMY_API_KEY]
export ENS_SUBGRAPH_URL_MAINNET="https://gateway-arbitrum.network.thegraph.com/api/[YOUR_SUBGRAPH_API_KEY]/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH"
diff --git a/packages/nameguard-python/coverage_badge.svg b/packages/nameguard-python/coverage_badge.svg
index 607d3de4d..a8c7e72ad 100644
--- a/packages/nameguard-python/coverage_badge.svg
+++ b/packages/nameguard-python/coverage_badge.svg
@@ -15,7 +15,7 @@
coverage
coverage
- 91%
- 91%
+ 92%
+ 92%
diff --git a/packages/nameguard-python/nameguard/models/result.py b/packages/nameguard-python/nameguard/models/result.py
index 4432a9f5e..e0b0de05e 100644
--- a/packages/nameguard-python/nameguard/models/result.py
+++ b/packages/nameguard-python/nameguard/models/result.py
@@ -344,14 +344,14 @@ class SecurePrimaryNameStatus(str, Enum):
The status of a secure primary ENS name lookup performed by NameGuard.
* `normalized`: The ENS primary name was found and it is normalized.
- * `no_primary_name`: The ENS primary name was not found.
- * `unnormalized`: The ENS primary name was found, but it is not normalized.
+ * `no_primary_name`: The ENS primary name was not found, or the primary name is unnormalized.
+ The ENSNode API only returns normalized primary names, so unnormalized primary names
+ are treated as having no primary name.
* `uninspected`: The name was exceptionally long and was not inspected for performance reasons.
"""
NORMALIZED = 'normalized'
NO_PRIMARY_NAME = 'no_primary_name'
- UNNORMALIZED = 'unnormalized'
UNINSPECTED = 'uninspected'
diff --git a/packages/nameguard-python/nameguard/nameguard.py b/packages/nameguard-python/nameguard/nameguard.py
index 90139e48f..481f87e52 100644
--- a/packages/nameguard-python/nameguard/nameguard.py
+++ b/packages/nameguard-python/nameguard/nameguard.py
@@ -1,17 +1,16 @@
import os
import re
-from typing import Union
+from typing import Union, Optional
from nameguard.models.checks import UNINSPECTED_CHECK_RESULT
from nameguard.models.result import UninspectedNameGuardReport
-from nameguard.our_ens import OurENS
from ens_normalize import is_ens_normalized, ens_cure, DisallowedSequence, ens_process
+import httpx
import requests
from label_inspector.inspector import Inspector
from label_inspector.config import initialize_inspector_config
from label_inspector.models import InspectorConfusableGraphemeResult, InspectorResult
-from web3 import HTTPProvider
from web3.exceptions import ContractLogicError
from dotenv import load_dotenv
@@ -169,15 +168,6 @@ class NameGuard:
def __init__(self):
self._inspector = init_inspector()
load_dotenv()
- # TODO use web sockets and async
- self.ns = {}
- for network_name, env_var in (
- (NetworkName.MAINNET, 'PROVIDER_URI_MAINNET'),
- (NetworkName.SEPOLIA, 'PROVIDER_URI_SEPOLIA'),
- ):
- if os.environ.get(env_var) is None:
- logger.warning(f'Environment variable {env_var} is not set')
- self.ns[network_name] = OurENS(HTTPProvider(os.environ.get(env_var)))
# optimization
self.eth_label = self._inspector.analyse_label('eth', simple_confusables=True, omit_cure=True)
@@ -447,11 +437,42 @@ def _inspect_confusable(self, grapheme: InspectorConfusableGraphemeResult) -> Co
is_canonical=False,
)
+ async def get_primary_name(self, address: str, network_name: NetworkName) -> Optional[str]:
+ """
+ Looks up the primary ENS name for an address using the ENSNode API.
+
+ The ENSNode API only returns normalized primary names. If the primary name
+ is unnormalized, this method returns None.
+
+ Args:
+ address: The Ethereum address to look up
+ network_name: The network to query (MAINNET or SEPOLIA)
+
+ Returns:
+ The normalized primary name, or None if no primary name exists or
+ the primary name is unnormalized.
+ """
+ if network_name == NetworkName.MAINNET:
+ url = f'https://api.alpha.ensnode.io/api/resolve/primary-name/{address}/1'
+ elif network_name == NetworkName.SEPOLIA:
+ url = f'http://api.alpha-sepolia.ensnode.io/api/resolve/primary-name/{address}/11155111'
+ else:
+ raise ValueError(f'Unsupported network: {network_name}')
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get(url, params={'accelerate': 'true'})
+ if response.status_code == 404:
+ return None
+ response.raise_for_status()
+ return response.json().get('name')
+
async def secure_primary_name(
self, address: str, network_name: str, return_nameguard_report: bool = False
) -> SecurePrimaryNameResult:
try:
- domain = self.ns[network_name].name(address)
+ domain = await self.get_primary_name(address, network_name)
+ except (httpx.RequestError, httpx.HTTPStatusError) as ex:
+ raise ProviderUnavailable(f'Communication error with ENSNode API occurred: {ex}')
except requests.exceptions.ConnectionError as ex:
raise ProviderUnavailable(f'Communication error with provider occurred: {ex}')
except ContractLogicError:
@@ -462,17 +483,16 @@ async def secure_primary_name(
primary_name = None
nameguard_report = None
if domain is None:
+ # ENSNode API returns None for addresses with no primary name or unnormalized primary names
status = SecurePrimaryNameStatus.NO_PRIMARY_NAME
impersonation_estimate = None
else:
+ # If ENSNode API returns a name, it's guaranteed to be normalized
nameguard_report = await self.inspect_name(network_name, domain)
if nameguard_report.highest_risk and nameguard_report.highest_risk.check.name == Check.UNINSPECTED.name:
status = SecurePrimaryNameStatus.UNINSPECTED
impersonation_estimate = None
- elif nameguard_report.normalization == Normalization.UNNORMALIZED:
- status = SecurePrimaryNameStatus.UNNORMALIZED
- impersonation_estimate = None
else:
display_name = nameguard_report.beautiful_name
status = SecurePrimaryNameStatus.NORMALIZED
diff --git a/packages/nameguard-python/nameguard/our_ens.py b/packages/nameguard-python/nameguard/our_ens.py
deleted file mode 100644
index dabef27e3..000000000
--- a/packages/nameguard-python/nameguard/our_ens.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2016 The Ethereum Foundation
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-# import json
-from functools import wraps
-from typing import Optional, Union, Tuple, cast
-
-from ens.constants import ENS_EXTENDED_RESOLVER_INTERFACE_ID, EMPTY_SHA3_BYTES
-from ens.ens import _resolver_supports_interface, ENS
-from ens.exceptions import ENSValidationError, ENSValueError
-from ens.utils import address_to_reverse_domain, is_empty_name, is_none_or_zero_address, Web3
-
-# from ens.utils import normalize_name
-from eth_typing import ChecksumAddress
-from eth_utils import to_checksum_address, is_address, to_bytes
-from hexbytes import HexBytes
-from web3.contract import Contract
-
-
-def label_to_hash(label: str) -> HexBytes:
- # label = normalize_name(label)
- if '.' in label:
- raise ENSValueError(f"Cannot generate hash for label {label!r} with a '.'")
- return Web3().keccak(text=label)
-
-
-def normal_name_to_hash(name: str) -> HexBytes:
- """
- Hashes a pre-normalized name.
- The normalization of the name is a prerequisite and is not handled by this function.
-
- :param str name: A normalized name string to be hashed.
- :return: namehash - the hash of the name
- :rtype: HexBytes
- """
- node = EMPTY_SHA3_BYTES
- if not is_empty_name(name):
- labels = name.split('.')
- for label in reversed(labels):
- labelhash = label_to_hash(label)
- assert isinstance(labelhash, bytes)
- assert isinstance(node, bytes)
- node = Web3().keccak(node + labelhash)
- return node
-
-
-def raw_name_to_hash(name: str) -> HexBytes:
- """
- Generate the namehash. This is also known as the ``node`` in ENS contracts.
-
- In normal operation, generating the namehash is handled
- behind the scenes. For advanced usage, it is a helpful utility.
-
- This normalizes the name with `nameprep
- `_ # blocklint: pragma # noqa: E501
- before hashing.
-
- :param str name: ENS name to hash
- :return: the namehash
- :rtype: bytes
- :raises InvalidName: if ``name`` has invalid syntax
- """
- # normalized_name = normalize_name(name)
- normalized_name = name
- return normal_name_to_hash(normalized_name)
-
-
-def ens_encode_name(name: str) -> bytes:
- r"""
- Encode a name according to DNS standards specified in section 3.1
- of RFC1035 with the following validations:
-
- - There is no limit on the total length of the encoded name
- and the limit on labels is the ENS standard of 255.
-
- - Return a single 0-octet, b'\x00', if empty name.
-
- :param str name: the dot-separated ENS name
- """
- if is_empty_name(name):
- return b'\x00'
-
- # normalized_name = normalize_name(name)
- normalized_name = name
-
- labels = normalized_name.split('.')
- labels_as_bytes = [to_bytes(text=label) for label in labels]
-
- # raises if len(label) > 255:
- for index, label in enumerate(labels):
- if len(label) > 255:
- raise ENSValidationError(f'Label at position {index} too long after encoding.')
-
- # concat label size in bytes to each label:
- dns_prepped_labels = [to_bytes(len(label)) + label for label in labels_as_bytes]
-
- # return the joined prepped labels in order and append the zero byte at the end:
- return b''.join(dns_prepped_labels) + b'\x00'
-
-
-class OurENS(ENS):
- """
- Name normalization is disabled.
- """
-
- def name(self, address: ChecksumAddress) -> Optional[str]:
- """
- Look up the name that the address points to, using a
- reverse lookup. Reverse lookup is opt-in for name owners.
-
- :param address:
- :type address: hex-string
- """
- reversed_domain = address_to_reverse_domain(address)
- name = self._resolve(reversed_domain, fn_name='name')
-
- # To be absolutely certain of the name, via reverse resolution,
- # the address must match in the forward resolution
- return name if to_checksum_address(address) == self.address(name) else None
-
- def resolver(self, name: str) -> Optional['Contract']:
- """
- Get the resolver for an ENS name.
-
- :param str name: The ENS name
- """
- # normal_name = normalize_name(name)
- normal_name = name
- return self._get_resolver(normal_name)[0]
-
- @staticmethod
- @wraps(raw_name_to_hash)
- def namehash(name: str) -> HexBytes:
- return raw_name_to_hash(name)
-
- def _resolve(self, name: str, fn_name: str = 'addr') -> Optional[Union[ChecksumAddress, str]]: # OK
- # normal_name = normalize_name(name)
- normal_name = name
- resolver, current_name = self._get_resolver(normal_name, fn_name)
- if not resolver:
- return None
-
- node = self.namehash(normal_name)
-
- # handle extended resolver case
- if _resolver_supports_interface(resolver, ENS_EXTENDED_RESOLVER_INTERFACE_ID):
- contract_func_with_args = (fn_name, [node])
-
- calldata = resolver.encode_abi(*contract_func_with_args)
- contract_call_result = resolver.caller.resolve(
- ens_encode_name(normal_name),
- calldata,
- )
- result = self._decode_ensip10_resolve_data(contract_call_result, resolver, fn_name)
- return to_checksum_address(result) if is_address(result) else result
- elif normal_name == current_name:
- lookup_function = getattr(resolver.functions, fn_name)
- result = lookup_function(node).call()
- if is_none_or_zero_address(result):
- return None
- return to_checksum_address(result) if is_address(result) else result
- return None
-
- def _get_resolver(
- self,
- normal_name: str,
- fn_name: str = 'addr',
- ) -> Tuple[Optional['Contract'], 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
- resolver = cast('Contract', self._type_aware_resolver(resolver_addr, fn_name))
- return resolver, current_name
-
- # set current_name to parent and try again
- current_name = self.parent(current_name)
diff --git a/packages/nameguard-python/nameguard/web_api.py b/packages/nameguard-python/nameguard/web_api.py
index 2fa52ada3..f5ae3fab5 100644
--- a/packages/nameguard-python/nameguard/web_api.py
+++ b/packages/nameguard-python/nameguard/web_api.py
@@ -494,9 +494,8 @@ async def secure_primary_name_get(
"""
## Performs a reverse lookup of an Ethereum `address` to a primary name.
- Data sources for the primary name lookup include:
- 1. The Ethereum Provider configured in the NameGuard instance.
- 2. For ENS names using CCIP-Read: requests to externally defined gateway servers.
+ The primary name lookup uses the ENSNode API, which only returns normalized primary names.
+ If an address has an unnormalized primary name, it will be treated as having no primary name.
Returns `display_name` to be shown to users and estimates `impersonation_estimate`.
diff --git a/packages/nameguard-python/tests/conftest.py b/packages/nameguard-python/tests/conftest.py
index 210fb1d99..40306b1bf 100644
--- a/packages/nameguard-python/tests/conftest.py
+++ b/packages/nameguard-python/tests/conftest.py
@@ -46,20 +46,22 @@ async def mock_get_nft_metadata(contract_address: str, token_id: str) -> dict:
monkeypatch.setattr('nameguard.nameguard.get_nft_metadata', mock_get_nft_metadata)
- original_name = nameguard.nameguard.OurENS.name
+ original_get_primary_name = nameguard.nameguard.NameGuard.get_primary_name
- def mock_name(self, address):
+ async def mock_get_primary_name(self, address: str, network_name):
try:
- return json.load(open(f'{TESTS_DATA_PATH}/name__{address}.json'))
+ return json.load(open(f'{TESTS_DATA_PATH}/primary_name__{address.lower()}.json'))
except FileNotFoundError:
- result = original_name(self, address)
+ result = await original_get_primary_name(self, address, network_name)
json.dump(
- result, open(f'{TESTS_DATA_PATH}/NEW-name__{address}.json', 'w'), indent=2, ensure_ascii=False
+ result,
+ open(f'{TESTS_DATA_PATH}/NEW-primary_name__{address.lower()}.json', 'w'),
+ indent=2,
+ ensure_ascii=False,
)
raise
- # monkeypatch.setattr('nameguard.our_ens.OurENS.name', mock_name)
- monkeypatch.setattr('nameguard.nameguard.OurENS.name', mock_name)
+ monkeypatch.setattr('nameguard.nameguard.NameGuard.get_primary_name', mock_get_primary_name)
original_call_subgraph = nameguard.subgraph.call_subgraph
diff --git a/packages/nameguard-python/tests/data/name__0x0d756ee0e8c250f88f5e0edd7c723dc3a0bf75cf.json b/packages/nameguard-python/tests/data/name__0x0d756ee0e8c250f88f5e0edd7c723dc3a0bf75cf.json
deleted file mode 100644
index 06d40c591..000000000
--- a/packages/nameguard-python/tests/data/name__0x0d756ee0e8c250f88f5e0edd7c723dc3a0bf75cf.json
+++ /dev/null
@@ -1 +0,0 @@
-"сбер.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x0ebdfd75d33c05025074fd7845848d44966ab367.json b/packages/nameguard-python/tests/data/name__0x0ebdfd75d33c05025074fd7845848d44966ab367.json
deleted file mode 100644
index 16aa8a8b2..000000000
--- a/packages/nameguard-python/tests/data/name__0x0ebdfd75d33c05025074fd7845848d44966ab367.json
+++ /dev/null
@@ -1 +0,0 @@
-"۸۸۷۵۴۲.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x744ec0a91d420c257ae3ee471b79b1a6a0312e36.json b/packages/nameguard-python/tests/data/name__0x744ec0a91d420c257ae3ee471b79b1a6a0312e36.json
deleted file mode 100644
index 03078d635..000000000
--- a/packages/nameguard-python/tests/data/name__0x744ec0a91d420c257ae3ee471b79b1a6a0312e36.json
+++ /dev/null
@@ -1 +0,0 @@
-"hello!.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x76fd9b1b2d8f2cd9ba06c925506627883f97b97c.json b/packages/nameguard-python/tests/data/name__0x76fd9b1b2d8f2cd9ba06c925506627883f97b97c.json
deleted file mode 100644
index f0193cb2b..000000000
--- a/packages/nameguard-python/tests/data/name__0x76fd9b1b2d8f2cd9ba06c925506627883f97b97c.json
+++ /dev/null
@@ -1 +0,0 @@
-"❤.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x7c7160a23b32402ad24ed5a617b8a83f434642d4.json b/packages/nameguard-python/tests/data/name__0x7c7160a23b32402ad24ed5a617b8a83f434642d4.json
deleted file mode 100644
index 38eb973cb..000000000
--- a/packages/nameguard-python/tests/data/name__0x7c7160a23b32402ad24ed5a617b8a83f434642d4.json
+++ /dev/null
@@ -1 +0,0 @@
-"vincξnt.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x7da3cde891a76416ec9d1c3354b8efe550bd4e20.json b/packages/nameguard-python/tests/data/name__0x7da3cde891a76416ec9d1c3354b8efe550bd4e20.json
deleted file mode 100644
index 5a1e00fc6..000000000
--- a/packages/nameguard-python/tests/data/name__0x7da3cde891a76416ec9d1c3354b8efe550bd4e20.json
+++ /dev/null
@@ -1 +0,0 @@
-"vitȧlik.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x9d32572997da4948063e3fc11c2552eb82f7208e.json b/packages/nameguard-python/tests/data/name__0x9d32572997da4948063e3fc11c2552eb82f7208e.json
deleted file mode 100644
index 560c2c6c2..000000000
--- a/packages/nameguard-python/tests/data/name__0x9d32572997da4948063e3fc11c2552eb82f7208e.json
+++ /dev/null
@@ -1 +0,0 @@
-"poet.base.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xaf738f6c83d7d2c46723b727ce794f9c79cc47e6.json b/packages/nameguard-python/tests/data/name__0xaf738f6c83d7d2c46723b727ce794f9c79cc47e6.json
deleted file mode 100644
index d17efd43a..000000000
--- a/packages/nameguard-python/tests/data/name__0xaf738f6c83d7d2c46723b727ce794f9c79cc47e6.json
+++ /dev/null
@@ -1 +0,0 @@
-"୨୨୨୨୨.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xb281405429c3bc91e52707a21754cdacecbb035e.json b/packages/nameguard-python/tests/data/name__0xb281405429c3bc91e52707a21754cdacecbb035e.json
deleted file mode 100644
index 61244c056..000000000
--- a/packages/nameguard-python/tests/data/name__0xb281405429c3bc91e52707a21754cdacecbb035e.json
+++ /dev/null
@@ -1 +0,0 @@
-"┣▇▇▇═─.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14.json b/packages/nameguard-python/tests/data/name__0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14.json
deleted file mode 100644
index a7bb1543d..000000000
--- a/packages/nameguard-python/tests/data/name__0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14.json
+++ /dev/null
@@ -1 +0,0 @@
-"vıtalik.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xf537a27f31d7a014c5b8008a0069c61f827fa7a1.json b/packages/nameguard-python/tests/data/name__0xf537a27f31d7a014c5b8008a0069c61f827fa7a1.json
deleted file mode 100644
index 616459ebb..000000000
--- a/packages/nameguard-python/tests/data/name__0xf537a27f31d7a014c5b8008a0069c61f827fa7a1.json
+++ /dev/null
@@ -1 +0,0 @@
-"٠٠۱.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xfa9a134f997b3d48e122d043e12d04e909b11073.json b/packages/nameguard-python/tests/data/name__0xfa9a134f997b3d48e122d043e12d04e909b11073.json
deleted file mode 100644
index 52ba0c2cf..000000000
--- a/packages/nameguard-python/tests/data/name__0xfa9a134f997b3d48e122d043e12d04e909b11073.json
+++ /dev/null
@@ -1 +0,0 @@
-"888.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xd8da6bf26964af9d7eed9e03e53415d37aa96046.json b/packages/nameguard-python/tests/data/primary_name__0x0d756ee0e8c250f88f5e0edd7c723dc3a0bf75cf.json
similarity index 100%
rename from packages/nameguard-python/tests/data/name__0xd8da6bf26964af9d7eed9e03e53415d37aa96046.json
rename to packages/nameguard-python/tests/data/primary_name__0x0d756ee0e8c250f88f5e0edd7c723dc3a0bf75cf.json
diff --git a/packages/nameguard-python/tests/data/primary_name__0x0ebdfd75d33c05025074fd7845848d44966ab367.json b/packages/nameguard-python/tests/data/primary_name__0x0ebdfd75d33c05025074fd7845848d44966ab367.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x0ebdfd75d33c05025074fd7845848d44966ab367.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0x2211d1d0020daea8039e46cf1367962070d77da9.json b/packages/nameguard-python/tests/data/primary_name__0x2211d1d0020daea8039e46cf1367962070d77da9.json
new file mode 100644
index 000000000..0d1a8b339
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x2211d1d0020daea8039e46cf1367962070d77da9.json
@@ -0,0 +1 @@
+"jesse.base.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x63a93f5843ad57d756097ef102a2886f05c7a29c.json b/packages/nameguard-python/tests/data/primary_name__0x63a93f5843ad57d756097ef102a2886f05c7a29c.json
similarity index 100%
rename from packages/nameguard-python/tests/data/name__0x63a93f5843ad57d756097ef102a2886f05c7a29c.json
rename to packages/nameguard-python/tests/data/primary_name__0x63a93f5843ad57d756097ef102a2886f05c7a29c.json
diff --git a/packages/nameguard-python/tests/data/primary_name__0x744ec0a91d420c257ae3ee471b79b1a6a0312e36.json b/packages/nameguard-python/tests/data/primary_name__0x744ec0a91d420c257ae3ee471b79b1a6a0312e36.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x744ec0a91d420c257ae3ee471b79b1a6a0312e36.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0x76fd9b1b2d8f2cd9ba06c925506627883f97b97c.json b/packages/nameguard-python/tests/data/primary_name__0x76fd9b1b2d8f2cd9ba06c925506627883f97b97c.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x76fd9b1b2d8f2cd9ba06c925506627883f97b97c.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0x7c7160a23b32402ad24ed5a617b8a83f434642d4.json b/packages/nameguard-python/tests/data/primary_name__0x7c7160a23b32402ad24ed5a617b8a83f434642d4.json
new file mode 100644
index 000000000..27dca9a91
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x7c7160a23b32402ad24ed5a617b8a83f434642d4.json
@@ -0,0 +1 @@
+"pudgyvincent.eth"
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0x7da3cde891a76416ec9d1c3354b8efe550bd4e20.json b/packages/nameguard-python/tests/data/primary_name__0x7da3cde891a76416ec9d1c3354b8efe550bd4e20.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x7da3cde891a76416ec9d1c3354b8efe550bd4e20.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0x8ae0e6dd8eace27045d9e017c8cf6daa9d08c776.json b/packages/nameguard-python/tests/data/primary_name__0x8ae0e6dd8eace27045d9e017c8cf6daa9d08c776.json
similarity index 100%
rename from packages/nameguard-python/tests/data/name__0x8ae0e6dd8eace27045d9e017c8cf6daa9d08c776.json
rename to packages/nameguard-python/tests/data/primary_name__0x8ae0e6dd8eace27045d9e017c8cf6daa9d08c776.json
diff --git a/packages/nameguard-python/tests/data/name__0x8b7863d67e1083ee1becbdd277cbbff1c1ccb631.json b/packages/nameguard-python/tests/data/primary_name__0x8b7863d67e1083ee1becbdd277cbbff1c1ccb631.json
similarity index 100%
rename from packages/nameguard-python/tests/data/name__0x8b7863d67e1083ee1becbdd277cbbff1c1ccb631.json
rename to packages/nameguard-python/tests/data/primary_name__0x8b7863d67e1083ee1becbdd277cbbff1c1ccb631.json
diff --git a/packages/nameguard-python/tests/data/primary_name__0x9d32572997da4948063e3fc11c2552eb82f7208e.json b/packages/nameguard-python/tests/data/primary_name__0x9d32572997da4948063e3fc11c2552eb82f7208e.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0x9d32572997da4948063e3fc11c2552eb82f7208e.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0xaf738f6c83d7d2c46723b727ce794f9c79cc47e6.json b/packages/nameguard-python/tests/data/primary_name__0xaf738f6c83d7d2c46723b727ce794f9c79cc47e6.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0xaf738f6c83d7d2c46723b727ce794f9c79cc47e6.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0xb281405429c3bc91e52707a21754cdacecbb035e.json b/packages/nameguard-python/tests/data/primary_name__0xb281405429c3bc91e52707a21754cdacecbb035e.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0xb281405429c3bc91e52707a21754cdacecbb035e.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14.json b/packages/nameguard-python/tests/data/primary_name__0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xd8da6bf26964af9d7eed9e03e53415d37aa96045.json b/packages/nameguard-python/tests/data/primary_name__0xd8da6bf26964af9d7eed9e03e53415d37aa96045.json
similarity index 100%
rename from packages/nameguard-python/tests/data/name__0xd8da6bf26964af9d7eed9e03e53415d37aa96045.json
rename to packages/nameguard-python/tests/data/primary_name__0xd8da6bf26964af9d7eed9e03e53415d37aa96045.json
diff --git a/packages/nameguard-python/tests/data/primary_name__0xd8da6bf26964af9d7eed9e03e53415d37aa96046.json b/packages/nameguard-python/tests/data/primary_name__0xd8da6bf26964af9d7eed9e03e53415d37aa96046.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0xd8da6bf26964af9d7eed9e03e53415d37aa96046.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/name__0xf4a4d9c75da65d507cfcd5ff0acb73d40d3a3bcb.json b/packages/nameguard-python/tests/data/primary_name__0xf4a4d9c75da65d507cfcd5ff0acb73d40d3a3bcb.json
similarity index 100%
rename from packages/nameguard-python/tests/data/name__0xf4a4d9c75da65d507cfcd5ff0acb73d40d3a3bcb.json
rename to packages/nameguard-python/tests/data/primary_name__0xf4a4d9c75da65d507cfcd5ff0acb73d40d3a3bcb.json
diff --git a/packages/nameguard-python/tests/data/primary_name__0xf537a27f31d7a014c5b8008a0069c61f827fa7a1.json b/packages/nameguard-python/tests/data/primary_name__0xf537a27f31d7a014c5b8008a0069c61f827fa7a1.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0xf537a27f31d7a014c5b8008a0069c61f827fa7a1.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/data/primary_name__0xfa9a134f997b3d48e122d043e12d04e909b11073.json b/packages/nameguard-python/tests/data/primary_name__0xfa9a134f997b3d48e122d043e12d04e909b11073.json
new file mode 100644
index 000000000..ec747fa47
--- /dev/null
+++ b/packages/nameguard-python/tests/data/primary_name__0xfa9a134f997b3d48e122d043e12d04e909b11073.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/packages/nameguard-python/tests/test_api.py b/packages/nameguard-python/tests/test_api.py
index e2809b096..5ceff0d18 100644
--- a/packages/nameguard-python/tests/test_api.py
+++ b/packages/nameguard-python/tests/test_api.py
@@ -266,7 +266,13 @@ def test_bulk_inspect_name_post_stress(test_client):
'vitalik.eth',
),
('mainnet', '0xe0fe380f4d877f643e88ceabbed4e5ee0efb66f079aabba23e8902336f7948da', 404, None),
- ('sepolia', '0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835', 200, 'vitalik.eth'),
+ pytest.param(
+ 'sepolia',
+ '0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835',
+ 200,
+ 'vitalik.eth',
+ marks=pytest.mark.xfail(reason='Sepolia subgraph is not working'),
+ ),
],
)
def test_inspect_namehash_get(
@@ -313,11 +319,11 @@ def test_inspect_namehash_get(
'unknown',
'[3fddf465ed81d79ae943b35800b1d187dc0b5d69614bf7e8ebddbae19d72cae8].genevaswis.eth',
),
- (
- '0x00f52438ae09d2f909ee2efc19ba8af75058e74ca4507aa091bd8282aa490e77',
- 'unknown',
- '🥛.[2e8eaa68c7e128861299162323c29c29672f5c094aceaf22d9c0935e4bbd3f85].🛸.👽.enspunks.eth',
- ),
+ # (
+ # '0x00f52438ae09d2f909ee2efc19ba8af75058e74ca4507aa091bd8282aa490e77',
+ # 'unknown',
+ # '🥛.[2e8eaa68c7e128861299162323c29c29672f5c094aceaf22d9c0935e4bbd3f85].🛸.👽.enspunks.eth',
+ # ), # now it is known
pytest.param(
'0x1bc53f6413409d078ec18a29b17f981eafab341598a4e970ac9efab7d29258af',
'unnormalized',
@@ -387,10 +393,10 @@ def test_inspect_namehash_get_root(test_client):
'0xb2636b6e3b1abdd3fbec454d4f4b1a904e7b15e3609cb208bcfc5a5487293308',
'[3fddf465ed81d79ae943b35800b1d187dc0b5d69614bf7e8ebddbae19d72cae8].genevaswis.eth',
),
- (
- '0x00f52438ae09d2f909ee2efc19ba8af75058e74ca4507aa091bd8282aa490e77',
- '[7710d5ebf94bcebcf1996bb7a3f5e24a6d24435b314b3cec815da03640c2940c].[2e8eaa68c7e128861299162323c29c29672f5c094aceaf22d9c0935e4bbd3f85].[a64d2b5a93eda272d27734cc2fb8d1c468562e279f1e97e759eea1a5a410f8e3].[462a1d6391f7ea5916874504f3b5fc8cd43626f6bbabc8a22fe4312dc1585362].enspunks.eth',
- ),
+ # (
+ # '0x00f52438ae09d2f909ee2efc19ba8af75058e74ca4507aa091bd8282aa490e77',
+ # '[7710d5ebf94bcebcf1996bb7a3f5e24a6d24435b314b3cec815da03640c2940c].[2e8eaa68c7e128861299162323c29c29672f5c094aceaf22d9c0935e4bbd3f85].[a64d2b5a93eda272d27734cc2fb8d1c468562e279f1e97e759eea1a5a410f8e3].[462a1d6391f7ea5916874504f3b5fc8cd43626f6bbabc8a22fe4312dc1585362].enspunks.eth',
+ # ), # now it is known
],
)
def test_inspect_namehash_get_unknown(test_client, namehash: str, expected_name: str):
@@ -644,14 +650,14 @@ def test_inspect_grapheme_multi(test_client):
'٧٣٧.eth',
),
(
- '0x9d32572997DA4948063E3Fc11c2552Eb82F7208E',
+ '0x2211d1D0020DAEA8039E46Cf1367962070d77DA9',
'unlikely',
'normalized',
- 'poet.base.eth',
- 'poet.base.eth',
- 'poet.base.eth',
+ 'jesse.base.eth',
+ 'jesse.base.eth',
+ 'jesse.base.eth',
False,
- 'poet.base.eth',
+ 'jesse.base.eth',
),
(
'0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96046',
@@ -666,7 +672,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0xfA9A134f997b3d48e122d043E12d04E909b11073',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed fa9a',
None,
@@ -676,7 +682,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0x76fd9b1B2d8F2cd9Ba06c925506627883F97B97C',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed 76fd',
None,
@@ -686,7 +692,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0xf537a27F31d7A014c5b8008a0069c61f827fA7A1',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed f537',
None,
@@ -696,7 +702,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0x0ebDfD75d33c05025074fd7845848D44966AB367',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed 0ebd',
None,
@@ -706,7 +712,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0xaf738F6C83d7D2C46723b727Ce794F9c79Cc47E6',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed af73',
None,
@@ -716,7 +722,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0xb281405429C3bc91e52707a21754cDaCeCbB035E',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed b281',
None,
@@ -726,7 +732,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0x0d756ee0e8C250f88f5e0eDd7C723dc3A0BF75cF',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed 0d75',
None,
@@ -736,7 +742,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0x7Da3CdE891a76416ec9D1c3354B8EfE550Bd4e20',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed 7da3',
'vitalik.eth',
@@ -746,7 +752,7 @@ def test_inspect_grapheme_multi(test_client):
(
'0xC9f598BC5BB554B6A15A96D19954B041C9FDbF14',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed c9f5',
'vitalik.eth',
@@ -757,16 +763,16 @@ def test_inspect_grapheme_multi(test_client):
'0x7c7160A23b32402ad24ED5a617b8a83f434642d4',
'unlikely',
'normalized',
- 'vincξnt.eth',
- 'vincΞnt.eth',
- 'vincξnt.eth',
+ 'pudgyvincent.eth',
+ 'pudgyvincent.eth',
+ 'pudgyvincent.eth',
False,
- 'vincξnt.eth',
+ 'pudgyvincent.eth',
),
(
'0x744Ec0A91D420c257aE3eE471B79B1A6a0312E36',
None,
- 'unnormalized',
+ 'no_primary_name',
None,
'Unnamed 744e',
None,
@@ -864,15 +870,15 @@ def test_primary_name_get_uppercase(test_client):
@pytest.mark.flaky(retries=2, condition=not pytest.use_monkeypatch)
def test_primary_name_get_offchain(test_client):
- address = '0x9d32572997DA4948063E3Fc11c2552Eb82F7208E'
+ address = '0x2211d1D0020DAEA8039E46Cf1367962070d77DA9'
response = test_client.get(f'/secure-primary-name/mainnet/{address}')
assert response.status_code == 200
res_json = response.json()
print(res_json)
assert res_json['impersonation_estimate'] == 'unlikely'
assert res_json['primary_name_status'] == 'normalized'
- assert res_json['primary_name'] == 'poet.base.eth'
- assert res_json['display_name'] == 'poet.base.eth'
+ assert res_json['primary_name'] == 'jesse.base.eth'
+ assert res_json['display_name'] == 'jesse.base.eth'
@pytest.mark.flaky(retries=2, condition=not pytest.use_monkeypatch)
@@ -896,24 +902,11 @@ def test_primary_name_get_unnormalized(test_client):
res_json = response.json()
print(res_json)
assert res_json['impersonation_estimate'] is None
- assert res_json['primary_name_status'] == 'unnormalized'
+ assert res_json['primary_name_status'] == 'no_primary_name'
assert res_json['primary_name'] is None
assert res_json['display_name'] == 'Unnamed fa9a'
-@pytest.mark.flaky(retries=2, condition=not pytest.use_monkeypatch)
-def test_primary_name_get_uninspected(test_client):
- address = '0xf4A4D9C75dA65d507cfcd5ff0aCB73D40D3A3bCB'
- response = test_client.get(f'/secure-primary-name/mainnet/{address}')
- assert response.status_code == 200
- res_json = response.json()
- print(res_json)
- assert res_json['impersonation_estimate'] is None
- assert res_json['primary_name_status'] == 'uninspected'
- assert res_json['primary_name'] is None
- assert res_json['display_name'] == 'Unnamed f4a4'
-
-
def test_primary_name_get_invalid_address(test_client):
address = '0xfA9A134f997b3d48e122d043E12d04E909b1107g'
response = test_client.get(f'/secure-primary-name/mainnet/{address}')
diff --git a/packages/nameguard-python/tests/test_nameguard.py b/packages/nameguard-python/tests/test_nameguard.py
index 7d00781d7..062dd2170 100644
--- a/packages/nameguard-python/tests/test_nameguard.py
+++ b/packages/nameguard-python/tests/test_nameguard.py
@@ -372,6 +372,16 @@ async def test_namehash_non_null_name(nameguard: NameGuard):
)
+@pytest.mark.asyncio
+@pytest.mark.xfail(reason='Sepolia subgraph is not working')
+async def test_namehash_sepolia(nameguard: NameGuard):
+ network_name = 'sepolia'
+ r = await nameguard.inspect_namehash(
+ network_name, '0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835'
+ )
+ assert r.name == 'vitalik.eth'
+
+
@pytest.mark.flaky(retries=2, condition=not pytest.use_monkeypatch)
@pytest.mark.asyncio
@pytest.mark.xfail
@@ -643,14 +653,14 @@ async def test_dynamic_check_order(nameguard: NameGuard):
assert r.checks[1].check == Check.TYPING_DIFFICULTY
assert r.checks[1].status == CheckStatus.WARN
- # normalized is ALERT but impersonation risk is WARN
- r = await nameguard.secure_primary_name(
- '0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14', 'mainnet', return_nameguard_report=True
- )
- assert r.nameguard_report.checks[0].check == Check.NORMALIZED
- assert r.nameguard_report.checks[0].status == CheckStatus.ALERT
- assert r.nameguard_report.checks[1].check == Check.TYPING_DIFFICULTY
- assert r.nameguard_report.checks[1].status == CheckStatus.WARN
+ # normalized is ALERT but impersonation risk is WARN - impossible now
+ # r = await nameguard.secure_primary_name(
+ # '0xc9f598bc5bb554b6a15a96d19954b041c9fdbf14', 'mainnet', return_nameguard_report=True
+ # )
+ # assert r.nameguard_report.checks[0].check == Check.NORMALIZED
+ # assert r.nameguard_report.checks[0].status == CheckStatus.ALERT
+ # assert r.nameguard_report.checks[1].check == Check.TYPING_DIFFICULTY
+ # assert r.nameguard_report.checks[1].status == CheckStatus.WARN
r = await nameguard.secure_primary_name(
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 'mainnet', return_nameguard_report=True
@@ -673,16 +683,46 @@ async def test_dynamic_check_order(nameguard: NameGuard):
endpoint_name.set(None)
+@pytest.mark.asyncio
+async def test_secure_primary_name(nameguard: NameGuard):
+ network = 'mainnet'
+ r = await nameguard.secure_primary_name(
+ '0x2211d1D0020DAEA8039E46Cf1367962070d77DA9', network, return_nameguard_report=True
+ )
+ assert r.primary_name_status == 'normalized'
+
+
@pytest.mark.asyncio
async def test_secure_primary_name_error(nameguard: NameGuard, monkeypatch):
network = 'mainnet'
- monkeypatch.setattr(nameguard.ns[network], 'name', lambda address: (_ for _ in ()).throw(Exception('Error')))
+
+ async def mock_get_primary_name_error(self, address, network_name):
+ raise Exception('Error')
+
+ monkeypatch.setattr(NameGuard, 'get_primary_name', mock_get_primary_name_error)
r = await nameguard.secure_primary_name(
- '0xFD9eE68000Dc92aa6c67F8f6EB5d9d1a24086fAd', network, return_nameguard_report=True
+ '0x2211d1D0020DAEA8039E46Cf1367962070d77DA9', network, return_nameguard_report=True
)
assert r.primary_name_status == 'no_primary_name'
+@pytest.mark.asyncio
+async def test_secure_primary_name_uninspected(nameguard: NameGuard, monkeypatch):
+ network = 'mainnet'
+
+ async def mock_get_primary_name_error(self, address, network_name):
+ return '●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●.eth'
+
+ monkeypatch.setattr(NameGuard, 'get_primary_name', mock_get_primary_name_error)
+ r = await nameguard.secure_primary_name(
+ '0xf4A4D9C75dA65d507cfcd5ff0aCB73D40D3A3bCB', network, return_nameguard_report=True
+ )
+ assert r.primary_name_status == 'uninspected'
+ assert r.impersonation_estimate is None
+ assert r.primary_name is None
+ assert r.display_name == 'Unnamed f4a4'
+
+
@pytest.mark.asyncio
async def test_stress_inspect_name(nameguard: NameGuard):
# with omit_cure=False takes 1 minute
diff --git a/packages/nameguard-sdk/src/index.test.ts b/packages/nameguard-sdk/src/index.test.ts
index efaaff50d..42ac4539f 100644
--- a/packages/nameguard-sdk/src/index.test.ts
+++ b/packages/nameguard-sdk/src/index.test.ts
@@ -150,49 +150,43 @@ describe("getSecurePrimaryName", () => {
expect(data.nameguard_report).toBeNull();
});
- it("getSecurePrimaryName: unnormalized", async () => {
+ it("getSecurePrimaryName: unnormalized (treated as no_primary_name)", async () => {
const data = await nameguard.getSecurePrimaryName(
"0xfA9A134f997b3d48e122d043E12d04E909b11073",
{ returnNameGuardReport: true },
);
- expect(data.primary_name_status).toBe("unnormalized");
+ expect(data.primary_name_status).toBe("no_primary_name");
expect(data.impersonation_estimate).toBeNull();
expect(data.primary_name).toBeNull();
expect(data.display_name).toBe("Unnamed fa9a");
- expect(data.nameguard_report).not.toBeNull();
- expect(data.nameguard_report?.name).toBe("888.eth");
- expect(data.nameguard_report?.canonical_name).toBeNull();
+ expect(data.nameguard_report).toBeNull();
});
- it("getSecurePrimaryName: unnormalized with canonical", async () => {
+ it("getSecurePrimaryName: unnormalized with canonical (treated as no_primary_name)", async () => {
const data = await nameguard.getSecurePrimaryName(
"0xaf738F6C83d7D2C46723b727Ce794F9c79Cc47E6",
{ returnNameGuardReport: true },
);
- expect(data.primary_name_status).toBe("unnormalized");
+ expect(data.primary_name_status).toBe("no_primary_name");
expect(data.impersonation_estimate).toBeNull();
expect(data.primary_name).toBeNull();
expect(data.display_name).toBe("Unnamed af73");
- expect(data.nameguard_report).not.toBeNull();
- expect(data.nameguard_report?.name).toBe("୨୨୨୨୨.eth");
- expect(data.nameguard_report?.canonical_name).toBeNull();
+ expect(data.nameguard_report).toBeNull();
});
- it("getSecurePrimaryName: unnormalized but normalizable", async () => {
+ it("getSecurePrimaryName: unnormalized but normalizable (treated as no_primary_name)", async () => {
const data = await nameguard.getSecurePrimaryName(
"0xf537a27F31d7A014c5b8008a0069c61f827fA7A1",
{ returnNameGuardReport: true },
);
- expect(data.primary_name_status).toBe("unnormalized");
+ expect(data.primary_name_status).toBe("no_primary_name");
expect(data.impersonation_estimate).toBeNull();
expect(data.primary_name).toBeNull();
expect(data.display_name).toBe("Unnamed f537");
- expect(data.nameguard_report).not.toBeNull();
- expect(data.nameguard_report?.name).toBe("٠٠۱.eth");
- expect(data.nameguard_report?.canonical_name).toBeNull();
+ expect(data.nameguard_report).toBeNull();
});
it("getSecurePrimaryName: normalized with different display_name", async () => {
@@ -210,18 +204,17 @@ describe("getSecurePrimaryName", () => {
expect(data.nameguard_report?.canonical_name).toBe("vincξnt.eth");
});
- it("getSecurePrimaryName: attempted code injection with primary name", async () => {
+ it("getSecurePrimaryName: attempted code injection with primary name (treated as no_primary_name)", async () => {
const data = await nameguard.getSecurePrimaryName(
"0x744Ec0A91D420c257aE3eE471B79B1A6a0312E36",
{ returnNameGuardReport: true },
);
- expect(data.primary_name_status).toBe("unnormalized");
+ expect(data.primary_name_status).toBe("no_primary_name");
expect(data.impersonation_estimate).toBeNull();
expect(data.primary_name).toBeNull();
expect(data.display_name).toBe("Unnamed 744e");
- expect(data.nameguard_report).not.toBeNull();
- expect(data.nameguard_report?.name).toBe("hello!.eth");
+ expect(data.nameguard_report).toBeNull();
expect(data.nameguard_report?.canonical_name).toBeNull();
});
});
diff --git a/packages/nameguard-sdk/src/index.ts b/packages/nameguard-sdk/src/index.ts
index 5442f14c3..95962757f 100644
--- a/packages/nameguard-sdk/src/index.ts
+++ b/packages/nameguard-sdk/src/index.ts
@@ -89,8 +89,8 @@ export enum Rating {
*/
export type SecurePrimaryNameStatus =
| "normalized" /** The ENS primary name was found and it is normalized. */
- | "no_primary_name" /** The ENS primary name was not found. */
- | "unnormalized" /** The ENS primary name was found, but it is not normalized. */
+ | "no_primary_name" /** The ENS primary name was not found, or the primary name is unnormalized. The ENSNode API only returns normalized primary names, so unnormalized primary names are treated as having no primary name. */
+ | "unnormalized" /** @deprecated This status is no longer returned. Unnormalized primary names are now treated as having no primary name. */
| "uninspected" /** A name was exceptionally long and was not inspected for performance reasons */;
export type ImpersonationEstimate =
@@ -688,9 +688,8 @@ export class NameGuard {
/**
* Performs a reverse lookup of an Ethereum `address` to a primary name.
*
- * Data sources for the primary name lookup include:
- * 1. The Ethereum Provider configured in the NameGuard instance.
- * 2. For ENS names using CCIP-Read: requests to externally defined gateway servers.
+ * The primary name lookup uses the ENSNode API, which only returns normalized primary names.
+ * If an address has an unnormalized primary name, it will be treated as having no primary name.
*
* Returns `display_name` to be shown to users and estimates `impersonation_estimate`
*