mwc_web3/types/
transaction_request.rs

1use crate::types::{Address, Bytes, U256};
2use serde::{Deserialize, Serialize};
3
4/// Call contract request (eth_call / eth_estimateGas)
5///
6/// When using this for `eth_estimateGas`, all the fields
7/// are optional. However, for usage in `eth_call` the
8/// `to` field must be provided.
9#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
10pub struct CallRequest {
11    /// Sender address (None for arbitrary address)
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub from: Option<Address>,
14    /// To address (None allowed for eth_estimateGas)
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub to: Option<Address>,
17    /// Supplied gas (None for sensible default)
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub gas: Option<U256>,
20    /// Gas price (None for sensible default)
21    #[serde(skip_serializing_if = "Option::is_none")]
22    #[serde(rename = "gasPrice")]
23    pub gas_price: Option<U256>,
24    /// Transfered value (None for no transfer)
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub value: Option<U256>,
27    /// Data (None for empty data)
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub data: Option<Bytes>,
30}
31
32/// Send Transaction Parameters
33#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
34pub struct TransactionRequest {
35    /// Sender address
36    pub from: Address,
37    /// Recipient address (None for contract creation)
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub to: Option<Address>,
40    /// Supplied gas (None for sensible default)
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub gas: Option<U256>,
43    /// Gas price (None for sensible default)
44    #[serde(skip_serializing_if = "Option::is_none")]
45    #[serde(rename = "gasPrice")]
46    pub gas_price: Option<U256>,
47    /// Transfered value (None for no transfer)
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub value: Option<U256>,
50    /// Transaction data (None for empty bytes)
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub data: Option<Bytes>,
53    /// Transaction nonce (None for next available nonce)
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub nonce: Option<U256>,
56    /// Min block inclusion (None for include immediately)
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub condition: Option<TransactionCondition>,
59}
60
61/// Represents condition on minimum block number or block timestamp.
62#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
63#[serde(deny_unknown_fields)]
64pub enum TransactionCondition {
65    /// Valid at this minimum block number.
66    #[serde(rename = "block")]
67    Block(u64),
68    /// Valid at given unix time.
69    #[serde(rename = "time")]
70    Timestamp(u64),
71}
72
73#[cfg(test)]
74mod tests {
75    use super::{Address, CallRequest, TransactionCondition, TransactionRequest};
76    use hex_literal::hex;
77
78    #[test]
79    fn should_serialize_call_request() {
80        // given
81        let call_request = CallRequest {
82            from: None,
83            to: Some(Address::from_low_u64_be(5)),
84            gas: Some(21_000.into()),
85            gas_price: None,
86            value: Some(5_000_000.into()),
87            data: Some(hex!("010203").into()),
88        };
89
90        // when
91        let serialized = serde_json::to_string_pretty(&call_request).unwrap();
92
93        // then
94        assert_eq!(
95            serialized,
96            r#"{
97  "to": "0x0000000000000000000000000000000000000005",
98  "gas": "0x5208",
99  "value": "0x4c4b40",
100  "data": "0x010203"
101}"#
102        );
103    }
104
105    #[test]
106    fn should_deserialize_call_request() {
107        let serialized = r#"{
108  "to": "0x0000000000000000000000000000000000000005",
109  "gas": "0x5208",
110  "value": "0x4c4b40",
111  "data": "0x010203"
112}"#;
113        let deserialized: CallRequest = serde_json::from_str(&serialized).unwrap();
114
115        assert_eq!(deserialized.from, None);
116        assert_eq!(deserialized.to, Some(Address::from_low_u64_be(5)));
117        assert_eq!(deserialized.gas, Some(21_000.into()));
118        assert_eq!(deserialized.gas_price, None);
119        assert_eq!(deserialized.value, Some(5_000_000.into()));
120        assert_eq!(deserialized.data, Some(hex!("010203").into()));
121    }
122
123    #[test]
124    fn should_serialize_transaction_request() {
125        // given
126        let tx_request = TransactionRequest {
127            from: Address::from_low_u64_be(5),
128            to: None,
129            gas: Some(21_000.into()),
130            gas_price: None,
131            value: Some(5_000_000.into()),
132            data: Some(hex!("010203").into()),
133            nonce: None,
134            condition: Some(TransactionCondition::Block(5)),
135        };
136
137        // when
138        let serialized = serde_json::to_string_pretty(&tx_request).unwrap();
139
140        // then
141        assert_eq!(
142            serialized,
143            r#"{
144  "from": "0x0000000000000000000000000000000000000005",
145  "gas": "0x5208",
146  "value": "0x4c4b40",
147  "data": "0x010203",
148  "condition": {
149    "block": 5
150  }
151}"#
152        );
153    }
154
155    #[test]
156    fn should_deserialize_transaction_request() {
157        let serialized = r#"{
158  "from": "0x0000000000000000000000000000000000000005",
159  "gas": "0x5208",
160  "value": "0x4c4b40",
161  "data": "0x010203",
162  "condition": {
163    "block": 5
164  }
165}"#;
166        let deserialized: TransactionRequest = serde_json::from_str(&serialized).unwrap();
167
168        assert_eq!(deserialized.from, Address::from_low_u64_be(5));
169        assert_eq!(deserialized.to, None);
170        assert_eq!(deserialized.gas, Some(21_000.into()));
171        assert_eq!(deserialized.gas_price, None);
172        assert_eq!(deserialized.value, Some(5_000_000.into()));
173        assert_eq!(deserialized.data, Some(hex!("010203").into()));
174        assert_eq!(deserialized.nonce, None);
175        assert_eq!(deserialized.condition, Some(TransactionCondition::Block(5)));
176    }
177}