1use crate::types::{AccountAddress, HashValue};
14use serde::{Deserialize, Serialize};
15use std::fmt;
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
21pub struct EventKey {
22 pub creation_number: u64,
24 pub account_address: AccountAddress,
26}
27
28impl EventKey {
29 pub fn new(creation_number: u64, account_address: AccountAddress) -> Self {
31 Self {
32 creation_number,
33 account_address,
34 }
35 }
36}
37
38impl fmt::Display for EventKey {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 write!(f, "{}:{}", self.account_address, self.creation_number)
41 }
42}
43
44#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
50pub struct EventHandle {
51 #[serde(with = "crate::types::string_num")]
53 pub counter: u64,
54 pub guid: EventHandleGuid,
56}
57
58#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
63pub struct EventHandleGuid {
64 pub id: EventHandleGuidId,
66}
67
68#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
70pub struct EventHandleGuidId {
71 pub addr: AccountAddress,
73 #[serde(with = "crate::types::string_num")]
75 pub creation_num: u64,
76}
77
78#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
85pub struct EventGuid {
86 #[serde(with = "crate::types::string_num")]
88 pub creation_number: u64,
89 pub account_address: AccountAddress,
91}
92
93#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
95pub struct Event {
96 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub guid: Option<EventGuid>,
99 #[serde(with = "crate::types::string_num")]
101 pub sequence_number: u64,
102 #[serde(rename = "type")]
104 pub typ: String,
105 pub data: serde_json::Value,
107}
108
109impl Event {
110 pub fn event_type(&self) -> &str {
112 &self.typ
113 }
114
115 pub fn data_as<T: for<'de> Deserialize<'de>>(&self) -> Result<T, serde_json::Error> {
121 serde_json::from_value(self.data.clone())
122 }
123}
124
125#[allow(dead_code)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
128pub struct VersionedEvent {
129 #[serde(with = "crate::types::string_num")]
131 pub version: u64,
132 #[serde(flatten)]
134 pub event: Event,
135 #[serde(default, skip_serializing_if = "Option::is_none")]
137 pub transaction_hash: Option<HashValue>,
138}
139
140#[allow(dead_code)] pub mod framework {
143 pub const DEPOSIT_EVENT: &str = "0x1::coin::DepositEvent";
145 pub const WITHDRAW_EVENT: &str = "0x1::coin::WithdrawEvent";
147 pub const ACCOUNT_CREATE_EVENT: &str = "0x1::account::CreateAccountEvent";
149 pub const KEY_ROTATION_EVENT: &str = "0x1::account::KeyRotationEvent";
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn test_event_key() {
159 let key = EventKey::new(42, AccountAddress::ONE);
160 assert_eq!(key.creation_number, 42);
161 assert_eq!(key.account_address, AccountAddress::ONE);
162 }
163
164 #[test]
165 fn test_event_key_display() {
166 let key = EventKey::new(42, AccountAddress::ONE);
167 let display = format!("{key}");
168 assert!(display.contains("42"));
169 assert!(display.contains(':'));
170 }
171
172 #[test]
173 fn test_event_deserialization() {
174 let json = r#"{
175 "sequence_number": 1,
176 "type": "0x1::coin::DepositEvent",
177 "data": {"amount": "1000"}
178 }"#;
179
180 let event: Event = serde_json::from_str(json).unwrap();
181 assert_eq!(event.sequence_number, 1);
182 assert_eq!(event.typ, "0x1::coin::DepositEvent");
183 }
184
185 #[test]
186 fn test_event_type() {
187 let json = r#"{
188 "sequence_number": 1,
189 "type": "0x1::coin::DepositEvent",
190 "data": {"amount": "1000"}
191 }"#;
192
193 let event: Event = serde_json::from_str(json).unwrap();
194 assert_eq!(event.event_type(), "0x1::coin::DepositEvent");
195 }
196
197 #[test]
198 fn test_event_data_as() {
199 #[derive(serde::Deserialize, Debug, PartialEq)]
200 struct DepositEvent {
201 amount: String,
202 }
203
204 let json = r#"{
205 "sequence_number": 1,
206 "type": "0x1::coin::DepositEvent",
207 "data": {"amount": "1000"}
208 }"#;
209
210 let event: Event = serde_json::from_str(json).unwrap();
211 let data: DepositEvent = event.data_as().unwrap();
212 assert_eq!(data.amount, "1000");
213 }
214
215 #[test]
216 fn test_event_handle_deserialization() {
217 let json = r#"{
220 "counter": "100",
221 "guid": {
222 "id": {
223 "addr": "0x1",
224 "creation_num": "5"
225 }
226 }
227 }"#;
228
229 let handle: EventHandle = serde_json::from_str(json).unwrap();
230 assert_eq!(handle.counter, 100);
231 assert_eq!(handle.guid.id.creation_num, 5);
232 assert_eq!(handle.guid.id.addr, AccountAddress::ONE);
233 }
234
235 #[test]
236 fn test_event_handle_roundtrips_to_api_shape() {
237 let handle = EventHandle {
238 counter: 7,
239 guid: EventHandleGuid {
240 id: EventHandleGuidId {
241 addr: AccountAddress::ONE,
242 creation_num: 3,
243 },
244 },
245 };
246 let json = serde_json::to_value(&handle).unwrap();
247 assert_eq!(json["counter"], serde_json::json!("7"));
249 assert_eq!(json["guid"]["id"]["creation_num"], serde_json::json!("3"));
250 let back: EventHandle = serde_json::from_value(json).unwrap();
251 assert_eq!(back, handle);
252 }
253
254 #[test]
255 fn test_event_deserialization_api_shape() {
256 let json = r#"{
259 "guid": {
260 "creation_number": "2",
261 "account_address": "0x1"
262 },
263 "sequence_number": "42",
264 "type": "0x1::coin::DepositEvent",
265 "data": {"amount": "1000"}
266 }"#;
267
268 let event: Event = serde_json::from_str(json).unwrap();
269 assert_eq!(event.sequence_number, 42);
270 assert_eq!(event.typ, "0x1::coin::DepositEvent");
271 let guid = event.guid.expect("guid present");
272 assert_eq!(guid.creation_number, 2);
273 assert_eq!(guid.account_address, AccountAddress::ONE);
274 }
275
276 #[test]
277 fn test_event_guid() {
278 let guid = EventGuid {
279 creation_number: 10,
280 account_address: AccountAddress::ONE,
281 };
282 assert_eq!(guid.creation_number, 10);
283 assert_eq!(guid.account_address, AccountAddress::ONE);
284 }
285
286 #[test]
287 fn test_versioned_event_deserialization() {
288 let json = r#"{
289 "version": 12345,
290 "sequence_number": 1,
291 "type": "0x1::coin::DepositEvent",
292 "data": {"amount": "1000"}
293 }"#;
294
295 let event: VersionedEvent = serde_json::from_str(json).unwrap();
296 assert_eq!(event.version, 12345);
297 assert_eq!(event.event.sequence_number, 1);
298 }
299
300 #[test]
301 fn test_framework_event_constants() {
302 assert_eq!(framework::DEPOSIT_EVENT, "0x1::coin::DepositEvent");
303 assert_eq!(framework::WITHDRAW_EVENT, "0x1::coin::WithdrawEvent");
304 assert_eq!(
305 framework::ACCOUNT_CREATE_EVENT,
306 "0x1::account::CreateAccountEvent"
307 );
308 assert_eq!(
309 framework::KEY_ROTATION_EVENT,
310 "0x1::account::KeyRotationEvent"
311 );
312 }
313}