eth-etl-core 0.1.0

Core types and utilities for Ethereum ETL
Documentation
use serde::{Deserialize, Serialize};

/// Event log emitted by smart contracts
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct EthLog {
    #[serde(rename = "type", default = "default_log_type")]
    pub item_type: String,
    pub log_index: u64,
    pub transaction_hash: String,
    pub transaction_index: u64,
    pub block_hash: String,
    pub block_number: u64,
    pub address: String,
    pub data: String,
    pub topics: Vec<String>,
    // Flattened topics for CSV export
    #[serde(skip_serializing_if = "Option::is_none")]
    pub topic0: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub topic1: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub topic2: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub topic3: Option<String>,
}

fn default_log_type() -> String {
    "log".to_string()
}

impl EthLog {
    /// Flatten topics into individual fields
    pub fn flatten_topics(&mut self) {
        self.topic0 = self.topics.first().cloned();
        self.topic1 = self.topics.get(1).cloned();
        self.topic2 = self.topics.get(2).cloned();
        self.topic3 = self.topics.get(3).cloned();
    }

    /// Get CSV headers for log export
    pub fn csv_headers() -> &'static [&'static str] {
        &[
            "log_index",
            "transaction_hash",
            "transaction_index",
            "block_hash",
            "block_number",
            "address",
            "data",
            "topic0",
            "topic1",
            "topic2",
            "topic3",
        ]
    }

    /// Convert to CSV row
    pub fn to_csv_row(&self) -> Vec<String> {
        vec![
            self.log_index.to_string(),
            self.transaction_hash.clone(),
            self.transaction_index.to_string(),
            self.block_hash.clone(),
            self.block_number.to_string(),
            self.address.clone(),
            self.data.clone(),
            self.topic0.clone().unwrap_or_default(),
            self.topic1.clone().unwrap_or_default(),
            self.topic2.clone().unwrap_or_default(),
            self.topic3.clone().unwrap_or_default(),
        ]
    }
}