Skip to content
Permalink
Browse files

Merge pull request #352 from input-output-hk/rest_account

Add account state getter to REST API
  • Loading branch information...
NicolasDP committed May 15, 2019
2 parents 9cb52df + ddbf489 commit 1e8d83fae68c9652e7e97d4780b7641d5eb3ba6d
@@ -0,0 +1,36 @@
use jcli_app::utils::HostAddr;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub enum Account {
/// Get account state
Get {
#[structopt(flatten)]
addr: HostAddr,
/// ID of an account, bech32-encoded
account_id: String,
},
}

impl Account {
pub fn exec(self) {
let (addr, account_id) = match self {
Account::Get { addr, account_id } => (addr, account_id),
};
let url = addr
.with_segments(&["v0", "account", &account_id])
.unwrap()
.into_url();
let state: serde_json::Value = reqwest::Client::new()
.get(url)
.send()
.unwrap()
.error_for_status()
.unwrap()
.json()
.unwrap();
let state_yaml = serde_yaml::to_string(&state).unwrap();
println!("{}", state_yaml);
}
}
@@ -1,3 +1,4 @@
mod account;
mod block;
mod message;
mod node;
@@ -9,6 +10,8 @@ use structopt::StructOpt;
#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub enum V0 {
/// Account operations
Account(account::Account),
/// Block operations
Block(block::Block),
/// Message sending
@@ -24,6 +27,7 @@ pub enum V0 {
impl V0 {
pub fn exec(self) {
match self {
V0::Account(account) => account.exec(),
V0::Block(block) => block.exec(),
V0::Message(message) => message.exec(),
V0::Node(node) => node.exec(),
@@ -22,6 +22,7 @@ pub fn start_rest_server(config: &Rest, context: Context) -> Result<Server, Conf
.map(|prefix| prefix.as_str())
.unwrap_or("");
Server::builder(config.pkcs12.clone(), config.listen.clone(), prefix)
.add_handler(v0::account::create_handler(context.blockchain.clone()))
.add_handler(v0::block::create_handler(context.blockchain.clone()))
.add_handler(v0::node::stats::create_handler(context.stats_counter))
.add_handler(v0::tip::create_handler(context.blockchain.clone()))
@@ -0,0 +1,54 @@
use crate::blockchain::BlockchainR;
use actix_web::error::{Error, ErrorBadRequest, ErrorNotFound};
use actix_web::{App, Json, Path, Responder, State};
use chain_crypto::PublicKey;
use chain_impl_mockchain::account::{AccountAlg, Identifier};
use chain_impl_mockchain::accounting::account::AccountState;
use std::str::FromStr;

pub fn create_handler(
blockchain: BlockchainR,
) -> impl Fn(&str) -> App<BlockchainR> + Send + Sync + Clone + 'static {
move |prefix: &str| {
App::with_state(blockchain.clone())
.prefix(format!("{}/v0/account", prefix))
.resource("/{account_id}", |r| r.get().with(handle_request))
}
}

fn handle_request(
blockchain: State<BlockchainR>,
account_id_hex: Path<String>,
) -> Result<impl Responder, Error> {
let account_id = parse_account_id(&account_id_hex)?;
let blockchain = blockchain.lock_read();
let state = blockchain
.multiverse
.get(&blockchain.get_tip().unwrap())
.unwrap()
.accounts()
.get_state(&account_id)
.map_err(|e| ErrorNotFound(e))?;
Ok(Json(AccountDto::from(state)))
}

fn parse_account_id(id_hex: &str) -> Result<Identifier, Error> {
PublicKey::<AccountAlg>::from_str(id_hex)
.map(Into::into)
.map_err(|e| ErrorBadRequest(e))
}

#[derive(Serialize)]
struct AccountDto {
value: u64,
counter: u32,
}

impl<'a> From<&'a AccountState> for AccountDto {
fn from(state: &'a AccountState) -> Self {
AccountDto {
value: state.get_value().as_ref().clone(),
counter: state.get_counter().into(),
}
}
}
@@ -1,3 +1,4 @@
pub mod account;
pub mod block;
pub mod message;
pub mod node;

0 comments on commit 1e8d83f

Please sign in to comment.
You can’t perform that action at this time.