sui_graphql_client/query_types/
transaction.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use base64ct::Encoding;
5use sui_types::SignedTransaction;
6use sui_types::Transaction;
7use sui_types::TransactionEffects;
8use sui_types::UserSignature;
9
10use crate::error;
11use crate::error::Error;
12use crate::error::Kind;
13use crate::query_types::schema;
14use crate::query_types::Address;
15use crate::query_types::Base64;
16use crate::query_types::PageInfo;
17
18// ===========================================================================
19// Transaction Block(s) Queries
20// ===========================================================================
21
22#[derive(cynic::QueryFragment, Debug)]
23#[cynic(
24    schema = "rpc",
25    graphql_type = "Query",
26    variables = "TransactionBlockArgs"
27)]
28pub struct TransactionBlockQuery {
29    #[arguments(digest: $digest)]
30    pub transaction_block: Option<TransactionBlock>,
31}
32
33#[derive(cynic::QueryFragment, Debug)]
34#[cynic(
35    schema = "rpc",
36    graphql_type = "Query",
37    variables = "TransactionBlockArgs"
38)]
39pub struct TransactionBlockWithEffectsQuery {
40    #[arguments(digest: $digest)]
41    pub transaction_block: Option<TransactionBlockWithEffects>,
42}
43
44#[derive(cynic::QueryFragment, Debug)]
45#[cynic(
46    schema = "rpc",
47    graphql_type = "Query",
48    variables = "TransactionBlockArgs"
49)]
50pub struct TransactionBlockEffectsQuery {
51    #[arguments(digest: $digest)]
52    pub transaction_block: Option<TxBlockEffects>,
53}
54
55#[derive(cynic::QueryFragment, Debug)]
56#[cynic(
57    schema = "rpc",
58    graphql_type = "Query",
59    variables = "TransactionBlocksQueryArgs"
60)]
61pub struct TransactionBlocksQuery {
62    #[arguments(first: $first, after: $after, last: $last, before: $before, filter: $filter)]
63    pub transaction_blocks: TransactionBlockConnection,
64}
65
66#[derive(cynic::QueryFragment, Debug)]
67#[cynic(
68    schema = "rpc",
69    graphql_type = "Query",
70    variables = "TransactionBlocksQueryArgs"
71)]
72pub struct TransactionBlocksWithEffectsQuery {
73    #[arguments(first: $first, after: $after, last: $last, before: $before, filter: $filter)]
74    pub transaction_blocks: TransactionBlockWithEffectsConnection,
75}
76
77#[derive(cynic::QueryFragment, Debug)]
78#[cynic(
79    schema = "rpc",
80    graphql_type = "Query",
81    variables = "TransactionBlocksQueryArgs"
82)]
83pub struct TransactionBlocksEffectsQuery {
84    #[arguments(first: $first, after: $after, last: $last, before: $before, filter: $filter)]
85    pub transaction_blocks: TransactionBlockEffectsConnection,
86}
87// ===========================================================================
88// Transaction Block(s) Query Args
89// ===========================================================================
90
91#[derive(cynic::QueryVariables, Debug)]
92pub struct TransactionBlockArgs {
93    pub digest: String,
94}
95
96#[derive(cynic::QueryVariables, Debug)]
97pub struct TransactionBlocksQueryArgs<'a> {
98    pub first: Option<i32>,
99    pub after: Option<&'a str>,
100    pub last: Option<i32>,
101    pub before: Option<&'a str>,
102    pub filter: Option<TransactionsFilter<'a>>,
103}
104
105// ===========================================================================
106// Transaction Block(s) Types
107// ===========================================================================
108
109#[derive(cynic::QueryFragment, Debug)]
110#[cynic(schema = "rpc", graphql_type = "TransactionBlock")]
111pub struct TransactionBlock {
112    pub bcs: Option<Base64>,
113    pub effects: Option<TransactionBlockEffects>,
114    pub signatures: Option<Vec<Base64>>,
115}
116
117#[derive(cynic::QueryFragment, Debug)]
118#[cynic(schema = "rpc", graphql_type = "TransactionBlock")]
119pub struct TransactionBlockWithEffects {
120    pub bcs: Option<Base64>,
121    pub effects: Option<TransactionBlockEffects>,
122    pub signatures: Option<Vec<Base64>>,
123}
124
125#[derive(cynic::QueryFragment, Debug)]
126#[cynic(schema = "rpc", graphql_type = "TransactionBlock")]
127pub struct TransactionBlockDigest {
128    pub digest: Option<String>,
129}
130
131#[derive(cynic::QueryFragment, Debug)]
132#[cynic(schema = "rpc", graphql_type = "TransactionBlock")]
133pub struct TxBlockEffects {
134    pub effects: Option<TransactionBlockEffects>,
135}
136
137#[derive(cynic::QueryFragment, Debug)]
138#[cynic(schema = "rpc", graphql_type = "TransactionBlockEffects")]
139pub struct TransactionBlockEffects {
140    pub bcs: Option<Base64>,
141}
142
143#[derive(cynic::Enum, Clone, Copy, Debug)]
144#[cynic(
145    schema = "rpc",
146    graphql_type = "TransactionBlockKindInput",
147    rename_all = "SCREAMING_SNAKE_CASE"
148)]
149pub enum TransactionBlockKindInput {
150    SystemTx,
151    ProgrammableTx,
152}
153
154#[derive(Clone, cynic::InputObject, Debug)]
155#[cynic(schema = "rpc", graphql_type = "TransactionBlockFilter")]
156pub struct TransactionsFilter<'a> {
157    pub function: Option<String>,
158    pub kind: Option<TransactionBlockKindInput>,
159    pub after_checkpoint: Option<u64>,
160    pub at_checkpoint: Option<u64>,
161    pub before_checkpoint: Option<u64>,
162    pub affected_address: Option<Address>,
163    pub sent_address: Option<Address>,
164    pub input_object: Option<Address>,
165    pub changed_object: Option<Address>,
166    pub transaction_ids: Option<Vec<&'a str>>,
167}
168
169#[derive(cynic::QueryFragment, Debug)]
170#[cynic(schema = "rpc", graphql_type = "TransactionBlockConnection")]
171pub struct TransactionBlockConnection {
172    pub nodes: Vec<TransactionBlock>,
173    pub page_info: PageInfo,
174}
175
176#[derive(cynic::QueryFragment, Debug)]
177#[cynic(schema = "rpc", graphql_type = "TransactionBlockConnection")]
178pub struct TransactionBlockWithEffectsConnection {
179    pub nodes: Vec<TransactionBlockWithEffects>,
180    pub page_info: PageInfo,
181}
182
183#[derive(cynic::QueryFragment, Debug)]
184#[cynic(schema = "rpc", graphql_type = "TransactionBlockConnection")]
185pub struct TransactionBlockEffectsConnection {
186    pub nodes: Vec<TxBlockEffects>,
187    pub page_info: PageInfo,
188}
189
190impl TryFrom<TransactionBlock> for SignedTransaction {
191    type Error = error::Error;
192
193    fn try_from(value: TransactionBlock) -> Result<Self, Self::Error> {
194        let transaction = value
195            .bcs
196            .map(|tx| base64ct::Base64::decode_vec(tx.0.as_str()))
197            .transpose()?
198            .map(|bcs| bcs::from_bytes::<Transaction>(&bcs))
199            .transpose()?;
200
201        let signatures = if let Some(sigs) = value.signatures {
202            sigs.iter()
203                .map(|s| UserSignature::from_base64(&s.0))
204                .collect::<Result<Vec<_>, _>>()?
205        } else {
206            vec![]
207        };
208
209        if let Some(transaction) = transaction {
210            Ok(SignedTransaction {
211                transaction,
212                signatures,
213            })
214        } else {
215            Err(Error::from_error(
216                Kind::Other,
217                "Expected a deserialized transaction but got None",
218            ))
219        }
220    }
221}
222
223impl TryFrom<TxBlockEffects> for TransactionEffects {
224    type Error = error::Error;
225
226    fn try_from(value: TxBlockEffects) -> Result<Self, Self::Error> {
227        let effects = value
228            .effects
229            .map(|fx| base64ct::Base64::decode_vec(fx.bcs.unwrap().0.as_str()))
230            .transpose()?
231            .map(|bcs| bcs::from_bytes::<TransactionEffects>(&bcs))
232            .transpose()?;
233        effects.ok_or_else(|| {
234            Error::from_error(
235                Kind::Other,
236                "Cannot convert GraphQL TxBlockEffects into TransactionEffects",
237            )
238        })
239    }
240}