sui_gql_client/queries/
transaction_blocks_status.rs

1use 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}