Quick Start

The Hemera Protocol offers a streamlined approach for developers to build data-driven dApps. The Hemera Indexer, a core component of this protocol, facilitates parallel execution of User-Defined Functions (UDFs) alongside essential indexing tasks, enhancing performance and simplifying complex data workflows.

To get started with Hemera Indexer and UDFs, you can follow this guide:

Set Up Your Development Environment

  • Clone the Repository:

git clone https://github.com/HemeraProtocol/hemera-indexer
  • Install Python 3.9:

    Ensure Python 3.9 is installed on your system. You can download it from the official Python website.

Building from Source is recommended when getting started with UDFs.

Building from Source

  • Install Dependencies and Activate Environment :

    Navigate to the cloned repository and run:

    make development
    source <your-environment>

    Replace <your-environment> with the name of your virtual environment.

  • Switch Branches:

    Depending on your development needs, you may switch between branches:

    git checkout <branch-name>

    Replace <branch-name> with the desired branch.

Writing a UDF

User-Defined Functions (UDFs) in Hemera are designed to streamline the extraction, transformation, and analysis of blockchain data. Here’s how you can create a UDF by defining a dataclass, integrating a model, and writing the job logic.

Define a Dataclass

A dataclass is used to structure the data you will process. It defines the schema for the blockchain data extracted by the Hemera Indexer.

from dataclasses import dataclass

@dataclass
class TransactionData:
    block_number: int
    transaction_hash: str
    sender: str
    receiver: str
    value: float

This example defines a schema for transactions with attributes like block number, transaction hash, sender, receiver, and value.

Learn more about Dataclass in the UDF: Components of UDFs


Create a Model

A model encapsulates the processing logic to transform or compute derived values from the raw data.

class TransactionModel:
    def __init__(self, data: TransactionData):
        self.data = data

    def compute_transaction_fee(self, gas_price: int, gas_used: int) -> float:
        """Calculate transaction fee."""
        return gas_price * gas_used / 1e9

    def to_dict(self):
        """Convert the data to a dictionary for database insertion."""
        return {
            "block_number": self.data.block_number,
            "transaction_hash": self.data.transaction_hash,
            "sender": self.data.sender,
            "receiver": self.data.receiver,
            "value": self.data.value,
        }

This TransactionModel processes the TransactionData and includes additional logic like calculating transaction fees.

Learn more about Model in the UDF section: Components of UDFs


Write the Job Logic

The job logic is where the UDF interacts with the Hemera Indexer to fetch and process blockchain data.

import json
from hemera.udf.base import HemeraJob

class ProcessTransactionsJob(HemeraJob):
    def run(self, block_data):
        """Process each block's transactions."""
        processed_transactions = []
        for transaction in block_data["transactions"]:
            # Map raw transaction data to dataclass
            tx_data = TransactionData(
                block_number=block_data["block_number"],
                transaction_hash=transaction["hash"],
                sender=transaction["from"],
                receiver=transaction["to"],
                value=float(transaction["value"]) / 1e18,  # Convert wei to ETH
            )

            # Process data using model
            model = TransactionModel(tx_data)
            processed_transactions.append(model.to_dict())

        # Output data (to database, file, or another pipeline stage)
        self.output_results(processed_transactions)

    def output_results(self, transactions):
        """Mock function to send results to a database or log output."""
        print(json.dumps(transactions, indent=2))

Here’s what’s happening:

  • The run method processes each block’s transactions.

  • Raw blockchain data is mapped to the TransactionData dataclass.

  • The TransactionModel performs transformations, and the results are formatted for output

Learn more about Job Logic: Components of UDFs


Running the Indexer with UDFs

Once your UDF is ready, it can be deployed and executed alongside the Hemera Indexer. The following example demonstrates how to run the indexer with a demo job:

Command to Execute a Demo Job with UDF

python3 hemera.py stream \
  --provider-uri https://ethereum.publicnode.com \
  --start-block 20804100 \
  --end-block 20804486 \
  --output-types demo_job \
  --block-batch-size 10000 \
  --postgres-url postgresql://uniswap:123asd@localhost:30432/uniswapv3 \
  --output postgres \
  --config-file config/indexer-config-template.yaml

CLI Parameters:

  • --provider-uri: The Ethereum node URL used to fetch blockchain data.

  • --start-block and --end-block: The block range for processing.

  • --output-types: Specifies the job type, here demo_job, to indicate the UDF logic applied.

  • --block-batch-size: Number of blocks processed in each batch for efficient indexing.

  • --postgres-url: PostgreSQL connection URL to store processed data.

  • --output: Specifies the output format, such as postgres.

  • --config-file: Path to the Hemera configuration file.

Learn more about the CLI Parameters: Configurations


Leveraging SocialScan Developer APIs

Hemera offers APIs to build advanced blockchain explorers with features like real-time transactions, token activity, and customizable wallet activity focus.

  • API Documentation:

    Access detailed API documentation to integrate these features into your applications.

Example Applications

Developers can utilize Hemera for various applications, including:

  • DeFi Analytics:

    Track liquidity pools and yield metrics.

  • NFT Monitoring:

    Visualize collections, sales, and holder activity.

  • Social Graphs:

    Map on-chain interactions and relationships.

Last updated