fc_rpc_v2_types/
sync.rs

1// This file is part of Frontier.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19use ethereum_types::U64;
20use serde::{de, Deserialize, Serialize};
21
22/// The syncing status of client.
23#[derive(Copy, Clone, Debug, Eq, PartialEq)]
24pub enum SyncingStatus {
25	/// Progress when syncing.
26	IsSyncing(SyncingProgress),
27	/// Not syncing.
28	NotSyncing,
29}
30
31impl serde::Serialize for SyncingStatus {
32	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33	where
34		S: serde::Serializer,
35	{
36		match self {
37			Self::IsSyncing(progress) => progress.serialize(serializer),
38			Self::NotSyncing => serializer.serialize_bool(false),
39		}
40	}
41}
42
43impl<'de> serde::Deserialize<'de> for SyncingStatus {
44	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45	where
46		D: serde::Deserializer<'de>,
47	{
48		#[derive(Deserialize)]
49		#[serde(untagged)]
50		enum Syncing {
51			IsSyncing(SyncingProgress),
52			NotSyncing(bool),
53		}
54
55		match Syncing::deserialize(deserializer)? {
56			Syncing::IsSyncing(sync) => Ok(Self::IsSyncing(sync)),
57			Syncing::NotSyncing(false) => Ok(Self::NotSyncing),
58			Syncing::NotSyncing(true) => Err(de::Error::custom(
59				"eth_syncing should always return false if not syncing.",
60			)),
61		}
62	}
63}
64
65/// The syncing progress.
66#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct SyncingProgress {
69	/// Block number this node started to synchronize from.
70	pub starting_block: U64,
71	/// Block number this node is currently importing.
72	pub current_block: U64,
73	/// Block number of the highest block header this node has received from peers.
74	pub highest_block: U64,
75}
76
77#[cfg(test)]
78mod tests {
79	use super::*;
80
81	#[test]
82	fn syncing_status_serde_impl() {
83		let valid_cases = [
84			(
85				r#"{"startingBlock":"0x64","currentBlock":"0xc8","highestBlock":"0x12c"}"#,
86				SyncingStatus::IsSyncing(SyncingProgress {
87					starting_block: 100.into(),
88					current_block: 200.into(),
89					highest_block: 300.into(),
90				}),
91			),
92			("false", SyncingStatus::NotSyncing),
93		];
94		for (raw, typed) in valid_cases {
95			let deserialized = serde_json::from_str::<SyncingStatus>(raw).unwrap();
96			assert_eq!(deserialized, typed);
97
98			let serialized = serde_json::to_string(&typed).unwrap();
99			assert_eq!(serialized, raw);
100		}
101
102		let invalid_cases = ["true"];
103		for raw in invalid_cases {
104			let status: Result<SyncingStatus, _> = serde_json::from_str(raw);
105			assert!(status.is_err());
106		}
107	}
108}