Skip to content
This repository was archived by the owner on Sep 26, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## Unreleased

### Changed
- Core 2.5 model update


## 1.0.0 - 2018-12-19
- Initial Release
98 changes: 44 additions & 54 deletions src/api/models.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use serde::de::{Deserialize, Deserializer};
use serde_json;
use std::collections::HashMap;

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -25,14 +23,23 @@ pub struct Response<T> {
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Meta {
#[serde(skip_if = Option::is_none)]
pub total_count_is_estimate: Option<bool>,
#[serde(default)]
pub count: u32,
#[serde(default)]
pub page_count: u32,
#[serde(default)]
pub total_count: u32,
#[serde(default)]
pub next: Option<String>,
#[serde(default)]
pub previous: Option<String>,
#[serde(rename = "self")]
pub self_url: String,
pub first: String,
#[serde(rename = "self", default)]
pub self_url: Option<String>,
#[serde(default)]
pub first: Option<String>,
#[serde(default)]
pub last: Option<String>,
}

Expand All @@ -48,15 +55,16 @@ pub struct Block {
pub generator: Generator,
pub signature: String,
pub transactions: u32,
pub confirmations: u64,
pub timestamp: Timestamp,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct Forged {
pub reward: u64,
pub fee: u64,
pub total: u64,
pub amount: u64,
pub reward: String,
pub fee: String,
pub total: String,
pub amount: String,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand Down Expand Up @@ -86,7 +94,7 @@ pub struct Delegate {
pub username: String,
pub address: String,
pub public_key: String,
pub votes: u64,
pub votes: String,
pub rank: u32,
pub blocks: Blocks,
pub production: Production,
Expand All @@ -96,15 +104,13 @@ pub struct Delegate {
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct Blocks {
pub produced: u64,
pub missed: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub last: Option<Last>,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct Production {
pub approval: f64,
pub productivity: f64,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -113,13 +119,13 @@ pub struct Last {
pub timestamp: Timestamp,
}

pub type Balances = HashMap<String, u64>;
pub type Balances = HashMap<String, String>;

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct DelegateForged {
pub rewards: u64,
pub fees: u64,
pub total: u64,
pub rewards: String,
pub fees: String,
pub total: String,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -131,9 +137,9 @@ pub struct NodeConfiguration {
pub symbol: String,
pub explorer: String,
pub version: u32,
pub ports: HashMap<String, u16>,
pub ports: HashMap<String, Option<u16>>,
pub constants: NodeConstants,
pub fee_statistics: Vec<FeeStatistics>,
pub transaction_pool: TransactionPool,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -142,6 +148,7 @@ pub struct NodeStatus {
pub synced: bool,
pub now: u64,
pub blocks_count: i64,
pub timestamp: u32,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -161,7 +168,6 @@ pub struct NodeConstants {
pub blocktime: u32,
pub block: NodeBlock,
pub epoch: String,
pub fees: Fees,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -172,13 +178,13 @@ pub struct NodeBlock {
pub max_payload: u64,
}

pub type NodeFees = Vec<FeeStatistics>;

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Fees {
pub dynamic: bool,
pub struct TransactionPool {
#[serde(skip_serializing_if = "Option::is_none")]
pub dynamic_fees: Option<DynamicFees>,
pub static_fees: FeeSchema,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand Down Expand Up @@ -207,27 +213,20 @@ pub struct FeeSchema {
pub struct FeeStatistics {
#[serde(rename = "type")]
pub transaction_type: TransactionType,
pub fees: FeeStats,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FeeStats {
pub min_fee: u64,
pub max_fee: u64,
pub avg_fee: u64,
pub avg: String,
pub min: String,
pub max: String,
pub sum: String,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct Peer {
pub ip: String,
pub port: u16,
pub ports: HashMap<String, i16>,
pub version: String,
pub height: u64,
pub status: u16,
pub os: String,
pub latency: u32,
pub hashid: String,
}

#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -240,19 +239,25 @@ pub struct Transaction {
pub version: Option<u16>,
#[serde(rename = "type")]
pub transaction_type: TransactionType,
pub amount: u64,
pub fee: u64,
pub amount: String,
pub fee: String,
pub sender: String,
pub sender_public_key: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub second_public_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recipient: Option<String>,
pub signature: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub sign_signature: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub second_signature: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vendor_field: Option<String>,
#[serde(skip_serializing_if = "Asset::is_none")]
pub asset: Asset,
pub confirmations: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub confirmations: Option<u64>,
pub timestamp: Timestamp,
}

Expand Down Expand Up @@ -291,26 +296,10 @@ pub struct Wallet {
pub public_key: Option<String>,
pub username: Option<String>,
pub second_public_key: Option<String>,
#[serde(deserialize_with = "deserialize_u64_as_number_or_string")]
pub balance: u64,
pub balance: String,
pub is_delegate: bool,
}

fn deserialize_u64_as_number_or_string<'de, D>(de: D) -> Result<u64, D::Error>
where
D: Deserializer<'de>,
{
let deser_result: serde_json::Value = try!(Deserialize::deserialize(de));

match deser_result {
serde_json::Value::Number(ref obj) if obj.is_u64() => Ok(obj.as_u64().unwrap()),
serde_json::Value::String(ref obj) if !obj.is_empty() => {
Ok(obj.as_str().parse::<u64>().unwrap())
}
_ => Ok(0),
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Asset {
Expand Down Expand Up @@ -360,6 +349,7 @@ enum_number!(TransactionType {
});

use std::mem::transmute;

impl From<u8> for TransactionType {
fn from(t: u8) -> TransactionType {
assert!(
Expand Down
6 changes: 5 additions & 1 deletion src/api/node.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use api::models::{NodeConfiguration, NodeStatus, NodeSyncing};
use api::models::{NodeConfiguration, NodeFees, NodeStatus, NodeSyncing};
use api::Result;
use http::client::Client;

Expand All @@ -22,4 +22,8 @@ impl Node {
pub fn configuration(&self) -> Result<NodeConfiguration> {
self.client.get("node/configuration")
}

pub fn fees(&self) -> Result<NodeFees> {
self.client.get("node/fees")
}
}
20 changes: 9 additions & 11 deletions src/http/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::{RequestBuilder, Url};
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde_json::{from_str, from_value, to_string};
use serde_json::{from_str, from_value, to_string, Value};
use std::borrow::Borrow;
use std::collections::HashMap;

Expand Down Expand Up @@ -90,17 +90,15 @@ impl Client {

fn send<T: DeserializeOwned>(&self, builder: RequestBuilder) -> Result<T> {
let response = builder.headers(self.headers.clone()).send()?.text()?;
let value: serde_json::Value = from_str(&response)?;
let parsed = from_str::<Value>(&response)?;

// Try to deserialize into T. If it fails, assume the API returned
// an error.
let parsed = from_value::<Response<T>>(value.clone());
match parsed {
Ok(item) => Ok(item),
Err(_) => {
// Assume the API returned a RequestError.
let request_error = from_value::<RequestError>(value)?;
Err(request_error.into())
if parsed.is_object() && parsed.as_object().unwrap().contains_key("statusCode") {
let request_error = from_value::<RequestError>(parsed)?;
Err(request_error.into())
} else {
match from_value::<Response<T>>(parsed) {
Ok(response) => Ok(response),
Err(err) => Err(err.into()),
}
}
}
Expand Down
15 changes: 4 additions & 11 deletions tests/api/blocks_test.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use crate::*;
use serde_json::to_string_pretty;
use *;

#[test]
fn test_all_blocks() {
let (_mock, body) = mock_http_request("blocks");
{
let client = mock_client();
let response = client.blocks.all().unwrap();
let actual = to_string_pretty(&response).unwrap();
assert_eq!(actual, body);
client.blocks.all().unwrap();
}
}

Expand All @@ -17,9 +15,7 @@ fn test_show() {
let (_mock, body) = mock_http_request("blocks/dummy");
{
let client = mock_client();
let response = client.blocks.show("dummy").unwrap();
let actual = to_string_pretty(&response).unwrap();
assert_eq!(actual, body);
client.blocks.show("dummy").unwrap();
}
}

Expand All @@ -28,10 +24,7 @@ fn test_transactions() {
let (_mock, body) = mock_http_request("blocks/dummy/transactions");
{
let client = mock_client();
let response = client.blocks.transactions("dummy").unwrap();

let actual = to_string_pretty(&response).unwrap();
assert_eq!(actual, body);
client.blocks.transactions("dummy").unwrap();
}
}

Expand Down
Loading