cardano_serialization_lib/builders/
tx_batch_builder.rs1use crate::*;
2use batch_tools::asset_categorizer::AssetCategorizer;
3use batch_tools::proposals::TxProposal;
4
5#[wasm_bindgen]
6pub struct TransactionBatchList(Vec<TransactionBatch>);
7
8#[wasm_bindgen]
9impl TransactionBatchList {
10 pub fn len(&self) -> usize {
11 self.0.len()
12 }
13
14 pub fn get(&self, index: usize) -> TransactionBatch {
15 self.0[index].clone()
16 }
17}
18
19impl<'a> IntoIterator for &'a TransactionBatchList {
20 type Item = &'a TransactionBatch;
21 type IntoIter = std::slice::Iter<'a, TransactionBatch>;
22
23 fn into_iter(self) -> std::slice::Iter<'a, TransactionBatch> {
24 self.0.iter()
25 }
26}
27
28#[wasm_bindgen]
29#[derive(Clone)]
30pub struct TransactionBatch {
31 transactions: Vec<Transaction>,
32}
33
34#[wasm_bindgen]
35impl TransactionBatch {
36 pub fn len(&self) -> usize {
37 self.transactions.len()
38 }
39
40 pub fn get(&self, index: usize) -> Transaction {
41 self.transactions[index].clone()
42 }
43}
44
45impl<'a> IntoIterator for &'a TransactionBatch {
46 type Item = &'a Transaction;
47 type IntoIter = std::slice::Iter<'a, Transaction>;
48
49 fn into_iter(self) -> std::slice::Iter<'a, Transaction> {
50 self.transactions.iter()
51 }
52}
53
54impl TransactionBatch {
55 pub fn new() -> Self {
56 Self {
57 transactions: Vec::new(),
58 }
59 }
60
61 pub fn add_transaction(&mut self, transaction: Transaction) {
62 self.transactions.push(transaction);
63 }
64}
65
66struct TxBatchBuilder {
67 asset_groups: AssetCategorizer,
68 tx_proposals: Vec<TxProposal>,
69}
70
71impl TxBatchBuilder {
72 pub fn new(
73 utxos: &TransactionUnspentOutputs,
74 address: &Address,
75 config: &TransactionBuilderConfig,
76 ) -> Result<Self, JsError> {
77 let asset_groups = AssetCategorizer::new(config, utxos, address)?;
78 Ok(Self {
79 asset_groups,
80 tx_proposals: Vec::new(),
81 })
82 }
83
84 pub fn build(
85 &mut self,
86 utxos: &TransactionUnspentOutputs,
87 ) -> Result<TransactionBatch, JsError> {
88 while self.asset_groups.has_assets() || self.asset_groups.has_ada() {
89 let mut current_tx_proposal = TxProposal::new();
90 while let Some(tx_proposal) = self
91 .asset_groups
92 .try_append_next_utxos(¤t_tx_proposal)?
93 {
94 current_tx_proposal = tx_proposal;
95 }
96
97 if current_tx_proposal.is_empty()
98 && (self.asset_groups.has_assets() || self.asset_groups.has_ada())
99 {
100 return Err(JsError::from_str("Unable to build transaction batch"));
101 }
102
103 current_tx_proposal.add_last_ada_to_last_output()?;
104 self.asset_groups
105 .set_min_ada_for_tx(&mut current_tx_proposal)?;
106 self.tx_proposals.push(current_tx_proposal);
107 }
108
109 let mut batch = TransactionBatch::new();
110 for tx_proposal in self.tx_proposals.iter_mut() {
111 batch.add_transaction(tx_proposal.create_tx(&self.asset_groups, utxos)?);
112 }
113
114 Ok(batch)
115 }
116}
117
118#[wasm_bindgen]
119pub fn create_send_all(
120 address: &Address,
121 utxos: &TransactionUnspentOutputs,
122 config: &TransactionBuilderConfig,
123) -> Result<TransactionBatchList, JsError> {
124 let mut tx_batch_builder = TxBatchBuilder::new(utxos, address, config)?;
125 let batch = tx_batch_builder.build(utxos)?;
126 Ok(TransactionBatchList(vec![batch]))
127}