iota_sdk_graphql_client/
transaction_builder_client.rs1use iota_transaction_builder::{
8 ObjectsPage, ProtocolConfig, TransactionBuilder, TransactionBuilderClientBase,
9 TransactionBuilderExecutionClient, TransactionBuilderLedgerClient,
10 TransactionBuilderSimulationClient, WaitForTransaction,
11};
12use iota_types::{
13 Address, Object, ObjectId, StructTag, Transaction, TransactionDigest, TransactionEffects,
14 UserSignature, Version,
15};
16
17use crate::{
18 DryRunResult, GraphQLClient,
19 pagination::{Direction, PaginationFilter},
20 query_types::ObjectFilter,
21};
22
23impl GraphQLClient {
24 pub fn transaction_builder(&self, sender: Address) -> TransactionBuilder<&Self> {
26 TransactionBuilder::new(sender).with_client(self)
27 }
28}
29
30impl TransactionBuilderClientBase for GraphQLClient {
31 type Error = crate::error::GraphQLError;
32}
33
34impl TransactionBuilderLedgerClient for GraphQLClient {
35 async fn object(
36 &self,
37 object_id: ObjectId,
38 version: impl Into<Option<Version>>,
39 ) -> Result<Option<Object>, Self::Error> {
40 let mut query = self.object(object_id);
41 if let Some(version) = version.into() {
42 query = query.version(version);
43 }
44 query.await
45 }
46
47 async fn objects(
48 &self,
49 struct_tag: Option<StructTag>,
50 owner: Address,
51 cursor: Option<Vec<u8>>,
52 limit: Option<usize>,
53 ) -> Result<ObjectsPage, Self::Error> {
54 let cursor = cursor.map(String::from_utf8).transpose()?;
59 let page = self
60 .objects()
61 .filter(ObjectFilter {
62 type_tag: struct_tag.map(|tag| tag.to_string()),
63 owner: Some(owner),
64 object_ids: None,
65 })
66 .pagination(PaginationFilter {
67 direction: Direction::Forward,
68 cursor,
69 limit: limit.map(|v| v as _),
70 })
71 .await?;
72 let (page_info, data) = page.into_parts();
73 let next_cursor = page_info
74 .has_next_page
75 .then_some(page_info.end_cursor)
76 .flatten()
77 .map(String::into_bytes);
78 Ok(ObjectsPage { data, next_cursor })
79 }
80
81 async fn protocol_config(&self) -> Result<ProtocolConfig, Self::Error> {
82 let cfg = self.protocol_config().await?;
83 let attributes = cfg
84 .configs
85 .into_iter()
86 .filter_map(|attr| attr.value.map(|v| (attr.key, v)))
87 .collect();
88 Ok(ProtocolConfig::new(attributes))
89 }
90
91 async fn reference_gas_price(
92 &self,
93 epoch: impl Into<Option<u64>>,
94 ) -> Result<Option<u64>, Self::Error> {
95 let mut query = self.reference_gas_price();
96 if let Some(epoch) = epoch.into() {
97 query = query.epoch_number(epoch);
98 }
99 query.await
100 }
101}
102
103impl TransactionBuilderSimulationClient for GraphQLClient {
104 type DryRunResult = DryRunResult;
105
106 async fn estimate_transaction_budget(
107 &self,
108 transaction: &Transaction,
109 ) -> Result<Option<u64>, Self::Error> {
110 let res = self
111 .dry_run_transaction(transaction)
112 .skip_checks(true)
113 .await?;
114 Ok(res.effects.map(|effects| match effects {
115 TransactionEffects::V1(v1) => v1.gas_cost_summary.gas_used(),
116 _ => unimplemented!(
117 "a new TransactionEffects enum variant was added and needs to be handled"
118 ),
119 }))
120 }
121
122 async fn dry_run_transaction(
123 &self,
124 transaction: &Transaction,
125 skip_checks: bool,
126 ) -> Result<Self::DryRunResult, Self::Error> {
127 self.dry_run_transaction(transaction)
128 .skip_checks(skip_checks)
129 .await
130 }
131}
132
133impl TransactionBuilderExecutionClient for GraphQLClient {
134 async fn execute_transaction(
135 &self,
136 signatures: &[UserSignature],
137 transaction: &Transaction,
138 wait_for: impl Into<Option<WaitForTransaction>>,
139 ) -> Result<TransactionEffects, Self::Error> {
140 let mut query = self.execute_transaction(signatures, transaction);
141 if let Some(wait_for) = wait_for.into() {
142 query = query.wait_for(wait_for);
143 }
144 query.await
145 }
146
147 async fn wait_for_transaction(
148 &self,
149 digest: TransactionDigest,
150 wait_for: WaitForTransaction,
151 ) -> Result<(), Self::Error> {
152 self.wait_for_transaction(digest, wait_for).await
153 }
154
155 async fn transaction_effects(
156 &self,
157 digest: TransactionDigest,
158 ) -> Result<Option<TransactionEffects>, Self::Error> {
159 self.transaction_effects(digest).await
160 }
161}