diff --git a/GDAXClient.Specs/GDAXClient.Specs.csproj b/GDAXClient.Specs/GDAXClient.Specs.csproj
index 61866fad..c127bc0c 100644
--- a/GDAXClient.Specs/GDAXClient.Specs.csproj
+++ b/GDAXClient.Specs/GDAXClient.Specs.csproj
@@ -84,6 +84,10 @@
+
+
+
+
@@ -94,6 +98,7 @@
+
diff --git a/GDAXClient.Specs/JsonFixtures/Deposits/CoinbaseDepositResponseFixture.cs b/GDAXClient.Specs/JsonFixtures/Deposits/CoinbaseDepositResponseFixture.cs
index 537a1127..786a86f7 100644
--- a/GDAXClient.Specs/JsonFixtures/Deposits/CoinbaseDepositResponseFixture.cs
+++ b/GDAXClient.Specs/JsonFixtures/Deposits/CoinbaseDepositResponseFixture.cs
@@ -1,6 +1,6 @@
namespace GDAXClient.Specs.JsonFixtures.Deposits
{
- class CoinbaseDepositResponseFixture
+ public static class CoinbaseDepositResponseFixture
{
public static string Create()
{
diff --git a/GDAXClient.Specs/JsonFixtures/Products/ProductStatsFixture.cs b/GDAXClient.Specs/JsonFixtures/Products/ProductStatsFixture.cs
new file mode 100644
index 00000000..643b8cfd
--- /dev/null
+++ b/GDAXClient.Specs/JsonFixtures/Products/ProductStatsFixture.cs
@@ -0,0 +1,19 @@
+namespace GDAXClient.Specs.JsonFixtures.Products
+{
+ public static class ProductStatsFixture
+ {
+ public static string Create()
+ {
+
+ var json = @"
+{
+ 'open': '34.19000000',
+ 'high': '95.70000000',
+ 'low': '7.06000000',
+ 'volume': '2.41000000'
+}";
+
+ return json;
+ }
+ }
+}
diff --git a/GDAXClient.Specs/JsonFixtures/Products/ProductTickerFixture.cs b/GDAXClient.Specs/JsonFixtures/Products/ProductTickerFixture.cs
new file mode 100644
index 00000000..08eaca8e
--- /dev/null
+++ b/GDAXClient.Specs/JsonFixtures/Products/ProductTickerFixture.cs
@@ -0,0 +1,21 @@
+namespace GDAXClient.Specs.JsonFixtures.Products
+{
+ public static class ProductTickerFixture
+ {
+ public static string Create()
+ {
+ var json = @"
+{
+ 'trade_id': 4729088,
+ 'price': '333.99',
+ 'size': '0.193',
+ 'bid': '333.98',
+ 'ask': '333.99',
+ 'volume': '5957.11914015',
+ 'time': '2016-12-08T24:00:00Z'
+}";
+
+ return json;
+ }
+ }
+}
diff --git a/GDAXClient.Specs/JsonFixtures/Products/ProductsOrderBookResponseFixture.cs b/GDAXClient.Specs/JsonFixtures/Products/ProductsOrderBookResponseFixture.cs
new file mode 100644
index 00000000..55ae3ee1
--- /dev/null
+++ b/GDAXClient.Specs/JsonFixtures/Products/ProductsOrderBookResponseFixture.cs
@@ -0,0 +1,21 @@
+namespace GDAXClient.Specs.JsonFixtures.Products
+{
+ public static class ProductsOrderBookResponseFixture
+ {
+ public static string Create()
+ {
+ var json = @"
+{
+ 'sequence': '3',
+ 'bids': [
+ [200, 100, 3],
+ ],
+ 'ask': [
+ [200, 100, 3],
+ ]
+}";
+
+ return json;
+ }
+ }
+}
diff --git a/GDAXClient.Specs/JsonFixtures/Products/ProductsResponseFixture.cs b/GDAXClient.Specs/JsonFixtures/Products/ProductsResponseFixture.cs
new file mode 100644
index 00000000..48d0f30b
--- /dev/null
+++ b/GDAXClient.Specs/JsonFixtures/Products/ProductsResponseFixture.cs
@@ -0,0 +1,22 @@
+namespace GDAXClient.Specs.JsonFixtures.Products
+{
+ public static class ProductsResponseFixture
+ {
+ public static string Create()
+ {
+ var json = @"
+[
+ {
+ 'id': 'BTC-USD',
+ 'base_currency': 'BTC',
+ 'quote_currency': 'USD',
+ 'base_min_size': '0.01',
+ 'base_max_size': '10000.00',
+ 'quote_increment': '0.01'
+ }
+]";
+
+ return json;
+ }
+ }
+}
diff --git a/GDAXClient.Specs/Services/Products/ProductsServiceSpecs.cs b/GDAXClient.Specs/Services/Products/ProductsServiceSpecs.cs
new file mode 100644
index 00000000..3a9a9c0e
--- /dev/null
+++ b/GDAXClient.Specs/Services/Products/ProductsServiceSpecs.cs
@@ -0,0 +1,150 @@
+using GDAXClient.Authentication;
+using GDAXClient.HttpClient;
+using GDAXClient.Products;
+using GDAXClient.Services.HttpRequest;
+using GDAXClient.Services.Orders;
+using GDAXClient.Services.Products;
+using GDAXClient.Services.Products.Models;
+using GDAXClient.Services.Products.Models.Responses;
+using GDAXClient.Specs.JsonFixtures.Products;
+using Machine.Fakes;
+using Machine.Specifications;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace GDAXClient.Specs.Services.Payments
+{
+ [Subject("ProductsService")]
+ public class ProductsServiceSpecs : WithSubject
+ {
+ static Authenticator authenticator;
+
+ static IEnumerable products_result;
+
+ static ProductsOrderBookResponse product_order_books_response;
+
+ static ProductTicker product_ticker_result;
+
+ static ProductStats product_stats_result;
+
+ Establish context = () =>
+ authenticator = new Authenticator("apiKey", new string('2', 100), "passPhrase");
+
+ class when_getting_all_products
+ {
+ Establish context = () =>
+ {
+ The().WhenToldTo(p => p.CreateHttpRequestMessage(Param.IsAny(), Param.IsAny(), Param.IsAny(), Param.IsAny()))
+ .Return(new HttpRequestMessage());
+
+ The().WhenToldTo(p => p.SendASync(Param.IsAny()))
+ .Return(Task.FromResult(new HttpResponseMessage()));
+
+ The().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny()))
+ .Return(Task.FromResult(ProductsResponseFixture.Create()));
+ };
+
+ Because of = () =>
+ products_result = Subject.GetAllProductsAsync().Result;
+
+ It should_have_correct_products_response_count = () =>
+ products_result.Count().ShouldEqual(1);
+
+ It should_have_correct_products = () =>
+ {
+ products_result.First().Id.ShouldEqual("BTC-USD");
+ products_result.First().Base_currency.ShouldEqual("BTC");
+ products_result.First().Quote_currency.ShouldEqual("USD");
+ products_result.First().Base_min_size.ShouldEqual("0.01");
+ products_result.First().Base_max_size.ShouldEqual("10000.00");
+ products_result.First().Quote_increment.ShouldEqual("0.01");
+ };
+ }
+
+ class when_getting_a_product_order_book
+ {
+ Establish context = () =>
+ {
+ The().WhenToldTo(p => p.CreateHttpRequestMessage(Param.IsAny(), Param.IsAny(), Param.IsAny(), Param.IsAny()))
+ .Return(new HttpRequestMessage());
+
+ The().WhenToldTo(p => p.SendASync(Param.IsAny()))
+ .Return(Task.FromResult(new HttpResponseMessage()));
+
+ The().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny()))
+ .Return(Task.FromResult(ProductsOrderBookResponseFixture.Create()));
+ };
+
+ Because of = () =>
+ product_order_books_response = Subject.GetProductOrderBookAsync(ProductType.BtcUsd).Result;
+
+ It should_have_correct_product_order_book_response = () =>
+ {
+ product_order_books_response.Sequence.ShouldEqual(3M);
+ product_order_books_response.Bids.SelectMany(p => p).ShouldContain(200);
+ product_order_books_response.Bids.SelectMany(p => p).ShouldContain(100);
+ product_order_books_response.Bids.SelectMany(p => p).ShouldContain(3);
+ product_order_books_response.Ask.SelectMany(p => p).ShouldContain(200);
+ product_order_books_response.Ask.SelectMany(p => p).ShouldContain(100);
+ product_order_books_response.Ask.SelectMany(p => p).ShouldContain(3);
+ };
+ }
+
+ class when_getting_a_product_ticker
+ {
+ Establish context = () =>
+ {
+ The().WhenToldTo(p => p.CreateHttpRequestMessage(Param.IsAny(), Param.IsAny(), Param.IsAny(), Param.IsAny()))
+ .Return(new HttpRequestMessage());
+
+ The().WhenToldTo(p => p.SendASync(Param.IsAny()))
+ .Return(Task.FromResult(new HttpResponseMessage()));
+
+ The().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny()))
+ .Return(Task.FromResult(ProductTickerFixture.Create()));
+ };
+
+ Because of = () =>
+ product_ticker_result = Subject.GetProductTickerAsync(ProductType.BtcUsd).Result;
+
+ It should_have_correct_product_ticker = () =>
+ {
+ product_ticker_result.Trade_id.ShouldEqual(4729088);
+ product_ticker_result.Price.ShouldEqual(333.99M);
+ product_ticker_result.Size.ShouldEqual(0.193M);
+ product_ticker_result.Bid.ShouldEqual(333.98M);
+ product_ticker_result.Ask.ShouldEqual(333.99M);
+ product_ticker_result.Volume.ShouldEqual(5957.11914015M);
+ product_ticker_result.Time.ShouldEqual(new System.DateTime(2016, 12, 9));
+ };
+ }
+
+ class when_getting_product_stats
+ {
+ Establish context = () =>
+ {
+ The().WhenToldTo(p => p.CreateHttpRequestMessage(Param.IsAny(), Param.IsAny(), Param.IsAny(), Param.IsAny()))
+ .Return(new HttpRequestMessage());
+
+ The().WhenToldTo(p => p.SendASync(Param.IsAny()))
+ .Return(Task.FromResult(new HttpResponseMessage()));
+
+ The().WhenToldTo(p => p.ReadAsStringAsync(Param.IsAny()))
+ .Return(Task.FromResult(ProductStatsFixture.Create()));
+ };
+
+ Because of = () =>
+ product_stats_result = Subject.GetProductStatsAsync(ProductType.BtcUsd).Result;
+
+ It should_have_correct_product_stats = () =>
+ {
+ product_stats_result.Open.ShouldEqual(34.19000000M);
+ product_stats_result.High.ShouldEqual(95.70000000M);
+ product_stats_result.Low.ShouldEqual(7.06000000M);
+ product_stats_result.Volume.ShouldEqual(2.41000000M);
+ };
+ }
+ }
+}
diff --git a/GDAXClient/GDAXClient.cs b/GDAXClient/GDAXClient.cs
index 3cc4e03d..285717c0 100644
--- a/GDAXClient/GDAXClient.cs
+++ b/GDAXClient/GDAXClient.cs
@@ -1,4 +1,5 @@
using GDAXClient.Authentication;
+using GDAXClient.Products;
using GDAXClient.Services.Accounts;
using GDAXClient.Services.CoinbaseAccounts;
using GDAXClient.Services.Deposits;
@@ -27,6 +28,7 @@ public GDAXClient(Authenticator authenticator, bool sandBox = false)
PaymentsService = new PaymentsService(httpClient, httpRequestMessageService, authenticator);
WithdrawalsService = new WithdrawalsService(httpClient, httpRequestMessageService, authenticator);
DepositsService = new DepositsService(httpClient, httpRequestMessageService, authenticator);
+ ProductsService = new ProductsService(httpClient, httpRequestMessageService, authenticator);
}
public AccountsService AccountsService { get; }
@@ -40,5 +42,7 @@ public GDAXClient(Authenticator authenticator, bool sandBox = false)
public WithdrawalsService WithdrawalsService { get; }
public DepositsService DepositsService { get; }
+
+ public ProductsService ProductsService { get; }
}
}
diff --git a/GDAXClient/GDAXClient.csproj b/GDAXClient/GDAXClient.csproj
index e6002553..7facd1c7 100644
--- a/GDAXClient/GDAXClient.csproj
+++ b/GDAXClient/GDAXClient.csproj
@@ -55,34 +55,39 @@
+
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -95,5 +100,6 @@
+
\ No newline at end of file
diff --git a/GDAXClient/Services/Accounts/Account.cs b/GDAXClient/Services/Accounts/Models/Account.cs
similarity index 100%
rename from GDAXClient/Services/Accounts/Account.cs
rename to GDAXClient/Services/Accounts/Models/Account.cs
diff --git a/GDAXClient/Services/CoinbaseAccounts/CoinbaseAccount.cs b/GDAXClient/Services/CoinbaseAccounts/Models/CoinbaseAccount.cs
similarity index 100%
rename from GDAXClient/Services/CoinbaseAccounts/CoinbaseAccount.cs
rename to GDAXClient/Services/CoinbaseAccounts/Models/CoinbaseAccount.cs
diff --git a/GDAXClient/Services/Deposits/Deposit.cs b/GDAXClient/Services/Deposits/Models/Deposit.cs
similarity index 100%
rename from GDAXClient/Services/Deposits/Deposit.cs
rename to GDAXClient/Services/Deposits/Models/Deposit.cs
diff --git a/GDAXClient/Services/Deposits/DepositResponse.cs b/GDAXClient/Services/Deposits/Models/Responses/DepositResponse.cs
similarity index 100%
rename from GDAXClient/Services/Deposits/DepositResponse.cs
rename to GDAXClient/Services/Deposits/Models/Responses/DepositResponse.cs
diff --git a/GDAXClient/Services/Orders/Order.cs b/GDAXClient/Services/Orders/Models/Order.cs
similarity index 100%
rename from GDAXClient/Services/Orders/Order.cs
rename to GDAXClient/Services/Orders/Models/Order.cs
diff --git a/GDAXClient/Services/Orders/OrderSide.cs b/GDAXClient/Services/Orders/Models/OrderSide.cs
similarity index 100%
rename from GDAXClient/Services/Orders/OrderSide.cs
rename to GDAXClient/Services/Orders/Models/OrderSide.cs
diff --git a/GDAXClient/Services/Orders/CancelOrderResponse.cs b/GDAXClient/Services/Orders/Models/Responses/CancelOrderResponse.cs
similarity index 100%
rename from GDAXClient/Services/Orders/CancelOrderResponse.cs
rename to GDAXClient/Services/Orders/Models/Responses/CancelOrderResponse.cs
diff --git a/GDAXClient/Services/Orders/OrderResponse.cs b/GDAXClient/Services/Orders/Models/Responses/OrderResponse.cs
similarity index 100%
rename from GDAXClient/Services/Orders/OrderResponse.cs
rename to GDAXClient/Services/Orders/Models/Responses/OrderResponse.cs
diff --git a/GDAXClient/Services/Payments/PaymentMethod.cs b/GDAXClient/Services/Payments/Models/PaymentMethod.cs
similarity index 100%
rename from GDAXClient/Services/Payments/PaymentMethod.cs
rename to GDAXClient/Services/Payments/Models/PaymentMethod.cs
diff --git a/GDAXClient/Services/Products/Models/Product.cs b/GDAXClient/Services/Products/Models/Product.cs
new file mode 100644
index 00000000..1bc07607
--- /dev/null
+++ b/GDAXClient/Services/Products/Models/Product.cs
@@ -0,0 +1,17 @@
+namespace GDAXClient.Services.Products
+{
+ public class Product
+ {
+ public string Id { get; set; }
+
+ public string Base_currency { get; set; }
+
+ public string Quote_currency { get; set; }
+
+ public string Base_min_size { get; set; }
+
+ public string Base_max_size { get; set; }
+
+ public string Quote_increment { get; set; }
+ }
+}
diff --git a/GDAXClient/Services/Products/Models/ProductStats.cs b/GDAXClient/Services/Products/Models/ProductStats.cs
new file mode 100644
index 00000000..777357b9
--- /dev/null
+++ b/GDAXClient/Services/Products/Models/ProductStats.cs
@@ -0,0 +1,13 @@
+namespace GDAXClient.Services.Products.Models
+{
+ public class ProductStats
+ {
+ public decimal Open { get; set; }
+
+ public decimal High { get; set; }
+
+ public decimal Low { get; set; }
+
+ public decimal Volume { get; set; }
+ }
+}
diff --git a/GDAXClient/Services/Products/Models/ProductTicker.cs b/GDAXClient/Services/Products/Models/ProductTicker.cs
new file mode 100644
index 00000000..56d20c3d
--- /dev/null
+++ b/GDAXClient/Services/Products/Models/ProductTicker.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace GDAXClient.Services.Products.Models
+{
+ public class ProductTicker
+ {
+ public int Trade_id { get; set; }
+
+ public decimal Price { get; set; }
+
+ public decimal Size { get; set; }
+
+ public decimal Bid { get; set; }
+
+ public decimal Ask { get; set; }
+
+ public decimal Volume { get; set; }
+
+ public DateTime Time { get; set; }
+ }
+}
diff --git a/GDAXClient/Services/Products/Models/Responses/ProductsOrderBookResponse.cs b/GDAXClient/Services/Products/Models/Responses/ProductsOrderBookResponse.cs
new file mode 100644
index 00000000..d2e67633
--- /dev/null
+++ b/GDAXClient/Services/Products/Models/Responses/ProductsOrderBookResponse.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace GDAXClient.Services.Products.Models.Responses
+{
+ public class ProductsOrderBookResponse
+ {
+ public decimal Sequence { get; set; }
+
+ public IEnumerable> Bids { get; set; }
+
+ public IEnumerable> Ask { get; set; }
+ }
+}
diff --git a/GDAXClient/Services/Products/ProductsService.cs b/GDAXClient/Services/Products/ProductsService.cs
new file mode 100644
index 00000000..800bb47e
--- /dev/null
+++ b/GDAXClient/Services/Products/ProductsService.cs
@@ -0,0 +1,68 @@
+using GDAXClient.HttpClient;
+using GDAXClient.Services;
+using GDAXClient.Services.Accounts;
+using GDAXClient.Services.HttpRequest;
+using GDAXClient.Services.Orders;
+using GDAXClient.Services.Products;
+using GDAXClient.Services.Products.Models;
+using GDAXClient.Services.Products.Models.Responses;
+using GDAXClient.Utilities.Extensions;
+using Newtonsoft.Json;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace GDAXClient.Products
+{
+ public class ProductsService : AbstractService
+ {
+ private readonly IHttpRequestMessageService httpRequestMessageService;
+
+ private readonly IHttpClient httpClient;
+
+ private readonly IAuthenticator authenticator;
+
+ public ProductsService(
+ IHttpClient httpClient,
+ IHttpRequestMessageService httpRequestMessageService,
+ IAuthenticator authenticator)
+ : base(httpClient, httpRequestMessageService, authenticator)
+ {
+ this.httpRequestMessageService = httpRequestMessageService;
+ this.httpClient = httpClient;
+ this.authenticator = authenticator;
+ }
+
+ public async Task> GetAllProductsAsync()
+ {
+ var contentBody = await SendHttpRequestMessage(HttpMethod.Get, authenticator, "/products");
+ var productsResponse = JsonConvert.DeserializeObject>(contentBody);
+
+ return productsResponse;
+ }
+
+ public async Task GetProductOrderBookAsync(ProductType productPair)
+ {
+ var contentBody = await SendHttpRequestMessage(HttpMethod.Get, authenticator, $"/products/{productPair.ToDasherizedUpper()}/book");
+ var productOrderBookResponse = JsonConvert.DeserializeObject(contentBody);
+
+ return productOrderBookResponse;
+ }
+
+ public async Task GetProductTickerAsync(ProductType productPair)
+ {
+ var contentBody = await SendHttpRequestMessage(HttpMethod.Get, authenticator, $"/products/{productPair.ToDasherizedUpper()}/ticker");
+ var productTickerResponse = JsonConvert.DeserializeObject(contentBody);
+
+ return productTickerResponse;
+ }
+
+ public async Task GetProductStatsAsync(ProductType productPair)
+ {
+ var contentBody = await SendHttpRequestMessage(HttpMethod.Get, authenticator, $"/products/{productPair.ToDasherizedUpper()}/stats");
+ var productStatsResponse = JsonConvert.DeserializeObject(contentBody);
+
+ return productStatsResponse;
+ }
+ }
+}
diff --git a/GDAXClient/Services/Withdrawals/Coinbase.cs b/GDAXClient/Services/Withdrawals/Models/Coinbase.cs
similarity index 100%
rename from GDAXClient/Services/Withdrawals/Coinbase.cs
rename to GDAXClient/Services/Withdrawals/Models/Coinbase.cs
diff --git a/GDAXClient/Services/Withdrawals/Crypto.cs b/GDAXClient/Services/Withdrawals/Models/Crypto.cs
similarity index 100%
rename from GDAXClient/Services/Withdrawals/Crypto.cs
rename to GDAXClient/Services/Withdrawals/Models/Crypto.cs
diff --git a/GDAXClient/Services/Withdrawals/CoinbaseResponse.cs b/GDAXClient/Services/Withdrawals/Models/Responses/CoinbaseResponse.cs
similarity index 100%
rename from GDAXClient/Services/Withdrawals/CoinbaseResponse.cs
rename to GDAXClient/Services/Withdrawals/Models/Responses/CoinbaseResponse.cs
diff --git a/GDAXClient/Services/Withdrawals/CryptoResponse.cs b/GDAXClient/Services/Withdrawals/Models/Responses/CryptoResponse.cs
similarity index 100%
rename from GDAXClient/Services/Withdrawals/CryptoResponse.cs
rename to GDAXClient/Services/Withdrawals/Models/Responses/CryptoResponse.cs
diff --git a/GDAXClient/Services/Withdrawals/WithdrawalResponse.cs b/GDAXClient/Services/Withdrawals/Models/Responses/WithdrawalResponse.cs
similarity index 100%
rename from GDAXClient/Services/Withdrawals/WithdrawalResponse.cs
rename to GDAXClient/Services/Withdrawals/Models/Responses/WithdrawalResponse.cs
diff --git a/GDAXClient/Services/Withdrawals/Withdrawal.cs b/GDAXClient/Services/Withdrawals/Models/Withdrawal.cs
similarity index 100%
rename from GDAXClient/Services/Withdrawals/Withdrawal.cs
rename to GDAXClient/Services/Withdrawals/Models/Withdrawal.cs
diff --git a/GDAXClient/Services/Currency.cs b/GDAXClient/Shared/Currency.cs
similarity index 100%
rename from GDAXClient/Services/Currency.cs
rename to GDAXClient/Shared/Currency.cs
diff --git a/GDAXClient/Services/Orders/ProductType.cs b/GDAXClient/Shared/ProductType.cs
similarity index 51%
rename from GDAXClient/Services/Orders/ProductType.cs
rename to GDAXClient/Shared/ProductType.cs
index 54c1d735..a39f307e 100644
--- a/GDAXClient/Services/Orders/ProductType.cs
+++ b/GDAXClient/Shared/ProductType.cs
@@ -3,7 +3,13 @@
public enum ProductType
{
BtcUsd,
+ BtcEur,
+ BtcGbp,
EthUsd,
- LtcUsd
+ EthEur,
+ EthBtc,
+ LtcUsd,
+ LtcEur,
+ LtcBtc
}
}
diff --git a/README.md b/README.md
index e22a811c..9d30561a 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,12 @@ var allAccounts = await gdaxClient.AccountsService.GetAllAccountsAsync();
- DepositFundsAsync(paymentMethodId, amount, currency) - deposits funds from a payment method
- DepositCoinbaseFundsAsync(coinbaseAccountId, amount, currency) - deposits funds from a coinbase account
+###### Products ######
+- GetAllProductsAsync() - get a list of available currency pairs for trading
+- GetProductOrderBookAsync(productType) - get a list of open orders for a product
+- GetProductTickerAsync(productType) - get information about the last trade (tick), best bid/ask and 24h volume
+- GetProductStatsAsync(productType) - get 24 hour stats for a product
+
Sandbox Support
Generate your key at https://public.sandbox.gdax.com/settings/api