Hemera Doc
  • 👋Welcome
    • Introduction
    • Quick Start
    • Account Centric Indexing Protocol
      • What is Account-Centric Indexing?
      • Why "account-centric" indexing?
      • The advantages of Account-Centric Indexing
      • What's next for account-centric indexing?
      • Why create a new protocol here?
      • The Hemera Network
        • Network Roles
        • Indexers
        • Validators
        • Proprietary models & knowledge
        • Proprietary data and labels
        • Smart Contracts
        • Key roadmap items
        • Supported blockchains
      • Example Hemera use cases
        • SocialScan Explorers
        • Anti-sybil UML algorithm
        • Ethereum long term DA
        • EVM chain history preservation
        • Ecosystem AI Agents
        • User-defined AI Agents
  • 👩‍💻Developer Resources
    • Smart Contract Developers
    • EVM-compatible chains
      • Blockchain explorers
      • SocialScan explorer API doc
      • Ecosystem AI Agents
    • Dapp developers
    • User-defined Agent creators
    • AVS Operator
  • 🖥️Hemera Indexer
    • Introduction
    • Installation
      • Prerequisites
      • Install & Run
      • Export Result
    • Configurations
    • Benchmark
    • Data Class
      • Raw Data Tables
        • Blocks
        • Transactions
        • Logs
        • Traces
      • Generated Tables
        • Contract Internal Transactions
        • ERC20 Token Transfers
        • Tokens
        • ERC20 Token Holders
        • ERC721 Token Transfers
        • ERC721 Token Holders
        • ERC1155 Token Transfers
        • ERC1155 Token Holders
        • Address Coin Balances
        • Address Token Balances
        • Address Current Token Balances
        • Daily Wallet Address Stats
        • Contracts
      • Other Tables
        • Inscriptions
        • Bridges
          • L1 to L2 Transactions
          • L2 to L1 Transactions
          • Optimistic Rollup Data Availability Batches
          • Optimistic Rollup State Batches
    • Use Cases
      • UniSwap V3
        • Data Class
        • Trigger and Function
        • Run & Query
      • ENS
        • Data Class
        • Trigger and Function
        • Run & Query
      • OpenSea
        • Data Class
        • Trigger and Function
        • Run & Query
      • Deposit to L2
        • Data Class
        • Trigger and Function
        • Run & Query
      • User Profile
  • UDFs - User Defined Functions
    • Introduction
    • Components of UDFs
    • Building User Defined Functions(UDF)
    • Testing and Running UDF
    • Troubleshooting and Support
    • Supported UDFs
    • FAQs
  • 😄About us
    • The story behind building Hemera
    • Partners & Backers
    • Partnership inquiries
    • Hemera Powered Explorers
    • Active Developer Hackathons
    • Developer Contribution
  • Documentation feedback
Powered by GitBook
On this page
  1. Hemera Indexer
  2. Use Cases
  3. ENS

Trigger and Function

PreviousData ClassNextRun & Query

Last updated 8 months ago

The ENS job is triggered when an ENS-related transaction occurs or an event is produced. Specifically:

  • NameRegistered: When a user registers an ENS name

def extract(self, address, tp0, log, ens_middle, contract_object_map, event_map, prev_logs=None) -> ENSMiddleD:
    if (tp0 == RegisterExtractor.tp0_register) or (tp0 == self.tp0a):
        event_data = decode_log(log, contract_object_map, event_map)
        tmp = event_data["args"]
        ens_middle.expires = convert_str_ts(tmp.get("expires", ""))
        ens_middle.name = tmp.get("name")
        if "." in ens_middle.name:
            # not supported
            return None
        ens_middle.name = ens_middle.name + ".eth"
        ens_middle.label = tmp.get("label").lower()
        ens_middle.owner = tmp.get("owner").lower()
        ens_middle.base_node = BASE_NODE
        ens_middle.node = namehash(ens_middle.name)
        ens_middle.event_name = event_data["_event"]
        token_id = None
        w_token_id = None
        for log in prev_logs:
            if (
                log["address"] == "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85"
                and log["topic1"] == "0x0000000000000000000000000000000000000000000000000000000000000000"
            ):
                token_id = str(int(log["topic3"], 16))
            if (
                log["address"] == "0xd4416b13d2b3a9abae7acd5d6c2bbdbe25686401"
                and log["topic0"] == "0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62"
            ):
                evd = decode_log(log, contract_object_map, event_map)
                if evd["args"].get("id"):
                    w_token_id = str(evd["args"].get("id"))
        return ENSMiddleD(
            transaction_hash=ens_middle.transaction_hash,
            log_index=ens_middle.log_index,
            transaction_index=ens_middle.transaction_index,
            block_number=ens_middle.block_number,
            block_hash=ens_middle.block_hash,
            block_timestamp=ens_middle.block_timestamp,
            from_address=ens_middle.from_address,
            to_address=ens_middle.to_address,
            expires=ens_middle.expires,
            name=ens_middle.name,
            label=ens_middle.label,
            owner=ens_middle.owner,
            base_node=ens_middle.base_node,
            node=ens_middle.node,
            event_name=ens_middle.event_name,
            method=ens_middle.method,
            token_id=token_id,
            w_token_id=w_token_id,
        )
    else:
        return None

The above code performs the following tasks:

  1. Extracts registration information from the log

  2. Extracts token_id or wrapped token_id from prev_logs

  • NameChanged: When a user sets a primary name (In some cases, there will be no log, so the transaction input needs to be decoded)

def extract(self, address, tp0, log, ens_middle, contract_object_map, event_map, prev_logs=None) -> ENSMiddleD:
    if tp0 == self.tp0:
        event_data = decode_log(log, contract_object_map, event_map)
        tmp = event_data["args"]
        name = tmp.get("name") or ""
        if not name or len(name) - 4 != name.find("."):
            return None
        ens_middle.reverse_name = name
        ens_middle.address = ens_middle.from_address
        ens_middle.node = namehash(name)
        ens_middle.reverse_base_node = REVERSE_BASE_NODE
        ens_middle.reverse_node = str(log["topic1"]).lower()
        ens_middle.event_name = event_data["_event"]
        return ENSMiddleD(
            transaction_hash=ens_middle.transaction_hash,
            log_index=ens_middle.log_index,
            transaction_index=ens_middle.transaction_index,
            block_number=ens_middle.block_number,
            block_hash=ens_middle.block_hash,
            block_timestamp=ens_middle.block_timestamp,
            from_address=ens_middle.from_address,
            to_address=ens_middle.to_address,
            reverse_name=ens_middle.reverse_name,
            address=ens_middle.address,
            node=ens_middle.node,
            reverse_node=ens_middle.reverse_node,
            reverse_base_node=REVERSE_BASE_NODE,
            event_name=ens_middle.event_name,
            method=ens_middle.method,
        )

The above code performs the following tasks:

  1. Decodes the log

  2. Retrieves the ENS name and address

Additionally, when the log does not exist, we need to decode the transaction input:

if method == "setName":
    d_tnx = self.decode_transaction(transaction)
    ens_middle = AttrDict(dic)
    ens_middle.log_index = -1
    name = None
    if d_tnx[1].get("name"):
        name = d_tnx[1]["name"]
    elif d_tnx[1].get("newName"):
        name = d_tnx[1]["newName"]
    if not name or len(name) - 4 != name.find("."):
        return []
    ens_middle.reverse_name = name

    ens_middle.node = namehash(name)
    ens_middle.address = tra["from_address"].lower()
    return [
        ENSMiddleD(
            transaction_hash=ens_middle.transaction_hash,
            log_index=ens_middle.log_index,
            transaction_index=ens_middle.transaction_index,
            block_number=ens_middle.block_number,
            block_hash=ens_middle.block_hash,
            block_timestamp=ens_middle.block_timestamp,
            from_address=ens_middle.from_address,
            to_address=ens_middle.to_address,
            reverse_name=ens_middle.reverse_name,
            address=ens_middle.address,
            node=ens_middle.node,
            reverse_node=None,
            reverse_base_node=REVERSE_BASE_NODE,
            event_name=None,
            method="setName",
        )
    ]
  • AddressChanged: When a user resolves an ENS name to an address. Processing is like the same

def extract(self, address, tp0, log, ens_middle, contract_object_map, event_map, prev_logs=None) -> ENSMiddleD:
    if tp0 == self.tp0:
        event_data = decode_log(log, contract_object_map, event_map)
        tmp = event_data["args"]
        coin_type = tmp["coinType"]
        if not coin_type or str(coin_type) != "60":
            return None
        ens_middle.node = tmp["node"]
        ens_middle.address = tmp["newAddress"].lower()
        ens_middle.event_name = event_data["_event"]
        return ENSMiddleD(
            transaction_hash=ens_middle.transaction_hash,
            log_index=ens_middle.log_index,
            transaction_index=ens_middle.transaction_index,
            block_number=ens_middle.block_number,
            block_hash=ens_middle.block_hash,
            block_timestamp=ens_middle.block_timestamp,
            topic0=tp0,
            from_address=ens_middle.from_address,
            to_address=ens_middle.to_address,
            node=ens_middle.node,
            address=ens_middle.address,
            event_name=ens_middle.event_name,
            method=ens_middle.method,
        )

    return None

newAddress in the event is which address the ens point to.

  • NameRenewed: When a user renews an ENS name. Processing is like the same

def extract(self, address, tp0, log, ens_middle, contract_object_map, event_map, prev_logs=None) -> ENSMiddleD:
    if tp0 == self.tp0:
        event_data = decode_log(log, contract_object_map, event_map)

        tmp = event_data["args"]
        name = tmp.get("name")
        if "." in name:
            return None
        name = name + '.eth'
        ens_middle.name = name
        ens_middle.node = namehash(name)
        ens_middle.label = tmp.get("label").lower()
        ens_middle.expires = convert_str_ts(tmp.get("expires", ""))
        ens_middle.event_name = event_data["_event"]

        return ENSMiddleD(
            transaction_hash=ens_middle.transaction_hash,
            log_index=ens_middle.log_index,
            transaction_index=ens_middle.transaction_index,
            block_number=ens_middle.block_number,
            block_hash=ens_middle.block_hash,
            block_timestamp=ens_middle.block_timestamp,
            topic0=tp0,
            from_address=ens_middle.from_address,
            to_address=ens_middle.to_address,
            name=ens_middle.name,
            node=ens_middle.node,
            label=ens_middle.label,
            expires=ens_middle.expires,
            event_name=ens_middle.event_name,
            method=ens_middle.method,
        )

expires is the new expiration date after renewal.

🖥️
Screenshot of ENS Data
Screenshot of ENS Data
Screenshot of ENS Data
Screenshot of ENS Data