fe_abi/
event.rs

1use super::types::AbiType;
2
3use fe_common::utils::keccak;
4use serde::Serialize;
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
7pub struct AbiEvent {
8    #[serde(rename = "type")]
9    pub ty: &'static str,
10    pub name: String,
11    pub inputs: Vec<AbiEventField>,
12    pub anonymous: bool,
13}
14
15impl AbiEvent {
16    pub fn new(name: String, fields: Vec<AbiEventField>, anonymous: bool) -> Self {
17        Self {
18            ty: "event",
19            name,
20            inputs: fields,
21            anonymous,
22        }
23    }
24
25    pub fn signature(&self) -> AbiEventSignature {
26        AbiEventSignature::new(self)
27    }
28}
29
30pub struct AbiEventSignature {
31    sig: String,
32}
33
34impl AbiEventSignature {
35    pub fn signature(&self) -> &str {
36        &self.sig
37    }
38
39    pub fn hash_hex(&self) -> String {
40        keccak::full(self.sig.as_bytes())
41    }
42
43    pub fn hash_raw(&self) -> [u8; 32] {
44        keccak::full_as_bytes(self.sig.as_bytes())
45    }
46
47    fn new(event: &AbiEvent) -> Self {
48        let sig = format!(
49            "{}({})",
50            event.name,
51            event
52                .inputs
53                .iter()
54                .map(|input| input.ty.selector_type_name())
55                .collect::<Vec<_>>()
56                .join(",")
57        );
58
59        Self { sig }
60    }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
64pub struct AbiEventField {
65    pub name: String,
66    #[serde(flatten)]
67    pub ty: AbiType,
68    pub indexed: bool,
69}
70
71impl AbiEventField {
72    pub fn new(name: String, ty: impl Into<AbiType>, indexed: bool) -> Self {
73        Self {
74            name,
75            ty: ty.into(),
76            indexed,
77        }
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    use serde_test::{assert_ser_tokens, Token};
86
87    fn test_event() -> AbiEvent {
88        let i32_ty = AbiType::Int(32);
89        let u32_ty = AbiType::UInt(32);
90        let field1 = AbiEventField::new("x".into(), i32_ty, true);
91        let field2 = AbiEventField::new("y".into(), u32_ty, false);
92
93        AbiEvent::new("MyEvent".into(), vec![field1, field2], false)
94    }
95
96    #[test]
97    fn serialize_event() {
98        let event = test_event();
99
100        assert_ser_tokens(
101            &event,
102            &[
103                Token::Struct {
104                    name: "AbiEvent",
105                    len: 4,
106                },
107                Token::Str("type"),
108                Token::Str("event"),
109                Token::String("name"),
110                Token::String("MyEvent"),
111                Token::Str("inputs"),
112                Token::Seq { len: Some(2) },
113                Token::Map { len: None },
114                Token::String("name"),
115                Token::String("x"),
116                Token::String("type"),
117                Token::String("int32"),
118                Token::Str("indexed"),
119                Token::Bool(true),
120                Token::MapEnd,
121                Token::Map { len: None },
122                Token::String("name"),
123                Token::String("y"),
124                Token::String("type"),
125                Token::String("uint32"),
126                Token::Str("indexed"),
127                Token::Bool(false),
128                Token::MapEnd,
129                Token::SeqEnd,
130                Token::Str("anonymous"),
131                Token::Bool(false),
132                Token::StructEnd,
133            ],
134        )
135    }
136
137    #[test]
138    fn event_signature() {
139        let event = test_event();
140
141        let sig = event.signature();
142        debug_assert_eq!(sig.signature(), "MyEvent(int32,uint32)");
143        debug_assert_eq!(
144            sig.hash_hex(),
145            "ec835d5150565cb216f72ba07d715e875b0738b1ac3f412e103839e5157b7ee6"
146        );
147    }
148}