1pub mod cbor_encodings;
5pub mod serialization;
6pub mod utils;
7
8use super::{NetworkId, Value};
9use crate::address::Address;
10use crate::assets::{Coin, Mint, PositiveCoin};
11use crate::auxdata::AuxiliaryData;
12use crate::crypto::{
13 AuxiliaryDataHash, DatumHash, Ed25519KeyHash, ScriptDataHash, TransactionHash,
14};
15use crate::governance::VotingProcedures;
16use crate::plutus::{PlutusData, Redeemers};
17use crate::{
18 NonemptySetBootstrapWitness, NonemptySetCertificate, NonemptySetNativeScript,
19 NonemptySetPlutusData, NonemptySetPlutusV1Script, NonemptySetPlutusV2Script,
20 NonemptySetPlutusV3Script, NonemptySetProposalProcedure, NonemptySetTransactionInput,
21 NonemptySetVkeywitness, RequiredSigners, Script, SetTransactionInput, Slot, Withdrawals,
22};
23use cbor_encodings::{
24 AlonzoFormatTxOutEncoding, ConwayFormatTxOutEncoding, ScriptAllEncoding, ScriptAnyEncoding,
25 ScriptInvalidBeforeEncoding, ScriptInvalidHereafterEncoding, ScriptNOfKEncoding,
26 ScriptPubkeyEncoding, TransactionBodyEncoding, TransactionEncoding, TransactionInputEncoding,
27 TransactionWitnessSetEncoding,
28};
29use cml_core::ordered_hash_map::OrderedHashMap;
30use cml_core::serialization::{LenEncoding, StringEncoding};
31use std::collections::BTreeMap;
32
33#[derive(
34 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
35)]
36#[derivative(Hash, Eq, PartialEq)]
37pub struct AlonzoFormatTxOut {
38 pub address: Address,
39 pub amount: Value,
40 pub datum_hash: Option<DatumHash>,
41 #[serde(skip)]
42 #[derivative(PartialEq = "ignore", Hash = "ignore")]
43 pub encodings: Option<AlonzoFormatTxOutEncoding>,
44}
45
46impl AlonzoFormatTxOut {
47 pub fn new(address: Address, amount: Value) -> Self {
48 Self {
49 address,
50 amount,
51 datum_hash: None,
52 encodings: None,
53 }
54 }
55}
56
57#[derive(
58 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
59)]
60#[derivative(Hash, Eq, PartialEq)]
61pub struct ConwayFormatTxOut {
62 pub address: Address,
63 pub amount: Value,
64 pub datum_option: Option<DatumOption>,
65 pub script_reference: Option<ScriptRef>,
66 #[serde(skip)]
67 #[derivative(PartialEq = "ignore", Hash = "ignore")]
68 pub encodings: Option<ConwayFormatTxOutEncoding>,
69}
70
71impl ConwayFormatTxOut {
72 pub fn new(address: Address, amount: Value) -> Self {
73 Self {
74 address,
75 amount,
76 datum_option: None,
77 script_reference: None,
78 encodings: None,
79 }
80 }
81}
82
83#[derive(
84 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
85)]
86#[derivative(Eq, PartialEq, Hash)]
87pub enum DatumOption {
88 Hash {
89 datum_hash: DatumHash,
90 #[serde(skip)]
91 #[derivative(PartialEq = "ignore", Hash = "ignore")]
92 len_encoding: LenEncoding,
93 #[serde(skip)]
94 #[derivative(PartialEq = "ignore", Hash = "ignore")]
95 tag_encoding: Option<cbor_event::Sz>,
96 #[serde(skip)]
97 #[derivative(PartialEq = "ignore", Hash = "ignore")]
98 datum_hash_encoding: StringEncoding,
99 },
100 Datum {
101 datum: PlutusData,
102 #[serde(skip)]
103 #[derivative(PartialEq = "ignore", Hash = "ignore")]
104 len_encoding: LenEncoding,
105 #[serde(skip)]
106 #[derivative(PartialEq = "ignore", Hash = "ignore")]
107 tag_encoding: Option<cbor_event::Sz>,
108 #[serde(skip)]
109 #[derivative(PartialEq = "ignore", Hash = "ignore")]
110 datum_tag_encoding: Option<cbor_event::Sz>,
111 #[serde(skip)]
112 #[derivative(PartialEq = "ignore", Hash = "ignore")]
113 datum_bytes_encoding: StringEncoding,
114 },
115}
116
117impl DatumOption {
118 pub fn new_hash(datum_hash: DatumHash) -> Self {
119 Self::Hash {
120 datum_hash,
121 len_encoding: LenEncoding::default(),
122 tag_encoding: None,
123 datum_hash_encoding: StringEncoding::default(),
124 }
125 }
126
127 pub fn new_datum(datum: PlutusData) -> Self {
128 Self::Datum {
129 datum,
130 len_encoding: LenEncoding::default(),
131 tag_encoding: None,
132 datum_tag_encoding: None,
133 datum_bytes_encoding: StringEncoding::default(),
134 }
135 }
136}
137
138#[derive(
139 Clone, Debug, Hash, PartialEq, Eq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
140)]
141pub enum NativeScript {
142 ScriptPubkey(ScriptPubkey),
143 ScriptAll(ScriptAll),
144 ScriptAny(ScriptAny),
145 ScriptNOfK(ScriptNOfK),
146 ScriptInvalidBefore(ScriptInvalidBefore),
148 ScriptInvalidHereafter(ScriptInvalidHereafter),
150}
151
152impl NativeScript {
153 pub fn new_script_pubkey(ed25519_key_hash: Ed25519KeyHash) -> Self {
154 Self::ScriptPubkey(ScriptPubkey::new(ed25519_key_hash))
155 }
156
157 pub fn new_script_all(native_scripts: Vec<NativeScript>) -> Self {
158 Self::ScriptAll(ScriptAll::new(native_scripts))
159 }
160
161 pub fn new_script_any(native_scripts: Vec<NativeScript>) -> Self {
162 Self::ScriptAny(ScriptAny::new(native_scripts))
163 }
164
165 pub fn new_script_n_of_k(n: u64, native_scripts: Vec<NativeScript>) -> Self {
166 Self::ScriptNOfK(ScriptNOfK::new(n, native_scripts))
167 }
168
169 pub fn new_script_invalid_before(before: Slot) -> Self {
171 Self::ScriptInvalidBefore(ScriptInvalidBefore::new(before))
172 }
173
174 pub fn new_script_invalid_hereafter(after: Slot) -> Self {
176 Self::ScriptInvalidHereafter(ScriptInvalidHereafter::new(after))
177 }
178}
179
180#[derive(
181 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
182)]
183#[derivative(Hash, PartialEq, Eq)]
184pub struct ScriptAll {
185 pub native_scripts: Vec<NativeScript>,
186 #[serde(skip)]
187 #[derivative(PartialEq = "ignore", Hash = "ignore")]
188 pub encodings: Option<ScriptAllEncoding>,
189}
190
191impl ScriptAll {
192 pub fn new(native_scripts: Vec<NativeScript>) -> Self {
193 Self {
194 native_scripts,
195 encodings: None,
196 }
197 }
198}
199
200#[derive(
201 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
202)]
203#[derivative(Hash, PartialEq, Eq)]
204pub struct ScriptAny {
205 pub native_scripts: Vec<NativeScript>,
206 #[serde(skip)]
207 #[derivative(PartialEq = "ignore", Hash = "ignore")]
208 pub encodings: Option<ScriptAnyEncoding>,
209}
210
211impl ScriptAny {
212 pub fn new(native_scripts: Vec<NativeScript>) -> Self {
213 Self {
214 native_scripts,
215 encodings: None,
216 }
217 }
218}
219
220#[derive(
221 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
222)]
223#[derivative(Hash, PartialEq, Eq)]
224pub struct ScriptInvalidBefore {
225 pub before: Slot,
226 #[serde(skip)]
227 #[derivative(PartialEq = "ignore", Hash = "ignore")]
228 pub encodings: Option<ScriptInvalidBeforeEncoding>,
229}
230
231impl ScriptInvalidBefore {
232 pub fn new(before: Slot) -> Self {
233 Self {
234 before,
235 encodings: None,
236 }
237 }
238}
239
240#[derive(
241 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
242)]
243#[derivative(Hash, PartialEq, Eq)]
244pub struct ScriptInvalidHereafter {
245 pub after: Slot,
246 #[serde(skip)]
247 #[derivative(PartialEq = "ignore", Hash = "ignore")]
248 pub encodings: Option<ScriptInvalidHereafterEncoding>,
249}
250
251impl ScriptInvalidHereafter {
252 pub fn new(after: Slot) -> Self {
253 Self {
254 after,
255 encodings: None,
256 }
257 }
258}
259
260#[derive(
261 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
262)]
263#[derivative(Hash, PartialEq, Eq)]
264pub struct ScriptNOfK {
265 pub n: u64,
266 pub native_scripts: Vec<NativeScript>,
267 #[serde(skip)]
268 #[derivative(PartialEq = "ignore", Hash = "ignore")]
269 pub encodings: Option<ScriptNOfKEncoding>,
270}
271
272impl ScriptNOfK {
273 pub fn new(n: u64, native_scripts: Vec<NativeScript>) -> Self {
274 Self {
275 n,
276 native_scripts,
277 encodings: None,
278 }
279 }
280}
281
282#[derive(
283 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
284)]
285#[derivative(Hash, PartialEq, Eq)]
286pub struct ScriptPubkey {
287 pub ed25519_key_hash: Ed25519KeyHash,
288 #[serde(skip)]
289 #[derivative(PartialEq = "ignore", Hash = "ignore")]
290 pub encodings: Option<ScriptPubkeyEncoding>,
291}
292
293impl ScriptPubkey {
294 pub fn new(ed25519_key_hash: Ed25519KeyHash) -> Self {
295 Self {
296 ed25519_key_hash,
297 encodings: None,
298 }
299 }
300}
301
302pub type ScriptRef = Script;
303
304#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
305pub struct Transaction {
306 pub body: TransactionBody,
307 pub witness_set: TransactionWitnessSet,
308 pub is_valid: bool,
309 pub auxiliary_data: Option<AuxiliaryData>,
310 #[serde(skip)]
311 pub encodings: Option<TransactionEncoding>,
312}
313
314impl Transaction {
315 pub fn new(
316 body: TransactionBody,
317 witness_set: TransactionWitnessSet,
318 is_valid: bool,
319 auxiliary_data: Option<AuxiliaryData>,
320 ) -> Self {
321 Self {
322 body,
323 witness_set,
324 is_valid,
325 auxiliary_data,
326 encodings: None,
327 }
328 }
329}
330
331#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
332pub struct TransactionBody {
333 pub inputs: SetTransactionInput,
334 pub outputs: Vec<TransactionOutput>,
335 pub fee: Coin,
336 pub ttl: Option<u64>,
337 pub certs: Option<NonemptySetCertificate>,
338 pub withdrawals: Option<Withdrawals>,
339 pub auxiliary_data_hash: Option<AuxiliaryDataHash>,
340 pub validity_interval_start: Option<u64>,
341 pub mint: Option<Mint>,
342 pub script_data_hash: Option<ScriptDataHash>,
343 pub collateral_inputs: Option<NonemptySetTransactionInput>,
344 pub required_signers: Option<RequiredSigners>,
345 pub network_id: Option<NetworkId>,
346 pub collateral_return: Option<TransactionOutput>,
347 pub total_collateral: Option<Coin>,
348 pub reference_inputs: Option<NonemptySetTransactionInput>,
349 pub voting_procedures: Option<VotingProcedures>,
350 pub proposal_procedures: Option<NonemptySetProposalProcedure>,
351 pub current_treasury_value: Option<Coin>,
352 pub donation: Option<PositiveCoin>,
353 #[serde(skip)]
354 pub encodings: Option<TransactionBodyEncoding>,
355}
356
357impl TransactionBody {
358 pub fn new(inputs: SetTransactionInput, outputs: Vec<TransactionOutput>, fee: Coin) -> Self {
359 Self {
360 inputs,
361 outputs,
362 fee,
363 ttl: None,
364 certs: None,
365 withdrawals: None,
366 auxiliary_data_hash: None,
367 validity_interval_start: None,
368 mint: None,
369 script_data_hash: None,
370 collateral_inputs: None,
371 required_signers: None,
372 network_id: None,
373 collateral_return: None,
374 total_collateral: None,
375 reference_inputs: None,
376 voting_procedures: None,
377 proposal_procedures: None,
378 current_treasury_value: None,
379 donation: None,
380 encodings: None,
381 }
382 }
383}
384
385#[derive(
386 Clone, Debug, derivative::Derivative, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
387)]
388#[derivative(Ord, PartialOrd, Eq, PartialEq, Hash)]
389pub struct TransactionInput {
390 pub transaction_id: TransactionHash,
391 pub index: u64,
392 #[serde(skip)]
393 #[derivative(
394 PartialEq = "ignore",
395 Ord = "ignore",
396 PartialOrd = "ignore",
397 Hash = "ignore"
398 )]
399 pub encodings: Option<TransactionInputEncoding>,
400}
401
402impl TransactionInput {
403 pub fn new(transaction_id: TransactionHash, index: u64) -> Self {
404 Self {
405 transaction_id,
406 index,
407 encodings: None,
408 }
409 }
410}
411
412#[derive(
413 Clone, Debug, Hash, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
414)]
415pub enum TransactionOutput {
416 AlonzoFormatTxOut(AlonzoFormatTxOut),
417 ConwayFormatTxOut(ConwayFormatTxOut),
418}
419
420impl TransactionOutput {
421 pub fn new_alonzo_format_tx_out(alonzo_format_tx_out: AlonzoFormatTxOut) -> Self {
422 Self::AlonzoFormatTxOut(alonzo_format_tx_out)
423 }
424
425 pub fn new_conway_format_tx_out(conway_format_tx_out: ConwayFormatTxOut) -> Self {
426 Self::ConwayFormatTxOut(conway_format_tx_out)
427 }
428}
429
430#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
431pub struct TransactionWitnessSet {
432 pub vkeywitnesses: Option<NonemptySetVkeywitness>,
433 pub native_scripts: Option<NonemptySetNativeScript>,
434 pub bootstrap_witnesses: Option<NonemptySetBootstrapWitness>,
435 pub plutus_v1_scripts: Option<NonemptySetPlutusV1Script>,
436 pub plutus_datums: Option<NonemptySetPlutusData>,
437 pub redeemers: Option<Redeemers>,
438 pub plutus_v2_scripts: Option<NonemptySetPlutusV2Script>,
439 pub plutus_v3_scripts: Option<NonemptySetPlutusV3Script>,
440 #[serde(skip)]
441 pub encodings: Option<TransactionWitnessSetEncoding>,
442}
443
444impl TransactionWitnessSet {
445 pub fn new() -> Self {
446 Self {
447 vkeywitnesses: None,
448 native_scripts: None,
449 bootstrap_witnesses: None,
450 plutus_v1_scripts: None,
451 plutus_datums: None,
452 redeemers: None,
453 plutus_v2_scripts: None,
454 plutus_v3_scripts: None,
455 encodings: None,
456 }
457 }
458}
459
460impl Default for TransactionWitnessSet {
461 fn default() -> Self {
462 Self::new()
463 }
464}