1use crate::chain::ChainId;
4use crate::types::NormalizedValue;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct RawEvent {
12 pub chain: ChainId,
14 pub tx_hash: String,
16 pub block_number: u64,
18 pub block_timestamp: i64,
20 pub log_index: u32,
22 pub topics: Vec<String>,
25 pub data: Vec<u8>,
27 pub address: String,
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub raw_receipt: Option<serde_json::Value>,
32}
33
34impl RawEvent {
35 pub fn evm_event_signature(&self) -> Option<&str> {
37 self.topics.first().map(|s| s.as_str())
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
44pub struct EventFingerprint(pub String);
45
46impl EventFingerprint {
47 pub fn new(hex: impl Into<String>) -> Self {
48 Self(hex.into())
49 }
50
51 pub fn as_hex(&self) -> &str {
52 &self.0
53 }
54}
55
56impl std::fmt::Display for EventFingerprint {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(f, "{}", self.0)
59 }
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct DecodedEvent {
65 pub chain: ChainId,
67 pub schema: String,
69 pub schema_version: u32,
71 pub tx_hash: String,
73 pub block_number: u64,
75 pub block_timestamp: i64,
77 pub log_index: u32,
79 pub address: String,
81 pub fields: HashMap<String, NormalizedValue>,
83 pub fingerprint: EventFingerprint,
85 #[serde(skip_serializing_if = "HashMap::is_empty", default)]
87 pub decode_errors: HashMap<String, String>,
88}
89
90impl DecodedEvent {
91 pub fn field(&self, name: &str) -> Option<&NormalizedValue> {
93 self.fields.get(name)
94 }
95
96 pub fn has_errors(&self) -> bool {
98 !self.decode_errors.is_empty()
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use crate::chain::chains;
106
107 fn sample_raw() -> RawEvent {
108 RawEvent {
109 chain: chains::ethereum(),
110 tx_hash: "0xabc123".into(),
111 block_number: 19_000_000,
112 block_timestamp: 1_700_000_000,
113 log_index: 2,
114 topics: vec![
115 "0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67".into(),
116 ],
117 data: vec![0u8; 32],
118 address: "0xe0554a476a092703abdb3ef35c80e0d76d32939f".into(),
119 raw_receipt: None,
120 }
121 }
122
123 #[test]
124 fn raw_event_evm_signature() {
125 let e = sample_raw();
126 assert!(e.evm_event_signature().unwrap().starts_with("0xc42079"));
127 }
128}