#!/usr/bin/env python3 """ Resolve ENS Names for Raid Guild Members This script resolves ENS names for Raid Guild members imported from the CSV file. It updates the contacts with ENS names and profile information, and links them to the data source. """ import os import sys import logging from typing import Dict, Any, List, Optional from web3 import Web3 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 # Load environment variables load_dotenv() # Setup logging logger = setup_logger("raid_guild_ens_resolver") class RaidGuildENSResolver: """Resolver for ENS names of Raid Guild members""" def __init__(self): """Initialize the resolver""" # Initialize database self.db = DatabaseConnector() # Initialize Web3 and ENS resolver alchemy_api_key = os.getenv("ALCHEMY_API_KEY") if not alchemy_api_key: raise ValueError("ALCHEMY_API_KEY not found in environment variables") self.web3 = Web3(Web3.HTTPProvider(f"https://eth-mainnet.g.alchemy.com/v2/{alchemy_api_key}")) self.ens_resolver = ENSResolver(self.web3) # Get data source ID self.data_source_id = self.get_data_source_id() def get_data_source_id(self) -> str: """Get the ID of the Raid Guild DAO CSV data source""" query = 'SELECT id FROM "DataSource" WHERE name = %(name)s' result = self.db.execute_query(query, {"name": "Raid Guild DAO CSV"}) if not result: raise ValueError("Raid Guild DAO CSV data source not found") return result[0]["id"] def get_raid_guild_members(self) -> List[Dict[str, Any]]: """Get all Raid Guild members from the database""" query = """ SELECT c.id, c."ethereumAddress", c."ensName" FROM "Contact" c JOIN "DaoMembership" dm ON c.id = dm."contactId" WHERE dm."daoName" = 'Raid Guild' """ return self.db.execute_query(query) def resolve_ens_for_member(self, contact_id: str, ethereum_address: str, current_ens: Optional[str] = None) -> bool: """ Resolve ENS name for a member and update their profile. Args: contact_id: ID of the contact ethereum_address: Ethereum address of the member current_ens: Current ENS name of the member, if any Returns: True if ENS was resolved or already exists, False otherwise """ # Skip if already has ENS if current_ens: logger.info(f"Contact {contact_id} already has ENS: {current_ens}") # Still update profile from ENS if needed self.ens_resolver.update_contact_from_ens(contact_id, current_ens) # Link to data source self.db.link_contact_to_data_source(contact_id, self.data_source_id) return True # Resolve ENS name ens_name = self.ens_resolver.get_ens_name(ethereum_address) if not ens_name: logger.info(f"No ENS name found for {ethereum_address}") # Still link to data source self.db.link_contact_to_data_source(contact_id, self.data_source_id) return False # Update contact with ENS name self.db.update_contact(contact_id, {"ensName": ens_name}) logger.info(f"Updated contact {contact_id} with ENS name: {ens_name}") # Update profile from ENS self.ens_resolver.update_contact_from_ens(contact_id, ens_name) # Link to data source self.db.link_contact_to_data_source(contact_id, self.data_source_id) return True def run(self): """Run the resolver""" logger.info("Starting ENS resolution for Raid Guild members") # Get all Raid Guild members members = self.get_raid_guild_members() logger.info(f"Found {len(members)} Raid Guild members") # Resolve ENS for each member resolved_count = 0 for member in members: if self.resolve_ens_for_member( member["id"], member["ethereumAddress"], member.get("ensName") ): resolved_count += 1 logger.info(f"Resolved ENS for {resolved_count} out of {len(members)} members") return resolved_count def main(): """Main function""" try: resolver = RaidGuildENSResolver() resolved_count = resolver.run() logger.info(f"ENS resolution completed successfully. Resolved {resolved_count} members.") return 0 except Exception as e: logger.exception(f"Error resolving ENS names: {e}") return 1 if __name__ == "__main__": sys.exit(main())