mwc_web3/types/
block.rs

1use crate::types::{Bytes, H160, H2048, H256, H64, U256, U64};
2use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
3
4/// The block header type returned from RPC calls.
5#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
6pub struct BlockHeader {
7    /// Hash of the block
8    pub hash: Option<H256>,
9    /// Hash of the parent
10    #[serde(rename = "parentHash")]
11    pub parent_hash: H256,
12    /// Hash of the uncles
13    #[serde(rename = "sha3Uncles")]
14    pub uncles_hash: H256,
15    /// Miner/author's address.
16    #[serde(rename = "miner")]
17    #[serde(default)]
18    pub author: H160,
19    /// State root hash
20    #[serde(rename = "stateRoot")]
21    pub state_root: H256,
22    /// Transactions root hash
23    #[serde(rename = "transactionsRoot")]
24    pub transactions_root: H256,
25    /// Transactions receipts root hash
26    #[serde(rename = "receiptsRoot")]
27    pub receipts_root: H256,
28    /// Block number. None if pending.
29    pub number: Option<U64>,
30    /// Gas Used
31    #[serde(rename = "gasUsed")]
32    pub gas_used: U256,
33    /// Gas Limit
34    #[serde(rename = "gasLimit")]
35    pub gas_limit: U256,
36    /// Extra data
37    #[serde(rename = "extraData")]
38    pub extra_data: Bytes,
39    /// Logs bloom
40    #[serde(rename = "logsBloom")]
41    pub logs_bloom: H2048,
42    /// Timestamp
43    pub timestamp: U256,
44    /// Difficulty
45    pub difficulty: U256,
46    /// Mix Hash
47    #[serde(rename = "mixHash")]
48    pub mix_hash: Option<H256>,
49    /// Nonce
50    pub nonce: Option<H64>,
51}
52
53/// The block type returned from RPC calls.
54/// This is generic over a `TX` type.
55#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
56pub struct Block<TX> {
57    /// Hash of the block
58    pub hash: Option<H256>,
59    /// Hash of the parent
60    #[serde(rename = "parentHash")]
61    pub parent_hash: H256,
62    /// Hash of the uncles
63    #[serde(rename = "sha3Uncles")]
64    pub uncles_hash: H256,
65    /// Miner/author's address.
66    #[serde(rename = "miner")]
67    #[serde(default)]
68    pub author: H160,
69    /// State root hash
70    #[serde(rename = "stateRoot")]
71    pub state_root: H256,
72    /// Transactions root hash
73    #[serde(rename = "transactionsRoot")]
74    pub transactions_root: H256,
75    /// Transactions receipts root hash
76    #[serde(rename = "receiptsRoot")]
77    pub receipts_root: H256,
78    /// Block number. None if pending.
79    pub number: Option<U64>,
80    /// Gas Used
81    #[serde(rename = "gasUsed")]
82    pub gas_used: U256,
83    /// Gas Limit
84    #[serde(rename = "gasLimit")]
85    pub gas_limit: U256,
86    /// Extra data
87    #[serde(rename = "extraData")]
88    pub extra_data: Bytes,
89    /// Logs bloom
90    #[serde(rename = "logsBloom")]
91    pub logs_bloom: Option<H2048>,
92    /// Timestamp
93    pub timestamp: U256,
94    /// Difficulty
95    pub difficulty: U256,
96    /// Total difficulty
97    #[serde(rename = "totalDifficulty")]
98    pub total_difficulty: Option<U256>,
99    /// Seal fields
100    #[serde(default, rename = "sealFields")]
101    pub seal_fields: Vec<Bytes>,
102    /// Uncles' hashes
103    pub uncles: Vec<H256>,
104    /// Transactions
105    pub transactions: Vec<TX>,
106    /// Size in bytes
107    pub size: Option<U256>,
108    /// Mix Hash
109    #[serde(rename = "mixHash")]
110    pub mix_hash: Option<H256>,
111    /// Nonce
112    pub nonce: Option<H64>,
113}
114
115/// Block Number
116#[derive(Copy, Clone, Debug, PartialEq)]
117pub enum BlockNumber {
118    /// Latest block
119    Latest,
120    /// Earliest block (genesis)
121    Earliest,
122    /// Pending block (not yet part of the blockchain)
123    Pending,
124    /// Block by number from canon chain
125    Number(U64),
126}
127
128impl<T: Into<U64>> From<T> for BlockNumber {
129    fn from(num: T) -> Self {
130        BlockNumber::Number(num.into())
131    }
132}
133
134impl Serialize for BlockNumber {
135    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
136    where
137        S: Serializer,
138    {
139        match *self {
140            BlockNumber::Number(ref x) => serializer.serialize_str(&format!("0x{:x}", x)),
141            BlockNumber::Latest => serializer.serialize_str("latest"),
142            BlockNumber::Earliest => serializer.serialize_str("earliest"),
143            BlockNumber::Pending => serializer.serialize_str("pending"),
144        }
145    }
146}
147
148/// Block Identifier
149#[derive(Copy, Clone, Debug, PartialEq)]
150pub enum BlockId {
151    /// By Hash
152    Hash(H256),
153    /// By Number
154    Number(BlockNumber),
155}
156
157impl Serialize for BlockId {
158    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
159    where
160        S: Serializer,
161    {
162        match *self {
163            BlockId::Hash(ref x) => {
164                let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?;
165                s.serialize_field("blockHash", &format!("{:?}", x))?;
166                s.end()
167            }
168            BlockId::Number(ref num) => num.serialize(serializer),
169        }
170    }
171}
172
173impl From<U64> for BlockId {
174    fn from(num: U64) -> Self {
175        BlockNumber::Number(num).into()
176    }
177}
178
179impl From<BlockNumber> for BlockId {
180    fn from(num: BlockNumber) -> Self {
181        BlockId::Number(num)
182    }
183}
184
185impl From<H256> for BlockId {
186    fn from(hash: H256) -> Self {
187        BlockId::Hash(hash)
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn block_without_miner() {
197        const EXAMPLE_BLOCK: &str = r#"{
198            "number": "0x1b4",
199            "hash": "0x0e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
200            "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5",
201            "mixHash": "0x1010101010101010101010101010101010101010101010101010101010101010",
202            "nonce": "0x0000000000000000",
203            "sealFields": [
204              "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2",
205              "0x0000000000000042"
206            ],
207            "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
208            "logsBloom":  "0x0e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
209            "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
210            "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
211            "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff",
212            "difficulty": "0x27f07",
213            "totalDifficulty": "0x27f07",
214            "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
215            "size": "0x27f07",
216            "gasLimit": "0x9f759",
217            "minGasPrice": "0x9f759",
218            "gasUsed": "0x9f759",
219            "timestamp": "0x54e34e8e",
220            "transactions": [],
221            "uncles": []
222          }"#;
223
224        let block: Block<()> = serde_json::from_str(&EXAMPLE_BLOCK).unwrap();
225
226        assert_eq!(block.author, Default::default());
227    }
228}