audit_trails/core/records/
transactions.rs1use async_trait::async_trait;
10use iota_interaction::OptionalSync;
11use iota_interaction::rpc_types::{IotaTransactionBlockEffects, IotaTransactionBlockEvents};
12use iota_interaction::types::base_types::{IotaAddress, ObjectID};
13use iota_interaction::types::transaction::ProgrammableTransaction;
14use product_common::core_client::CoreClientReadOnly;
15use product_common::transaction::transaction_builder::Transaction;
16use tokio::sync::OnceCell;
17
18use super::operations::RecordsOps;
19use crate::core::types::{Data, Event, RecordAdded, RecordDeleted};
20use crate::error::Error;
21
22#[derive(Debug, Clone)]
33pub struct AddRecord {
34 pub trail_id: ObjectID,
36 pub owner: IotaAddress,
38 pub data: Data,
40 pub metadata: Option<String>,
42 pub tag: Option<String>,
44 pub selected_capability_id: Option<ObjectID>,
46 cached_ptb: OnceCell<ProgrammableTransaction>,
47}
48
49impl AddRecord {
50 pub fn new(
52 trail_id: ObjectID,
53 owner: IotaAddress,
54 data: Data,
55 metadata: Option<String>,
56 tag: Option<String>,
57 selected_capability_id: Option<ObjectID>,
58 ) -> Self {
59 Self {
60 trail_id,
61 owner,
62 data,
63 metadata,
64 tag,
65 selected_capability_id,
66 cached_ptb: OnceCell::new(),
67 }
68 }
69
70 async fn make_ptb<C>(&self, client: &C) -> Result<ProgrammableTransaction, Error>
71 where
72 C: CoreClientReadOnly + OptionalSync,
73 {
74 RecordsOps::add_record(
75 client,
76 self.trail_id,
77 self.owner,
78 self.data.clone(),
79 self.metadata.clone(),
80 self.tag.clone(),
81 self.selected_capability_id,
82 )
83 .await
84 }
85}
86
87#[cfg_attr(not(feature = "send-sync"), async_trait(?Send))]
88#[cfg_attr(feature = "send-sync", async_trait)]
89impl Transaction for AddRecord {
90 type Error = Error;
91 type Output = RecordAdded;
92
93 async fn build_programmable_transaction<C>(&self, client: &C) -> Result<ProgrammableTransaction, Self::Error>
94 where
95 C: CoreClientReadOnly + OptionalSync,
96 {
97 self.cached_ptb.get_or_try_init(|| self.make_ptb(client)).await.cloned()
98 }
99
100 async fn apply_with_events<C>(
101 mut self,
102 _: &mut IotaTransactionBlockEffects,
103 events: &mut IotaTransactionBlockEvents,
104 _: &C,
105 ) -> Result<Self::Output, Self::Error>
106 where
107 C: CoreClientReadOnly + OptionalSync,
108 {
109 let event = events
110 .data
111 .iter()
112 .find_map(|data| serde_json::from_value::<Event<RecordAdded>>(data.parsed_json.clone()).ok())
113 .ok_or_else(|| Error::UnexpectedApiResponse("RecordAdded event not found".to_string()))?;
114
115 Ok(event.data)
116 }
117
118 async fn apply<C>(mut self, _: &mut IotaTransactionBlockEffects, _: &C) -> Result<Self::Output, Self::Error>
119 where
120 C: CoreClientReadOnly + OptionalSync,
121 {
122 unreachable!()
123 }
124}
125
126#[derive(Debug, Clone)]
137pub struct DeleteRecord {
138 pub trail_id: ObjectID,
140 pub owner: IotaAddress,
142 pub sequence_number: u64,
144 pub selected_capability_id: Option<ObjectID>,
146 cached_ptb: OnceCell<ProgrammableTransaction>,
147}
148
149impl DeleteRecord {
150 pub fn new(
152 trail_id: ObjectID,
153 owner: IotaAddress,
154 sequence_number: u64,
155 selected_capability_id: Option<ObjectID>,
156 ) -> Self {
157 Self {
158 trail_id,
159 owner,
160 sequence_number,
161 selected_capability_id,
162 cached_ptb: OnceCell::new(),
163 }
164 }
165
166 async fn make_ptb<C>(&self, client: &C) -> Result<ProgrammableTransaction, Error>
167 where
168 C: CoreClientReadOnly + OptionalSync,
169 {
170 RecordsOps::delete_record(
171 client,
172 self.trail_id,
173 self.owner,
174 self.sequence_number,
175 self.selected_capability_id,
176 )
177 .await
178 }
179}
180
181#[cfg_attr(not(feature = "send-sync"), async_trait(?Send))]
182#[cfg_attr(feature = "send-sync", async_trait)]
183impl Transaction for DeleteRecord {
184 type Error = Error;
185 type Output = RecordDeleted;
186
187 async fn build_programmable_transaction<C>(&self, client: &C) -> Result<ProgrammableTransaction, Self::Error>
188 where
189 C: CoreClientReadOnly + OptionalSync,
190 {
191 self.cached_ptb.get_or_try_init(|| self.make_ptb(client)).await.cloned()
192 }
193
194 async fn apply_with_events<C>(
195 mut self,
196 _: &mut IotaTransactionBlockEffects,
197 events: &mut IotaTransactionBlockEvents,
198 _: &C,
199 ) -> Result<Self::Output, Self::Error>
200 where
201 C: CoreClientReadOnly + OptionalSync,
202 {
203 let event = events
204 .data
205 .iter()
206 .find_map(|data| serde_json::from_value::<Event<RecordDeleted>>(data.parsed_json.clone()).ok())
207 .ok_or_else(|| Error::UnexpectedApiResponse("RecordDeleted event not found".to_string()))?;
208
209 Ok(event.data)
210 }
211
212 async fn apply<C>(mut self, _: &mut IotaTransactionBlockEffects, _: &C) -> Result<Self::Output, Self::Error>
213 where
214 C: CoreClientReadOnly + OptionalSync,
215 {
216 unreachable!()
217 }
218}
219
220#[derive(Debug, Clone)]
240pub struct DeleteRecordsBatch {
241 pub trail_id: ObjectID,
243 pub owner: IotaAddress,
245 pub limit: u64,
247 pub selected_capability_id: Option<ObjectID>,
249 cached_ptb: OnceCell<ProgrammableTransaction>,
250}
251
252impl DeleteRecordsBatch {
253 pub fn new(trail_id: ObjectID, owner: IotaAddress, limit: u64, selected_capability_id: Option<ObjectID>) -> Self {
255 Self {
256 trail_id,
257 owner,
258 limit,
259 selected_capability_id,
260 cached_ptb: OnceCell::new(),
261 }
262 }
263
264 async fn make_ptb<C>(&self, client: &C) -> Result<ProgrammableTransaction, Error>
265 where
266 C: CoreClientReadOnly + OptionalSync,
267 {
268 RecordsOps::delete_records_batch(
269 client,
270 self.trail_id,
271 self.owner,
272 self.limit,
273 self.selected_capability_id,
274 )
275 .await
276 }
277}
278
279#[cfg_attr(not(feature = "send-sync"), async_trait(?Send))]
280#[cfg_attr(feature = "send-sync", async_trait)]
281impl Transaction for DeleteRecordsBatch {
282 type Error = Error;
283 type Output = Vec<u64>;
284
285 async fn build_programmable_transaction<C>(&self, client: &C) -> Result<ProgrammableTransaction, Self::Error>
286 where
287 C: CoreClientReadOnly + OptionalSync,
288 {
289 self.cached_ptb.get_or_try_init(|| self.make_ptb(client)).await.cloned()
290 }
291
292 async fn apply_with_events<C>(
293 self,
294 _: &mut IotaTransactionBlockEffects,
295 events: &mut IotaTransactionBlockEvents,
296 _: &C,
297 ) -> Result<Self::Output, Self::Error>
298 where
299 C: CoreClientReadOnly + OptionalSync,
300 {
301 let deleted = events
302 .data
303 .iter()
304 .filter_map(|data| serde_json::from_value::<Event<RecordDeleted>>(data.parsed_json.clone()).ok())
305 .map(|event| event.data.sequence_number)
306 .collect();
307
308 Ok(deleted)
309 }
310
311 async fn apply<C>(self, _: &mut IotaTransactionBlockEffects, _: &C) -> Result<Self::Output, Self::Error>
312 where
313 C: CoreClientReadOnly + OptionalSync,
314 {
315 unreachable!()
316 }
317}