iota_sdk_graphql_client/api/
events.rs1use cynic::QueryBuilder;
8use futures::Stream;
9
10use crate::{
11 GraphQLClient,
12 api::define_query,
13 error::GraphQLResult,
14 pagination::{Page, PaginationFilter, PaginationFilterResponse},
15 query_types::{Event, EventFilter, EventsQueryArgs, EventsQueryFragment},
16 streams::stream_paginated_query,
17};
18
19define_query! {
20 #[derive(Clone)]
22 pub struct ListEventsQuery {
23 client: GraphQLClient,
24 filter: Option<EventFilter>,
25 pagination: PaginationFilter,
26 }
27 output: GraphQLResult<Page<Event>>;
28}
29
30impl ListEventsQuery {
31 pub fn filter(mut self, filter: EventFilter) -> Self {
33 self.filter = Some(filter);
34 self
35 }
36
37 pub fn pagination(mut self, pagination: PaginationFilter) -> Self {
39 self.pagination = pagination;
40 self
41 }
42
43 pub fn stream(self) -> impl Stream<Item = GraphQLResult<Event>> + Unpin {
46 let pagination = self.pagination.clone();
47 stream_paginated_query(move |page| self.clone().pagination(page).send(), pagination)
48 }
49
50 fn operation<'a>(
51 filter: Option<EventFilter>,
52 pagination: &'a PaginationFilterResponse,
53 ) -> cynic::Operation<EventsQueryFragment, EventsQueryArgs<'a>> {
54 EventsQueryFragment::build(EventsQueryArgs {
55 filter,
56 after: pagination.after.as_deref(),
57 before: pagination.before.as_deref(),
58 first: pagination.first,
59 last: pagination.last,
60 })
61 }
62
63 async fn send(self) -> GraphQLResult<Page<Event>> {
64 let Self {
65 client,
66 pagination,
67 filter,
68 } = self;
69 let pagination = client.pagination_filter(pagination).await;
70 let response = client
71 .run_query(&Self::operation(filter, &pagination))
72 .await?;
73
74 let ec = response.events;
75 let page_info = ec.page_info;
76
77 let events = ec.nodes;
78
79 Ok(Page::new(page_info, events))
80 }
81}
82
83impl GraphQLClient {
84 pub fn events(&self) -> ListEventsQuery {
86 ListEventsQuery {
87 client: self.clone(),
88 filter: None,
89 pagination: PaginationFilter::default(),
90 }
91 }
92}
93
94#[cfg(all(test, not(target_arch = "wasm32")))]
95mod tests {
96 use iota_types::Address;
97
98 use crate::{
99 query_types::EventFilter,
100 test_utils::{
101 assert_backward_page, assert_forward_page, backward_page, forward_page, sent_variables,
102 test_client,
103 },
104 };
105
106 #[tokio::test]
107 async fn events_sends_the_filter_and_pagination() {
108 let vars = sent_variables("EventsQueryFragment", |client| async move {
109 let _ = client
110 .events()
111 .filter(EventFilter {
112 sender: Some(Address::FRAMEWORK),
113 ..Default::default()
114 })
115 .pagination(backward_page())
116 .await;
117 })
118 .await;
119 assert_eq!(vars["filter"]["sender"], Address::FRAMEWORK.to_string());
120 assert_backward_page(&vars);
121
122 let vars = sent_variables("EventsQueryFragment", |client| async move {
123 let _ = client
124 .events()
125 .filter(EventFilter {
126 sender: Some(Address::FRAMEWORK),
127 ..Default::default()
128 })
129 .pagination(forward_page())
130 .await;
131 })
132 .await;
133 assert_forward_page(&vars);
134 }
135
136 #[tokio::test]
137 async fn test_events_query() {
138 let client = test_client();
139 let events = client
140 .events()
141 .await
142 .map_err(|e| {
143 format!(
144 "Events query failed for {} network: Error {e}",
145 client.rpc_server()
146 )
147 })
148 .unwrap();
149 assert!(
150 !events.is_empty(),
151 "Events query returned no data for {} network",
152 client.rpc_server()
153 );
154 }
155}