Skip to content

Commit 8f2f30e

Browse files
author
Mykhailo Slyvka
committed
added xcb.syncing command support
1 parent e4b3ede commit 8f2f30e

File tree

10 files changed

+111
-4
lines changed

10 files changed

+111
-4
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ keywords = ["core blockchain", "xcb", "cli"]
2424
license = "MIT OR Apache-2.0"
2525
homepage = "https://github.com/core-coin/core-cli"
2626
repository = "https://github.com/core-coin/core-cli"
27-
version = "0.0.3"
27+
version = "0.0.4"
2828

2929
[workspace.dependencies]
3030
# Workspace members

crates/console/src/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fn list() {
2222
println!(" 'get_block(<hash>|<number>|'latest')' - get block information by hash or number. Use 'latest' to get the latest block");
2323
println!(" 'get_energy_price()' - get the current energy price to allow a timely execution of a transaction");
2424
println!(" 'get_network_id()' - get the nework ID of the current network");
25+
println!(" 'syncing()' - get the syncing status of the node");
2526

2627
println!("'xcbkey' - XCB Key module commands:");
2728
println!(" 'list()' - list all accounts");

crates/modules/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ atoms-rpc-types.workspace = true
3131
xcb-keystore.workspace = true
3232

3333
rpassword = "5.0"
34+
35+
[dev-dependencies]
36+
base-primitives.workspace = true

crates/modules/src/xcb.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ impl XcbModule {
8686
Err(e) => Err(e),
8787
}
8888
}
89+
90+
async fn syncing(&self) -> Result<Response, CliError> {
91+
let syncing = self.client().await.lock().await.syncing().await;
92+
match syncing {
93+
Ok(syncing) => Ok(Response::SyncStatus(syncing)),
94+
Err(e) => Err(e),
95+
}
96+
}
8997
}
9098

9199
#[async_trait::async_trait]
@@ -96,6 +104,7 @@ impl Module for XcbModule {
96104
"get_block" => self.block(args).await,
97105
"get_energy_price" => self.get_energy_price().await,
98106
"get_network_id" => self.get_network_id().await,
107+
"syncing" => self.syncing().await,
99108
_ => Err(CliError::UnknownCommand),
100109
}
101110
}

crates/modules/tests/xcb_tests.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#[cfg(test)]
22
mod tests {
3-
use atoms_rpc_types::Block;
3+
use atoms_rpc_types::{Block, SyncInfo};
4+
use base_primitives::U256;
45
use cli_error::CliError;
56
use modules::{Module, XcbModule};
67
use rpc::MockRpcClient;
@@ -23,6 +24,11 @@ mod tests {
2324
XcbModule::new(client)
2425
}
2526

27+
fn get_module_with_rpc_client(client: MockRpcClient) -> XcbModule {
28+
let client = Arc::new(Mutex::new(client));
29+
XcbModule::new(client)
30+
}
31+
2632
#[tokio::test]
2733
async fn test_execute_get_block_height() {
2834
let mut module = get_module();
@@ -139,4 +145,49 @@ mod tests {
139145
Err(CliError::InvalidNumberOfArguments(_))
140146
));
141147
}
148+
149+
#[tokio::test]
150+
async fn test_syncing() {
151+
let mut module = get_module();
152+
let response = module.execute("syncing".to_string(), vec![]).await.unwrap();
153+
assert_eq!(
154+
response,
155+
Response::SyncStatus(atoms_rpc_types::SyncStatus::None)
156+
);
157+
158+
assert_eq!(
159+
response.format(types::ResponseView::Human),
160+
"RPC node is synced and data is up to date"
161+
);
162+
}
163+
164+
#[tokio::test]
165+
async fn test_syncing_active() {
166+
let mut module = get_module_with_rpc_client(MockRpcClient::new().with_syncing(
167+
atoms_rpc_types::SyncStatus::Info(SyncInfo {
168+
starting_block: U256::from(0),
169+
current_block: U256::from(100),
170+
highest_block: U256::from(1000),
171+
warp_chunks_amount: None,
172+
warp_chunks_processed: None,
173+
}),
174+
));
175+
176+
let response = module.execute("syncing".to_string(), vec![]).await.unwrap();
177+
assert_eq!(
178+
response,
179+
Response::SyncStatus(atoms_rpc_types::SyncStatus::Info(SyncInfo {
180+
starting_block: U256::from(0),
181+
current_block: U256::from(100),
182+
highest_block: U256::from(1000),
183+
warp_chunks_amount: None,
184+
warp_chunks_processed: None,
185+
}))
186+
);
187+
188+
assert_eq!(
189+
response.format(types::ResponseView::Human),
190+
"RPC node is syncing now. Current block: 100, highest block: 1000, starting block: 0"
191+
);
192+
}
142193
}

crates/rpc/src/go_core.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::RpcClient;
22
use async_trait::async_trait;
33
use atoms_provider::{network::Ethereum, Provider, RootProvider};
44
use atoms_rpc_client::RpcClient as AtomsRpcClient;
5-
use atoms_rpc_types::{Block, BlockId, BlockNumberOrTag, RpcBlockHash};
5+
use atoms_rpc_types::{Block, BlockId, BlockNumberOrTag, RpcBlockHash, SyncStatus};
66
use atoms_transport_http::{Client, Http};
77
use base_primitives::{hex::FromHex, FixedBytes};
88
use cli_error::CliError;
@@ -90,4 +90,13 @@ impl RpcClient for GoCoreClient {
9090
.map_err(|e| CliError::RpcError(e.to_string()))?;
9191
Ok(response)
9292
}
93+
94+
async fn syncing(&self) -> Result<SyncStatus, CliError> {
95+
let response = self
96+
.provider
97+
.syncing()
98+
.await
99+
.map_err(|e| CliError::RpcError(e.to_string()))?;
100+
Ok(response)
101+
}
93102
}

crates/rpc/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use async_trait::async_trait;
2-
use atoms_rpc_types::Block;
2+
use atoms_rpc_types::{Block, SyncStatus};
33
use cli_error::CliError;
44

55
pub mod go_core;
@@ -17,4 +17,6 @@ pub trait RpcClient {
1717

1818
async fn get_energy_price(&self) -> Result<u128, CliError>;
1919
async fn get_network_id(&self) -> Result<u64, CliError>;
20+
21+
async fn syncing(&self) -> Result<SyncStatus, CliError>;
2022
}

crates/rpc/src/mock.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub struct MockRpcClient {
99
pub block_latest: Block,
1010
pub energy_price: u128,
1111
pub network_id: u64,
12+
pub syncing: atoms_rpc_types::SyncStatus,
1213
}
1314

1415
impl MockRpcClient {
@@ -20,6 +21,7 @@ impl MockRpcClient {
2021
block_latest: Block::default(),
2122
energy_price: 0,
2223
network_id: 0,
24+
syncing: atoms_rpc_types::SyncStatus::None,
2325
}
2426
}
2527

@@ -52,6 +54,11 @@ impl MockRpcClient {
5254
self.network_id = network_id;
5355
self
5456
}
57+
58+
pub fn with_syncing(mut self, syncing: atoms_rpc_types::SyncStatus) -> Self {
59+
self.syncing = syncing;
60+
self
61+
}
5562
}
5663

5764
impl Default for MockRpcClient {
@@ -85,4 +92,8 @@ impl RpcClient for MockRpcClient {
8592
async fn get_network_id(&self) -> Result<u64, CliError> {
8693
Ok(self.network_id)
8794
}
95+
96+
async fn syncing(&self) -> Result<atoms_rpc_types::SyncStatus, CliError> {
97+
Ok(self.syncing)
98+
}
8899
}

crates/rpc/tests/go_core_tests.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#[cfg(test)]
44
mod tests {
5+
use atoms_rpc_types::SyncStatus;
56
use cli_error::CliError;
67
use rpc::{GoCoreClient, RpcClient};
78
use types::DEFAULT_BACKEND;
@@ -92,4 +93,12 @@ mod tests {
9293
let response = go_core_client.get_block_by_number(999999999).await;
9394
assert!(matches!(response, Err(CliError::RpcError(_))));
9495
}
96+
97+
#[tokio::test]
98+
async fn test_syncing() {
99+
let go_core_client = gocore_client().await;
100+
101+
let response = go_core_client.syncing().await.unwrap();
102+
assert_eq!(response, SyncStatus::None);
103+
}
95104
}

crates/types/src/response.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use atoms_rpc_types::Block;
22
use serde::Serialize;
33

44
use crate::{account::KeyFile, Account};
5+
use atoms_rpc_types::SyncStatus;
56
use std::str::FromStr;
7+
68
/// ResponseView decided if response of call will be returned as a string, json object or human readable format
79
#[derive(Debug, Clone, PartialEq, Default)]
810
pub enum ResponseView {
@@ -38,6 +40,7 @@ pub enum Response {
3840

3941
Block(Block),
4042
Struct(serde_json::Value), // Use serde_json::Value for custom structs
43+
SyncStatus(SyncStatus),
4144

4245
Accounts(Vec<Account>),
4346
Keyfile(KeyFile),
@@ -71,6 +74,14 @@ impl std::fmt::Display for Response {
7174
}
7275
Ok(())
7376
}
77+
Response::SyncStatus(sync_info) => {
78+
if let SyncStatus::Info(sync_info) = sync_info {
79+
write!(f, "RPC node is syncing now. Current block: {}, highest block: {}, starting block: {}", sync_info.current_block, sync_info.highest_block, sync_info.starting_block)
80+
} else {
81+
write!(f, "RPC node is synced and data is up to date")
82+
}
83+
}
84+
7485
Response::Keyfile(keyfile) => write!(f, "{}", keyfile),
7586
}
7687
}
@@ -96,6 +107,7 @@ impl Response {
96107
Response::Struct(val) => format!("Struct value: {:#?}", val),
97108
Response::Accounts(_) => self.to_string(),
98109
Response::Keyfile(_) => self.to_string(),
110+
Response::SyncStatus(_) => self.to_string(),
99111
}
100112
}
101113
}

0 commit comments

Comments
 (0)