Skip to content

Commit 89cde88

Browse files
authored
Merge pull request #39 from ainestal/BigDecimal
Use BigDecimal instead of f64
2 parents 73f34e0 + 6fad3ab commit 89cde88

File tree

9 files changed

+99
-110
lines changed

9 files changed

+99
-110
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ bidir-map = "0.3.2"
4040
data-encoding = "2.0.0-rc.1"
4141
error-chain = "0.7.1"
4242
sha2 = "0.6.0"
43-
hmac = "0.3"
43+
hmac = "0.3"
44+
bigdecimal = "0.0.10"

src/bitstamp/generic_api.rs

+11-29
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ impl ExchangeApi for BitstampApi {
1515

1616
let result = self.return_ticker(pair)?;
1717

18-
let price = helpers::from_json_float(&result["last"], "last")?;
19-
let ask = helpers::from_json_float(&result["ask"], "ask")?;
20-
let bid = helpers::from_json_float(&result["bid"], "bid")?;
21-
let vol = helpers::from_json_float(&result["volume"], "volume")?;
18+
let price = helpers::from_json_bigdecimal(&result["last"], "last")?;
19+
let ask = helpers::from_json_bigdecimal(&result["ask"], "ask")?;
20+
let bid = helpers::from_json_bigdecimal(&result["bid"], "bid")?;
21+
let vol = helpers::from_json_bigdecimal(&result["volume"], "volume")?;
2222

2323
Ok(Ticker {
2424
timestamp: helpers::get_unix_timestamp_ms(),
@@ -49,31 +49,16 @@ impl ExchangeApi for BitstampApi {
4949
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", result["asks"])))?;
5050

5151
for ask in ask_array {
52-
let price = ask[0]
53-
.as_str()
54-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[0])))?
55-
.parse::<f64>()
56-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[0])))?;
57-
58-
let volume = ask[1]
59-
.as_str()
60-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[1])))?
61-
.parse::<f64>()
62-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[1])))?;
52+
let price = helpers::from_json_bigdecimal(&ask[0], "ask price")?;
53+
let volume = helpers::from_json_bigdecimal(&ask[1], "ask volume")?;
54+
6355
ask_offers.push((price, volume));
6456
}
6557

6658
for bid in bid_array {
67-
let price = bid[0]
68-
.as_str()
69-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[0])))?
70-
.parse::<f64>()
71-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[0])))?;
72-
let volume = bid[1]
73-
.as_str()
74-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[1])))?
75-
.parse::<f64>()
76-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[1])))?;
59+
let price = helpers::from_json_bigdecimal(&bid[0], "bid price")?;
60+
let volume = helpers::from_json_bigdecimal(&bid[1], "bid volume")?;
61+
7762
bid_offers.push((price, volume));
7863
}
7964

@@ -140,10 +125,7 @@ impl ExchangeApi for BitstampApi {
140125

141126
match currency {
142127
Some(c) => {
143-
let amount = val.as_str()
144-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", val)))?
145-
.parse::<f64>()
146-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", val)))?;
128+
let amount = helpers::from_json_bigdecimal(&val, "amount")?;
147129

148130
balances.insert(c, amount);
149131
},

src/helpers/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
use serde_json::Value;
55
use error::*;
6+
use bigdecimal::BigDecimal;
7+
use std::str::FromStr;
68

79
use std::collections::HashMap;
810
use time;
@@ -45,10 +47,10 @@ pub fn get_json_string<'a>(json_obj: &'a Value, key: &str) -> Result<&'a str> {
4547
.ok_or_else(|| ErrorKind::InvalidFieldFormat(key.to_string()))?)
4648
}
4749

48-
pub fn from_json_float(json_obj: &Value, key: &str) -> Result<f64> {
49-
Ok(json_obj
50-
.as_str()
51-
.ok_or_else(|| ErrorKind::MissingField(key.to_string()))?
52-
.parse::<f64>()
53-
.chain_err(|| ErrorKind::InvalidFieldFormat(key.to_string()))?)
50+
pub fn from_json_bigdecimal(json_obj: &Value, key: &str) -> Result<BigDecimal> {
51+
let num = json_obj
52+
.as_str()
53+
.ok_or_else(|| ErrorKind::MissingField(key.to_string()))?;
54+
55+
Ok(BigDecimal::from_str(num).chain_err(|| ErrorKind::InvalidFieldFormat(key.to_string()))?)
5456
}

src/kraken/generic_api.rs

+10-28
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ impl ExchangeApi for KrakenApi {
2121

2222
let result = utils::parse_result(&raw_response)?;
2323

24-
let price = helpers::from_json_float(&result[*pair_name]["c"][0], "c")?;
25-
let ask = helpers::from_json_float(&result[*pair_name]["a"][0], "a")?;
26-
let bid = helpers::from_json_float(&result[*pair_name]["b"][0], "b")?;
27-
let vol = helpers::from_json_float(&result[*pair_name]["v"][0], "v")?;
24+
let price = helpers::from_json_bigdecimal(&result[*pair_name]["c"][0], "c")?;
25+
let ask = helpers::from_json_bigdecimal(&result[*pair_name]["a"][0], "a")?;
26+
let bid = helpers::from_json_bigdecimal(&result[*pair_name]["b"][0], "b")?;
27+
let vol = helpers::from_json_bigdecimal(&result[*pair_name]["v"][0], "v")?;
2828

2929
Ok(Ticker {
3030
timestamp: helpers::get_unix_timestamp_ms(),
@@ -66,30 +66,15 @@ impl ExchangeApi for KrakenApi {
6666
})?;
6767

6868
for ask in ask_array {
69-
let price = ask[0]
70-
.as_str()
71-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[0])))?
72-
.parse::<f64>()
73-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[0])))?;
74-
let volume = ask[1]
75-
.as_str()
76-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[1])))?
77-
.parse::<f64>()
78-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[1])))?;
69+
let price = helpers::from_json_bigdecimal(&ask[0], "ask price")?;
70+
let volume = helpers::from_json_bigdecimal(&ask[1], "ask volume")?;
71+
7972
ask_offers.push((price, volume));
8073
}
8174

8275
for bid in bid_array {
83-
let price = bid[0]
84-
.as_str()
85-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[0])))?
86-
.parse::<f64>()
87-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[0])))?;
88-
let volume = bid[1]
89-
.as_str()
90-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[1])))?
91-
.parse::<f64>()
92-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[1])))?;
76+
let price = helpers::from_json_bigdecimal(&bid[0], "bid price")?;
77+
let volume = helpers::from_json_bigdecimal(&bid[1], "bid volume")?;
9378

9479
bid_offers.push((price, volume));
9580
}
@@ -173,10 +158,7 @@ impl ExchangeApi for KrakenApi {
173158

174159
match currency {
175160
Some(c) => {
176-
let amount = val.as_str()
177-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", val)))?
178-
.parse::<f64>()
179-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", val)))?;
161+
let amount = helpers::from_json_bigdecimal(&val, "amount")?;
180162

181163
balances.insert(c, amount);
182164
},

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern crate bidir_map;
4141
extern crate data_encoding;
4242
#[macro_use]
4343
extern crate error_chain;
44+
extern crate bigdecimal;
4445

4546
pub mod coinnect;
4647
pub mod exchange;

src/poloniex/generic_api.rs

+16-22
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
use exchange::ExchangeApi;
66
use poloniex::api::PoloniexApi;
77

8+
use bigdecimal::BigDecimal;
9+
use std::str::FromStr;
10+
811
use error::*;
912
use types::*;
1013
use poloniex::utils;
@@ -20,10 +23,10 @@ impl ExchangeApi for PoloniexApi {
2023

2124
let result = utils::parse_result(&raw_response)?;
2225

23-
let price = helpers::from_json_float(&result[*pair_name]["last"], "last")?;
24-
let ask = helpers::from_json_float(&result[*pair_name]["lowestAsk"], "lowestAsk")?;
25-
let bid = helpers::from_json_float(&result[*pair_name]["highestBid"], "highestBid")?;
26-
let vol = helpers::from_json_float(&result[*pair_name]["quoteVolume"], "quoteVolume")?;
26+
let price = helpers::from_json_bigdecimal(&result[*pair_name]["last"], "last")?;
27+
let ask = helpers::from_json_bigdecimal(&result[*pair_name]["lowestAsk"], "lowestAsk")?;
28+
let bid = helpers::from_json_bigdecimal(&result[*pair_name]["highestBid"], "highestBid")?;
29+
let vol = helpers::from_json_bigdecimal(&result[*pair_name]["quoteVolume"], "quoteVolume")?;
2730

2831
Ok(Ticker {
2932
timestamp: helpers::get_unix_timestamp_ms(),
@@ -56,28 +59,19 @@ impl ExchangeApi for PoloniexApi {
5659
.as_array()
5760
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", result["asks"])))?;
5861

59-
for ask in ask_array {
60-
let price = ask[0]
61-
.as_str()
62-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[0])))?
63-
.parse::<f64>()
64-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[0])))?;
62+
for ask in ask_array {
63+
let price = helpers::from_json_bigdecimal(&ask[0], "ask price")?;
64+
let volume_str = ask[1].as_f64().unwrap().to_string();
65+
let volume = BigDecimal::from_str(&volume_str).unwrap();
6566

66-
let volume = ask[1]
67-
.as_f64()
68-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", ask[1])))?;
6967
ask_offers.push((price, volume));
7068
}
7169

7270
for bid in bid_array {
73-
let price = bid[0]
74-
.as_str()
75-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[0])))?
76-
.parse::<f64>()
77-
.chain_err(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[0])))?;
78-
let volume = bid[1]
79-
.as_f64()
80-
.ok_or_else(|| ErrorKind::InvalidFieldFormat(format!("{}", bid[1])))?;
71+
let price = helpers::from_json_bigdecimal(&bid[0], "bid price")?;
72+
let volume_str = bid[1].as_f64().unwrap().to_string();
73+
let volume = BigDecimal::from_str(&volume_str).unwrap();
74+
8175
bid_offers.push((price, volume));
8276
}
8377

@@ -151,7 +145,7 @@ impl ExchangeApi for PoloniexApi {
151145
let currency = utils::get_currency_enum(key);
152146

153147
if currency.is_some() {
154-
let amount = val.as_str().unwrap().parse::<f64>()?;
148+
let amount = helpers::from_json_bigdecimal(&val, "amount")?;
155149
balances.insert(currency.unwrap(), amount);
156150
}
157151
}

src/types.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Types definition used for handling returned data when generic API is used.
22
33
use std::collections::HashMap;
4+
use bigdecimal::BigDecimal;
5+
use std::str::FromStr;
46

57

6-
pub type Amount = f64;
7-
pub type Price = f64;
8-
pub type Volume = f64;
8+
pub type Amount = BigDecimal;
9+
pub type Price = BigDecimal;
10+
pub type Volume = BigDecimal;
911

1012
pub type Balances = HashMap<Currency, Amount>;
1113

@@ -46,7 +48,11 @@ impl Orderbook {
4648
if self.asks.is_empty() || self.bids.is_empty() {
4749
return None;
4850
}
49-
Some((self.asks[0].0 + self.bids[0].0) / 2.0)
51+
Some(
52+
(self.asks[0].0.clone() + self.bids[0].0.clone())
53+
/
54+
BigDecimal::from_str("2.0").unwrap()
55+
)
5056
}
5157
}
5258

tests/bitstamp.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#[cfg(test)]
22
mod bitstamp_tests {
33
extern crate coinnect;
4+
extern crate bigdecimal;
5+
6+
use self::bigdecimal::BigDecimal;
7+
use std::str::FromStr;
8+
49
use self::coinnect::bitstamp::utils;
510
use self::coinnect::bitstamp::{BitstampApi, BitstampCreds};
611
use self::coinnect::kraken::KrakenCreds;
@@ -40,28 +45,32 @@ mod bitstamp_tests {
4045
let creds = BitstampCreds::new("", "", "", "");
4146
let mut api = BitstampApi::new(creds).unwrap();
4247
let result = api.ticker(Pair::BTC_USD);
43-
assert_ne!(result.unwrap().last_trade_price, 0.0);
48+
assert_ne!(result.unwrap().last_trade_price,
49+
BigDecimal::from_str("0.0").unwrap());
4450
}
4551
#[test]
4652
fn ticker_should_have_the_correct_high() {
4753
let creds = BitstampCreds::new("", "", "", "");
4854
let mut api = BitstampApi::new(creds).unwrap();
4955
let result = api.ticker(Pair::BTC_USD);
50-
assert_ne!(result.unwrap().highest_bid, 0.0);
56+
assert_ne!(result.unwrap().highest_bid,
57+
BigDecimal::from_str("0.0").unwrap());
5158
}
5259
#[test]
5360
fn ticker_should_have_the_correct_low() {
5461
let creds = BitstampCreds::new("", "", "", "");
5562
let mut api = BitstampApi::new(creds).unwrap();
5663
let result = api.ticker(Pair::BTC_USD);
57-
assert_ne!(result.unwrap().lowest_ask, 0.0);
64+
assert_ne!(result.unwrap().lowest_ask,
65+
BigDecimal::from_str("0.0").unwrap());
5866
}
5967
#[test]
6068
fn ticker_should_have_the_correct_volume() {
6169
let creds = BitstampCreds::new("", "", "", "");
6270
let mut api = BitstampApi::new(creds).unwrap();
6371
let result = api.ticker(Pair::BTC_USD);
64-
assert_ne!(result.unwrap().volume.unwrap(), 0.0);
72+
assert_ne!(result.unwrap().volume.unwrap(),
73+
BigDecimal::from_str("0.0").unwrap());
6574
}
6675

6776
#[test]

0 commit comments

Comments
 (0)