#!/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()