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 pub hash: Option<H256>,
52 #[serde(rename = "parentHash")]
54 pub parent_hash: H256,
55
56 #[serde(rename = "sha3Uncles")]
58 pub sha3_uncles: Option<H256>,
59
60 pub miner: Address,
62
63 #[serde(rename = "stateRoot")]
65 pub state_root: H256,
66
67 #[serde(rename = "transactionsRoot")]
69 pub transactions_root: H256,
70
71 #[serde(rename = "receiptsRoot")]
73 pub receipts_root: H256,
74
75 #[serde(rename = "logsBloom")]
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub logs_bloom: Option<Bloom>,
79
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub difficulty: Option<Difficulty>,
83
84 pub number: Option<U256>,
86
87 #[serde(rename = "gasLimit")]
90 pub gas_limit: U256,
91
92 #[serde(rename = "gasUsed")]
94 pub gas_used: U256,
95
96 pub timestamp: U256,
98
99 #[serde(rename = "extraData")]
101 pub extra_data: Bytecode,
102
103 #[serde(rename = "mixHash")]
105 pub mix_hash: Option<H256>,
106
107 pub nonce: Option<U256>,
109
110 #[serde(rename = "totalDeffficult")]
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub total_deffficult: Option<Difficulty>,
114
115 #[serde(rename = "baseFeePerGas")]
117 #[serde(skip_serializing_if = "Option::is_none")]
118 pub base_fee_per_gas: Option<U256>,
119
120 pub size: U256,
122
123 #[serde_as(as = "VecSkipError<_>")]
125 pub transactions: Vec<TransactionOrHash>,
126
127 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 #[serde(rename = "0x00")]
143 Legacy,
144 #[serde(rename = "0x01")]
146 Eip2930,
147 #[serde(rename = "0x02")]
149 Eip1559,
150}
151
152#[serde_as]
153#[derive(Default, Serialize, Deserialize, Debug, Clone)]
154pub struct Transaction {
155 #[serde(skip_serializing_if = "Option::is_none")]
161 pub r#type: Option<TransactionType>,
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub nonce: Option<U256>,
165 pub to: Address,
167 #[serde(skip_serializing_if = "Option::is_none")]
169 pub gas: Option<U256>,
170
171 #[serde(rename = "transactionIndex")]
173 #[serde(skip_serializing_if = "Option::is_none")]
174 transaction_index: Option<U256>,
175 #[serde(rename = "blockHash")]
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub block_hash: Option<H256>,
179 #[serde(rename = "blockNumber")]
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub block_number: Option<U256>,
183 #[serde(rename = "gasPrice")]
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub gas_price: Option<U256>,
187 #[serde(skip_serializing_if = "Option::is_none")]
189 pub hash: Option<H256>,
190 #[serde(skip_serializing_if = "Option::is_none")]
192 pub value: Option<U256>,
193 pub input: Bytecode,
195 #[serde(rename = "maxPriorityFeePerGas")]
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub max_priority_fee_per_gas: Option<U256>,
199 #[serde(rename = "maxFeePerGas")]
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub max_fee_per_gas: Option<U256>,
204 #[serde(skip_serializing_if = "Option::is_none")]
206 pub access_list: Option<AccessList>,
207 #[serde(rename = "chainId")]
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub chain_id: Option<U256>,
211 #[serde(skip_serializing_if = "Option::is_none")]
213 pub v: Option<U256>,
214 #[serde(skip_serializing_if = "Option::is_none")]
216 pub r: Option<U256>,
217 #[serde(skip_serializing_if = "Option::is_none")]
219 pub s: Option<U256>,
220}
221
222from_json!(Transaction);
223
224#[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#[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 #[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 #[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 #[serde(rename = "startingBlock")]
417 starting_block: U256,
418
419 #[serde(rename = "currentBlock")]
421 current_block: U256,
422
423 #[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 pub from: Address,
477 pub to: Option<Address>,
479 #[serde(rename = "contractAddress")]
481 pub contract_address: Option<Address>,
482 #[serde(rename = "gasUsed")]
484 pub gas_used: U256,
485 #[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 #[serde(rename = "blockHash")]
496 pub block_hash: H256,
497 #[serde(rename = "blockNumber")]
499 pub block_number: U256,
500 pub status: Option<Status>,
502 pub logs: Vec<Log>,
504 #[serde(rename = "logsBloom")]
506 pub logs_bloom: Bloom,
507 pub root: Option<H256>,
509}
510
511#[derive(Debug, Clone, Serialize, Deserialize)]
512pub enum Status {
513 #[serde(rename = "0x1")]
515 Success,
516 #[serde(rename = "0x0")]
518 Failure,
519}