1use crate::types::{AccountAddress, HashValue};
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub struct EventKey {
15 pub creation_number: u64,
17 pub account_address: AccountAddress,
19}
20
21impl EventKey {
22 pub fn new(creation_number: u64, account_address: AccountAddress) -> Self {
24 Self {
25 creation_number,
26 account_address,
27 }
28 }
29}
30
31impl fmt::Display for EventKey {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{}:{}", self.account_address, self.creation_number)
34 }
35}
36
37#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
39pub struct EventHandle {
40 pub counter: u64,
42 pub guid: EventGuid,
44}
45
46#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
48pub struct EventGuid {
49 pub creation_number: u64,
51 pub account_address: AccountAddress,
53}
54
55#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
57pub struct Event {
58 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub guid: Option<EventGuid>,
61 pub sequence_number: u64,
63 #[serde(rename = "type")]
65 pub typ: String,
66 pub data: serde_json::Value,
68}
69
70impl Event {
71 pub fn event_type(&self) -> &str {
73 &self.typ
74 }
75
76 pub fn data_as<T: for<'de> Deserialize<'de>>(&self) -> Result<T, serde_json::Error> {
82 serde_json::from_value(self.data.clone())
83 }
84}
85
86#[allow(dead_code)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
89pub struct VersionedEvent {
90 pub version: u64,
92 #[serde(flatten)]
94 pub event: Event,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
97 pub transaction_hash: Option<HashValue>,
98}
99
100#[allow(dead_code)] pub mod framework {
103 pub const DEPOSIT_EVENT: &str = "0x1::coin::DepositEvent";
105 pub const WITHDRAW_EVENT: &str = "0x1::coin::WithdrawEvent";
107 pub const ACCOUNT_CREATE_EVENT: &str = "0x1::account::CreateAccountEvent";
109 pub const KEY_ROTATION_EVENT: &str = "0x1::account::KeyRotationEvent";
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_event_key() {
119 let key = EventKey::new(42, AccountAddress::ONE);
120 assert_eq!(key.creation_number, 42);
121 assert_eq!(key.account_address, AccountAddress::ONE);
122 }
123
124 #[test]
125 fn test_event_key_display() {
126 let key = EventKey::new(42, AccountAddress::ONE);
127 let display = format!("{key}");
128 assert!(display.contains("42"));
129 assert!(display.contains(':'));
130 }
131
132 #[test]
133 fn test_event_deserialization() {
134 let json = r#"{
135 "sequence_number": 1,
136 "type": "0x1::coin::DepositEvent",
137 "data": {"amount": "1000"}
138 }"#;
139
140 let event: Event = serde_json::from_str(json).unwrap();
141 assert_eq!(event.sequence_number, 1);
142 assert_eq!(event.typ, "0x1::coin::DepositEvent");
143 }
144
145 #[test]
146 fn test_event_type() {
147 let json = r#"{
148 "sequence_number": 1,
149 "type": "0x1::coin::DepositEvent",
150 "data": {"amount": "1000"}
151 }"#;
152
153 let event: Event = serde_json::from_str(json).unwrap();
154 assert_eq!(event.event_type(), "0x1::coin::DepositEvent");
155 }
156
157 #[test]
158 fn test_event_data_as() {
159 #[derive(serde::Deserialize, Debug, PartialEq)]
160 struct DepositEvent {
161 amount: String,
162 }
163
164 let json = r#"{
165 "sequence_number": 1,
166 "type": "0x1::coin::DepositEvent",
167 "data": {"amount": "1000"}
168 }"#;
169
170 let event: Event = serde_json::from_str(json).unwrap();
171 let data: DepositEvent = event.data_as().unwrap();
172 assert_eq!(data.amount, "1000");
173 }
174
175 #[test]
176 fn test_event_handle_deserialization() {
177 let json = r#"{
178 "counter": 100,
179 "guid": {
180 "creation_number": 5,
181 "account_address": "0x1"
182 }
183 }"#;
184
185 let handle: EventHandle = serde_json::from_str(json).unwrap();
186 assert_eq!(handle.counter, 100);
187 assert_eq!(handle.guid.creation_number, 5);
188 }
189
190 #[test]
191 fn test_event_guid() {
192 let guid = EventGuid {
193 creation_number: 10,
194 account_address: AccountAddress::ONE,
195 };
196 assert_eq!(guid.creation_number, 10);
197 assert_eq!(guid.account_address, AccountAddress::ONE);
198 }
199
200 #[test]
201 fn test_versioned_event_deserialization() {
202 let json = r#"{
203 "version": 12345,
204 "sequence_number": 1,
205 "type": "0x1::coin::DepositEvent",
206 "data": {"amount": "1000"}
207 }"#;
208
209 let event: VersionedEvent = serde_json::from_str(json).unwrap();
210 assert_eq!(event.version, 12345);
211 assert_eq!(event.event.sequence_number, 1);
212 }
213
214 #[test]
215 fn test_framework_event_constants() {
216 assert_eq!(framework::DEPOSIT_EVENT, "0x1::coin::DepositEvent");
217 assert_eq!(framework::WITHDRAW_EVENT, "0x1::coin::WithdrawEvent");
218 assert_eq!(
219 framework::ACCOUNT_CREATE_EVENT,
220 "0x1::account::CreateAccountEvent"
221 );
222 assert_eq!(
223 framework::KEY_ROTATION_EVENT,
224 "0x1::account::KeyRotationEvent"
225 );
226 }
227}