1use cml_chain::builders::tx_builder::{ChangeSelectionAlgo, CoinSelectionStrategyCIP2};
2use cml_core_wasm::{impl_wasm_cbor_event_serialize_api, impl_wasm_conversions};
3use cml_crypto_wasm::Ed25519KeyHash;
4use wasm_bindgen::prelude::{wasm_bindgen, JsError};
5
6use crate::{
7 address::Address,
8 assets::Mint,
9 auxdata::AuxiliaryData,
10 builders::{
11 certificate_builder::CertificateBuilderResult, input_builder::InputBuilderResult,
12 mint_builder::MintBuilderResult, output_builder::SingleOutputBuilderResult,
13 proposal_builder::ProposalBuilderResult, redeemer_builder::RedeemerWitnessKey,
14 vote_builder::VoteBuilderResult, withdrawal_builder::WithdrawalBuilderResult,
15 witness_builder::TransactionWitnessSetBuilder,
16 },
17 crypto::{BootstrapWitness, Vkeywitness},
18 fees::LinearFee,
19 plutus::{CostModels, ExUnitPrices, ExUnits, Redeemers},
20 transaction::{Transaction, TransactionBody, TransactionInput, TransactionOutput},
21 Coin, NetworkId, Slot, Value, Withdrawals,
22};
23
24#[wasm_bindgen]
25#[derive(Clone, Debug)]
26pub struct TransactionUnspentOutput(cml_chain::builders::tx_builder::TransactionUnspentOutput);
27
28impl_wasm_conversions!(
29 cml_chain::builders::tx_builder::TransactionUnspentOutput,
30 TransactionUnspentOutput
31);
32
33impl_wasm_cbor_event_serialize_api!(TransactionUnspentOutput);
34
35#[wasm_bindgen]
36impl TransactionUnspentOutput {
37 pub fn new(input: &TransactionInput, output: &TransactionOutput) -> Self {
38 cml_chain::builders::tx_builder::TransactionUnspentOutput::new(
39 input.clone().into(),
40 output.clone().into(),
41 )
42 .into()
43 }
44
45 pub fn input(&self) -> TransactionInput {
46 self.0.input.clone().into()
47 }
48
49 pub fn output(&self) -> TransactionOutput {
50 self.0.output.clone().into()
51 }
52}
53
54#[wasm_bindgen]
55#[derive(Clone, Debug)]
56pub struct TransactionBuilderConfig(cml_chain::builders::tx_builder::TransactionBuilderConfig);
57
58impl_wasm_conversions!(
59 cml_chain::builders::tx_builder::TransactionBuilderConfig,
60 TransactionBuilderConfig
61);
62
63#[wasm_bindgen]
64#[derive(Clone, Debug, Default)]
65pub struct TransactionBuilderConfigBuilder(
66 cml_chain::builders::tx_builder::TransactionBuilderConfigBuilder,
67);
68
69impl_wasm_conversions!(
70 cml_chain::builders::tx_builder::TransactionBuilderConfigBuilder,
71 TransactionBuilderConfigBuilder
72);
73
74#[wasm_bindgen]
75impl TransactionBuilderConfigBuilder {
76 pub fn new() -> Self {
77 Self::default()
79 }
80
81 pub fn fee_algo(&self, fee_algo: &LinearFee) -> Self {
82 self.0.clone().fee_algo(fee_algo.clone().into()).into()
83 }
84
85 pub fn coins_per_utxo_byte(&self, coins_per_utxo_byte: Coin) -> Self {
86 self.0
87 .clone()
88 .coins_per_utxo_byte(coins_per_utxo_byte)
89 .into()
90 }
91
92 pub fn pool_deposit(&self, pool_deposit: u64) -> Self {
93 self.0.clone().pool_deposit(pool_deposit).into()
94 }
95
96 pub fn key_deposit(&self, key_deposit: u64) -> Self {
97 self.0.clone().key_deposit(key_deposit).into()
98 }
99
100 pub fn max_value_size(&self, max_value_size: u32) -> Self {
101 self.0.clone().max_value_size(max_value_size).into()
102 }
103
104 pub fn max_tx_size(&self, max_tx_size: u32) -> Self {
105 self.0.clone().max_tx_size(max_tx_size).into()
106 }
107
108 pub fn prefer_pure_change(&self, prefer_pure_change: bool) -> Self {
109 self.0.clone().prefer_pure_change(prefer_pure_change).into()
110 }
111
112 pub fn ex_unit_prices(&self, ex_unit_prices: &ExUnitPrices) -> Self {
113 self.0
114 .clone()
115 .ex_unit_prices(ex_unit_prices.clone().into())
116 .into()
117 }
118
119 pub fn cost_models(&self, cost_models: &CostModels) -> Self {
120 self.0
121 .clone()
122 .cost_models(cost_models.clone().into())
123 .into()
124 }
125
126 pub fn collateral_percentage(&self, collateral_percentage: u32) -> Self {
127 self.0
128 .clone()
129 .collateral_percentage(collateral_percentage)
130 .into()
131 }
132
133 pub fn max_collateral_inputs(&self, max_collateral_inputs: u32) -> Self {
134 self.0
135 .clone()
136 .max_collateral_inputs(max_collateral_inputs)
137 .into()
138 }
139
140 pub fn build(&self) -> Result<TransactionBuilderConfig, JsError> {
141 self.0.clone().build().map(Into::into).map_err(Into::into)
142 }
143}
144
145#[wasm_bindgen]
146#[derive(Clone, Debug)]
147pub struct TransactionBuilder(cml_chain::builders::tx_builder::TransactionBuilder);
148
149impl_wasm_conversions!(
150 cml_chain::builders::tx_builder::TransactionBuilder,
151 TransactionBuilder
152);
153
154#[wasm_bindgen]
155impl TransactionBuilder {
156 pub fn select_utxos(&mut self, strategy: CoinSelectionStrategyCIP2) -> Result<(), JsError> {
164 self.0.select_utxos(strategy).map_err(Into::into)
165 }
166
167 pub fn add_input(&mut self, result: &InputBuilderResult) -> Result<(), JsError> {
168 self.0.add_input(result.clone().into()).map_err(Into::into)
169 }
170
171 pub fn add_utxo(&mut self, result: &InputBuilderResult) {
172 self.0.add_utxo(result.clone().into())
173 }
174
175 pub fn fee_for_input(&self, result: &InputBuilderResult) -> Result<Coin, JsError> {
177 self.0.fee_for_input(result.as_ref()).map_err(Into::into)
178 }
179
180 pub fn add_reference_input(&mut self, utxo: &TransactionUnspentOutput) {
182 self.0.add_reference_input(utxo.clone().into())
183 }
184
185 pub fn add_output(
187 &mut self,
188 builder_result: &SingleOutputBuilderResult,
189 ) -> Result<(), JsError> {
190 self.0
191 .add_output(builder_result.clone().into())
192 .map_err(Into::into)
193 }
194
195 pub fn fee_for_output(&self, builder: &SingleOutputBuilderResult) -> Result<Coin, JsError> {
197 self.0.fee_for_output(builder.as_ref()).map_err(Into::into)
198 }
199
200 pub fn set_fee(&mut self, fee: Coin) {
201 self.0.set_fee(fee)
202 }
203
204 pub fn set_donation(&mut self, donation: Coin) {
205 self.0.set_donation(donation)
206 }
207
208 pub fn set_current_treasury_value(&mut self, current_treasury_value: Coin) {
209 self.0.set_current_treasury_value(current_treasury_value)
210 }
211
212 pub fn set_ttl(&mut self, ttl: Slot) {
213 self.0.set_ttl(ttl)
214 }
215
216 pub fn set_validity_start_interval(&mut self, validity_start_interval: Slot) {
217 self.0.set_validity_start_interval(validity_start_interval)
218 }
219
220 pub fn add_cert(&mut self, result: &CertificateBuilderResult) {
221 self.0.add_cert(result.clone().into())
222 }
223
224 pub fn add_proposal(&mut self, result: ProposalBuilderResult) {
225 self.0.add_proposal(result.clone().into())
226 }
227
228 pub fn add_vote(&mut self, result: VoteBuilderResult) {
229 self.0.add_vote(result.clone().into())
230 }
231
232 pub fn get_withdrawals(&self) -> Option<Withdrawals> {
233 self.0.get_withdrawals().map(|wd| wd.into())
234 }
235
236 pub fn add_withdrawal(&mut self, result: &WithdrawalBuilderResult) {
237 self.0.add_withdrawal(result.clone().into())
238 }
239
240 pub fn get_auxiliary_data(&self) -> Option<AuxiliaryData> {
241 self.0.get_auxiliary_data().map(|aux| aux.into())
242 }
243
244 pub fn set_auxiliary_data(&mut self, new_aux_data: &AuxiliaryData) {
245 self.0.set_auxiliary_data(new_aux_data.clone().into())
246 }
247
248 pub fn add_auxiliary_data(&mut self, new_aux_data: &AuxiliaryData) {
249 self.0.add_auxiliary_data(new_aux_data.clone().into())
250 }
251
252 pub fn add_mint(&mut self, result: &MintBuilderResult) -> Result<(), JsError> {
253 self.0.add_mint(result.clone().into()).map_err(Into::into)
254 }
255
256 pub fn get_mint(&self) -> Option<Mint> {
258 self.0.get_mint().map(|m| m.into())
259 }
260
261 pub fn new(cfg: &TransactionBuilderConfig) -> Self {
262 cml_chain::builders::tx_builder::TransactionBuilder::new(cfg.clone().into()).into()
263 }
264
265 pub fn add_collateral(&mut self, result: &InputBuilderResult) -> Result<(), JsError> {
266 self.0
267 .add_collateral(result.clone().into())
268 .map_err(Into::into)
269 }
270
271 pub fn add_required_signer(&mut self, hash: &Ed25519KeyHash) {
272 self.0.add_required_signer(hash.clone().into())
273 }
274
275 pub fn set_network_id(&mut self, network_id: &NetworkId) {
276 self.0.set_network_id(network_id.clone().into())
277 }
278
279 pub fn network_id(&self) -> Option<NetworkId> {
280 self.0.network_id().map(Into::into)
281 }
282
283 pub fn get_explicit_input(&self) -> Result<Value, JsError> {
285 self.0
286 .get_explicit_input()
287 .map(Into::into)
288 .map_err(Into::into)
289 }
290
291 pub fn get_implicit_input(&self) -> Result<Value, JsError> {
293 self.0
294 .get_implicit_input()
295 .map(Into::into)
296 .map_err(Into::into)
297 }
298
299 pub fn get_total_input(&self) -> Result<Value, JsError> {
301 self.0.get_total_input().map(Into::into).map_err(Into::into)
302 }
303
304 pub fn get_total_output(&self) -> Result<Value, JsError> {
306 self.0
307 .get_total_output()
308 .map(Into::into)
309 .map_err(Into::into)
310 }
311
312 pub fn get_explicit_output(&self) -> Result<Value, JsError> {
314 self.0
315 .get_explicit_output()
316 .map(Into::into)
317 .map_err(Into::into)
318 }
319
320 pub fn get_deposit(&self) -> Result<Coin, JsError> {
321 self.0.get_deposit().map_err(Into::into)
322 }
323
324 pub fn get_fee_if_set(&self) -> Option<Coin> {
325 self.0.get_fee_if_set()
326 }
327
328 pub fn set_collateral_return(&mut self, output: &TransactionOutput) {
329 self.0.set_collateral_return(output.clone().into())
330 }
331
332 pub fn full_size(&self) -> Result<usize, JsError> {
333 self.0.full_size().map_err(Into::into)
334 }
335
336 pub fn output_sizes(&self) -> Vec<usize> {
337 self.0.output_sizes()
338 }
339
340 pub fn build_for_evaluation(
345 &self,
346 algo: ChangeSelectionAlgo,
347 change_address: &Address,
348 ) -> Result<TxRedeemerBuilder, JsError> {
349 self.0
350 .build_for_evaluation(algo, change_address.as_ref())
351 .map(Into::into)
352 .map_err(Into::into)
353 }
354
355 pub fn build(
359 &mut self,
360 algo: ChangeSelectionAlgo,
361 change_address: &Address,
362 ) -> Result<SignedTxBuilder, JsError> {
363 self.0
364 .build(algo, change_address.as_ref())
365 .map(Into::into)
366 .map_err(Into::into)
367 }
368
369 pub fn set_exunits(&mut self, redeemer: &RedeemerWitnessKey, ex_units: &ExUnits) {
371 self.0
372 .set_exunits((*redeemer).into(), ex_units.clone().into())
373 }
374
375 pub fn min_fee(&self, script_calulation: bool) -> Result<Coin, JsError> {
379 self.0.min_fee(script_calulation).map_err(Into::into)
380 }
381
382 pub fn add_change_if_needed(
387 &mut self,
388 address: &Address,
389 include_exunits: bool,
390 ) -> Result<bool, JsError> {
391 cml_chain::builders::tx_builder::add_change_if_needed(
392 &mut self.0,
393 address.as_ref(),
394 include_exunits,
395 )
396 .map_err(Into::into)
397 }
398}
399
400#[wasm_bindgen]
401#[derive(Debug, Clone)]
402pub struct TxRedeemerBuilder(cml_chain::builders::tx_builder::TxRedeemerBuilder);
403
404impl_wasm_conversions!(
405 cml_chain::builders::tx_builder::TxRedeemerBuilder,
406 TxRedeemerBuilder
407);
408
409#[wasm_bindgen]
410impl TxRedeemerBuilder {
411 pub fn build(&self) -> Result<Redeemers, JsError> {
415 self.0.build().map(Into::into).map_err(Into::into)
416 }
417
418 pub fn set_exunits(&mut self, redeemer: &RedeemerWitnessKey, ex_units: &ExUnits) {
420 self.0
421 .set_exunits((*redeemer).into(), ex_units.clone().into())
422 }
423
424 pub fn draft_body(&self) -> TransactionBody {
427 self.0.draft_body().into()
428 }
429
430 pub fn auxiliary_data(&self) -> Option<AuxiliaryData> {
431 self.0.auxiliary_data().map(Into::into)
432 }
433
434 pub fn draft_tx(&self) -> Result<Transaction, JsError> {
438 self.0.draft_tx().map(Into::into).map_err(Into::into)
439 }
440}
441
442#[wasm_bindgen]
443#[derive(Debug, Clone)]
444pub struct SignedTxBuilder(cml_chain::builders::tx_builder::SignedTxBuilder);
445
446impl_wasm_conversions!(
447 cml_chain::builders::tx_builder::SignedTxBuilder,
448 SignedTxBuilder
449);
450
451#[wasm_bindgen]
452impl SignedTxBuilder {
453 pub fn new_with_data(
454 body: &TransactionBody,
455 witness_set: &TransactionWitnessSetBuilder,
456 is_valid: bool,
457 auxiliary_data: &AuxiliaryData,
458 ) -> SignedTxBuilder {
459 cml_chain::builders::tx_builder::SignedTxBuilder::new_with_data(
460 body.clone().into(),
461 witness_set.clone().into(),
462 is_valid,
463 auxiliary_data.clone().into(),
464 )
465 .into()
466 }
467
468 pub fn new_without_data(
469 body: &TransactionBody,
470 witness_set: &TransactionWitnessSetBuilder,
471 is_valid: bool,
472 ) -> SignedTxBuilder {
473 cml_chain::builders::tx_builder::SignedTxBuilder::new_without_data(
474 body.clone().into(),
475 witness_set.clone().into(),
476 is_valid,
477 )
478 .into()
479 }
480
481 pub fn build_checked(&self) -> Result<Transaction, JsError> {
485 self.0
486 .clone()
487 .build_checked()
488 .map(Into::into)
489 .map_err(Into::into)
490 }
491
492 pub fn build_unchecked(&self) -> Transaction {
500 self.0.clone().build_unchecked().into()
501 }
502
503 pub fn add_vkey(&mut self, vkey: &Vkeywitness) {
514 self.0.add_vkey(vkey.clone().into())
515 }
516
517 pub fn add_bootstrap(&mut self, bootstrap: &BootstrapWitness) {
518 self.0.add_bootstrap(bootstrap.clone().into())
519 }
520
521 pub fn body(&self) -> TransactionBody {
522 self.0.body().into()
523 }
524
525 pub fn witness_set(&self) -> TransactionWitnessSetBuilder {
526 self.0.witness_set().into()
527 }
528
529 pub fn is_valid(&self) -> bool {
530 self.0.is_valid()
531 }
532
533 pub fn auxiliary_data(&self) -> Option<AuxiliaryData> {
534 self.0.auxiliary_data().map(|aux| aux.into())
535 }
536}