1use std::str::FromStr;
6
7use anyhow::ensure;
8use iota_sdk_move_types::iota_system::iota_system_state_inner::{
9 SystemEpochInfoEventV1, SystemEpochInfoEventV2,
10};
11use iota_sdk_types::{Event, TransactionDigest};
12use serde::{Deserialize, Serialize};
13use serde_json::Value;
14use serde_with::serde_as;
15
16use crate::iota_serde::{BigInt, Readable};
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct EventEnvelope {
21 pub timestamp: u64,
23 pub tx_digest: TransactionDigest,
25 pub event_num: u64,
27 pub event: Event,
29 pub parsed_json: Value,
31}
32#[serde_as]
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
36#[serde(rename_all = "camelCase")]
37pub struct EventID {
38 pub tx_digest: TransactionDigest,
39 #[serde_as(as = "Readable<BigInt<u64>, _>")]
40 pub event_seq: u64,
41}
42
43impl From<(TransactionDigest, u64)> for EventID {
44 fn from((tx_digest_num, event_seq_number): (TransactionDigest, u64)) -> Self {
45 Self {
46 tx_digest: tx_digest_num as TransactionDigest,
47 event_seq: event_seq_number,
48 }
49 }
50}
51
52impl From<EventID> for String {
53 fn from(id: EventID) -> Self {
54 format!("{:?}:{}", id.tx_digest, id.event_seq)
55 }
56}
57
58impl TryFrom<String> for EventID {
59 type Error = anyhow::Error;
60
61 fn try_from(value: String) -> Result<Self, Self::Error> {
62 let values = value.split(':').collect::<Vec<_>>();
63 ensure!(values.len() == 2, "Malformed EventID : {value}");
64 Ok((
65 TransactionDigest::from_str(values[0])?,
66 u64::from_str(values[1])?,
67 )
68 .into())
69 }
70}
71
72impl EventEnvelope {
73 pub fn new(
74 timestamp: u64,
75 tx_digest: TransactionDigest,
76 event_num: u64,
77 event: Event,
78 move_struct_json_value: Value,
79 ) -> Self {
80 Self {
81 timestamp,
82 tx_digest,
83 event_num,
84 event,
85 parsed_json: move_struct_json_value,
86 }
87 }
88}
89
90#[derive(Deserialize)]
91pub enum SystemEpochInfoEvent {
92 V1(SystemEpochInfoEventV1),
93 V2(SystemEpochInfoEventV2),
94}
95
96impl SystemEpochInfoEvent {
97 pub fn supply_change(&self) -> i64 {
98 match self {
99 SystemEpochInfoEvent::V1(event) => {
100 event.minted_tokens_amount as i64 - event.burnt_tokens_amount as i64
101 }
102 SystemEpochInfoEvent::V2(event) => {
103 event.minted_tokens_amount as i64 - event.burnt_tokens_amount as i64
104 }
105 }
106 }
107}
108
109impl From<Event> for SystemEpochInfoEvent {
110 fn from(event: Event) -> Self {
111 if event.is_system_epoch_info_event_v2() {
112 SystemEpochInfoEvent::V2(
113 bcs::from_bytes::<SystemEpochInfoEventV2>(&event.contents)
114 .expect("event deserialization should succeed as type was pre-validated"),
115 )
116 } else {
117 SystemEpochInfoEvent::V1(
118 bcs::from_bytes::<SystemEpochInfoEventV1>(&event.contents)
119 .expect("event deserialization should succeed as type was pre-validated"),
120 )
121 }
122 }
123}