waves_rust/model/transaction/
transaction_builder.rs

1use crate::error::Result;
2use crate::model::{Amount, PublicKey, Transaction, TransactionData};
3use crate::util::get_current_epoch_millis;
4
5#[derive(Clone, Eq, PartialEq, Debug)]
6pub struct TransactionBuilder {
7    data: TransactionData,
8    fee: Option<Amount>,
9    timestamp: Option<u64>,
10    public_key: PublicKey,
11    version: Option<u8>,
12    chain_id: u8,
13}
14
15impl TransactionBuilder {
16    pub fn new(public_key: &PublicKey, chain_id: u8, data: &TransactionData) -> TransactionBuilder {
17        TransactionBuilder {
18            data: data.clone(),
19            fee: None,
20            timestamp: None,
21            public_key: public_key.clone(),
22            version: None,
23            chain_id,
24        }
25    }
26
27    pub fn fee(&mut self, fee: Amount) -> &mut Self {
28        self.fee = Some(fee);
29        self
30    }
31
32    pub fn timestamp(&mut self, timestamp: u64) -> &mut Self {
33        self.timestamp = Some(timestamp);
34        self
35    }
36
37    pub fn version(&mut self, version: u8) -> &mut Self {
38        self.version = Some(version);
39        self
40    }
41
42    pub fn build(&self) -> Result<Transaction> {
43        let transaction_data = self.data.clone();
44        let fee = match self.fee.clone() {
45            Some(fee) => fee,
46            None => transaction_data.get_min_fee()?,
47        };
48
49        let timestamp = match self.timestamp {
50            Some(timestamp) => timestamp,
51            None => get_current_epoch_millis(),
52        };
53
54        let version = match self.version {
55            Some(version) => version,
56            None => transaction_data.get_min_supported_version(),
57        };
58
59        Ok(Transaction::new(
60            transaction_data,
61            fee,
62            timestamp,
63            self.public_key.clone(),
64            version,
65            self.chain_id,
66        ))
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use crate::model::{
73        Amount, BurnTransaction, ChainId, PrivateKey, TransactionBuilder, TransactionData,
74    };
75
76    #[test]
77    fn test_builder_default_params() {
78        let private_key = PrivateKey::from_seed("123", 0).unwrap();
79
80        let burn_transaction = BurnTransaction::new(Amount::new(1, None));
81
82        let signed_tx = TransactionBuilder::new(
83            &private_key.public_key(),
84            ChainId::TESTNET.byte(),
85            &TransactionData::Burn(burn_transaction),
86        )
87        .build()
88        .unwrap()
89        .sign(&private_key)
90        .unwrap();
91
92        assert_eq!(signed_tx.tx().fee().value(), 100_000);
93        assert_eq!(signed_tx.tx().public_key(), private_key.public_key());
94        assert_eq!(signed_tx.tx().tx_type(), 6);
95        assert_eq!(signed_tx.tx().version(), 3);
96        assert_eq!(signed_tx.tx().chain_id(), ChainId::TESTNET.byte())
97    }
98
99    #[test]
100    fn test_builder_user_defined_params() {
101        let private_key = PrivateKey::from_seed("123", 0).unwrap();
102
103        let burn_transaction = BurnTransaction::new(Amount::new(1, None));
104        let signed_tx = TransactionBuilder::new(
105            &private_key.public_key(),
106            ChainId::TESTNET.byte(),
107            &TransactionData::Burn(burn_transaction),
108        )
109        .fee(Amount::new(10, None))
110        .timestamp(100)
111        .version(4)
112        .build()
113        .unwrap()
114        .sign(&private_key)
115        .unwrap();
116
117        assert_eq!(signed_tx.tx().fee().value(), 10);
118        assert_eq!(signed_tx.tx().timestamp(), 100);
119        assert_eq!(signed_tx.tx().public_key(), private_key.public_key());
120        assert_eq!(signed_tx.tx().tx_type(), 6);
121        assert_eq!(signed_tx.tx().version(), 4);
122        assert_eq!(signed_tx.tx().chain_id(), ChainId::TESTNET.byte())
123    }
124}