sui_gql_client/queries/
transaction_blocks_status.rs1use futures::StreamExt as _;
2
3use self::stream::UpdatePageInfo;
4use super::fragments::{PageInfoForward, TransactionBlockFilter};
5use super::stream;
6use crate::queries::Error;
7use crate::{GraphQlClient, GraphQlResponseExt as _, schema};
8
9type Item = (String, bool);
10
11#[expect(deprecated, reason = "Internal `extract` module deprecated")]
12pub(super) async fn query<C: GraphQlClient>(
13 client: &C,
14 transaction_digests: Vec<String>,
15) -> super::Result<impl Iterator<Item = Result<Item, crate::extract::Error>> + use<C>, C> {
16 let filter = TransactionBlockFilter {
17 transaction_ids: Some(transaction_digests),
18 ..Default::default()
19 };
20 let vars = Variables {
21 filter: Some(&filter),
22 first: None,
23 after: None,
24 };
25
26 let mut vec = vec![];
27 let mut stream = std::pin::pin!(stream::forward(client, vars, request));
28 while let Some(res) = stream.next().await {
29 match res {
30 Ok(item) => vec.push(Ok(item)),
31 Err(Error::MissingData(err)) => vec.push(Err(crate::extract::Error::new(err))),
32 Err(other) => return Err(other),
33 }
34 }
35
36 Ok(vec.into_iter())
37}
38
39async fn request<C: GraphQlClient>(
40 client: &C,
41 vars: Variables<'_>,
42) -> super::Result<stream::Page<impl Iterator<Item = super::Result<Item, C>> + use<C>>, C> {
43 let data = client
44 .query::<Query, _>(vars)
45 .await
46 .map_err(Error::Client)?
47 .try_into_data()?;
48
49 graphql_extract::extract!(data => {
50 transaction_blocks {
51 page_info
52 nodes[] {
53 digest?
54 effects? {
55 status?
56 }
57 }
58 }
59 });
60
61 Ok(stream::Page::new(
62 page_info,
63 nodes.map(|r| r.map(|(d, s)| (d, s.into())).map_err(super::Error::from)),
64 ))
65}
66
67#[derive(cynic::QueryVariables, Debug, Clone)]
68pub struct Variables<'a> {
69 filter: Option<&'a TransactionBlockFilter>,
70 after: Option<String>,
71 first: Option<i32>,
72}
73
74impl UpdatePageInfo for Variables<'_> {
75 fn update_page_info(&mut self, info: &super::fragments::PageInfo) {
76 self.after.clone_from(&info.end_cursor)
77 }
78}
79
80#[derive(cynic::QueryFragment, Debug)]
81#[cynic(graphql_type = "Query")]
82#[cynic(variables = "Variables")]
83pub struct Query {
84 #[arguments(filter: $filter, first: $first, after: $after)]
85 pub transaction_blocks: TransactionBlockConnection,
86}
87
88#[derive(cynic::QueryFragment, Debug)]
89pub struct TransactionBlockConnection {
90 pub page_info: PageInfoForward,
91 pub nodes: Vec<TransactionBlock>,
92}
93
94#[derive(cynic::QueryFragment, Debug)]
95pub struct TransactionBlock {
96 digest: Option<String>,
97 effects: Option<TransactionBlockEffects>,
98}
99
100#[derive(cynic::QueryFragment, Debug)]
101struct TransactionBlockEffects {
102 status: Option<ExecutionStatus>,
103}
104
105#[derive(cynic::Enum, Clone, Copy, Debug)]
106pub enum ExecutionStatus {
107 Success,
108 Failure,
109}
110
111impl From<ExecutionStatus> for bool {
112 fn from(value: ExecutionStatus) -> Self {
113 match value {
114 ExecutionStatus::Success => true,
115 ExecutionStatus::Failure => false,
116 }
117 }
118}
119
120#[cfg(test)]
121#[test]
122fn gql_output() {
123 use cynic::QueryBuilder as _;
124
125 let vars = Variables {
126 filter: None,
127 after: None,
128 first: None,
129 };
130 let operation = Query::build(vars);
131 insta::assert_snapshot!(operation.query, @r###"
132 query Query($filter: TransactionBlockFilter, $after: String, $first: Int) {
133 transactionBlocks(filter: $filter, first: $first, after: $after) {
134 pageInfo {
135 hasNextPage
136 endCursor
137 }
138 nodes {
139 digest
140 effects {
141 status
142 }
143 }
144 }
145 }
146 "###);
147}