diff --git a/HISTORY.md b/HISTORY.md
index 2fe856c..031bb62 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,3 +1,7 @@
+## v5.0.4
+* Ensures all requests have a `User-Agent` string, including `Data` requests.
+* Added missing `CancellationToken` to `GetCurrenciesAsync()`
+
## v5.0.3
* PR #47: Extra DI interfaces for DI support. Notification event and transaction status constants. Changed `Transaction.Description` return from object to string. Thanks granthoff1107!
diff --git a/Source/Coinbase.Tests/ExtensionsForTesting.cs b/Source/Coinbase.Tests/ExtensionsForTesting.cs
index 5518034..a6238f6 100644
--- a/Source/Coinbase.Tests/ExtensionsForTesting.cs
+++ b/Source/Coinbase.Tests/ExtensionsForTesting.cs
@@ -3,6 +3,7 @@
using FluentAssertions;
using Flurl.Http.Testing;
using Newtonsoft.Json;
+using Z.ExtensionMethods;
namespace Coinbase.Tests
{
@@ -29,5 +30,10 @@ public static HttpCallAssertion ShouldHaveRequestBody(this HttpTest test, string
test.CallLog.First().RequestBody.Should().Be(json);
return new HttpCallAssertion(test.CallLog);
}
+
+ public static bool IsAppVeyor(this OperatingSystem os)
+ {
+ return Environment.GetEnvironmentVariable("APPVEYOR").IsNotNullOrWhiteSpace();
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Source/Coinbase.Tests/Integration/DataTests.cs b/Source/Coinbase.Tests/Integration/DataTests.cs
index dd88484..9d18c60 100644
--- a/Source/Coinbase.Tests/Integration/DataTests.cs
+++ b/Source/Coinbase.Tests/Integration/DataTests.cs
@@ -4,8 +4,10 @@
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
+using Flurl.Http;
using Flurl.Http.Configuration;
using NUnit.Framework;
+using Z.ExtensionMethods;
namespace Coinbase.Tests.Integration
{
@@ -13,6 +15,20 @@ public class DataTests
{
private CoinbaseClient client;
+ [OneTimeSetUp]
+ public void BeforeAllTests()
+ {
+ if( !Environment.OSVersion.IsAppVeyor() )
+ {
+ var webProxy = new WebProxy("http://localhost.:8888", BypassOnLocal: false);
+
+ FlurlHttp.Configure(settings =>
+ {
+ settings.HttpClientFactory = new ProxyFactory(webProxy);
+ });
+ }
+ }
+
[SetUp]
public void BeforeEachTest()
{
diff --git a/Source/Coinbase/CoinbaseClient.Data.cs b/Source/Coinbase/CoinbaseClient.Data.cs
index d86e65d..de3a7fc 100644
--- a/Source/Coinbase/CoinbaseClient.Data.cs
+++ b/Source/Coinbase/CoinbaseClient.Data.cs
@@ -40,7 +40,7 @@ public interface IDataEndpoint
///
/// List known currencies. Currency codes will conform to the ISO 4217 standard where possible. Currencies which have or had no representation in ISO 4217 may use a custom code (e.g. BTC).
///
- Task> GetCurrenciesAsync();
+ Task> GetCurrenciesAsync(CancellationToken cancellationToken = default);
///
/// Get the API server time.
@@ -60,6 +60,7 @@ public partial class CoinbaseClient : IDataEndpoint
Task> IDataEndpoint.GetBuyPriceAsync(string currencyPair, CancellationToken cancellationToken)
{
return this.PricesEndpoint
+ .WithClient(this)
.AppendPathSegments(currencyPair, "buy")
.GetJsonAsync>(cancellationToken);
}
@@ -72,6 +73,7 @@ Task> IDataEndpoint.GetBuyPriceAsync(string currencyPair, Cancel
Task> IDataEndpoint.GetSellPriceAsync(string currencyPair, CancellationToken cancellationToken)
{
return this.PricesEndpoint
+ .WithClient(this)
.AppendPathSegments(currencyPair, "sell")
.GetJsonAsync>(cancellationToken);
}
@@ -85,6 +87,7 @@ Task> IDataEndpoint.GetSellPriceAsync(string currencyPair, Cance
Task> IDataEndpoint.GetSpotPriceAsync(string currencyPair, DateTime? date, CancellationToken cancellationToken)
{
var req = this.PricesEndpoint
+ .WithClient(this)
.AppendPathSegments(currencyPair, "spot");
if (!(date is null))
@@ -101,7 +104,8 @@ Task> IDataEndpoint.GetSpotPriceAsync(string currencyPair, DateT
/// Base currency (default: USD)
Task> IDataEndpoint.GetExchangeRatesAsync(string currency, CancellationToken cancellationToken)
{
- var req = this.ExchangeRatesEndpoint;
+ var req = this.ExchangeRatesEndpoint
+ .WithClient(this);
if (!(currency is null))
{
@@ -114,9 +118,11 @@ Task> IDataEndpoint.GetExchangeRatesAsync(string currenc
///
/// List known currencies. Currency codes will conform to the ISO 4217 standard where possible. Currencies which have or had no representation in ISO 4217 may use a custom code (e.g. BTC).
///
- Task> IDataEndpoint.GetCurrenciesAsync()
+ Task> IDataEndpoint.GetCurrenciesAsync(CancellationToken cancellationToken)
{
- return this.CurrenciesEndpoint.GetJsonAsync>();
+ return this.CurrenciesEndpoint
+ .WithClient(this)
+ .GetJsonAsync>(cancellationToken);
}
@@ -125,7 +131,16 @@ Task> IDataEndpoint.GetCurrenciesAsync()
///
Task> IDataEndpoint.GetCurrentTimeAsync(CancellationToken cancellationToken)
{
- return this.TimeEndpoint.GetJsonAsync>(cancellationToken);
+ // Manually make this request outside the scope of .WithClient(this)
+ // because when UseTimeApi =true and when the user makes the first request,
+ // we need to know the server time but if we use .WithClient(this),
+ // we'll get stuck in a recursive situation with no base case
+ // to resolve the actual server time. So, we have to make this
+ // request out of scope of this configured client.
+ return this.TimeEndpoint
+ .WithHeader(HeaderNames.Version, ApiVersionDate)
+ .WithHeader("User-Agent", UserAgent)
+ .GetJsonAsync>(cancellationToken);
}
}