Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/api.nameai.io/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions packages/nameguard-python/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 3 additions & 3 deletions packages/nameguard-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions packages/nameguard-python/coverage_badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions packages/nameguard-python/nameguard/models/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'


Expand Down
52 changes: 36 additions & 16 deletions packages/nameguard-python/nameguard/nameguard.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
205 changes: 0 additions & 205 deletions packages/nameguard-python/nameguard/our_ens.py

This file was deleted.

5 changes: 2 additions & 3 deletions packages/nameguard-python/nameguard/web_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand Down
Loading
Loading