Skip to main content

cardano_serialization_lib/builders/
tx_batch_builder.rs

1use 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(&current_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}