dusk_node_data/events/
contract.rs1use anyhow::Result;
10use dusk_core::abi::{ContractId, Event, CONTRACT_ID_BYTES};
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13pub const ORIGIN_HASH_BYTES: usize = 32;
14pub type OriginHash = [u8; ORIGIN_HASH_BYTES];
17
18#[serde_with::serde_as]
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
21pub struct ContractTxEvent {
22 pub event: ContractEvent,
23 #[serde_as(as = "serde_with::hex::Hex")]
24 pub origin: OriginHash,
25}
26
27#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
28#[repr(C)]
29pub struct WrappedContractId(pub ContractId);
30
31impl TryFrom<String> for WrappedContractId {
32 type Error = anyhow::Error;
33
34 fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
35 let source_bytes = hex::decode(value)?;
36 let mut source_array = [0u8; CONTRACT_ID_BYTES];
37
38 if source_bytes.len() != CONTRACT_ID_BYTES {
39 return Err(anyhow::anyhow!(
40 "Invalid length: expected {} bytes, got {}",
41 CONTRACT_ID_BYTES,
42 source_bytes.len()
43 ));
44 } else {
45 source_array.copy_from_slice(&source_bytes);
46 }
47
48 Ok(WrappedContractId(ContractId::from_bytes(source_array)))
49 }
50}
51
52impl Serialize for WrappedContractId {
53 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
54 where
55 S: Serializer,
56 {
57 let source_hex = hex::encode(self.0.as_bytes());
58 s.serialize_str(&source_hex)
59 }
60}
61
62impl<'de> Deserialize<'de> for WrappedContractId {
63 fn deserialize<D>(deserializer: D) -> Result<WrappedContractId, D::Error>
64 where
65 D: Deserializer<'de>,
66 {
67 let source_hex: String = Deserialize::deserialize(deserializer)?;
68 let source_bytes =
69 hex::decode(source_hex).map_err(serde::de::Error::custom)?;
70 let mut source_array = [0u8; CONTRACT_ID_BYTES];
71
72 if source_bytes.len() != CONTRACT_ID_BYTES {
73 return Err(serde::de::Error::custom(format!(
74 "Invalid length: expected {} bytes, got {}",
75 CONTRACT_ID_BYTES,
76 source_bytes.len()
77 )));
78 } else {
79 source_array.copy_from_slice(&source_bytes);
80 }
81
82 Ok(WrappedContractId(ContractId::from_bytes(source_array)))
83 }
84}
85
86#[serde_with::serde_as]
89#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
90pub struct ContractEvent {
91 pub target: WrappedContractId,
92 pub topic: String,
93 #[serde_as(as = "serde_with::hex::Hex")]
94 pub data: Vec<u8>,
95}
96
97impl From<Event> for ContractEvent {
98 fn from(event: Event) -> Self {
99 Self {
100 target: WrappedContractId(event.source),
101 topic: event.topic,
102 data: event.data,
103 }
104 }
105}
106
107impl From<ContractEvent> for Event {
108 fn from(contract_event: ContractEvent) -> Self {
109 Event {
110 source: contract_event.target.0,
111 topic: contract_event.topic,
112 data: contract_event.data,
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 fn exec_core_event() -> Event {
122 Event {
123 source: ContractId::from_bytes([0; CONTRACT_ID_BYTES]),
124 topic: "contract".to_string(),
125 data: vec![1, 2, 3],
126 }
127 }
128
129 #[test]
130 fn test_converting_contract_event() {
131 let contract_event: ContractEvent = exec_core_event().into();
132
133 assert_eq!(Event::from(contract_event), exec_core_event());
134 }
135
136 #[test]
137 fn test_serialize_contract_event() {
138 let event: ContractEvent = exec_core_event().into();
139 let json_event = serde_json::to_string(&event).unwrap();
140 assert_eq!(event, serde_json::from_str(&json_event).unwrap());
141
142 let events: Vec<ContractEvent> = vec![event.clone(), event];
143 let json_events = serde_json::to_string(&events).unwrap();
144 assert_eq!(
145 events,
146 serde_json::from_str::<Vec<ContractEvent>>(&json_events).unwrap()
147 );
148
149 let empty_events: Vec<ContractEvent> = vec![];
150 let empty_json_events = serde_json::to_string(&empty_events).unwrap();
151 assert_eq!(
152 empty_events,
153 serde_json::from_str::<Vec<ContractEvent>>(&empty_json_events)
154 .unwrap()
155 );
156 }
157}