zilliqa_rs/transaction/
builder.rs

1use crate::core::parse_zil;
2use crate::core::{CreateTransactionRequest, ZilAddress};
3
4use super::Version;
5
6#[derive(Default, Debug, Clone)]
7pub struct TransactionParams {
8    pub version: Option<Version>,
9    pub nonce: Option<u64>,
10    pub to_addr: Option<ZilAddress>,
11    pub amount: Option<u128>,
12    pub pub_key: Option<String>,
13    pub gas_price: Option<u128>,
14    pub gas_limit: Option<u64>,
15    pub code: Option<String>,
16    pub data: Option<String>,
17    pub signature: Option<String>,
18}
19
20/// A builder to compose transaction.
21///
22/// The TransactionBuilder struct is used to construct transactions with
23/// specified parameters.
24///
25/// # Example
26/// ```
27/// use zilliqa_rs::providers::{Http, Provider};
28/// use zilliqa_rs::core::CreateTransactionResponse;
29/// use zilliqa_rs::transaction::TransactionBuilder;
30/// use zilliqa_rs::signers::LocalWallet;
31/// use zilliqa_rs::core::parse_zil;
32/// use zilliqa_rs::middlewares::Middleware;
33///
34/// #[tokio::main]
35/// async fn main() -> anyhow::Result<()> {
36///     const END_POINT: &str = "http://localhost:5555";
37///
38///     let wallet = "d96e9eb5b782a80ea153c937fa83e5948485fbfc8b7e7c069d7b914dbc350aba".parse::<LocalWallet>()?;
39///
40///     let provider = Provider::<Http>::try_from(END_POINT)?
41///         .with_chain_id(222)
42///         .with_signer(wallet.clone());
43///
44///     let receiver = LocalWallet::create_random()?;
45///     let tx = TransactionBuilder::default()
46///         .to_address(receiver.address)
47///         .amount(parse_zil("0.2")?)
48///         .gas_price(2000000000u128)
49///         .gas_limit(50u64)
50///         .build();
51///
52///     provider.send_transaction_without_confirm::<CreateTransactionResponse>(tx).await?;
53///     Ok(())
54/// }
55/// ```
56/// ## Use pay() function
57/// TransactionBuilder has an auxiliary function named `pay` to simplify payment transaction creation:
58///
59/// ```rust
60/// use zilliqa_rs::providers::{Http, Provider};
61/// use zilliqa_rs::core::CreateTransactionResponse;
62/// use zilliqa_rs::transaction::TransactionBuilder;
63/// use zilliqa_rs::signers::LocalWallet;
64/// use zilliqa_rs::middlewares::Middleware;
65/// use zilliqa_rs::core::parse_zil;
66///
67/// #[tokio::main]
68/// async fn main() -> anyhow::Result<()> {
69///     const END_POINT: &str = "http://localhost:5555";
70///
71///     let wallet = "d96e9eb5b782a80ea153c937fa83e5948485fbfc8b7e7c069d7b914dbc350aba".parse::<LocalWallet>()?;
72///     let provider = Provider::<Http>::try_from(END_POINT)?
73///         .with_chain_id(222)
74///         .with_signer(wallet.clone());
75///
76///     let receiver = LocalWallet::create_random()?;
77///     let amount = parse_zil("0.2")?;
78///
79///     let tx = TransactionBuilder::default().pay(amount, receiver.address.clone()).build();
80///     provider.send_transaction_without_confirm::<CreateTransactionResponse>(tx).await?;
81///
82///     Ok(())
83/// }
84/// ```
85#[derive(Default, Debug)]
86pub struct TransactionBuilder {
87    inner_transaction: TransactionParams,
88}
89
90impl TransactionBuilder {
91    /// Simplify payment transaction creation.
92    ///
93    /// # Example
94    /// ```
95    /// use zilliqa_rs::transaction::TransactionBuilder;
96    /// use zilliqa_rs::core::parse_zil;
97    /// use zilliqa_rs::signers::LocalWallet;
98    ///
99    /// let receiver = LocalWallet::create_random().unwrap();
100    /// let amount = parse_zil("0.2").unwrap();
101    ///
102    /// let tx = TransactionBuilder::default().pay(amount, receiver.address.clone()).build();
103    /// ```
104    pub fn pay(mut self, amount: u128, to_addr: ZilAddress) -> Self {
105        self.inner_transaction.amount = Some(amount);
106        self.inner_transaction.to_addr = Some(to_addr);
107        self.gas_price_if_none(parse_zil("0.002").unwrap()).gas_limit_if_none(50u64)
108    }
109
110    /// Sets the chain id of the final transaction request.
111    pub fn chain_id(mut self, chain_id: u16) -> Self {
112        self.inner_transaction.version = Some(Version::new(chain_id));
113        self
114    }
115
116    /// Sets the nonce of the final transaction request.
117    pub fn nonce(mut self, nonce: u64) -> Self {
118        self.inner_transaction.nonce = Some(nonce);
119        self
120    }
121
122    /// Sets the destination of the final transaction request.
123    pub fn to_address(mut self, to_addr: ZilAddress) -> Self {
124        self.inner_transaction.to_addr = Some(to_addr);
125        self
126    }
127
128    /// Sets the amount of the final transaction request in Qa.
129    pub fn amount(mut self, amount: u128) -> Self {
130        self.inner_transaction.amount = Some(amount);
131        self
132    }
133
134    /// Sets the amount if it's none.
135    pub fn amount_if_none(mut self, amount: u128) -> Self {
136        if self.inner_transaction.amount.is_some() {
137            return self;
138        }
139
140        self.inner_transaction.amount = Some(amount);
141        self
142    }
143
144    /// Sets the gas price of the final transaction request.
145    pub fn gas_price(mut self, gas_price: u128) -> Self {
146        self.inner_transaction.gas_price = Some(gas_price);
147        self
148    }
149
150    /// Sets the gas price of the final transaction request if it's none.
151    pub fn gas_price_if_none(mut self, gas_price: u128) -> Self {
152        if self.inner_transaction.gas_price.is_some() {
153            return self;
154        }
155
156        self.inner_transaction.gas_price = Some(gas_price);
157        self
158    }
159
160    /// Sets the gas limit of the final transaction request.
161    pub fn gas_limit(mut self, gas_limit: u64) -> Self {
162        self.inner_transaction.gas_limit = Some(gas_limit);
163        self
164    }
165
166    /// Sets the gas limit of the final transaction request if it's none.
167    pub fn gas_limit_if_none(mut self, gas_limit: u64) -> Self {
168        if self.inner_transaction.gas_limit.is_some() {
169            return self;
170        }
171        self.inner_transaction.gas_limit = Some(gas_limit);
172        self
173    }
174
175    /// Sets the public key of the final transaction request.
176    pub fn pub_key(mut self, pub_key: String) -> Self {
177        self.inner_transaction.pub_key = Some(pub_key);
178        self
179    }
180
181    /// Sets the data of the final transaction request.
182    pub fn data(mut self, data: String) -> Self {
183        self.inner_transaction.data = Some(data);
184        self
185    }
186
187    /// Sets the code of the final transaction request.
188    pub fn code(mut self, code: String) -> Self {
189        self.inner_transaction.code = Some(code);
190        self
191    }
192
193    /// Sets the signature of the final transaction request.
194    pub fn signature(mut self, signature: String) -> Self {
195        self.inner_transaction.signature = Some(signature);
196        self
197    }
198
199    /// Builds a new transaction request based on the specified parameters.
200    ///
201    /// # Example
202    /// ```
203    /// use zilliqa_rs::transaction::TransactionBuilder;
204    /// use zilliqa_rs::core::parse_zil;
205    /// use zilliqa_rs::signers::LocalWallet;
206    ///
207    /// let receiver = LocalWallet::create_random().unwrap();
208    /// let tx = TransactionBuilder::default()
209    ///     .to_address(receiver.address)
210    ///     .amount(parse_zil("0.2").unwrap())
211    ///     .gas_price(2000000000u128)
212    ///     .gas_limit(50u64)
213    ///     .build();
214    /// ```
215    ///
216    pub fn build(self) -> CreateTransactionRequest {
217        CreateTransactionRequest {
218            version: self.inner_transaction.version.unwrap_or_default(),
219            nonce: self.inner_transaction.nonce.unwrap_or_default(),
220            to_addr: self.inner_transaction.to_addr.unwrap_or_default(),
221            amount: self.inner_transaction.amount.unwrap_or_default(),
222            pub_key: self.inner_transaction.pub_key,
223            gas_price: self.inner_transaction.gas_price.unwrap_or_default(),
224            gas_limit: self.inner_transaction.gas_limit.unwrap_or_default(),
225            code: self.inner_transaction.code,
226            data: self.inner_transaction.data,
227            signature: self.inner_transaction.signature,
228        }
229    }
230}
231
232impl From<TransactionParams> for TransactionBuilder {
233    fn from(value: TransactionParams) -> Self {
234        Self {
235            inner_transaction: value,
236        }
237    }
238}