stones/scripts/utils/resolve_ens_for_contacts.py

224 lines
8.4 KiB
Python

#!/usr/bin/env python3
"""
Resolve ENS for Contacts
This script resolves ENS names for all contacts in the database and
updates their profiles with additional information from ENS.
Usage:
python resolve_ens_for_contacts.py
"""
import os
import sys
import time
import json
from dotenv import load_dotenv
# Add parent directory to path to import utils
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.db_connector import DatabaseConnector
from utils.ens_resolver import ENSResolver
from utils.logger import setup_logger
from web3 import Web3
# Load environment variables
load_dotenv()
# Setup logging
logger = setup_logger("resolve_ens_for_contacts")
def resolve_ens_for_contacts():
"""
Resolve ENS names for all contacts in the database and update their profiles.
"""
logger.info("Resolving ENS names for contacts")
db = DatabaseConnector()
# Initialize Web3 and ENS resolver
alchemy_api_key = os.getenv("ALCHEMY_API_KEY")
if not alchemy_api_key:
logger.error("ALCHEMY_API_KEY not found in environment variables")
sys.exit(1)
web3 = Web3(Web3.HTTPProvider(f"https://eth-mainnet.g.alchemy.com/v2/{alchemy_api_key}"))
ens_resolver = ENSResolver(web3)
# Get all contacts without ENS names
query = """
SELECT id, "ethereumAddress"
FROM "Contact"
WHERE "ensName" IS NULL
AND "ethereumAddress" IS NOT NULL
"""
contacts_without_ens = db.execute_query(query)
logger.info(f"Found {len(contacts_without_ens)} contacts without ENS names")
# Resolve ENS names for contacts
contacts_updated = 0
ens_names_found = 0
for contact in contacts_without_ens:
contact_id = contact["id"]
ethereum_address = contact["ethereumAddress"]
try:
# Try to resolve ENS name
ens_name = ens_resolver.get_ens_name(ethereum_address)
if ens_name:
logger.info(f"Found ENS name {ens_name} for address {ethereum_address}")
ens_names_found += 1
# Update contact with ENS name
db.update_contact(contact_id, {"ensName": ens_name})
# Get ENS profile
ens_profile = ens_resolver.get_ens_profile(ens_name)
if ens_profile:
# Extract relevant information from ENS profile
update_data = {}
# Handle Farcaster information
if "farcaster" in ens_profile:
update_data["farcaster"] = json.dumps(ens_profile["farcaster"])
# Handle Twitter
if "com.twitter" in ens_profile:
update_data["twitter"] = ens_profile["com.twitter"]
# Handle Email
if "email" in ens_profile:
update_data["email"] = ens_profile["email"]
# Handle Telegram
if "org.telegram" in ens_profile:
update_data["telegram"] = ens_profile["org.telegram"]
# Handle Discord
if "com.discord" in ens_profile:
update_data["discord"] = ens_profile["com.discord"]
# Handle GitHub
if "com.github" in ens_profile:
update_data["github"] = ens_profile["com.github"]
# Handle URL
if "url" in ens_profile:
update_data["url"] = ens_profile["url"]
# Handle Description
if "description" in ens_profile:
update_data["description"] = ens_profile["description"]
# Handle Avatar
if "avatar" in ens_profile:
update_data["avatar"] = ens_profile["avatar"]
# Handle other social media
other_social = {}
for key, value in ens_profile.items():
if key.startswith("com.") and key not in ["com.twitter", "com.discord", "com.github", "com.farcaster"]:
other_social[key] = value
if other_social:
update_data["otherSocial"] = json.dumps(other_social)
# Update contact with profile information
if update_data:
db.update_contact(contact_id, update_data)
contacts_updated += 1
# Rate limiting to avoid API throttling
time.sleep(0.1)
except Exception as e:
logger.error(f"Error resolving ENS for {ethereum_address}: {str(e)}")
# Get all contacts with ENS names but without profile information
query = """
SELECT id, "ensName"
FROM "Contact"
WHERE "ensName" IS NOT NULL
AND ("twitter" IS NULL AND "email" IS NULL AND "farcaster" IS NULL)
"""
contacts_without_profiles = db.execute_query(query)
logger.info(f"Found {len(contacts_without_profiles)} contacts with ENS names but without profiles")
# Update profiles for contacts with ENS names
for contact in contacts_without_profiles:
contact_id = contact["id"]
ens_name = contact["ensName"]
try:
# Get ENS profile
ens_profile = ens_resolver.get_ens_profile(ens_name)
if ens_profile:
# Extract relevant information from ENS profile
update_data = {}
# Handle Farcaster information
if "farcaster" in ens_profile:
update_data["farcaster"] = json.dumps(ens_profile["farcaster"])
# Handle Twitter
if "com.twitter" in ens_profile:
update_data["twitter"] = ens_profile["com.twitter"]
# Handle Email
if "email" in ens_profile:
update_data["email"] = ens_profile["email"]
# Handle Telegram
if "org.telegram" in ens_profile:
update_data["telegram"] = ens_profile["org.telegram"]
# Handle Discord
if "com.discord" in ens_profile:
update_data["discord"] = ens_profile["com.discord"]
# Handle GitHub
if "com.github" in ens_profile:
update_data["github"] = ens_profile["com.github"]
# Handle URL
if "url" in ens_profile:
update_data["url"] = ens_profile["url"]
# Handle Description
if "description" in ens_profile:
update_data["description"] = ens_profile["description"]
# Handle Avatar
if "avatar" in ens_profile:
update_data["avatar"] = ens_profile["avatar"]
# Handle other social media
other_social = {}
for key, value in ens_profile.items():
if key.startswith("com.") and key not in ["com.twitter", "com.discord", "com.github", "com.farcaster"]:
other_social[key] = value
if other_social:
update_data["otherSocial"] = json.dumps(other_social)
# Update contact with profile information
if update_data:
db.update_contact(contact_id, update_data)
contacts_updated += 1
# Rate limiting to avoid API throttling
time.sleep(0.1)
except Exception as e:
logger.error(f"Error getting profile for {ens_name}: {str(e)}")
logger.info(f"Found {ens_names_found} ENS names")
logger.info(f"Updated {contacts_updated} contact profiles")
logger.info("ENS resolution completed")
if __name__ == "__main__":
resolve_ens_for_contacts()