1use crate::types::{AccessList, Address, Bytes, U256, U64};
2use serde::{Deserialize, Serialize};
3
4#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
10pub struct CallRequest {
11 #[serde(skip_serializing_if = "Option::is_none")]
13 pub from: Option<Address>,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub to: Option<Address>,
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub gas: Option<U256>,
20 #[serde(skip_serializing_if = "Option::is_none")]
22 #[serde(rename = "gasPrice")]
23 pub gas_price: Option<U256>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub value: Option<U256>,
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub data: Option<Bytes>,
30 #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
32 pub transaction_type: Option<U64>,
33 #[serde(rename = "accessList", default, skip_serializing_if = "Option::is_none")]
35 pub access_list: Option<AccessList>,
36 #[serde(rename = "maxFeePerGas", skip_serializing_if = "Option::is_none")]
38 pub max_fee_per_gas: Option<U256>,
39 #[serde(rename = "maxPriorityFeePerGas", skip_serializing_if = "Option::is_none")]
41 pub max_priority_fee_per_gas: Option<U256>,
42}
43
44impl CallRequest {
45 pub fn builder() -> CallRequestBuilder {
47 CallRequestBuilder::new()
48 }
49}
50
51#[derive(Clone, Debug, Default)]
53pub struct CallRequestBuilder {
54 call_request: CallRequest,
55}
56
57impl CallRequestBuilder {
58 pub fn new() -> CallRequestBuilder {
60 CallRequestBuilder {
61 call_request: CallRequest::default(),
62 }
63 }
64
65 pub fn from(mut self, from: Address) -> Self {
67 self.call_request.from = Some(from);
68 self
69 }
70
71 pub fn to(mut self, to: Address) -> Self {
73 self.call_request.to = Some(to);
74 self
75 }
76
77 pub fn gas(mut self, gas: U256) -> Self {
79 self.call_request.gas = Some(gas);
80 self
81 }
82
83 pub fn gas_price(mut self, gas_price: U256) -> Self {
85 self.call_request.gas_price = Some(gas_price);
86 self
87 }
88
89 pub fn value(mut self, value: U256) -> Self {
91 self.call_request.value = Some(value);
92 self
93 }
94
95 pub fn data(mut self, data: Bytes) -> Self {
97 self.call_request.data = Some(data);
98 self
99 }
100
101 pub fn transaction_type(mut self, transaction_type: U64) -> Self {
103 self.call_request.transaction_type = Some(transaction_type);
104 self
105 }
106
107 pub fn access_list(mut self, access_list: AccessList) -> Self {
109 self.call_request.access_list = Some(access_list);
110 self
111 }
112
113 pub fn build(&self) -> CallRequest {
115 self.call_request.clone()
116 }
117}
118
119#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
121pub struct TransactionRequest {
122 pub from: Address,
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub to: Option<Address>,
127 #[serde(skip_serializing_if = "Option::is_none")]
129 pub gas: Option<U256>,
130 #[serde(skip_serializing_if = "Option::is_none")]
132 #[serde(rename = "gasPrice")]
133 pub gas_price: Option<U256>,
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub value: Option<U256>,
137 #[serde(skip_serializing_if = "Option::is_none")]
139 pub data: Option<Bytes>,
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub nonce: Option<U256>,
143 #[serde(skip_serializing_if = "Option::is_none")]
145 pub condition: Option<TransactionCondition>,
146 #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
148 pub transaction_type: Option<U64>,
149 #[serde(rename = "accessList", default, skip_serializing_if = "Option::is_none")]
151 pub access_list: Option<AccessList>,
152 #[serde(rename = "maxFeePerGas", skip_serializing_if = "Option::is_none")]
154 pub max_fee_per_gas: Option<U256>,
155 #[serde(rename = "maxPriorityFeePerGas", skip_serializing_if = "Option::is_none")]
157 pub max_priority_fee_per_gas: Option<U256>,
158}
159
160impl TransactionRequest {
161 pub fn builder() -> TransactionRequestBuilder {
163 TransactionRequestBuilder::new()
164 }
165}
166
167#[derive(Clone, Debug, Default)]
169pub struct TransactionRequestBuilder {
170 transaction_request: TransactionRequest,
171}
172
173impl TransactionRequestBuilder {
174 pub fn new() -> TransactionRequestBuilder {
176 TransactionRequestBuilder {
177 transaction_request: TransactionRequest::default(),
178 }
179 }
180
181 pub fn from(mut self, from: Address) -> Self {
183 self.transaction_request.from = from;
184 self
185 }
186
187 pub fn to(mut self, to: Address) -> Self {
189 self.transaction_request.to = Some(to);
190 self
191 }
192
193 pub fn gas(mut self, gas: U256) -> Self {
195 self.transaction_request.gas = Some(gas);
196 self
197 }
198
199 pub fn value(mut self, value: U256) -> Self {
201 self.transaction_request.value = Some(value);
202 self
203 }
204
205 pub fn data(mut self, data: Bytes) -> Self {
207 self.transaction_request.data = Some(data);
208 self
209 }
210
211 pub fn nonce(mut self, nonce: U256) -> Self {
213 self.transaction_request.nonce = Some(nonce);
214 self
215 }
216
217 pub fn condition(mut self, condition: TransactionCondition) -> Self {
219 self.transaction_request.condition = Some(condition);
220 self
221 }
222
223 pub fn transaction_type(mut self, transaction_type: U64) -> Self {
225 self.transaction_request.transaction_type = Some(transaction_type);
226 self
227 }
228
229 pub fn access_list(mut self, access_list: AccessList) -> Self {
231 self.transaction_request.access_list = Some(access_list);
232 self
233 }
234
235 pub fn build(&self) -> TransactionRequest {
237 self.transaction_request.clone()
238 }
239}
240
241#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
243#[serde(deny_unknown_fields)]
244pub enum TransactionCondition {
245 #[serde(rename = "block")]
247 Block(u64),
248 #[serde(rename = "time")]
250 Timestamp(u64),
251}
252
253#[cfg(test)]
254mod tests {
255 use super::{
256 Address, CallRequest, CallRequestBuilder, TransactionCondition, TransactionRequest, TransactionRequestBuilder,
257 };
258 use hex_literal::hex;
259
260 #[test]
261 fn should_serialize_call_request() {
262 let call_request = CallRequest {
264 from: None,
265 to: Some(Address::from_low_u64_be(5)),
266 gas: Some(21_000.into()),
267 gas_price: None,
268 value: Some(5_000_000.into()),
269 data: Some(hex!("010203").into()),
270 transaction_type: None,
271 access_list: None,
272 max_fee_per_gas: None,
273 max_priority_fee_per_gas: None,
274 };
275
276 let serialized = serde_json::to_string_pretty(&call_request).unwrap();
278
279 assert_eq!(
281 serialized,
282 r#"{
283 "to": "0x0000000000000000000000000000000000000005",
284 "gas": "0x5208",
285 "value": "0x4c4b40",
286 "data": "0x010203"
287}"#
288 );
289 }
290
291 #[test]
292 fn should_deserialize_call_request() {
293 let serialized = r#"{
294 "to": "0x0000000000000000000000000000000000000005",
295 "gas": "0x5208",
296 "value": "0x4c4b40",
297 "data": "0x010203"
298}"#;
299 let deserialized: CallRequest = serde_json::from_str(serialized).unwrap();
300
301 assert_eq!(deserialized.from, None);
302 assert_eq!(deserialized.to, Some(Address::from_low_u64_be(5)));
303 assert_eq!(deserialized.gas, Some(21_000.into()));
304 assert_eq!(deserialized.gas_price, None);
305 assert_eq!(deserialized.value, Some(5_000_000.into()));
306 assert_eq!(deserialized.data, Some(hex!("010203").into()));
307 }
308
309 #[test]
310 fn should_serialize_transaction_request() {
311 let tx_request = TransactionRequest {
313 from: Address::from_low_u64_be(5),
314 to: None,
315 gas: Some(21_000.into()),
316 gas_price: None,
317 value: Some(5_000_000.into()),
318 data: Some(hex!("010203").into()),
319 nonce: None,
320 condition: Some(TransactionCondition::Block(5)),
321 transaction_type: None,
322 access_list: None,
323 max_fee_per_gas: None,
324 max_priority_fee_per_gas: None,
325 };
326
327 let serialized = serde_json::to_string_pretty(&tx_request).unwrap();
329
330 assert_eq!(
332 serialized,
333 r#"{
334 "from": "0x0000000000000000000000000000000000000005",
335 "gas": "0x5208",
336 "value": "0x4c4b40",
337 "data": "0x010203",
338 "condition": {
339 "block": 5
340 }
341}"#
342 );
343 }
344
345 #[test]
346 fn should_deserialize_transaction_request() {
347 let serialized = r#"{
348 "from": "0x0000000000000000000000000000000000000005",
349 "gas": "0x5208",
350 "value": "0x4c4b40",
351 "data": "0x010203",
352 "condition": {
353 "block": 5
354 }
355}"#;
356 let deserialized: TransactionRequest = serde_json::from_str(serialized).unwrap();
357
358 assert_eq!(deserialized.from, Address::from_low_u64_be(5));
359 assert_eq!(deserialized.to, None);
360 assert_eq!(deserialized.gas, Some(21_000.into()));
361 assert_eq!(deserialized.gas_price, None);
362 assert_eq!(deserialized.value, Some(5_000_000.into()));
363 assert_eq!(deserialized.data, Some(hex!("010203").into()));
364 assert_eq!(deserialized.nonce, None);
365 assert_eq!(deserialized.condition, Some(TransactionCondition::Block(5)));
366 }
367
368 #[test]
369 fn should_build_default_call_request() {
370 let call_request = CallRequest::default();
372 let call_request_builder = CallRequestBuilder::new();
374 assert_eq!(call_request_builder.build(), call_request);
376 }
377
378 #[test]
379 fn should_build_call_request() {
380 let call_request = CallRequest {
382 from: None,
383 to: Some(Address::from_low_u64_be(5)),
384 gas: Some(21_000.into()),
385 gas_price: None,
386 value: Some(5_000_000.into()),
387 data: Some(hex!("010203").into()),
388 transaction_type: None,
389 access_list: None,
390 max_fee_per_gas: None,
391 max_priority_fee_per_gas: None,
392 };
393 let call_request_builder = CallRequestBuilder::new()
395 .to(Address::from_low_u64_be(5))
396 .gas(21_000.into())
397 .value(5_000_000.into())
398 .data(hex!("010203").into())
399 .build();
400 assert_eq!(call_request_builder, call_request);
402 }
403
404 #[test]
405 fn should_build_default_transaction_request() {
406 let tx_request = TransactionRequest::default();
408 let tx_request_builder = TransactionRequestBuilder::new();
410 assert_eq!(tx_request_builder.build(), tx_request);
412 }
413
414 #[test]
415 fn should_build_transaction_request() {
416 let tx_request = TransactionRequest {
418 from: Address::from_low_u64_be(5),
419 to: None,
420 gas: Some(21_000.into()),
421 gas_price: None,
422 value: Some(5_000_000.into()),
423 data: Some(hex!("010203").into()),
424 nonce: None,
425 condition: Some(TransactionCondition::Block(5)),
426 transaction_type: None,
427 access_list: None,
428 max_fee_per_gas: None,
429 max_priority_fee_per_gas: None,
430 };
431 let tx_request_builder = TransactionRequestBuilder::new()
433 .from(Address::from_low_u64_be(5))
434 .gas(21_000.into())
435 .value(5_000_000.into())
436 .data(hex!("010203").into())
437 .condition(TransactionCondition::Block(5));
438 assert_eq!(tx_request_builder.build(), tx_request);
440 }
441}