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