ethers_types_rs/
block.rs

1use crate::{bytes_def, request::AccessList};
2
3use ethabi::ethereum_types::{Bloom, H256, U256};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_with::*;
6
7pub use ethabi::TopicFilter;
8
9use crate::Address;
10
11macro_rules! from_json {
12    ($name: ident) => {
13        impl TryFrom<&str> for $name {
14            type Error = serde_json::Error;
15
16            fn try_from(value: &str) -> Result<Self, Self::Error> {
17                serde_json::from_str(value)
18            }
19        }
20
21        impl TryFrom<String> for $name {
22            type Error = serde_json::Error;
23            fn try_from(value: String) -> Result<Self, Self::Error> {
24                Self::try_from(value.as_ref())
25            }
26        }
27
28        impl TryFrom<serde_json::Value> for $name {
29            type Error = serde_json::Error;
30            fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
31                serde_json::from_value(value)
32            }
33        }
34    };
35}
36
37#[derive(Debug, Clone, thiserror::Error)]
38pub enum BlockError {
39    #[error("Invalid syning status, expect bool or status")]
40    InvalidSyning,
41}
42
43bytes_def!(Difficulty);
44bytes_def!(Bytecode);
45
46#[serde_as]
47#[derive(Serialize, Deserialize)]
48#[serde(rename_all = "camelCase")]
49pub struct Block {
50    /// Current block hash value
51    pub hash: Option<H256>,
52    /// Parent block hash
53    #[serde(rename = "parentHash")]
54    pub parent_hash: H256,
55
56    /// Ommers hash
57    #[serde(rename = "sha3Uncles")]
58    pub sha3_uncles: Option<H256>,
59
60    /// Coinbase
61    pub miner: Address,
62
63    /// State root
64    #[serde(rename = "stateRoot")]
65    pub state_root: H256,
66
67    /// Transactions root
68    #[serde(rename = "transactionsRoot")]
69    pub transactions_root: H256,
70
71    /// Receipts root
72    #[serde(rename = "receiptsRoot")]
73    pub receipts_root: H256,
74
75    /// Bloom filter
76    #[serde(rename = "logsBloom")]
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub logs_bloom: Option<Bloom>,
79
80    /// Difficulty
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub difficulty: Option<Difficulty>,
83
84    /// U256
85    pub number: Option<U256>,
86
87    /// Gas limit
88
89    #[serde(rename = "gasLimit")]
90    pub gas_limit: U256,
91
92    /// Gas used
93    #[serde(rename = "gasUsed")]
94    pub gas_used: U256,
95
96    /// Timestamp
97    pub timestamp: U256,
98
99    /// Extra data
100    #[serde(rename = "extraData")]
101    pub extra_data: Bytecode,
102
103    /// Mix hash
104    #[serde(rename = "mixHash")]
105    pub mix_hash: Option<H256>,
106
107    /// Nonce
108    pub nonce: Option<U256>,
109
110    /// Total difficult
111    #[serde(rename = "totalDeffficult")]
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub total_deffficult: Option<Difficulty>,
114
115    /// Base fee per gas
116    #[serde(rename = "baseFeePerGas")]
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub base_fee_per_gas: Option<U256>,
119
120    /// Block size
121    pub size: U256,
122
123    /// transactions
124    #[serde_as(as = "VecSkipError<_>")]
125    pub transactions: Vec<TransactionOrHash>,
126
127    /// Uncles
128    pub uncles: Vec<H256>,
129}
130
131#[derive(Serialize, Deserialize)]
132#[serde(untagged)]
133pub enum TransactionOrHash {
134    Null,
135    Hash(H256),
136    Transaction(Transaction),
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub enum TransactionType {
141    // 0x00
142    #[serde(rename = "0x00")]
143    Legacy,
144    // 0x01
145    #[serde(rename = "0x01")]
146    Eip2930,
147    // 0x02
148    #[serde(rename = "0x02")]
149    Eip1559,
150}
151
152#[serde_as]
153#[derive(Default, Serialize, Deserialize, Debug, Clone)]
154pub struct Transaction {
155    /// transaction type
156    ///
157    /// 1. Legacy (pre-EIP2718) `0x00`
158    /// 2. EIP2930 (state access lists) `0x01`
159    /// 3. EIP1559 0x02
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub r#type: Option<TransactionType>,
162    /// transaction nonce
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub nonce: Option<U256>,
165    /// To address
166    pub to: Address,
167    /// Gas limit
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub gas: Option<U256>,
170
171    /// Transaction index in block
172    #[serde(rename = "transactionIndex")]
173    #[serde(skip_serializing_if = "Option::is_none")]
174    transaction_index: Option<U256>,
175    /// Block hash
176    #[serde(rename = "blockHash")]
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub block_hash: Option<H256>,
179    /// Block number
180    #[serde(rename = "blockNumber")]
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub block_number: Option<U256>,
183    /// Gas limit
184    #[serde(rename = "gasPrice")]
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub gas_price: Option<U256>,
187    /// Transaction hash
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub hash: Option<H256>,
190    /// Transfer eth value
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub value: Option<U256>,
193    /// Input data to call contract.
194    pub input: Bytecode,
195    /// Maximum fee per gas the sender is willing to pay to miners in wei
196    #[serde(rename = "maxPriorityFeePerGas")]
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub max_priority_fee_per_gas: Option<U256>,
199    /// Maximum total fee per gas the sender is willing to
200    /// pay(includes the network/base fee and miner/ priority fee) in wei
201    #[serde(rename = "maxFeePerGas")]
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub max_fee_per_gas: Option<U256>,
204    /// EIP-2930 access list
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub access_list: Option<AccessList>,
207    /// Chain ID tha this transaction is valid on
208    #[serde(rename = "chainId")]
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub chain_id: Option<U256>,
211    /// The parity(0 for even, 1 for odd) of the y-value of the secp256k1 signature.
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub v: Option<U256>,
214    /// r-value of the secp256k1
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub r: Option<U256>,
217    /// s-value of the secp256k1
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub s: Option<U256>,
220}
221
222from_json!(Transaction);
223
224/// eth_getBlockByNumber parameter `Block`
225#[derive(Serialize, Deserialize, PartialEq, Debug)]
226#[serde(untagged)]
227pub enum BlockNumberOrTag {
228    U256(U256),
229    Tag(BlockTag),
230}
231
232impl From<U256> for BlockNumberOrTag {
233    fn from(v: U256) -> Self {
234        BlockNumberOrTag::U256(v)
235    }
236}
237
238impl From<BlockTag> for BlockNumberOrTag {
239    fn from(v: BlockTag) -> Self {
240        BlockNumberOrTag::Tag(v)
241    }
242}
243
244impl Default for BlockNumberOrTag {
245    fn default() -> Self {
246        BlockNumberOrTag::Tag(BlockTag::Latest)
247    }
248}
249
250/// eth_getBlockByNumber parameter `Block` valid tag enum
251#[derive(Serialize, Deserialize, PartialEq, Debug)]
252#[serde(rename_all = "lowercase")]
253pub enum BlockTag {
254    Earliest,
255    Finalized,
256    Safe,
257    Latest,
258    Pending,
259}
260
261impl<'a> TryFrom<&'a str> for BlockNumberOrTag {
262    type Error = anyhow::Error;
263    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
264        if value.starts_with("0x") {
265            Ok(BlockNumberOrTag::U256(value.parse()?))
266        } else {
267            Ok(BlockNumberOrTag::Tag(serde_json::from_str(&format!(
268                "\"{}\"",
269                value
270            ))?))
271        }
272    }
273}
274
275#[derive(Serialize, Deserialize)]
276pub struct FeeHistory {
277    /// The lowest number block of returned range.
278    #[serde(rename = "oldestBlock")]
279    pub oldest_block: U256,
280    #[serde(rename = "baseFeePerGas")]
281    pub base_fee_per_gas: Vec<U256>,
282
283    pub reward: Vec<Vec<U256>>,
284}
285
286#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
287pub struct Filter {
288    /// The lowest number block of returned range.
289    #[serde(rename = "fromBlock")]
290    pub from_block: Option<U256>,
291    #[serde(rename = "toBlock")]
292    pub to_block: Option<U256>,
293
294    pub address: Option<AddressFilter>,
295
296    pub topics: Option<TopicFilter>,
297}
298
299impl From<(Address, TopicFilter)> for Filter {
300    fn from(value: (Address, TopicFilter)) -> Self {
301        Filter {
302            from_block: None,
303            to_block: None,
304            address: Some(AddressFilter::Address(value.0)),
305            topics: Some(value.1),
306        }
307    }
308}
309
310impl From<(Vec<Address>, TopicFilter)> for Filter {
311    fn from(value: (Vec<Address>, TopicFilter)) -> Self {
312        Filter {
313            from_block: None,
314            to_block: None,
315            address: Some(AddressFilter::Addresses(value.0)),
316            topics: Some(value.1),
317        }
318    }
319}
320
321from_json!(Filter);
322
323#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
324#[serde(untagged)]
325pub enum AddressFilter {
326    Address(Address),
327    Addresses(Vec<Address>),
328}
329
330impl From<Address> for AddressFilter {
331    fn from(value: Address) -> Self {
332        AddressFilter::Address(value)
333    }
334}
335
336impl From<Vec<Address>> for AddressFilter {
337    fn from(value: Vec<Address>) -> Self {
338        AddressFilter::Addresses(value)
339    }
340}
341
342from_json!(AddressFilter);
343
344#[derive(Serialize, Deserialize, Debug)]
345pub struct Log {
346    pub removed: bool,
347
348    #[serde(rename = "logIndex")]
349    pub log_index: U256,
350
351    #[serde(rename = "transactionIndex")]
352    pub transaction_index: U256,
353
354    #[serde(rename = "transactionHash")]
355    pub transaction_hash: U256,
356
357    #[serde(rename = "blockHash")]
358    pub block_hash: H256,
359
360    #[serde(rename = "blockNumber")]
361    pub block_number: U256,
362
363    pub address: Address,
364
365    pub data: Bytecode,
366
367    pub topics: Vec<H256>,
368}
369
370#[derive(Serialize, Deserialize, Debug)]
371#[serde(untagged)]
372pub enum FilterEvents {
373    BlocksOrTransactions(Vec<H256>),
374
375    Logs(Vec<Log>),
376}
377
378#[derive(Debug, Serialize, Deserialize, PartialEq)]
379#[serde(untagged)]
380pub enum SyncingStatus {
381    Syncing(Syncing),
382
383    #[serde(deserialize_with = "from_bool", serialize_with = "as_bool")]
384    False,
385}
386
387impl Default for SyncingStatus {
388    fn default() -> Self {
389        SyncingStatus::False
390    }
391}
392
393fn from_bool<'de, D>(d: D) -> std::result::Result<(), D::Error>
394where
395    D: Deserializer<'de>,
396{
397    bool::deserialize(d).and_then(|flag| {
398        if !flag {
399            Ok(())
400        } else {
401            Err(BlockError::InvalidSyning).map_err(serde::de::Error::custom)
402        }
403    })
404}
405
406fn as_bool<S>(serializer: S) -> std::result::Result<S::Ok, S::Error>
407where
408    S: Serializer,
409{
410    serializer.serialize_bool(false)
411}
412
413#[derive(Debug, Serialize, Deserialize, Default, PartialEq)]
414pub struct Syncing {
415    /// Starting block
416    #[serde(rename = "startingBlock")]
417    starting_block: U256,
418
419    /// Current block
420    #[serde(rename = "currentBlock")]
421    current_block: U256,
422
423    /// Highest block
424    #[serde(rename = "highestBlock")]
425    highest_block: U256,
426}
427
428#[cfg(test)]
429mod tests {
430    use jsonrpc_rs::Response;
431    use serde_json::json;
432
433    use super::*;
434
435    #[test]
436    fn dser_syncing() {
437        let value = json!({
438            "jsonrpc": "2.0",
439            "result": false,
440            "id": 0
441        });
442
443        let status: Response<String, SyncingStatus, ()> =
444            serde_json::from_value(value).expect("Parse syncing false");
445
446        assert_eq!(status.result, Some(SyncingStatus::False));
447
448        let value = json!({
449            "jsonrpc": "2.0",
450            "result": {
451                "startingBlock": "0x11",
452                "currentBlock": "0x12",
453                "highestBlock": "0x33",
454            },
455            "id": 0
456        });
457
458        let status: Response<String, SyncingStatus, ()> =
459            serde_json::from_value(value).expect("Parse syncing status object");
460
461        assert_eq!(
462            status.result,
463            Some(SyncingStatus::Syncing(Syncing {
464                starting_block: 0x11.into(),
465                current_block: 0x12.into(),
466                highest_block: 0x33.into(),
467            }))
468        );
469    }
470}
471
472#[serde_as]
473#[derive(Default, Serialize, Deserialize, Debug)]
474pub struct TransactionReceipt {
475    /// From address
476    pub from: Address,
477    /// To address
478    pub to: Option<Address>,
479    /// Contract address created by this transaction.
480    #[serde(rename = "contractAddress")]
481    pub contract_address: Option<Address>,
482    /// Gas used
483    #[serde(rename = "gasUsed")]
484    pub gas_used: U256,
485    /// Gas used
486    #[serde(rename = "cumulativeGasUsed")]
487    pub cumulative_gas_used: U256,
488
489    #[serde(rename = "effectiveGasPrice")]
490    pub effective_gas_price: U256,
491
492    #[serde(rename = "transactionIndex")]
493    transaction_index: U256,
494    /// Block hash
495    #[serde(rename = "blockHash")]
496    pub block_hash: H256,
497    /// Block number
498    #[serde(rename = "blockNumber")]
499    pub block_number: U256,
500    /// 1 for success, 0 for failure.
501    pub status: Option<Status>,
502    /// Logs
503    pub logs: Vec<Log>,
504    /// Logs bloom filter string
505    #[serde(rename = "logsBloom")]
506    pub logs_bloom: Bloom,
507    /// Only include before the Byzantium upgrade
508    pub root: Option<H256>,
509}
510
511#[derive(Debug, Clone, Serialize, Deserialize)]
512pub enum Status {
513    // 0x00
514    #[serde(rename = "0x1")]
515    Success,
516    // 0x01
517    #[serde(rename = "0x0")]
518    Failure,
519}