blueprint_tangle_extra/extract/
block_events.rs1use blueprint_core::__composite_rejection as composite_rejection;
2use blueprint_core::__define_rejection as define_rejection;
3use blueprint_core::{FromJobCallParts, job::call::Parts as JobCallParts};
4use tangle_subxt::subxt::events::Events;
5use tangle_subxt::subxt::events::StaticEvent;
6
7use crate::producer::TangleConfig;
8
9#[derive(Debug, Clone)]
11pub struct BlockEvents(pub Events<TangleConfig>);
12
13blueprint_core::__impl_deref!(BlockEvents: Events<TangleConfig>);
14blueprint_core::__impl_from!(Events<TangleConfig>, BlockEvents);
15
16define_rejection! {
17 #[body = "No events found in the extensions. Did you forget to add the `AddBlockEventsLayer`?"]
18 pub struct MissingBlockEvents;
21}
22
23impl TryFrom<&mut JobCallParts> for BlockEvents {
24 type Error = MissingBlockEvents;
25
26 fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
27 let events = parts
28 .extensions
29 .get::<Events<TangleConfig>>()
30 .ok_or(MissingBlockEvents)?;
31 Ok(BlockEvents(events.clone()))
32 }
33}
34
35impl<Ctx> FromJobCallParts<Ctx> for BlockEvents
36where
37 Ctx: Send + Sync,
38{
39 type Rejection = MissingBlockEvents;
40
41 async fn from_job_call_parts(
42 parts: &mut JobCallParts,
43 _: &Ctx,
44 ) -> Result<Self, Self::Rejection> {
45 Self::try_from(parts)
46 }
47}
48
49pub struct FirstEvent<T>(pub T);
51
52pub struct LastEvent<T>(pub T);
54
55pub struct Event<T>(pub Vec<T>);
57
58blueprint_core::__impl_deref!(FirstEvent);
59blueprint_core::__impl_deref!(LastEvent);
60
61define_rejection! {
62 #[body = "No event that matches this event found in the extensions. Did you forget to add the `AddBlockEventsLayer`?"]
63 pub struct MissingEvent;
66}
67
68define_rejection! {
69 #[body = "An error occurred while trying to extract the event from subxt"]
70 pub struct ClientError(Error);
72}
73
74composite_rejection! {
75 pub enum MissingEventRejection {
80 MissingBlockEvents,
81 MissingEvent,
82 ClientError,
83 }
84}
85
86macro_rules! impl_try_from {
87 ($t:ident, $method:ident) => {
88 impl<T> TryFrom<&mut JobCallParts> for $t<T>
89 where
90 T: StaticEvent,
91 {
92 type Error = MissingEventRejection;
93
94 fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
95 let event = parts
96 .extensions
97 .get::<Events<TangleConfig>>()
98 .ok_or(MissingBlockEvents)?
99 .$method::<T>()
100 .map_err(ClientError::from_err)?
101 .ok_or(MissingEvent)?;
102 Ok($t(event))
103 }
104 }
105 };
106}
107impl_try_from!(FirstEvent, find_first);
108impl_try_from!(LastEvent, find_last);
109
110impl<T> TryFrom<&mut JobCallParts> for Event<T>
111where
112 T: StaticEvent,
113{
114 type Error = MissingEventRejection;
115
116 fn try_from(parts: &mut JobCallParts) -> Result<Self, Self::Error> {
117 let events = parts
118 .extensions
119 .get::<Events<TangleConfig>>()
120 .ok_or(MissingBlockEvents)?
121 .find::<T>()
122 .collect::<Result<Vec<T>, _>>()
123 .map_err(ClientError::from_err)?;
124 Ok(Event(events))
125 }
126}
127
128macro_rules! impl_from_job_call_parts {
129 ($t:ident) => {
130 impl<Ctx, T> FromJobCallParts<Ctx> for $t<T>
131 where
132 Ctx: Send + Sync,
133 T: StaticEvent,
134 {
135 type Rejection = MissingEventRejection;
136
137 async fn from_job_call_parts(
138 parts: &mut JobCallParts,
139 _: &Ctx,
140 ) -> Result<Self, Self::Rejection> {
141 Self::try_from(parts)
142 }
143 }
144 };
145}
146
147impl_from_job_call_parts!(FirstEvent);
148impl_from_job_call_parts!(LastEvent);
149impl_from_job_call_parts!(Event);