sc_rpc_spec_v2/transaction/
event.rs1use serde::{Deserialize, Serialize};
22
23#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct TransactionBlock<Hash> {
27 pub hash: Hash,
29 pub index: usize,
31}
32
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(rename_all = "camelCase")]
36pub struct TransactionError {
37 pub error: String,
39}
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct TransactionDropped {
45 pub error: String,
47}
48
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
71#[serde(bound(
74 serialize = "Hash: Serialize + Clone",
75 deserialize = "Hash: Deserialize<'de> + Clone"
76))]
77#[serde(into = "TransactionEventIR<Hash>", from = "TransactionEventIR<Hash>")]
78pub enum TransactionEvent<Hash> {
79 Validated,
81 BestChainBlockIncluded(Option<TransactionBlock<Hash>>),
88 Finalized(TransactionBlock<Hash>),
90 Error(TransactionError),
92 Invalid(TransactionError),
94 Dropped(TransactionDropped),
96}
97
98impl<Hash> TransactionEvent<Hash> {
99 pub fn is_final(&self) -> bool {
101 matches!(
102 &self,
103 TransactionEvent::Finalized(_) |
104 TransactionEvent::Error(_) |
105 TransactionEvent::Invalid(_) |
106 TransactionEvent::Dropped(_)
107 )
108 }
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
124#[serde(rename_all = "camelCase")]
125#[serde(tag = "event", content = "block")]
126enum TransactionEventBlockIR<Hash> {
127 BestChainBlockIncluded(Option<TransactionBlock<Hash>>),
129 Finalized(TransactionBlock<Hash>),
131}
132
133#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147#[serde(tag = "event")]
148enum TransactionEventNonBlockIR {
149 Validated,
150 Error(TransactionError),
151 Invalid(TransactionError),
152 Dropped(TransactionDropped),
153}
154
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
163#[serde(bound(serialize = "Hash: Serialize", deserialize = "Hash: Deserialize<'de>"))]
164#[serde(rename_all = "camelCase")]
165#[serde(untagged)]
166enum TransactionEventIR<Hash> {
167 Block(TransactionEventBlockIR<Hash>),
168 NonBlock(TransactionEventNonBlockIR),
169}
170
171impl<Hash> From<TransactionEvent<Hash>> for TransactionEventIR<Hash> {
172 fn from(value: TransactionEvent<Hash>) -> Self {
173 match value {
174 TransactionEvent::Validated => {
175 TransactionEventIR::NonBlock(TransactionEventNonBlockIR::Validated)
176 },
177 TransactionEvent::BestChainBlockIncluded(event) => {
178 TransactionEventIR::Block(TransactionEventBlockIR::BestChainBlockIncluded(event))
179 },
180 TransactionEvent::Finalized(event) => {
181 TransactionEventIR::Block(TransactionEventBlockIR::Finalized(event))
182 },
183 TransactionEvent::Error(event) => {
184 TransactionEventIR::NonBlock(TransactionEventNonBlockIR::Error(event))
185 },
186 TransactionEvent::Invalid(event) => {
187 TransactionEventIR::NonBlock(TransactionEventNonBlockIR::Invalid(event))
188 },
189 TransactionEvent::Dropped(event) => {
190 TransactionEventIR::NonBlock(TransactionEventNonBlockIR::Dropped(event))
191 },
192 }
193 }
194}
195
196impl<Hash> From<TransactionEventIR<Hash>> for TransactionEvent<Hash> {
197 fn from(value: TransactionEventIR<Hash>) -> Self {
198 match value {
199 TransactionEventIR::NonBlock(status) => match status {
200 TransactionEventNonBlockIR::Validated => TransactionEvent::Validated,
201 TransactionEventNonBlockIR::Error(event) => TransactionEvent::Error(event),
202 TransactionEventNonBlockIR::Invalid(event) => TransactionEvent::Invalid(event),
203 TransactionEventNonBlockIR::Dropped(event) => TransactionEvent::Dropped(event),
204 },
205 TransactionEventIR::Block(block) => match block {
206 TransactionEventBlockIR::Finalized(event) => TransactionEvent::Finalized(event),
207 TransactionEventBlockIR::BestChainBlockIncluded(event) => {
208 TransactionEvent::BestChainBlockIncluded(event)
209 },
210 },
211 }
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218 use sp_core::H256;
219
220 #[test]
221 fn validated_event() {
222 let event: TransactionEvent<()> = TransactionEvent::Validated;
223 let ser = serde_json::to_string(&event).unwrap();
224
225 let exp = r#"{"event":"validated"}"#;
226 assert_eq!(ser, exp);
227
228 let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap();
229 assert_eq!(event_dec, event);
230 }
231
232 #[test]
233 fn best_chain_event() {
234 let event: TransactionEvent<()> = TransactionEvent::BestChainBlockIncluded(None);
235 let ser = serde_json::to_string(&event).unwrap();
236
237 let exp = r#"{"event":"bestChainBlockIncluded","block":null}"#;
238 assert_eq!(ser, exp);
239
240 let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap();
241 assert_eq!(event_dec, event);
242
243 let event: TransactionEvent<H256> =
244 TransactionEvent::BestChainBlockIncluded(Some(TransactionBlock {
245 hash: H256::from_low_u64_be(1),
246 index: 2,
247 }));
248 let ser = serde_json::to_string(&event).unwrap();
249
250 let exp = r#"{"event":"bestChainBlockIncluded","block":{"hash":"0x0000000000000000000000000000000000000000000000000000000000000001","index":2}}"#;
251 assert_eq!(ser, exp);
252
253 let event_dec: TransactionEvent<H256> = serde_json::from_str(exp).unwrap();
254 assert_eq!(event_dec, event);
255 }
256
257 #[test]
258 fn finalized_event() {
259 let event: TransactionEvent<H256> = TransactionEvent::Finalized(TransactionBlock {
260 hash: H256::from_low_u64_be(1),
261 index: 10,
262 });
263 let ser = serde_json::to_string(&event).unwrap();
264
265 let exp = r#"{"event":"finalized","block":{"hash":"0x0000000000000000000000000000000000000000000000000000000000000001","index":10}}"#;
266 assert_eq!(ser, exp);
267
268 let event_dec: TransactionEvent<H256> = serde_json::from_str(exp).unwrap();
269 assert_eq!(event_dec, event);
270 }
271
272 #[test]
273 fn error_event() {
274 let event: TransactionEvent<()> =
275 TransactionEvent::Error(TransactionError { error: "abc".to_string() });
276 let ser = serde_json::to_string(&event).unwrap();
277
278 let exp = r#"{"event":"error","error":"abc"}"#;
279 assert_eq!(ser, exp);
280
281 let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap();
282 assert_eq!(event_dec, event);
283 }
284
285 #[test]
286 fn invalid_event() {
287 let event: TransactionEvent<()> =
288 TransactionEvent::Invalid(TransactionError { error: "abc".to_string() });
289 let ser = serde_json::to_string(&event).unwrap();
290
291 let exp = r#"{"event":"invalid","error":"abc"}"#;
292 assert_eq!(ser, exp);
293
294 let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap();
295 assert_eq!(event_dec, event);
296 }
297
298 #[test]
299 fn dropped_event() {
300 let event: TransactionEvent<()> =
301 TransactionEvent::Dropped(TransactionDropped { error: "abc".to_string() });
302 let ser = serde_json::to_string(&event).unwrap();
303
304 let exp = r#"{"event":"dropped","error":"abc"}"#;
305 assert_eq!(ser, exp);
306
307 let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap();
308 assert_eq!(event_dec, event);
309 }
310}