sui_sdk_types/transaction/
serialization.rs

1use serde::Deserialize;
2use serde::Deserializer;
3use serde::Serialize;
4use serde::Serializer;
5use serde_with::DeserializeAs;
6use serde_with::SerializeAs;
7
8use crate::ObjectId;
9use crate::ObjectReference;
10
11use super::Argument;
12
13mod transaction {
14    use super::*;
15    use crate::transaction::GasPayment;
16    use crate::transaction::Transaction;
17    use crate::transaction::TransactionExpiration;
18    use crate::transaction::TransactionKind;
19    use crate::Address;
20
21    #[derive(serde_derive::Serialize)]
22    #[serde(tag = "version")]
23    #[serde(rename = "Transaction")]
24    enum TransactionDataRef<'a> {
25        #[serde(rename = "1")]
26        V1(TransactionV1Ref<'a>),
27    }
28
29    #[derive(serde_derive::Deserialize)]
30    #[serde(tag = "version")]
31    #[serde(rename = "Transaction")]
32    enum TransactionData {
33        #[serde(rename = "1")]
34        V1(TransactionV1),
35    }
36
37    #[derive(serde_derive::Serialize)]
38    #[serde(rename = "Transaction")]
39    enum BinaryTransactionDataRef<'a> {
40        #[serde(rename = "1")]
41        V1(TransactionV1Ref<'a>),
42    }
43
44    #[derive(serde_derive::Deserialize)]
45    #[serde(rename = "Transaction")]
46    enum BinaryTransactionData {
47        #[serde(rename = "1")]
48        V1(TransactionV1),
49    }
50
51    #[derive(serde_derive::Serialize)]
52    #[serde(rename = "TransactionV1")]
53    struct TransactionV1Ref<'a> {
54        kind: &'a TransactionKind,
55        sender: &'a Address,
56        gas_payment: &'a GasPayment,
57        expiration: &'a TransactionExpiration,
58    }
59
60    #[derive(serde_derive::Deserialize)]
61    #[serde(rename = "TransactionV1")]
62    struct TransactionV1 {
63        kind: TransactionKind,
64        sender: Address,
65        gas_payment: GasPayment,
66        expiration: TransactionExpiration,
67    }
68
69    impl Serialize for Transaction {
70        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71        where
72            S: Serializer,
73        {
74            let transaction = TransactionV1Ref {
75                kind: &self.kind,
76                sender: &self.sender,
77                gas_payment: &self.gas_payment,
78                expiration: &self.expiration,
79            };
80
81            if serializer.is_human_readable() {
82                TransactionDataRef::V1(transaction).serialize(serializer)
83            } else {
84                BinaryTransactionDataRef::V1(transaction).serialize(serializer)
85            }
86        }
87    }
88
89    impl<'de> Deserialize<'de> for Transaction {
90        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91        where
92            D: Deserializer<'de>,
93        {
94            let TransactionV1 {
95                kind,
96                sender,
97                gas_payment,
98                expiration,
99            } = if deserializer.is_human_readable() {
100                let TransactionData::V1(transaction) = Deserialize::deserialize(deserializer)?;
101                transaction
102            } else {
103                let BinaryTransactionData::V1(transaction) =
104                    Deserialize::deserialize(deserializer)?;
105                transaction
106            };
107
108            Ok(Transaction {
109                kind,
110                sender,
111                gas_payment,
112                expiration,
113            })
114        }
115    }
116}
117
118mod transaction_kind {
119    use super::*;
120    use crate::transaction::AuthenticatorStateUpdate;
121    use crate::transaction::ChangeEpoch;
122    use crate::transaction::ConsensusCommitPrologue;
123    use crate::transaction::ConsensusCommitPrologueV2;
124    use crate::transaction::ConsensusCommitPrologueV3;
125    use crate::transaction::ConsensusCommitPrologueV4;
126    use crate::transaction::EndOfEpochTransactionKind;
127    use crate::transaction::GenesisTransaction;
128    use crate::transaction::ProgrammableTransaction;
129    use crate::transaction::RandomnessStateUpdate;
130    use crate::transaction::TransactionKind;
131
132    #[derive(serde_derive::Serialize)]
133    #[serde(tag = "kind", rename_all = "snake_case")]
134    enum ReadableTransactionKindRef<'a> {
135        ProgrammableTransaction(&'a ProgrammableTransaction),
136        ChangeEpoch(&'a ChangeEpoch),
137        Genesis(&'a GenesisTransaction),
138        ConsensusCommitPrologue(&'a ConsensusCommitPrologue),
139        AuthenticatorStateUpdate(&'a AuthenticatorStateUpdate),
140        EndOfEpoch {
141            commands: &'a Vec<EndOfEpochTransactionKind>,
142        },
143        RandomnessStateUpdate(&'a RandomnessStateUpdate),
144        ConsensusCommitPrologueV2(&'a ConsensusCommitPrologueV2),
145        ConsensusCommitPrologueV3(&'a ConsensusCommitPrologueV3),
146        ConsensusCommitPrologueV4(&'a ConsensusCommitPrologueV4),
147        ProgrammableSystemTransaction(&'a ProgrammableTransaction),
148    }
149
150    #[derive(serde_derive::Deserialize)]
151    #[serde(tag = "kind", rename_all = "snake_case")]
152    #[serde(rename = "TransactionKind")]
153    enum ReadableTransactionKind {
154        ProgrammableTransaction(ProgrammableTransaction),
155        ChangeEpoch(ChangeEpoch),
156        Genesis(GenesisTransaction),
157        ConsensusCommitPrologue(ConsensusCommitPrologue),
158        AuthenticatorStateUpdate(AuthenticatorStateUpdate),
159        EndOfEpoch {
160            commands: Vec<EndOfEpochTransactionKind>,
161        },
162        RandomnessStateUpdate(RandomnessStateUpdate),
163        ConsensusCommitPrologueV2(ConsensusCommitPrologueV2),
164        ConsensusCommitPrologueV3(ConsensusCommitPrologueV3),
165        ConsensusCommitPrologueV4(ConsensusCommitPrologueV4),
166        ProgrammableSystemTransaction(ProgrammableTransaction),
167    }
168
169    #[derive(serde_derive::Serialize)]
170    enum BinaryTransactionKindRef<'a> {
171        ProgrammableTransaction(&'a ProgrammableTransaction),
172        ChangeEpoch(&'a ChangeEpoch),
173        Genesis(&'a GenesisTransaction),
174        ConsensusCommitPrologue(&'a ConsensusCommitPrologue),
175        AuthenticatorStateUpdate(&'a AuthenticatorStateUpdate),
176        EndOfEpoch(&'a Vec<EndOfEpochTransactionKind>),
177        RandomnessStateUpdate(&'a RandomnessStateUpdate),
178        ConsensusCommitPrologueV2(&'a ConsensusCommitPrologueV2),
179        ConsensusCommitPrologueV3(&'a ConsensusCommitPrologueV3),
180        ConsensusCommitPrologueV4(&'a ConsensusCommitPrologueV4),
181        ProgrammableSystemTransaction(&'a ProgrammableTransaction),
182    }
183    #[derive(serde_derive::Deserialize)]
184    enum BinaryTransactionKind {
185        ProgrammableTransaction(ProgrammableTransaction),
186        ChangeEpoch(ChangeEpoch),
187        Genesis(GenesisTransaction),
188        ConsensusCommitPrologue(ConsensusCommitPrologue),
189        AuthenticatorStateUpdate(AuthenticatorStateUpdate),
190        EndOfEpoch(Vec<EndOfEpochTransactionKind>),
191        RandomnessStateUpdate(RandomnessStateUpdate),
192        ConsensusCommitPrologueV2(ConsensusCommitPrologueV2),
193        ConsensusCommitPrologueV3(ConsensusCommitPrologueV3),
194        ConsensusCommitPrologueV4(ConsensusCommitPrologueV4),
195        ProgrammableSystemTransaction(ProgrammableTransaction),
196    }
197
198    impl Serialize for TransactionKind {
199        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
200        where
201            S: Serializer,
202        {
203            if serializer.is_human_readable() {
204                let readable = match self {
205                    Self::ProgrammableTransaction(k) => {
206                        ReadableTransactionKindRef::ProgrammableTransaction(k)
207                    }
208                    Self::ChangeEpoch(k) => ReadableTransactionKindRef::ChangeEpoch(k),
209                    Self::Genesis(k) => ReadableTransactionKindRef::Genesis(k),
210                    Self::ConsensusCommitPrologue(k) => {
211                        ReadableTransactionKindRef::ConsensusCommitPrologue(k)
212                    }
213                    Self::AuthenticatorStateUpdate(k) => {
214                        ReadableTransactionKindRef::AuthenticatorStateUpdate(k)
215                    }
216                    Self::EndOfEpoch(commands) => {
217                        ReadableTransactionKindRef::EndOfEpoch { commands }
218                    }
219                    Self::RandomnessStateUpdate(k) => {
220                        ReadableTransactionKindRef::RandomnessStateUpdate(k)
221                    }
222                    Self::ConsensusCommitPrologueV2(k) => {
223                        ReadableTransactionKindRef::ConsensusCommitPrologueV2(k)
224                    }
225                    Self::ConsensusCommitPrologueV3(k) => {
226                        ReadableTransactionKindRef::ConsensusCommitPrologueV3(k)
227                    }
228                    Self::ConsensusCommitPrologueV4(k) => {
229                        ReadableTransactionKindRef::ConsensusCommitPrologueV4(k)
230                    }
231                    Self::ProgrammableSystemTransaction(k) => {
232                        ReadableTransactionKindRef::ProgrammableSystemTransaction(k)
233                    }
234                };
235                readable.serialize(serializer)
236            } else {
237                let binary = match self {
238                    Self::ProgrammableTransaction(k) => {
239                        BinaryTransactionKindRef::ProgrammableTransaction(k)
240                    }
241                    Self::ChangeEpoch(k) => BinaryTransactionKindRef::ChangeEpoch(k),
242                    Self::Genesis(k) => BinaryTransactionKindRef::Genesis(k),
243                    Self::ConsensusCommitPrologue(k) => {
244                        BinaryTransactionKindRef::ConsensusCommitPrologue(k)
245                    }
246                    Self::AuthenticatorStateUpdate(k) => {
247                        BinaryTransactionKindRef::AuthenticatorStateUpdate(k)
248                    }
249                    Self::EndOfEpoch(k) => BinaryTransactionKindRef::EndOfEpoch(k),
250                    Self::RandomnessStateUpdate(k) => {
251                        BinaryTransactionKindRef::RandomnessStateUpdate(k)
252                    }
253                    Self::ConsensusCommitPrologueV2(k) => {
254                        BinaryTransactionKindRef::ConsensusCommitPrologueV2(k)
255                    }
256                    Self::ConsensusCommitPrologueV3(k) => {
257                        BinaryTransactionKindRef::ConsensusCommitPrologueV3(k)
258                    }
259                    Self::ConsensusCommitPrologueV4(k) => {
260                        BinaryTransactionKindRef::ConsensusCommitPrologueV4(k)
261                    }
262                    Self::ProgrammableSystemTransaction(k) => {
263                        BinaryTransactionKindRef::ProgrammableSystemTransaction(k)
264                    }
265                };
266                binary.serialize(serializer)
267            }
268        }
269    }
270
271    impl<'de> Deserialize<'de> for TransactionKind {
272        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
273        where
274            D: Deserializer<'de>,
275        {
276            if deserializer.is_human_readable() {
277                ReadableTransactionKind::deserialize(deserializer).map(|readable| match readable {
278                    ReadableTransactionKind::ProgrammableTransaction(k) => {
279                        Self::ProgrammableTransaction(k)
280                    }
281                    ReadableTransactionKind::ChangeEpoch(k) => Self::ChangeEpoch(k),
282                    ReadableTransactionKind::Genesis(k) => Self::Genesis(k),
283                    ReadableTransactionKind::ConsensusCommitPrologue(k) => {
284                        Self::ConsensusCommitPrologue(k)
285                    }
286                    ReadableTransactionKind::AuthenticatorStateUpdate(k) => {
287                        Self::AuthenticatorStateUpdate(k)
288                    }
289                    ReadableTransactionKind::EndOfEpoch { commands } => Self::EndOfEpoch(commands),
290                    ReadableTransactionKind::RandomnessStateUpdate(k) => {
291                        Self::RandomnessStateUpdate(k)
292                    }
293                    ReadableTransactionKind::ConsensusCommitPrologueV2(k) => {
294                        Self::ConsensusCommitPrologueV2(k)
295                    }
296                    ReadableTransactionKind::ConsensusCommitPrologueV3(k) => {
297                        Self::ConsensusCommitPrologueV3(k)
298                    }
299                    ReadableTransactionKind::ConsensusCommitPrologueV4(k) => {
300                        Self::ConsensusCommitPrologueV4(k)
301                    }
302                    ReadableTransactionKind::ProgrammableSystemTransaction(k) => {
303                        Self::ProgrammableSystemTransaction(k)
304                    }
305                })
306            } else {
307                BinaryTransactionKind::deserialize(deserializer).map(|binary| match binary {
308                    BinaryTransactionKind::ProgrammableTransaction(k) => {
309                        Self::ProgrammableTransaction(k)
310                    }
311                    BinaryTransactionKind::ChangeEpoch(k) => Self::ChangeEpoch(k),
312                    BinaryTransactionKind::Genesis(k) => Self::Genesis(k),
313                    BinaryTransactionKind::ConsensusCommitPrologue(k) => {
314                        Self::ConsensusCommitPrologue(k)
315                    }
316                    BinaryTransactionKind::AuthenticatorStateUpdate(k) => {
317                        Self::AuthenticatorStateUpdate(k)
318                    }
319                    BinaryTransactionKind::EndOfEpoch(k) => Self::EndOfEpoch(k),
320                    BinaryTransactionKind::RandomnessStateUpdate(k) => {
321                        Self::RandomnessStateUpdate(k)
322                    }
323                    BinaryTransactionKind::ConsensusCommitPrologueV2(k) => {
324                        Self::ConsensusCommitPrologueV2(k)
325                    }
326                    BinaryTransactionKind::ConsensusCommitPrologueV3(k) => {
327                        Self::ConsensusCommitPrologueV3(k)
328                    }
329                    BinaryTransactionKind::ConsensusCommitPrologueV4(k) => {
330                        Self::ConsensusCommitPrologueV4(k)
331                    }
332                    BinaryTransactionKind::ProgrammableSystemTransaction(k) => {
333                        Self::ProgrammableSystemTransaction(k)
334                    }
335                })
336            }
337        }
338    }
339}
340
341mod end_of_epoch {
342    use super::*;
343    use crate::transaction::AuthenticatorStateExpire;
344    use crate::transaction::ChangeEpoch;
345    use crate::transaction::EndOfEpochTransactionKind;
346    use crate::CheckpointDigest;
347
348    #[derive(serde_derive::Serialize)]
349    #[serde(tag = "kind", rename_all = "snake_case")]
350    enum ReadableEndOfEpochTransactionKindRef<'a> {
351        ChangeEpoch(&'a ChangeEpoch),
352        AuthenticatorStateCreate,
353        AuthenticatorStateExpire(&'a AuthenticatorStateExpire),
354        RandomnessStateCreate,
355        DenyListStateCreate,
356        BridgeStateCreate {
357            chain_id: &'a CheckpointDigest,
358        },
359        BridgeCommitteeInit {
360            #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
361            bridge_object_version: u64,
362        },
363        StoreExecutionTimeObservations(&'a crate::transaction::ExecutionTimeObservations),
364        AccumulatorRootCreate,
365    }
366
367    #[derive(serde_derive::Deserialize)]
368    #[serde(tag = "kind", rename_all = "snake_case")]
369    enum ReadableEndOfEpochTransactionKind {
370        ChangeEpoch(ChangeEpoch),
371        AuthenticatorStateCreate,
372        AuthenticatorStateExpire(AuthenticatorStateExpire),
373        RandomnessStateCreate,
374        DenyListStateCreate,
375        BridgeStateCreate {
376            chain_id: CheckpointDigest,
377        },
378        BridgeCommitteeInit {
379            #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
380            bridge_object_version: u64,
381        },
382        StoreExecutionTimeObservations(crate::transaction::ExecutionTimeObservations),
383        AccumulatorRootCreate,
384    }
385
386    #[derive(serde_derive::Serialize)]
387    enum BinaryEndOfEpochTransactionKindRef<'a> {
388        ChangeEpoch(&'a ChangeEpoch),
389        AuthenticatorStateCreate,
390        AuthenticatorStateExpire(&'a AuthenticatorStateExpire),
391        RandomnessStateCreate,
392        DenyListStateCreate,
393        BridgeStateCreate { chain_id: &'a CheckpointDigest },
394        BridgeCommitteeInit { bridge_object_version: u64 },
395        StoreExecutionTimeObservations(&'a crate::transaction::ExecutionTimeObservations),
396        AccumulatorRootCreate,
397    }
398
399    #[derive(serde_derive::Deserialize)]
400    enum BinaryEndOfEpochTransactionKind {
401        ChangeEpoch(ChangeEpoch),
402        AuthenticatorStateCreate,
403        AuthenticatorStateExpire(AuthenticatorStateExpire),
404        RandomnessStateCreate,
405        DenyListStateCreate,
406        BridgeStateCreate { chain_id: CheckpointDigest },
407        BridgeCommitteeInit { bridge_object_version: u64 },
408        StoreExecutionTimeObservations(crate::transaction::ExecutionTimeObservations),
409        AccumulatorRootCreate,
410    }
411
412    impl Serialize for EndOfEpochTransactionKind {
413        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
414        where
415            S: Serializer,
416        {
417            if serializer.is_human_readable() {
418                let readable = match self {
419                    Self::ChangeEpoch(k) => ReadableEndOfEpochTransactionKindRef::ChangeEpoch(k),
420                    Self::AuthenticatorStateCreate => {
421                        ReadableEndOfEpochTransactionKindRef::AuthenticatorStateCreate
422                    }
423                    Self::AuthenticatorStateExpire(k) => {
424                        ReadableEndOfEpochTransactionKindRef::AuthenticatorStateExpire(k)
425                    }
426                    Self::RandomnessStateCreate => {
427                        ReadableEndOfEpochTransactionKindRef::RandomnessStateCreate
428                    }
429                    Self::DenyListStateCreate => {
430                        ReadableEndOfEpochTransactionKindRef::DenyListStateCreate
431                    }
432                    Self::BridgeStateCreate { chain_id } => {
433                        ReadableEndOfEpochTransactionKindRef::BridgeStateCreate { chain_id }
434                    }
435                    Self::BridgeCommitteeInit {
436                        bridge_object_version,
437                    } => ReadableEndOfEpochTransactionKindRef::BridgeCommitteeInit {
438                        bridge_object_version: *bridge_object_version,
439                    },
440                    Self::StoreExecutionTimeObservations(obs) => {
441                        ReadableEndOfEpochTransactionKindRef::StoreExecutionTimeObservations(obs)
442                    }
443                    Self::AccumulatorRootCreate => {
444                        ReadableEndOfEpochTransactionKindRef::AccumulatorRootCreate
445                    }
446                };
447                readable.serialize(serializer)
448            } else {
449                let binary = match self {
450                    Self::ChangeEpoch(k) => BinaryEndOfEpochTransactionKindRef::ChangeEpoch(k),
451                    Self::AuthenticatorStateCreate => {
452                        BinaryEndOfEpochTransactionKindRef::AuthenticatorStateCreate
453                    }
454                    Self::AuthenticatorStateExpire(k) => {
455                        BinaryEndOfEpochTransactionKindRef::AuthenticatorStateExpire(k)
456                    }
457                    Self::RandomnessStateCreate => {
458                        BinaryEndOfEpochTransactionKindRef::RandomnessStateCreate
459                    }
460                    Self::DenyListStateCreate => {
461                        BinaryEndOfEpochTransactionKindRef::DenyListStateCreate
462                    }
463                    Self::BridgeStateCreate { chain_id } => {
464                        BinaryEndOfEpochTransactionKindRef::BridgeStateCreate { chain_id }
465                    }
466                    Self::BridgeCommitteeInit {
467                        bridge_object_version,
468                    } => BinaryEndOfEpochTransactionKindRef::BridgeCommitteeInit {
469                        bridge_object_version: *bridge_object_version,
470                    },
471                    Self::StoreExecutionTimeObservations(obs) => {
472                        BinaryEndOfEpochTransactionKindRef::StoreExecutionTimeObservations(obs)
473                    }
474                    Self::AccumulatorRootCreate => {
475                        BinaryEndOfEpochTransactionKindRef::AccumulatorRootCreate
476                    }
477                };
478                binary.serialize(serializer)
479            }
480        }
481    }
482
483    impl<'de> Deserialize<'de> for EndOfEpochTransactionKind {
484        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
485        where
486            D: Deserializer<'de>,
487        {
488            if deserializer.is_human_readable() {
489                ReadableEndOfEpochTransactionKind::deserialize(deserializer).map(|readable| {
490                    match readable {
491                        ReadableEndOfEpochTransactionKind::ChangeEpoch(k) => Self::ChangeEpoch(k),
492                        ReadableEndOfEpochTransactionKind::AuthenticatorStateCreate => {
493                            Self::AuthenticatorStateCreate
494                        }
495                        ReadableEndOfEpochTransactionKind::AuthenticatorStateExpire(k) => {
496                            Self::AuthenticatorStateExpire(k)
497                        }
498                        ReadableEndOfEpochTransactionKind::RandomnessStateCreate => {
499                            Self::RandomnessStateCreate
500                        }
501                        ReadableEndOfEpochTransactionKind::DenyListStateCreate => {
502                            Self::DenyListStateCreate
503                        }
504                        ReadableEndOfEpochTransactionKind::BridgeStateCreate { chain_id } => {
505                            Self::BridgeStateCreate { chain_id }
506                        }
507                        ReadableEndOfEpochTransactionKind::BridgeCommitteeInit {
508                            bridge_object_version,
509                        } => Self::BridgeCommitteeInit {
510                            bridge_object_version,
511                        },
512                        ReadableEndOfEpochTransactionKind::StoreExecutionTimeObservations(obs) => {
513                            Self::StoreExecutionTimeObservations(obs)
514                        }
515                        ReadableEndOfEpochTransactionKind::AccumulatorRootCreate => {
516                            Self::AccumulatorRootCreate
517                        }
518                    }
519                })
520            } else {
521                BinaryEndOfEpochTransactionKind::deserialize(deserializer).map(
522                    |binary| match binary {
523                        BinaryEndOfEpochTransactionKind::ChangeEpoch(k) => Self::ChangeEpoch(k),
524                        BinaryEndOfEpochTransactionKind::AuthenticatorStateCreate => {
525                            Self::AuthenticatorStateCreate
526                        }
527                        BinaryEndOfEpochTransactionKind::AuthenticatorStateExpire(k) => {
528                            Self::AuthenticatorStateExpire(k)
529                        }
530                        BinaryEndOfEpochTransactionKind::RandomnessStateCreate => {
531                            Self::RandomnessStateCreate
532                        }
533                        BinaryEndOfEpochTransactionKind::DenyListStateCreate => {
534                            Self::DenyListStateCreate
535                        }
536                        BinaryEndOfEpochTransactionKind::BridgeStateCreate { chain_id } => {
537                            Self::BridgeStateCreate { chain_id }
538                        }
539                        BinaryEndOfEpochTransactionKind::BridgeCommitteeInit {
540                            bridge_object_version,
541                        } => Self::BridgeCommitteeInit {
542                            bridge_object_version,
543                        },
544                        BinaryEndOfEpochTransactionKind::StoreExecutionTimeObservations(obs) => {
545                            Self::StoreExecutionTimeObservations(obs)
546                        }
547                        BinaryEndOfEpochTransactionKind::AccumulatorRootCreate => {
548                            Self::AccumulatorRootCreate
549                        }
550                    },
551                )
552            }
553        }
554    }
555}
556
557mod version_assignments {
558    use super::*;
559    use crate::transaction::CanceledTransaction;
560    use crate::transaction::CanceledTransactionV2;
561    use crate::transaction::ConsensusDeterminedVersionAssignments;
562
563    #[derive(serde_derive::Serialize)]
564    #[serde(tag = "kind", rename_all = "snake_case")]
565    enum ReadableConsensusDeterminedVersionAssignmentsRef<'a> {
566        CanceledTransactions {
567            canceled_transactions: &'a Vec<CanceledTransaction>,
568        },
569        CanceledTransactionsV2 {
570            canceled_transactions: &'a Vec<CanceledTransactionV2>,
571        },
572    }
573
574    #[derive(serde_derive::Deserialize)]
575    #[serde(tag = "kind", rename_all = "snake_case")]
576    enum ReadableConsensusDeterminedVersionAssignments {
577        CanceledTransactions {
578            canceled_transactions: Vec<CanceledTransaction>,
579        },
580        CanceledTransactionsV2 {
581            canceled_transactions: Vec<CanceledTransactionV2>,
582        },
583    }
584
585    #[derive(serde_derive::Serialize)]
586    enum BinaryConsensusDeterminedVersionAssignmentsRef<'a> {
587        CanceledTransactions {
588            canceled_transactions: &'a Vec<CanceledTransaction>,
589        },
590        CanceledTransactionsV2 {
591            canceled_transactions: &'a Vec<CanceledTransactionV2>,
592        },
593    }
594
595    #[derive(serde_derive::Deserialize)]
596    enum BinaryConsensusDeterminedVersionAssignments {
597        CanceledTransactions {
598            canceled_transactions: Vec<CanceledTransaction>,
599        },
600        CanceledTransactionsV2 {
601            canceled_transactions: Vec<CanceledTransactionV2>,
602        },
603    }
604
605    impl Serialize for ConsensusDeterminedVersionAssignments {
606        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
607        where
608            S: Serializer,
609        {
610            if serializer.is_human_readable() {
611                let readable = match self {
612                    Self::CanceledTransactions {
613                        canceled_transactions,
614                    } => ReadableConsensusDeterminedVersionAssignmentsRef::CanceledTransactions {
615                        canceled_transactions,
616                    },
617                    Self::CanceledTransactionsV2 {
618                        canceled_transactions,
619                    } => ReadableConsensusDeterminedVersionAssignmentsRef::CanceledTransactionsV2 {
620                        canceled_transactions,
621                    },
622                };
623                readable.serialize(serializer)
624            } else {
625                let binary = match self {
626                    Self::CanceledTransactions {
627                        canceled_transactions,
628                    } => BinaryConsensusDeterminedVersionAssignmentsRef::CanceledTransactions {
629                        canceled_transactions,
630                    },
631                    Self::CanceledTransactionsV2 {
632                        canceled_transactions,
633                    } => BinaryConsensusDeterminedVersionAssignmentsRef::CanceledTransactionsV2 {
634                        canceled_transactions,
635                    },
636                };
637                binary.serialize(serializer)
638            }
639        }
640    }
641
642    impl<'de> Deserialize<'de> for ConsensusDeterminedVersionAssignments {
643        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
644        where
645            D: Deserializer<'de>,
646        {
647            if deserializer.is_human_readable() {
648                ReadableConsensusDeterminedVersionAssignments::deserialize(deserializer).map(
649                    |readable| match readable {
650                        ReadableConsensusDeterminedVersionAssignments::CanceledTransactions {
651                            canceled_transactions,
652                        } => Self::CanceledTransactions {
653                            canceled_transactions,
654                        },
655                        ReadableConsensusDeterminedVersionAssignments::CanceledTransactionsV2 {
656                            canceled_transactions,
657                        } => Self::CanceledTransactionsV2 {
658                            canceled_transactions,
659                        },
660                    },
661                )
662            } else {
663                BinaryConsensusDeterminedVersionAssignments::deserialize(deserializer).map(
664                    |binary| match binary {
665                        BinaryConsensusDeterminedVersionAssignments::CanceledTransactions {
666                            canceled_transactions,
667                        } => Self::CanceledTransactions {
668                            canceled_transactions,
669                        },
670                        BinaryConsensusDeterminedVersionAssignments::CanceledTransactionsV2 {
671                            canceled_transactions,
672                        } => Self::CanceledTransactionsV2 {
673                            canceled_transactions,
674                        },
675                    },
676                )
677            }
678        }
679    }
680}
681
682mod input_argument {
683    use crate::transaction::Input;
684
685    use super::*;
686
687    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
688    #[serde(tag = "type", rename_all = "snake_case")]
689    enum ReadableInput {
690        Pure {
691            #[serde(with = "::serde_with::As::<crate::_serde::Base64Encoded>")]
692            value: Vec<u8>,
693        },
694        ImmutableOrOwned(ObjectReference),
695        Shared {
696            object_id: ObjectId,
697            #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))]
698            initial_shared_version: u64,
699            mutable: bool,
700        },
701        Receiving(ObjectReference),
702    }
703
704    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
705    enum CallArg {
706        Pure(#[serde(with = "::serde_with::As::<::serde_with::Bytes>")] Vec<u8>),
707        Object(ObjectArg),
708    }
709
710    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
711    enum ObjectArg {
712        ImmutableOrOwned(ObjectReference),
713        Shared {
714            object_id: ObjectId,
715            initial_shared_version: u64,
716            mutable: bool,
717        },
718        Receiving(ObjectReference),
719    }
720
721    impl Serialize for Input {
722        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
723        where
724            S: Serializer,
725        {
726            if serializer.is_human_readable() {
727                let readable = match self.clone() {
728                    Input::Pure { value } => ReadableInput::Pure { value },
729                    Input::ImmutableOrOwned(object_ref) => {
730                        ReadableInput::ImmutableOrOwned(object_ref)
731                    }
732                    Input::Shared {
733                        object_id,
734                        initial_shared_version,
735                        mutable,
736                    } => ReadableInput::Shared {
737                        object_id,
738                        initial_shared_version,
739                        mutable,
740                    },
741                    Input::Receiving(object_ref) => ReadableInput::Receiving(object_ref),
742                };
743                readable.serialize(serializer)
744            } else {
745                let binary = match self.clone() {
746                    Input::Pure { value } => CallArg::Pure(value),
747                    Input::ImmutableOrOwned(object_ref) => {
748                        CallArg::Object(ObjectArg::ImmutableOrOwned(object_ref))
749                    }
750                    Input::Shared {
751                        object_id,
752                        initial_shared_version,
753                        mutable,
754                    } => CallArg::Object(ObjectArg::Shared {
755                        object_id,
756                        initial_shared_version,
757                        mutable,
758                    }),
759                    Input::Receiving(object_ref) => {
760                        CallArg::Object(ObjectArg::Receiving(object_ref))
761                    }
762                };
763                binary.serialize(serializer)
764            }
765        }
766    }
767
768    impl<'de> Deserialize<'de> for Input {
769        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
770        where
771            D: Deserializer<'de>,
772        {
773            if deserializer.is_human_readable() {
774                ReadableInput::deserialize(deserializer).map(|readable| match readable {
775                    ReadableInput::Pure { value } => Input::Pure { value },
776                    ReadableInput::ImmutableOrOwned(object_ref) => {
777                        Input::ImmutableOrOwned(object_ref)
778                    }
779                    ReadableInput::Shared {
780                        object_id,
781                        initial_shared_version,
782                        mutable,
783                    } => Input::Shared {
784                        object_id,
785                        initial_shared_version,
786                        mutable,
787                    },
788                    ReadableInput::Receiving(object_ref) => Input::Receiving(object_ref),
789                })
790            } else {
791                CallArg::deserialize(deserializer).map(|binary| match binary {
792                    CallArg::Pure(value) => Input::Pure { value },
793                    CallArg::Object(ObjectArg::ImmutableOrOwned(object_ref)) => {
794                        Input::ImmutableOrOwned(object_ref)
795                    }
796                    CallArg::Object(ObjectArg::Shared {
797                        object_id,
798                        initial_shared_version,
799                        mutable,
800                    }) => Input::Shared {
801                        object_id,
802                        initial_shared_version,
803                        mutable,
804                    },
805                    CallArg::Object(ObjectArg::Receiving(object_ref)) => {
806                        Input::Receiving(object_ref)
807                    }
808                })
809            }
810        }
811    }
812}
813
814mod argument {
815    use super::*;
816
817    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
818    #[serde(rename = "Argument", untagged, rename_all = "lowercase")]
819    enum ReadableArgument {
820        /// # Gas
821        Gas(Gas),
822        /// # Input
823        Input { input: u16 },
824        /// # Result
825        Result { result: u16 },
826        /// # NestedResult
827        NestedResult { result: (u16, u16) },
828    }
829
830    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
831    #[serde(rename_all = "lowercase")]
832    enum Gas {
833        Gas,
834    }
835
836    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
837    enum BinaryArgument {
838        Gas,
839        Input(u16),
840        Result(u16),
841        NestedResult(u16, u16),
842    }
843
844    impl Serialize for Argument {
845        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
846        where
847            S: Serializer,
848        {
849            if serializer.is_human_readable() {
850                let readable = match *self {
851                    Argument::Gas => ReadableArgument::Gas(Gas::Gas),
852                    Argument::Input(input) => ReadableArgument::Input { input },
853                    Argument::Result(result) => ReadableArgument::Result { result },
854                    Argument::NestedResult(result, subresult) => ReadableArgument::NestedResult {
855                        result: (result, subresult),
856                    },
857                };
858                readable.serialize(serializer)
859            } else {
860                let binary = match *self {
861                    Argument::Gas => BinaryArgument::Gas,
862                    Argument::Input(input) => BinaryArgument::Input(input),
863                    Argument::Result(result) => BinaryArgument::Result(result),
864                    Argument::NestedResult(result, subresult) => {
865                        BinaryArgument::NestedResult(result, subresult)
866                    }
867                };
868                binary.serialize(serializer)
869            }
870        }
871    }
872
873    impl<'de> Deserialize<'de> for Argument {
874        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
875        where
876            D: Deserializer<'de>,
877        {
878            if deserializer.is_human_readable() {
879                ReadableArgument::deserialize(deserializer).map(|readable| match readable {
880                    ReadableArgument::Gas(_) => Argument::Gas,
881                    ReadableArgument::Input { input } => Argument::Input(input),
882                    ReadableArgument::Result { result } => Argument::Result(result),
883                    ReadableArgument::NestedResult {
884                        result: (result, subresult),
885                    } => Argument::NestedResult(result, subresult),
886                })
887            } else {
888                BinaryArgument::deserialize(deserializer).map(|binary| match binary {
889                    BinaryArgument::Gas => Argument::Gas,
890                    BinaryArgument::Input(input) => Argument::Input(input),
891                    BinaryArgument::Result(result) => Argument::Result(result),
892                    BinaryArgument::NestedResult(result, subresult) => {
893                        Argument::NestedResult(result, subresult)
894                    }
895                })
896            }
897        }
898    }
899}
900
901mod command {
902    use super::*;
903
904    use crate::transaction::Command;
905    use crate::transaction::MakeMoveVector;
906    use crate::transaction::MergeCoins;
907    use crate::transaction::MoveCall;
908    use crate::transaction::Publish;
909    use crate::transaction::SplitCoins;
910    use crate::transaction::TransferObjects;
911    use crate::transaction::Upgrade;
912
913    #[derive(serde_derive::Serialize)]
914    #[serde(tag = "command", rename_all = "snake_case")]
915    enum ReadableCommandRef<'a> {
916        MoveCall(&'a MoveCall),
917        TransferObjects(&'a TransferObjects),
918        SplitCoins(&'a SplitCoins),
919        MergeCoins(&'a MergeCoins),
920        Publish(&'a Publish),
921        MakeMoveVector(&'a MakeMoveVector),
922        Upgrade(&'a Upgrade),
923    }
924
925    #[derive(serde_derive::Deserialize)]
926    #[serde(tag = "command", rename_all = "snake_case")]
927    enum ReadableCommand {
928        MoveCall(MoveCall),
929        TransferObjects(TransferObjects),
930        SplitCoins(SplitCoins),
931        MergeCoins(MergeCoins),
932        Publish(Publish),
933        MakeMoveVector(MakeMoveVector),
934        Upgrade(Upgrade),
935    }
936
937    #[derive(serde_derive::Serialize)]
938    enum BinaryCommandRef<'a> {
939        MoveCall(&'a MoveCall),
940        TransferObjects(&'a TransferObjects),
941        SplitCoins(&'a SplitCoins),
942        MergeCoins(&'a MergeCoins),
943        Publish(&'a Publish),
944        MakeMoveVector(&'a MakeMoveVector),
945        Upgrade(&'a Upgrade),
946    }
947
948    #[derive(serde_derive::Deserialize)]
949    enum BinaryCommand {
950        MoveCall(MoveCall),
951        TransferObjects(TransferObjects),
952        SplitCoins(SplitCoins),
953        MergeCoins(MergeCoins),
954        Publish(Publish),
955        MakeMoveVector(MakeMoveVector),
956        Upgrade(Upgrade),
957    }
958
959    impl Serialize for Command {
960        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
961        where
962            S: Serializer,
963        {
964            if serializer.is_human_readable() {
965                let readable = match self {
966                    Command::MoveCall(c) => ReadableCommandRef::MoveCall(c),
967                    Command::TransferObjects(c) => ReadableCommandRef::TransferObjects(c),
968                    Command::SplitCoins(c) => ReadableCommandRef::SplitCoins(c),
969                    Command::MergeCoins(c) => ReadableCommandRef::MergeCoins(c),
970                    Command::Publish(c) => ReadableCommandRef::Publish(c),
971                    Command::MakeMoveVector(c) => ReadableCommandRef::MakeMoveVector(c),
972                    Command::Upgrade(c) => ReadableCommandRef::Upgrade(c),
973                };
974                readable.serialize(serializer)
975            } else {
976                let binary = match self {
977                    Command::MoveCall(c) => BinaryCommandRef::MoveCall(c),
978                    Command::TransferObjects(c) => BinaryCommandRef::TransferObjects(c),
979                    Command::SplitCoins(c) => BinaryCommandRef::SplitCoins(c),
980                    Command::MergeCoins(c) => BinaryCommandRef::MergeCoins(c),
981                    Command::Publish(c) => BinaryCommandRef::Publish(c),
982                    Command::MakeMoveVector(c) => BinaryCommandRef::MakeMoveVector(c),
983                    Command::Upgrade(c) => BinaryCommandRef::Upgrade(c),
984                };
985                binary.serialize(serializer)
986            }
987        }
988    }
989
990    impl<'de> Deserialize<'de> for Command {
991        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
992        where
993            D: Deserializer<'de>,
994        {
995            if deserializer.is_human_readable() {
996                ReadableCommand::deserialize(deserializer).map(|readable| match readable {
997                    ReadableCommand::MoveCall(c) => Command::MoveCall(c),
998                    ReadableCommand::TransferObjects(c) => Command::TransferObjects(c),
999                    ReadableCommand::SplitCoins(c) => Command::SplitCoins(c),
1000                    ReadableCommand::MergeCoins(c) => Command::MergeCoins(c),
1001                    ReadableCommand::Publish(c) => Command::Publish(c),
1002                    ReadableCommand::MakeMoveVector(c) => Command::MakeMoveVector(c),
1003                    ReadableCommand::Upgrade(c) => Command::Upgrade(c),
1004                })
1005            } else {
1006                BinaryCommand::deserialize(deserializer).map(|binary| match binary {
1007                    BinaryCommand::MoveCall(c) => Command::MoveCall(c),
1008                    BinaryCommand::TransferObjects(c) => Command::TransferObjects(c),
1009                    BinaryCommand::SplitCoins(c) => Command::SplitCoins(c),
1010                    BinaryCommand::MergeCoins(c) => Command::MergeCoins(c),
1011                    BinaryCommand::Publish(c) => Command::Publish(c),
1012                    BinaryCommand::MakeMoveVector(c) => Command::MakeMoveVector(c),
1013                    BinaryCommand::Upgrade(c) => Command::Upgrade(c),
1014                })
1015            }
1016        }
1017    }
1018}
1019
1020pub(crate) use signed_transaction::SignedTransactionWithIntentMessage;
1021
1022mod signed_transaction {
1023    use serde::ser::SerializeSeq;
1024
1025    use super::*;
1026    use crate::transaction::SignedTransaction;
1027    use crate::transaction::Transaction;
1028    use crate::UserSignature;
1029
1030    /// serde implementation that serializes a transaction prefixed with the signing intent. See
1031    /// [struct Intent] for more info.
1032    ///
1033    /// So we need to serialize Transaction as (0, 0, 0, Transaction)
1034    struct IntentMessageWrappedTransaction;
1035
1036    impl SerializeAs<Transaction> for IntentMessageWrappedTransaction {
1037        fn serialize_as<S>(transaction: &Transaction, serializer: S) -> Result<S::Ok, S::Error>
1038        where
1039            S: Serializer,
1040        {
1041            use serde::ser::SerializeTuple;
1042
1043            let mut s = serializer.serialize_tuple(4)?;
1044            s.serialize_element(&0u8)?;
1045            s.serialize_element(&0u8)?;
1046            s.serialize_element(&0u8)?;
1047            s.serialize_element(transaction)?;
1048            s.end()
1049        }
1050    }
1051
1052    impl<'de> DeserializeAs<'de, Transaction> for IntentMessageWrappedTransaction {
1053        fn deserialize_as<D>(deserializer: D) -> Result<Transaction, D::Error>
1054        where
1055            D: Deserializer<'de>,
1056        {
1057            let (scope, version, app, transaction): (u8, u8, u8, Transaction) =
1058                Deserialize::deserialize(deserializer)?;
1059            match (scope, version, app) {
1060                (0, 0, 0) => {}
1061                _ => {
1062                    return Err(serde::de::Error::custom(format!(
1063                        "invalid intent message ({scope}, {version}, {app})"
1064                    )))
1065                }
1066            }
1067
1068            Ok(transaction)
1069        }
1070    }
1071
1072    pub(crate) struct SignedTransactionWithIntentMessage;
1073
1074    #[derive(serde_derive::Serialize)]
1075    struct BinarySignedTransactionWithIntentMessageRef<'a> {
1076        #[serde(with = "::serde_with::As::<IntentMessageWrappedTransaction>")]
1077        transaction: &'a Transaction,
1078        signatures: &'a Vec<UserSignature>,
1079    }
1080
1081    #[derive(serde_derive::Deserialize)]
1082    struct BinarySignedTransactionWithIntentMessage {
1083        #[serde(with = "::serde_with::As::<IntentMessageWrappedTransaction>")]
1084        transaction: Transaction,
1085        signatures: Vec<UserSignature>,
1086    }
1087
1088    impl SerializeAs<SignedTransaction> for SignedTransactionWithIntentMessage {
1089        fn serialize_as<S>(
1090            transaction: &SignedTransaction,
1091            serializer: S,
1092        ) -> Result<S::Ok, S::Error>
1093        where
1094            S: Serializer,
1095        {
1096            if serializer.is_human_readable() {
1097                transaction.serialize(serializer)
1098            } else {
1099                let SignedTransaction {
1100                    transaction,
1101                    signatures,
1102                } = transaction;
1103                let binary = BinarySignedTransactionWithIntentMessageRef {
1104                    transaction,
1105                    signatures,
1106                };
1107
1108                let mut s = serializer.serialize_seq(Some(1))?;
1109                s.serialize_element(&binary)?;
1110                s.end()
1111            }
1112        }
1113    }
1114
1115    impl<'de> DeserializeAs<'de, SignedTransaction> for SignedTransactionWithIntentMessage {
1116        fn deserialize_as<D>(deserializer: D) -> Result<SignedTransaction, D::Error>
1117        where
1118            D: Deserializer<'de>,
1119        {
1120            if deserializer.is_human_readable() {
1121                SignedTransaction::deserialize(deserializer)
1122            } else {
1123                struct V;
1124                impl<'de> serde::de::Visitor<'de> for V {
1125                    type Value = SignedTransaction;
1126
1127                    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1128                        formatter.write_str("expected a sequence with length 1")
1129                    }
1130
1131                    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1132                    where
1133                        A: serde::de::SeqAccess<'de>,
1134                    {
1135                        if seq.size_hint().is_some_and(|size| size != 1) {
1136                            return Err(serde::de::Error::custom(
1137                                "expected a sequence with length 1",
1138                            ));
1139                        }
1140
1141                        let BinarySignedTransactionWithIntentMessage {
1142                            transaction,
1143                            signatures,
1144                        } = seq.next_element()?.ok_or_else(|| {
1145                            serde::de::Error::custom("expected a sequence with length 1")
1146                        })?;
1147                        Ok(SignedTransaction {
1148                            transaction,
1149                            signatures,
1150                        })
1151                    }
1152                }
1153
1154                deserializer.deserialize_seq(V)
1155            }
1156        }
1157    }
1158}
1159
1160mod transaction_expiration {
1161    use crate::EpochId;
1162    use crate::TransactionExpiration;
1163    use serde::Deserialize;
1164    use serde::Deserializer;
1165    use serde::Serialize;
1166    use serde::Serializer;
1167
1168    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
1169    #[serde(rename = "TransactionExpiration")]
1170    #[serde(rename_all = "lowercase")]
1171    enum ReadableTransactionExpiration {
1172        /// Validators wont sign a transaction unless the expiration Epoch
1173        /// is greater than or equal to the current epoch
1174        Epoch(
1175            #[cfg_attr(feature = "serde", serde(with = "crate::_serde::ReadableDisplay"))] EpochId,
1176        ),
1177    }
1178
1179    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
1180    pub enum BinaryTransactionExpiration {
1181        /// The transaction has no expiration
1182        None,
1183        /// Validators wont sign a transaction unless the expiration Epoch
1184        /// is greater than or equal to the current epoch
1185        Epoch(EpochId),
1186    }
1187
1188    impl Serialize for TransactionExpiration {
1189        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1190        where
1191            S: Serializer,
1192        {
1193            if serializer.is_human_readable() {
1194                match *self {
1195                    Self::None => None,
1196                    Self::Epoch(epoch) => Some(ReadableTransactionExpiration::Epoch(epoch)),
1197                }
1198                .serialize(serializer)
1199            } else {
1200                match *self {
1201                    Self::None => BinaryTransactionExpiration::None,
1202                    Self::Epoch(epoch) => BinaryTransactionExpiration::Epoch(epoch),
1203                }
1204                .serialize(serializer)
1205            }
1206        }
1207    }
1208
1209    impl<'de> Deserialize<'de> for TransactionExpiration {
1210        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1211        where
1212            D: Deserializer<'de>,
1213        {
1214            if deserializer.is_human_readable() {
1215                Option::<ReadableTransactionExpiration>::deserialize(deserializer).map(|readable| {
1216                    match readable {
1217                        None => Self::None,
1218                        Some(ReadableTransactionExpiration::Epoch(epoch)) => Self::Epoch(epoch),
1219                    }
1220                })
1221            } else {
1222                BinaryTransactionExpiration::deserialize(deserializer).map(|binary| match binary {
1223                    BinaryTransactionExpiration::None => Self::None,
1224                    BinaryTransactionExpiration::Epoch(epoch) => Self::Epoch(epoch),
1225                })
1226            }
1227        }
1228    }
1229}
1230
1231#[cfg(test)]
1232mod test {
1233    use base64ct::Base64;
1234    use base64ct::Encoding;
1235
1236    use crate::transaction::Argument;
1237    use crate::transaction::Input;
1238    use crate::transaction::Transaction;
1239    use crate::ObjectDigest;
1240    use crate::ObjectId;
1241    use crate::ObjectReference;
1242
1243    #[cfg(target_arch = "wasm32")]
1244    use wasm_bindgen_test::wasm_bindgen_test as test;
1245
1246    #[test]
1247    fn argument() {
1248        let test_cases = [
1249            (Argument::Gas, serde_json::json!("gas")),
1250            (Argument::Input(1), serde_json::json!({"input": 1})),
1251            (Argument::Result(2), serde_json::json!({"result": 2})),
1252            (
1253                Argument::NestedResult(3, 4),
1254                serde_json::json!({"result": [3, 4]}),
1255            ),
1256        ];
1257
1258        for (case, expected) in test_cases {
1259            let actual = serde_json::to_value(case).unwrap();
1260            assert_eq!(actual, expected);
1261            println!("{actual}");
1262
1263            let deser = serde_json::from_value(expected).unwrap();
1264            assert_eq!(case, deser);
1265        }
1266    }
1267
1268    #[test]
1269    fn input_argument() {
1270        let test_cases = [
1271            (
1272                Input::Pure {
1273                    value: vec![1, 2, 3, 4],
1274                },
1275                serde_json::json!({
1276                  "type": "pure",
1277                  "value": "AQIDBA=="
1278                }),
1279            ),
1280            (
1281                Input::ImmutableOrOwned(ObjectReference::new(
1282                    ObjectId::ZERO,
1283                    1,
1284                    ObjectDigest::ZERO,
1285                )),
1286                serde_json::json!({
1287                  "type": "immutable_or_owned",
1288                  "object_id": "0x0000000000000000000000000000000000000000000000000000000000000000",
1289                  "version": "1",
1290                  "digest": "11111111111111111111111111111111"
1291                }),
1292            ),
1293            (
1294                Input::Shared {
1295                    object_id: ObjectId::ZERO,
1296                    initial_shared_version: 1,
1297                    mutable: true,
1298                },
1299                serde_json::json!({
1300                  "type": "shared",
1301                  "object_id": "0x0000000000000000000000000000000000000000000000000000000000000000",
1302                  "initial_shared_version": "1",
1303                  "mutable": true
1304                }),
1305            ),
1306            (
1307                Input::Receiving(ObjectReference::new(ObjectId::ZERO, 1, ObjectDigest::ZERO)),
1308                serde_json::json!({
1309                  "type": "receiving",
1310                  "object_id": "0x0000000000000000000000000000000000000000000000000000000000000000",
1311                  "version": "1",
1312                  "digest": "11111111111111111111111111111111"
1313                }),
1314            ),
1315        ];
1316
1317        for (case, expected) in test_cases {
1318            let actual = serde_json::to_value(&case).unwrap();
1319            assert_eq!(actual, expected);
1320            println!("{actual}");
1321
1322            let deser = serde_json::from_value(expected).unwrap();
1323            assert_eq!(case, deser);
1324        }
1325    }
1326
1327    #[test]
1328    fn transaction_fixtures() {
1329        const GENESIS_TRANSACTION: &str = include_str!("fixtures/genesis-transaction");
1330        const CONSENSUS_PROLOGUE: &str = "AAMAAAAAAAAAAAIAAAAAAAAAtkjHeocBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA==";
1331        const EPOCH_CHANGE: &str = "AAUCAmkBAAAAAAAAmSrgAQAAAAAAagEAAAAAAAApAAAAAAAAALAQCoNLLwAAnNn0sywGAABsVBEfSC0AAKQnlhd1AAAAzve+vo4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA=";
1332        const AUTHENTICATOR_STATE_UPDATE: &str =
1333            include_str!("fixtures/authenticator_state_update");
1334        const PTB: &str = "AAADAQFEBbUNeR/TNGdU6Bcaqra8LtJsLEbv3QM8FLMK5QesMyx96QEAAAAAAQAIVsakAAAAAAABALyyokbZ/8ynfWQer6UyP1DpeCnPU1NC7AyFNJSaTztnQF40BQAAAAAgffPXh5XuG6TWjHk6qC5w9k2a+41oTWfm0sC1FOYRqsEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN7pB2Nsb2JfdjIMY2FuY2VsX29yZGVyAgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNzdWkDU1VJAAddSzAlBmRcN/8TO5jEtQpa4UhBZZc41tcz1Z0NIXqTvwRjb2luBENPSU4AAwEAAAEBAAECAPgh00g/x3Jeuvqlo9Ejc9SZAb384UhPIZ2qcGajDfd9ASXQjpFOD6mfycbzwD1wc+IOkCXQ8rHQo/Vi5SDOGMR/Jl40BQAAAAAgV7P1E0IMKon5uI82R/0arWLt+dc1ng/4VwKDqpTCxHT4IdNIP8dyXrr6paPRI3PUmQG9/OFITyGdqnBmow33fe4CAAAAAAAAAMqaOwAAAAAA";
1335        const WORMHOLE_PYTH_TRANSACTION: &str = include_str!("fixtures/wormhole-pyth-transaction");
1336
1337        for fixture in [
1338            GENESIS_TRANSACTION,
1339            CONSENSUS_PROLOGUE,
1340            EPOCH_CHANGE,
1341            AUTHENTICATOR_STATE_UPDATE,
1342            PTB,
1343            WORMHOLE_PYTH_TRANSACTION,
1344        ] {
1345            let fixture = Base64::decode_vec(fixture.trim()).unwrap();
1346            let tx: Transaction = bcs::from_bytes(&fixture).unwrap();
1347            assert_eq!(bcs::to_bytes(&tx).unwrap(), fixture);
1348
1349            let json = serde_json::to_string_pretty(&tx).unwrap();
1350            println!("{json}");
1351            assert_eq!(tx, serde_json::from_str(&json).unwrap());
1352        }
1353    }
1354}