Skip to content

Commit

Permalink
Implement Commands of Massa public-api in the client
Browse files Browse the repository at this point in the history
  • Loading branch information
yvan-sraka committed Oct 5, 2021
1 parent 008f769 commit 08c225a
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 51 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions rpc-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ strum = "0.21"
strum_macros = "0.21"
tokio = { version = "1", features = ["full"] }
# custom modules
api-dto = { path = "../api-dto" }
crypto = { path = "../crypto" }
models = {path = "../models"}
time = {path = "../time"}
110 changes: 63 additions & 47 deletions rpc-client/src/cmds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ pub enum Command {
)]
ban,

#[strum(ascii_case_insensitive, message = "start a node")]
node_start,

// TODO:
// #[strum(ascii_case_insensitive, message = "start a node")]
// node_start,
#[strum(ascii_case_insensitive, message = "stops the node")]
node_stop,

Expand Down Expand Up @@ -72,28 +72,28 @@ pub enum Command {
props(args = "[Addresses]"),
message = "gets info about a list of addresses"
)]
get_addresses_info,
get_addresses,

#[strum(
ascii_case_insensitive,
props(args = "[BlockIds]"),
message = "gets info about a list of blocks"
)]
get_blocks_info,
get_blocks,

#[strum(
ascii_case_insensitive,
props(args = "[EndorsementIds]"),
message = "gets info about a list of endorsements"
)]
get_endorsements_info,
get_endorsements,

#[strum(
ascii_case_insensitive,
props(args = "[OperationIds]"),
message = "gets info about a list of operations"
)]
get_operations_info,
get_operations,

#[strum(ascii_case_insensitive, message = "prints wallet info")]
wallet_info,
Expand Down Expand Up @@ -212,20 +212,22 @@ impl Command {
Err(_) => self.wrong_parameters(),
},

Command::node_start => match process::Command::new("massa-node").spawn() {
Ok(_) => repl_ok!("Node successfully started!"),
Err(e) => repl_err!(e),
},

// TODO: process spawn should be detached
// Command::node_start => match process::Command::new("massa-node").spawn() {
// Ok(_) => repl_ok!("Node successfully started!"),
// Err(e) => repl_err!(e),
// },
//
Command::node_stop => match &client.private.stop_node().await {
Ok(_) => repl_ok!("Request of stopping the Node successfully sent"),
Err(e) => repl_err!(e),
},

Command::node_get_staking_addresses => {
match &client.private.get_staking_addresses().await {
Ok(output) => serde_json::to_string(output)
.expect("Failed to serialized command output ..."),
Ok(output) => {
serde_json::to_string(output).expect("failed to serialize command output")
}
Err(e) => repl_err!(e),
}
}
Expand All @@ -248,53 +250,67 @@ impl Command {
Err(_) => self.wrong_parameters(),
},

Command::node_testnet_rewards_program_ownership_proof => {
todo!()
}
Command::node_testnet_rewards_program_ownership_proof => todo!(),

Command::get_status => {
todo!()
}
// TODO: format!("{:?}" ...) should be replaced by impl std::fmt::Display
Command::get_status => match serde_json::from_str(&parameters[0]) {
Ok(()) => match &client.public.get_status().await {
Ok(status) => repl_ok!(format!("{:?}", status)),
Err(e) => repl_err!(e),
},
Err(_) => self.wrong_parameters(),
},

Command::get_addresses_info => {
todo!()
// TODO: parameters parsing is fuzzy here, should be replace by .parse() trait impl
Command::get_addresses => {
match serde_json::from_str(&serde_json::to_string(parameters).unwrap()) {
Ok(adresses) => match &client.public.get_addresses(adresses).await {
Ok(adresses_info) => repl_ok!(format!("{:?}", adresses_info)),
Err(e) => repl_err!(e),
},
Err(_) => self.wrong_parameters(),
}
}

Command::get_blocks_info => {
todo!()
}
Command::get_blocks => match serde_json::from_str(&parameters[0]) {
Ok(block_id) => match &client.public.get_block(block_id).await {
Ok(block_info) => repl_ok!(format!("{:?}", block_info)),
Err(e) => repl_err!(e),
},
Err(_) => self.wrong_parameters(),
},

Command::get_endorsements_info => {
todo!()
Command::get_endorsements => {
match serde_json::from_str(&serde_json::to_string(parameters).unwrap()) {
Ok(endorsements) => match &client.public.get_endorsements(endorsements).await {
Ok(endorsements_info) => repl_ok!(format!("{:?}", endorsements_info)),
Err(e) => repl_err!(e),
},
Err(_) => self.wrong_parameters(),
}
}

Command::get_operations_info => {
todo!()
Command::get_operations => {
match serde_json::from_str(&serde_json::to_string(parameters).unwrap()) {
Ok(operations) => match &client.public.get_operations(operations).await {
Ok(operations_info) => repl_ok!(format!("{:?}", operations_info)),
Err(e) => repl_err!(e),
},
Err(_) => self.wrong_parameters(),
}
}

Command::wallet_info => {
todo!()
}
Command::wallet_info => todo!(),

Command::wallet_add_private_keys => {
todo!()
}
Command::wallet_add_private_keys => todo!(),

Command::wallet_remove_addresses => {
todo!()
}
Command::wallet_remove_addresses => todo!(),

Command::buy_rolls => {
todo!()
}
Command::buy_rolls => todo!(),

Command::sell_rolls => {
todo!()
}
Command::sell_rolls => todo!(),

Command::send_transaction => {
todo!()
}
Command::send_transaction => todo!(),
}
}
}
3 changes: 1 addition & 2 deletions rpc-client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ fn main(args: Args) {
println!(
"{}",
if args.json {
serde_json::to_string(&output)
.expect("Failed to serialized command output ...")
serde_json::to_string(&output).expect("failed to serialize command output")
} else {
output
}
Expand Down
98 changes: 96 additions & 2 deletions rpc-client/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// Copyright (c) 2021 MASSA LABS <info@massa.net>

use api_dto::{
AddressInfo, BlockInfo, BlockSummary, EndorsementInfo, NodeStatus, OperationInfo, RollsInfo,
};
use crypto::signature::{PrivateKey, PublicKey, Signature};
use jsonrpc_core_client::transports::http;
use jsonrpc_core_client::{RpcChannel, RpcResult, TypedClient};
use models::address::AddressHashSet;
use models::address::{AddressHashMap, AddressHashSet};
use models::clique::Clique;
use models::node::NodeId;
use models::Address;
use models::{Address, BlockId, EndorsementId, Operation, OperationId};
use std::net::IpAddr;
use time::UTime;

// TODO: This crate should at some point be renamed `client`, `massa` or `massa-client`
// and replace the previous one!
Expand Down Expand Up @@ -56,6 +61,10 @@ impl RpcClient {
}
}

/////////////////
// private-api //
/////////////////

/// Gracefully stop the node.
pub(crate) async fn stop_node(&self) -> RpcResult<()> {
self.0.call_method("stop_node", "()", ()).await
Expand Down Expand Up @@ -109,4 +118,89 @@ impl RpcClient {
pub(crate) async fn unban(&self, ip: &Vec<IpAddr>) -> RpcResult<()> {
self.0.call_method("unban", "()", ip).await
}

////////////////
// public-api //
////////////////

// Explorer (aggregated stats)

/// summary of the current state: time, last final blocks (hash, thread, slot, timestamp), clique count, connected nodes count
pub(crate) async fn get_status(&self) -> RpcResult<NodeStatus> {
self.0.call_method("get_status", "NodeStatus", ()).await
}

pub(crate) async fn get_cliques(&self) -> RpcResult<Vec<Clique>> {
self.0.call_method("get_cliques", "Vec<Clique>", ()).await
}

// Debug (specific information)

/// Returns the active stakers and their roll counts for the current cycle.
pub(crate) async fn get_stakers(&self) -> RpcResult<AddressHashMap<RollsInfo>> {
self.0
.call_method("get_stakers", "AddressHashMap<RollsInfo>", ())
.await
}

/// Returns operations information associated to a given list of operations' IDs.
pub(crate) async fn get_operations(
&self,
operation_ids: Vec<OperationId>,
) -> RpcResult<Vec<OperationInfo>> {
self.0
.call_method("get_operations", "Vec<OperationInfo>", operation_ids)
.await
}

pub(crate) async fn get_endorsements(
&self,
endorsement_ids: Vec<EndorsementId>,
) -> RpcResult<Vec<EndorsementInfo>> {
self.0
.call_method("get_endorsements", "Vec<EndorsementInfo>", endorsement_ids)
.await
}

/// Get information on a block given its hash
pub(crate) async fn get_block(&self, block_id: BlockId) -> RpcResult<BlockInfo> {
self.0.call_method("get_block", "BlockInfo", block_id).await
}

/// Get the block graph within the specified time interval.
/// Optional parameters: from <time_start> (included) and to <time_end> (excluded) millisecond timestamp
pub(crate) async fn get_graph_interval(
&self,
time_start: Option<UTime>,
time_end: Option<UTime>,
) -> RpcResult<Vec<BlockSummary>> {
self.0
.call_method(
"get_graph_interval",
"Vec<BlockSummary>",
(time_start, time_end),
)
.await
}

pub(crate) async fn get_addresses(
&self,
addresses: Vec<Address>,
) -> RpcResult<Vec<AddressInfo>> {
self.0
.call_method("get_addresses", "Vec<AddressInfo>", addresses)
.await
}

// User (interaction with the node)

/// Adds operations to pool. Returns operations that were ok and sent to pool.
pub(crate) async fn send_operations(
&self,
operations: Vec<Operation>,
) -> RpcResult<Vec<OperationId>> {
self.0
.call_method("send_operations", "Vec<OperationId>", operations)
.await
}
}

0 comments on commit 08c225a

Please sign in to comment.