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}