From b12d67a780c8c983c6db587b16d5e973d605351e Mon Sep 17 00:00:00 2001 From: Marechaux Tristan Date: Tue, 7 Jun 2022 18:08:58 +0000 Subject: [PATCH 1/3] [WIP] --- .devcontainer/Dockerfile | 9 ++++++++ .devcontainer/devcontainer.json | 20 ++++++++++++++++ .devcontainer/setup.sh | 32 ++++++++++++++++++++++++++ Cargo.toml | 13 ++++++----- src/currencies.rs | 7 +++--- src/error.rs | 8 +++---- src/lib.rs | 14 ----------- src/products/get_24hr_stats.rs | 7 +++--- src/products/get_historic_rates.rs | 6 +++-- src/products/get_product_order_book.rs | 7 +++--- src/products/get_product_ticker.rs | 9 +++++--- src/products/get_products.rs | 7 +++--- src/products/get_trades.rs | 8 ++++--- src/rest_client.rs | 6 +++-- src/time.rs | 5 ++-- src/url.rs | 6 ++--- 16 files changed, 113 insertions(+), 51 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/setup.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..3c6253d --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:18.04 + +WORKDIR /home/ + +COPY . . + +RUN bash ./setup.sh + +ENV PATH="/root/.cargo/bin:$PATH" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..6e9695e --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +{ + "name": "Codespaces Rust Starter", + "extensions": [ + "cschleiden.vscode-github-actions", + "ms-vsliveshare.vsliveshare", + "matklad.rust-analyzer", + "serayuzgur.crates", + "vadimcn.vscode-lldb", + "GitHub.copilot" + ], + "dockerFile": "Dockerfile", + "settings": { + "editor.formatOnSave": true, + "terminal.integrated.shell.linux": "/usr/bin/zsh", + "files.exclude": { + "**/CODE_OF_CONDUCT.md": true, + "**/LICENSE": true + } + } +} \ No newline at end of file diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100644 index 0000000..b139217 --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,32 @@ +## update and install some things we should probably have +apt-get update +apt-get install -y \ + curl \ + git \ + gnupg2 \ + jq \ + sudo \ + zsh \ + vim \ + build-essential \ + openssl \ + pkg-config \ + libssl-dev + +## Install rustup and common components +curl https://sh.rustup.rs -sSf | sh -s -- -y +rustup install nightly +rustup component add rustfmt +rustup component add rustfmt --toolchain nightly +rustup component add clippy +rustup component add clippy --toolchain nightly + +cargo install cargo-expand +cargo install cargo-edit + +## setup and install oh-my-zsh +sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" +cp -R /root/.oh-my-zsh /home/$USERNAME +cp /root/.zshrc /home/$USERNAME +sed -i -e "s/\/root\/.oh-my-zsh/\/home\/$USERNAME\/.oh-my-zsh/g" /home/$USERNAME/.zshrc +chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index a287a89..d68add5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,16 +2,17 @@ name = "gdax_rs" version = "0.1.0" authors = ["Tristan Marechaux "] +edition = "2021" [dependencies] -mockito = "0.9.0" -hyper = "0.11" +mockito = "0.31" +hyper = "0.14" tokio-core = "0.1" -hyper-tls = "0.1.2" -futures = "0.1" +hyper-tls = "0.5" +futures = "0.3" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -itertools = "0.7.4" +itertools = "0.10" chrono = { version = "0.4", features = ["serde"] } -percent-encoding = "1.0.0" \ No newline at end of file +percent-encoding = "2.1" \ No newline at end of file diff --git a/src/currencies.rs b/src/currencies.rs index 444dc90..3c8ebd9 100644 --- a/src/currencies.rs +++ b/src/currencies.rs @@ -2,10 +2,11 @@ //! "Market Data/Currencies" section () use hyper::Method; +use serde_derive::{Serialize, Deserialize}; -use serde_util::deserialize_from_str; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; +use crate::serde_util::deserialize_from_str; #[derive(Default)] pub struct GetCurrencies; diff --git a/src/error.rs b/src/error.rs index d775d22..2dcbd78 100644 --- a/src/error.rs +++ b/src/error.rs @@ -82,14 +82,14 @@ impl fmt::Display for RestError { } } -impl From for RestError { - fn from(uri_error: hyper::error::UriError) -> RestError { +impl From for RestError { + fn from(uri_error: hyper::Error) -> RestError { RestError::UriError(uri_error.to_string()) } } -impl From for RestError { - fn from(error: hyper::error::Error) -> RestError { +impl From for RestError { + fn from(error: hyper::Error) -> RestError { RestError::RequestError(error.to_string()) } } diff --git a/src/lib.rs b/src/lib.rs index 65ed1a6..3ba0db0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,20 +13,6 @@ //! The public modules are organised following the same tree as the [GDAX documentation](https://docs.gdax.com/). //! //! # Examples - -extern crate chrono; -extern crate futures; -extern crate hyper; -extern crate hyper_tls; -extern crate itertools; -extern crate mockito; -extern crate percent_encoding; -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate tokio_core; - pub mod products; pub mod currencies; pub mod time; diff --git a/src/products/get_24hr_stats.rs b/src/products/get_24hr_stats.rs index a8ef310..acde27a 100644 --- a/src/products/get_24hr_stats.rs +++ b/src/products/get_24hr_stats.rs @@ -1,8 +1,9 @@ use hyper::Method; +use serde_derive::{Serialize, Deserialize}; -use serde_util::deserialize_from_str; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; +use crate::serde_util::deserialize_from_str; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; pub struct Get24hrStats { product_id: String, diff --git a/src/products/get_historic_rates.rs b/src/products/get_historic_rates.rs index 0c17f4c..7dfbf40 100644 --- a/src/products/get_historic_rates.rs +++ b/src/products/get_historic_rates.rs @@ -1,8 +1,10 @@ use chrono::{DateTime, Utc}; use hyper::Method; +use serde_derive::{Serialize, Deserialize}; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; + +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; pub struct GetHistoricRates { product_id: String, diff --git a/src/products/get_product_order_book.rs b/src/products/get_product_order_book.rs index 2c27736..e34451c 100644 --- a/src/products/get_product_order_book.rs +++ b/src/products/get_product_order_book.rs @@ -1,8 +1,9 @@ use hyper::Method; +use serde_derive::{Serialize, Deserialize}; -use serde_util::deserialize_from_str; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; +use crate::serde_util::deserialize_from_str; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; /// This struct represent the endpoint `Get Product Order Book` /// (The level 3 requests are not implemented) diff --git a/src/products/get_product_ticker.rs b/src/products/get_product_ticker.rs index 056fa39..17ca056 100644 --- a/src/products/get_product_ticker.rs +++ b/src/products/get_product_ticker.rs @@ -1,9 +1,12 @@ use hyper::Method; use chrono::{DateTime, Utc}; +use serde_derive::{Serialize, Deserialize}; + +use crate::serde_util::deserialize_from_str; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; + -use serde_util::deserialize_from_str; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; /// This struct represents the `Get Product Ticker` end point. /// diff --git a/src/products/get_products.rs b/src/products/get_products.rs index e475b01..669edf9 100644 --- a/src/products/get_products.rs +++ b/src/products/get_products.rs @@ -1,8 +1,9 @@ use hyper::Method; +use serde_derive::{Serialize, Deserialize}; -use serde_util::deserialize_from_str; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; +use crate::serde_util::deserialize_from_str; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; /// This struct is the request handler #[derive(Default)] diff --git a/src/products/get_trades.rs b/src/products/get_trades.rs index 5822369..8567ba8 100644 --- a/src/products/get_trades.rs +++ b/src/products/get_trades.rs @@ -1,10 +1,12 @@ // TODO : handle pagination use chrono::{DateTime, Utc}; use hyper::Method; +use serde_derive::{Serialize, Deserialize}; -use serde_util::deserialize_from_str; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; + +use crate::serde_util::deserialize_from_str; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; pub struct GetTrades { product_id: String, diff --git a/src/rest_client.rs b/src/rest_client.rs index 99b86d2..300055a 100644 --- a/src/rest_client.rs +++ b/src/rest_client.rs @@ -7,9 +7,10 @@ use hyper::client::HttpConnector; use hyper_tls::HttpsConnector; use tokio_core::reactor::Handle; use futures::{Future, Stream}; +use serde_derive::{Serialize, Deserialize}; -use url::Route; -use error::RestError; +use crate::url::Route; +use crate::error::RestError; const PUBLIC_API: &str = "https://api.gdax.com"; const SANDBOX_API: &str = "https://api-public.sandbox.gdax.com"; @@ -92,6 +93,7 @@ pub trait EndPointRequest { #[cfg(test)] mod tests { use tokio_core::reactor::Core; + use serde_derive::{Serialize, Deserialize}; use mockito::{mock, SERVER_URL}; use hyper::Method; diff --git a/src/time.rs b/src/time.rs index 5fd40ec..7eca566 100644 --- a/src/time.rs +++ b/src/time.rs @@ -3,9 +3,10 @@ use hyper::Method; use chrono::{DateTime, Utc}; +use serde_derive::{Serialize, Deserialize}; -use rest_client::{EndPointRequest, RestRequest}; -use url::Route; +use crate::rest_client::{EndPointRequest, RestRequest}; +use crate::url::Route; #[derive(Default)] pub struct GetTime; diff --git a/src/url.rs b/src/url.rs index aa3e870..13044ef 100644 --- a/src/url.rs +++ b/src/url.rs @@ -1,7 +1,7 @@ use std::fmt; use itertools::join; -use percent_encoding::{percent_encode, DEFAULT_ENCODE_SET}; +use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; #[derive(PartialEq, Debug, Default)] pub struct Route { @@ -53,14 +53,14 @@ impl fmt::Display for Route { impl fmt::Display for AttributeValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // encode the value with percents - let encoded_value = percent_encode(self.value.as_bytes(), DEFAULT_ENCODE_SET).to_string(); + let encoded_value = percent_encode(self.value.as_bytes(), NON_ALPHANUMERIC).to_string(); write!(f, "{}={}", &self.attribute, encoded_value) } } #[cfg(test)] mod tests { - use url::Route; + use crate::url::Route; #[test] fn test_simple_route_string() { From 4c9c48367a9e7a41cd02c670bbd2b1a9d6b34f95 Mon Sep 17 00:00:00 2001 From: Marechaux Tristan Date: Wed, 8 Jun 2022 10:33:43 +0000 Subject: [PATCH 2/3] wip on migration --- Cargo.toml | 3 +- examples/get_24hr_stats.rs | 9 ++- examples/get_currencies.rs | 8 +-- examples/get_historic_rates.rs | 9 +-- examples/get_product.rs | 8 +-- examples/get_product_order_book.rs | 15 ++--- examples/get_product_ticker.rs | 11 ++-- examples/get_time.rs | 14 +++-- examples/get_trades.rs | 10 +-- src/currencies.rs | 4 +- src/error.rs | 9 +-- src/products/get_24hr_stats.rs | 4 +- src/products/get_historic_rates.rs | 4 +- src/products/get_product_order_book.rs | 4 +- src/products/get_product_ticker.rs | 4 +- src/products/get_products.rs | 4 +- src/products/get_trades.rs | 4 +- src/rest_client.rs | 86 ++++++++++++++++---------- src/time.rs | 4 +- 19 files changed, 118 insertions(+), 96 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d68add5..303c31e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ edition = "2021" [dependencies] mockito = "0.31" -hyper = "0.14" +hyper = { version = "0.14", features = ["full"] } +tokio = { version = "1", features = ["full"] } tokio-core = "0.1" hyper-tls = "0.5" futures = "0.3" diff --git a/examples/get_24hr_stats.rs b/examples/get_24hr_stats.rs index c5c9ad7..c6a7ca8 100644 --- a/examples/get_24hr_stats.rs +++ b/examples/get_24hr_stats.rs @@ -6,14 +6,13 @@ use tokio_core::reactor::Core; use gdax_rs::RESTClient; use gdax_rs::products::Get24hrStats; -fn main() { +#[tokio::main] +async fn main() { let mut core = Core::new().unwrap(); let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let product_ticker = core.run( - test_client.send_request(&Get24hrStats::new(String::from("BTC-USD"))), - ).unwrap(); + let mut test_client = RESTClient::default(); + let product_ticker = test_client.send_request(&Get24hrStats::new(String::from("BTC-USD"))).await.unwrap(); println!("{:?}", product_ticker); } diff --git a/examples/get_currencies.rs b/examples/get_currencies.rs index 76d3d94..32457da 100644 --- a/examples/get_currencies.rs +++ b/examples/get_currencies.rs @@ -6,13 +6,13 @@ use tokio_core::reactor::Core; use gdax_rs::RESTClient; use gdax_rs::currencies::GetCurrencies; -fn main() { +#[tokio::main] +async fn main() { let mut core = Core::new().unwrap(); let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let products = core.run(test_client.send_request(&GetCurrencies::new())) - .unwrap(); + let mut test_client = RESTClient::default(); + let products = test_client.send_request(&GetCurrencies::new()).await.unwrap(); println!("{:?}", products); } diff --git a/examples/get_historic_rates.rs b/examples/get_historic_rates.rs index b766c3c..b997513 100644 --- a/examples/get_historic_rates.rs +++ b/examples/get_historic_rates.rs @@ -8,17 +8,18 @@ use chrono::{TimeZone, Utc}; use gdax_rs::RESTClient; use gdax_rs::products::GetHistoricRates; -fn main() { +#[tokio::main] +async fn main() { let mut core = Core::new().unwrap(); let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let candles = core.run(test_client.send_request(&GetHistoricRates::new( + let mut test_client = RESTClient::default(); + let candles = test_client.send_request(&GetHistoricRates::new( String::from("BTC-USD"), Utc.ymd(2017, 12, 21).and_hms_micro(10, 10, 10, 10), Utc.ymd(2017, 12, 21).and_hms_micro(10, 15, 15, 10), 60, - ))).unwrap(); + )).await.unwrap(); println!("{:?}", candles); } diff --git a/examples/get_product.rs b/examples/get_product.rs index 4094dc2..a007a51 100644 --- a/examples/get_product.rs +++ b/examples/get_product.rs @@ -6,13 +6,13 @@ use tokio_core::reactor::Core; use gdax_rs::RESTClient; use gdax_rs::products::GetProducts; -fn main() { +#[tokio::main] +async fn main() { let mut core = Core::new().unwrap(); let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let products = core.run(test_client.send_request(&GetProducts::new())) - .unwrap(); + let mut test_client = RESTClient::default(); + let products = test_client.send_request(&GetProducts::new()).await.unwrap(); println!("{:?}", products); } diff --git a/examples/get_product_order_book.rs b/examples/get_product_order_book.rs index 979ad66..be81f6f 100644 --- a/examples/get_product_order_book.rs +++ b/examples/get_product_order_book.rs @@ -1,20 +1,21 @@ extern crate gdax_rs; extern crate tokio_core; -use tokio_core::reactor::Core; +// use tokio_core::reactor::Core; use gdax_rs::RESTClient; use gdax_rs::products::{GetProductOrderBook, Level}; -fn main() { - let mut core = Core::new().unwrap(); - let handle = core.handle(); +#[tokio::main] +async fn main() { + // let mut core = Core::new().unwrap(); + // let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let order_book = core.run(test_client.send_request(&GetProductOrderBook::new( + let mut test_client = RESTClient::default(); + let order_book = test_client.send_request(&GetProductOrderBook::new( String::from("BTC-USD"), Level::Level2, - ))).unwrap(); + )).await.unwrap(); println!("{:?}", order_book); } diff --git a/examples/get_product_ticker.rs b/examples/get_product_ticker.rs index 79dc8f6..5027086 100644 --- a/examples/get_product_ticker.rs +++ b/examples/get_product_ticker.rs @@ -6,14 +6,15 @@ use tokio_core::reactor::Core; use gdax_rs::RESTClient; use gdax_rs::products::GetProductTicker; -fn main() { +#[tokio::main] +async fn main() { let mut core = Core::new().unwrap(); let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let product_ticker = core.run( - test_client.send_request(&GetProductTicker::new(String::from("BTC-USD"))), - ).unwrap(); + let mut test_client = RESTClient::default(); + let product_ticker = + test_client.send_request(&GetProductTicker::new(String::from("BTC-USD"))) + .await.unwrap(); println!("{:?}", product_ticker); } diff --git a/examples/get_time.rs b/examples/get_time.rs index 3718da5..0ddce12 100644 --- a/examples/get_time.rs +++ b/examples/get_time.rs @@ -1,17 +1,19 @@ extern crate gdax_rs; extern crate tokio_core; -use tokio_core::reactor::Core; +// use tokio_core::reactor::Core; use gdax_rs::RESTClient; use gdax_rs::time::GetTime; -fn main() { - let mut core = Core::new().unwrap(); - let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let products = core.run(test_client.send_request(&GetTime::new())).unwrap(); +#[tokio::main] +async fn main() { + // let mut core = Core::new().unwrap(); + // let handle = core.handle(); + + let mut test_client = RESTClient::default(); + let products = test_client.send_request(&GetTime::new()).await.unwrap(); println!("{:?}", products); } diff --git a/examples/get_trades.rs b/examples/get_trades.rs index 81e1ba0..909915c 100644 --- a/examples/get_trades.rs +++ b/examples/get_trades.rs @@ -2,18 +2,18 @@ extern crate gdax_rs; extern crate tokio_core; use tokio_core::reactor::Core; +use tokio; use gdax_rs::RESTClient; use gdax_rs::products::GetTrades; -fn main() { +#[tokio::main] +async fn main() { let mut core = Core::new().unwrap(); let handle = core.handle(); - let mut test_client = RESTClient::default(&handle); - let product_ticker = core.run( - test_client.send_request(&GetTrades::new(String::from("BTC-USD"))), - ).unwrap(); + let mut test_client = RESTClient::default(); + let product_ticker = test_client.send_request(&GetTrades::new(String::from("BTC-USD"))).await.unwrap(); println!("{:?}", product_ticker); } diff --git a/src/currencies.rs b/src/currencies.rs index 3c8ebd9..bc6ff6e 100644 --- a/src/currencies.rs +++ b/src/currencies.rs @@ -28,7 +28,7 @@ pub struct Currency { impl EndPointRequest> for GetCurrencies { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new().add_segment(&"currencies"), body: String::new(), } @@ -47,7 +47,7 @@ mod tests { let result = GetCurrencies::new().create_request(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new().add_segment(&"currencies"), body: String::new(), }; diff --git a/src/error.rs b/src/error.rs index 2dcbd78..b5d18c7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -52,7 +52,7 @@ impl Error for RestError { } } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { None } } @@ -88,12 +88,6 @@ impl From for RestError { } } -impl From for RestError { - fn from(error: hyper::Error) -> RestError { - RestError::RequestError(error.to_string()) - } -} - impl From for RestError { fn from(utf8_error: FromUtf8Error) -> RestError { RestError::FromUtf8Error(utf8_error) @@ -105,3 +99,4 @@ impl From for RestError { RestError::CoreError(io_error) } } + diff --git a/src/products/get_24hr_stats.rs b/src/products/get_24hr_stats.rs index acde27a..9bb05c5 100644 --- a/src/products/get_24hr_stats.rs +++ b/src/products/get_24hr_stats.rs @@ -28,7 +28,7 @@ pub struct Stats { impl EndPointRequest for Get24hrStats { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&self.product_id) @@ -49,7 +49,7 @@ mod tests { let result = Get24hrStats::new(String::from("BTC-USD")).create_request(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&"BTC-USD") diff --git a/src/products/get_historic_rates.rs b/src/products/get_historic_rates.rs index 7dfbf40..c6f9afb 100644 --- a/src/products/get_historic_rates.rs +++ b/src/products/get_historic_rates.rs @@ -43,7 +43,7 @@ pub struct Candle { impl EndPointRequest> for GetHistoricRates { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&self.product_id) @@ -74,7 +74,7 @@ mod tests { ).create_request(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&"BTC-USD") diff --git a/src/products/get_product_order_book.rs b/src/products/get_product_order_book.rs index e34451c..b9bb8e0 100644 --- a/src/products/get_product_order_book.rs +++ b/src/products/get_product_order_book.rs @@ -45,7 +45,7 @@ pub struct PriceLevel { impl EndPointRequest> for GetProductOrderBook { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&self.product_id) @@ -69,7 +69,7 @@ mod tests { let request_handler = GetProductOrderBook::new(String::from("BTC-USD"), Level::Level2); let result = request_handler.create_request(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&"BTC-USD") diff --git a/src/products/get_product_ticker.rs b/src/products/get_product_ticker.rs index 17ca056..e8bf246 100644 --- a/src/products/get_product_ticker.rs +++ b/src/products/get_product_ticker.rs @@ -40,7 +40,7 @@ pub struct Ticker { impl EndPointRequest for GetProductTicker { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&self.product_id) @@ -62,7 +62,7 @@ mod tests { fn test_create_request() { let result = GetProductTicker::new(String::from("BTC-USD")).create_request(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&"BTC-USD") diff --git a/src/products/get_products.rs b/src/products/get_products.rs index 669edf9..361c68b 100644 --- a/src/products/get_products.rs +++ b/src/products/get_products.rs @@ -33,7 +33,7 @@ pub struct Product { impl EndPointRequest> for GetProducts { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new().add_segment(&"/products"), body: String::new(), } @@ -52,7 +52,7 @@ mod tests { let handler = GetProducts::new(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new().add_segment(&"/products"), body: String::new(), }; diff --git a/src/products/get_trades.rs b/src/products/get_trades.rs index 8567ba8..c5060dd 100644 --- a/src/products/get_trades.rs +++ b/src/products/get_trades.rs @@ -38,7 +38,7 @@ pub struct Trade { impl EndPointRequest> for GetTrades { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&self.product_id) @@ -59,7 +59,7 @@ mod tests { fn test_create_request() { let result = GetTrades::new(String::from("BTC-USD")).create_request(); let expected = RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new() .add_segment(&"products") .add_segment(&"BTC-USD") diff --git a/src/rest_client.rs b/src/rest_client.rs index 300055a..d0f71b4 100644 --- a/src/rest_client.rs +++ b/src/rest_client.rs @@ -2,11 +2,10 @@ use hyper; use serde::de; use serde_json; use hyper::{Body, Client, Method, Request, Uri}; -use hyper::header::{ContentLength, UserAgent}; +use hyper::header::{CONTENT_LENGTH, USER_AGENT, HeaderValue}; use hyper::client::HttpConnector; use hyper_tls::HttpsConnector; -use tokio_core::reactor::Handle; -use futures::{Future, Stream}; +use futures::{Future, Stream, TryFuture, TryFutureExt}; use serde_derive::{Serialize, Deserialize}; use crate::url::Route; @@ -14,7 +13,7 @@ use crate::error::RestError; const PUBLIC_API: &str = "https://api.gdax.com"; const SANDBOX_API: &str = "https://api-public.sandbox.gdax.com"; -const USER_AGENT: &str = concat!("gdax_rs/", env!("CARGO_PKG_VERSION")); +const USER_AGENT_VALUE: &str = concat!("gdax_rs/", env!("CARGO_PKG_VERSION")); pub struct RESTClient { api_url: String, @@ -25,10 +24,13 @@ pub struct RESTClient { impl RESTClient { /// Create a new `RESTClient` object with a specified API URL, for most cases, you should use /// `RESTClient::default` or `RESTClient::staging` to connect to GDAX - pub fn new(api_url: &str, handle: &Handle) -> Result { - let connector = HttpsConnector::new(4, handle) - .map_err(|e| RestError::HttpsConnectorError(e.to_string()))?; - let client = Client::configure().connector(connector).build(handle); + pub fn new(api_url: &str) -> Result { + let https = HttpsConnector::new(); + let client = Client::builder() + .build::<_, hyper::Body>(https); + // let connector = HttpsConnector::new(4, handle) + // .map_err(|e| RestError::HttpsConnectorError(e.to_string()))?; + // let client = Client::configure().connector(connector).build(handle); Ok(RESTClient { api_url: String::from(api_url), client, @@ -36,20 +38,20 @@ impl RESTClient { } /// Returns the default APIConnector (connected to the staging API) - pub fn default(handle: &Handle) -> RESTClient { - RESTClient::new(PUBLIC_API, handle).unwrap() + pub fn default() -> RESTClient { + RESTClient::new(PUBLIC_API).unwrap() } /// Returns the sandbox APIConnector (connected to the sandbox API) - pub fn sandbox(handle: &Handle) -> RESTClient { - RESTClient::new(SANDBOX_API, handle).unwrap() + pub fn sandbox() -> RESTClient { + RESTClient::new(SANDBOX_API).unwrap() } /// This method send a request to GDAX API and return the result as a `Future` - pub fn send_request( + pub async fn send_request( &mut self, - request: &EndPointRequest, - ) -> Box + 'static> { + request: &dyn EndPointRequest, + ) -> Result { let request = request.create_request(); // create the full request uri @@ -59,20 +61,39 @@ impl RESTClient { .unwrap(); // create request - let mut req = Request::new(request.http_method.clone(), uri); - req.headers_mut() - .set(ContentLength(request.body.len() as u64)); - req.set_body(request.body.clone()); + let mut req = Request::builder() + .method(request.http_method.clone()) + .uri(uri) + .header(USER_AGENT, HeaderValue::from_static(USER_AGENT_VALUE)) + // .header(CONTENT_LENGTH, HeaderValue::from_static(&request.body.len().to_string())) + .body(Body::from(request.body.clone())).unwrap(); + // .and_then(|res| res.body().concat2()) + // .and_then(|body| Ok(serde_json::from_slice(&body).unwrap())); + + + // req.headers_mut() + // .insert(CONTENT_LENGTH, HeaderValue::from_static(&request.body.len().to_string())); + // req.set_body(request.body.clone()); // set the user agent (required by the API) - req.headers_mut().set(UserAgent::new(USER_AGENT)); + // req.headers_mut().insert(USER_AGENT, HeaderValue::from_static(USER_AGENT_VALUE)); - let work = self.client - .request(req) - .and_then(|res| res.body().concat2()) - .and_then(|body| Ok(serde_json::from_slice(&body).unwrap())); + let client = Client::new(); - Box::new(work) + + // let work = self.client + let resp = client.request(req).await?; + + let body_bytes = hyper::body::to_bytes(resp.into_body()).await?; + + Ok(serde_json::from_slice(&body_bytes.to_vec()).unwrap()) + // .map_ok(|res| res.body().concat2()) + // .map_ok(hyper::body::to_bytes) + // .map_ok(|body| Ok(serde_json::from_slice(&body.body().to_string()).unwrap())); + + // Box::new(work) + + // resp } } @@ -92,6 +113,7 @@ pub trait EndPointRequest { // TODO: test error handling! #[cfg(test)] mod tests { + use tokio; use tokio_core::reactor::Core; use serde_derive::{Serialize, Deserialize}; @@ -110,25 +132,25 @@ mod tests { impl EndPointRequest for FakeRequestHandler { fn create_request(&self) -> RestRequest { RestRequest { - http_method: Method::Get, + http_method: Method::GET, route: Route::new().add_segment(&"test"), body: String::from(""), } } } - #[test] - fn test_fake_request() { + #[tokio::test] + async fn test_fake_request() { let _m = mock("GET", "/test").with_body("{\"value\": 1}").create(); let mut core = Core::new().unwrap(); - let handle = core.handle(); + // let handle = core.handle(); - let mut test_client = RESTClient::new(SERVER_URL, &handle).unwrap(); + let mut test_client = RESTClient::new(SERVER_URL).unwrap(); let request = FakeRequestHandler {}; - let future = test_client.send_request(&request); + let value = test_client.send_request(&request).await.unwrap(); - let value = core.run(future).unwrap(); + // let value = core.run(future).unwrap(); assert_eq!(value.value, 1); } diff --git a/src/time.rs b/src/time.rs index 7eca566..7b0d108 100644 --- a/src/time.rs +++ b/src/time.rs @@ -26,7 +26,7 @@ pub struct Time { impl EndPointRequest