make exchange fee rate providers support cancellation token
MODIFY
WalletWasabi.Backend/Controllers/BatchController.cs
WalletWasabi.Backend/Controllers/BatchController.cs
@@ -96,7 +96,7 @@ public class BatchController : ControllerBase
}
}
- response.ExchangeRates = await OffchainController.GetExchangeRatesCollectionAsync();
+ response.ExchangeRates = await OffchainController.GetExchangeRatesCollectionAsync(cancellationToken);
response.UnconfirmedCoinJoins = ChaumianCoinJoinController.GetUnconfirmedCoinJoinCollection();

MODIFY
WalletWasabi.Backend/Controllers/LegacyController.cs
WalletWasabi.Backend/Controllers/LegacyController.cs
@@ -26,6 +26,6 @@ public class LegacyController : ControllerBase
=> await BlockchainController.GetAllFeesAsync(estimateSmartFeeMode, cancellationToken);
[HttpGet("api/v3/btc/Offchain/exchange-rates")]
- public async Task<IActionResult> GetExchangeRatesV3Async()
- => await OffchainController.GetExchangeRatesAsync();
+ public async Task<IActionResult> GetExchangeRatesV3Async(CancellationToken cancellationToken)
+ => await OffchainController.GetExchangeRatesAsync(cancellationToken);
}

MODIFY
WalletWasabi.Backend/Controllers/OffchainController.cs
WalletWasabi.Backend/Controllers/OffchainController.cs
@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Helpers;
@@ -34,9 +35,9 @@ public class OffchainController : ControllerBase
[HttpGet("exchange-rates")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
- public async Task<IActionResult> GetExchangeRatesAsync()
+ public async Task<IActionResult> GetExchangeRatesAsync(CancellationToken cancellationToken)
{
- IEnumerable<ExchangeRate> exchangeRates = await GetExchangeRatesCollectionAsync();
+ IEnumerable<ExchangeRate> exchangeRates = await GetExchangeRatesCollectionAsync(cancellationToken);
if (!exchangeRates.Any())
{
@@ -46,13 +47,13 @@ public class OffchainController : ControllerBase
return Ok(exchangeRates);
}
- internal async Task<IEnumerable<ExchangeRate>> GetExchangeRatesCollectionAsync()
+ internal async Task<IEnumerable<ExchangeRate>> GetExchangeRatesCollectionAsync(CancellationToken cancellationToken)
{
var cacheKey = nameof(GetExchangeRatesCollectionAsync);
if (!Cache.TryGetValue(cacheKey, out IEnumerable<ExchangeRate> exchangeRates))
{
- exchangeRates = await ExchangeRateProvider.GetExchangeRateAsync();
+ exchangeRates = await ExchangeRateProvider.GetExchangeRateAsync(cancellationToken);
if (exchangeRates.Any())
{

MODIFY
WalletWasabi.Tests/IntegrationTests/ExternalApiTests.cs
WalletWasabi.Tests/IntegrationTests/ExternalApiTests.cs
@@ -9,6 +9,7 @@ using WalletWasabi.WebClients.Gemini;
using WalletWasabi.WebClients.ItBit;
using Xunit;
using WalletWasabi.Interfaces;
+using System.Threading;
namespace WalletWasabi.Tests.IntegrationTests;
@@ -40,7 +41,7 @@ public class ExternalApiTests
private async Task AssertProviderAsync(IExchangeRateProvider provider)
{
- IEnumerable<ExchangeRate> rates = await provider.GetExchangeRateAsync();
+ IEnumerable<ExchangeRate> rates = await provider.GetExchangeRateAsync(CancellationToken.None);
var usdRate = Assert.Single(rates, x => x.Ticker == "USD");
Assert.NotEqual(0.0m, usdRate.Rate);

MODIFY
WalletWasabi/Interfaces/IExchangeRateProvider.cs
WalletWasabi/Interfaces/IExchangeRateProvider.cs
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
@@ -6,5 +7,5 @@ namespace WalletWasabi.Interfaces;
public interface IExchangeRateProvider
{
- Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync();
+ Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken);
}

MODIFY
WalletWasabi/WebClients/Bitstamp/BitstampExchangeRateProvider.cs
WalletWasabi/WebClients/Bitstamp/BitstampExchangeRateProvider.cs
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Interfaces;
@@ -9,13 +10,13 @@ namespace WalletWasabi.WebClients.Bitstamp;
public class BitstampExchangeRateProvider : IExchangeRateProvider
{
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://www.bitstamp.net")
};
- using var response = await httpClient.GetAsync("/api/v2/ticker/btcusd").ConfigureAwait(false);
+ using var response = await httpClient.GetAsync("/api/v2/ticker/btcusd", cancellationToken).ConfigureAwait(false);
using var content = response.Content;
var rate = await content.ReadAsJsonAsync<BitstampExchangeRate>().ConfigureAwait(false);

MODIFY
WalletWasabi/WebClients/BlockchainInfo/BlockchainInfoExchangeRateProvider.cs
WalletWasabi/WebClients/BlockchainInfo/BlockchainInfoExchangeRateProvider.cs
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Interfaces;
@@ -9,13 +10,13 @@ namespace WalletWasabi.WebClients.BlockchainInfo;
public class BlockchainInfoExchangeRateProvider : IExchangeRateProvider
{
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://blockchain.info")
};
- using var response = await httpClient.GetAsync("/ticker").ConfigureAwait(false);
+ using var response = await httpClient.GetAsync("/ticker", cancellationToken).ConfigureAwait(false);
using var content = response.Content;
var rates = await content.ReadAsJsonAsync<BlockchainInfoExchangeRates>().ConfigureAwait(false);

MODIFY
WalletWasabi/WebClients/CoinGecko/CoinGeckoExchangeRateProvider.cs
WalletWasabi/WebClients/CoinGecko/CoinGeckoExchangeRateProvider.cs
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Interfaces;
@@ -9,13 +10,13 @@ namespace WalletWasabi.WebClients.CoinGecko;
public class CoinGeckoExchangeRateProvider : IExchangeRateProvider
{
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.coingecko.com")
};
- using var response = await httpClient.GetAsync("/api/v3/coins/markets?vs_currency=usd&ids=bitcoin").ConfigureAwait(false);
+ using var response = await httpClient.GetAsync("/api/v3/coins/markets?vs_currency=usd&ids=bitcoin", cancellationToken).ConfigureAwait(false);
using var content = response.Content;
var rates = await content.ReadAsJsonAsync<CoinGeckoExchangeRate[]>().ConfigureAwait(false);

MODIFY
WalletWasabi/WebClients/Coinbase/CoinbaseExchangeRateProvider.cs
WalletWasabi/WebClients/Coinbase/CoinbaseExchangeRateProvider.cs
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Interfaces;
@@ -9,13 +10,13 @@ namespace WalletWasabi.WebClients.Coinbase;
public class CoinbaseExchangeRateProvider : IExchangeRateProvider
{
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.coinbase.com")
};
- using var response = await httpClient.GetAsync("/v2/exchange-rates?currency=BTC").ConfigureAwait(false);
+ using var response = await httpClient.GetAsync("/v2/exchange-rates?currency=BTC", cancellationToken).ConfigureAwait(false);
using var content = response.Content;
var wrapper = await content.ReadAsJsonAsync<DataWrapper>().ConfigureAwait(false);

MODIFY
WalletWasabi/WebClients/ExchangeRateProviders.cs
WalletWasabi/WebClients/ExchangeRateProviders.cs
@@ -10,6 +10,7 @@ using WalletWasabi.WebClients.CoinGecko;
using WalletWasabi.WebClients.Gemini;
using WalletWasabi.WebClients.ItBit;
using System.Linq;
+using System.Threading;
namespace WalletWasabi.WebClients;
@@ -25,13 +26,13 @@ public class ExchangeRateProvider : IExchangeRateProvider
new ItBitExchangeRateProvider()
};
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
foreach (var provider in _exchangeRateProviders)
{
try
{
- return await provider.GetExchangeRateAsync().ConfigureAwait(false);
+ return await provider.GetExchangeRateAsync(cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{

MODIFY
WalletWasabi/WebClients/Gemini/GeminiExchangeRateProvider.cs
WalletWasabi/WebClients/Gemini/GeminiExchangeRateProvider.cs
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Interfaces;
@@ -9,13 +10,13 @@ namespace WalletWasabi.WebClients.Gemini;
public class GeminiExchangeRateProvider : IExchangeRateProvider
{
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.gemini.com")
};
- using var response = await httpClient.GetAsync("/v1/pubticker/btcusd").ConfigureAwait(false);
+ using var response = await httpClient.GetAsync("/v1/pubticker/btcusd", cancellationToken).ConfigureAwait(false);
using var content = response.Content;
var data = await content.ReadAsJsonAsync<GeminiExchangeRateInfo>().ConfigureAwait(false);

MODIFY
WalletWasabi/WebClients/ItBit/ItBitExchangeRateProvider.cs
WalletWasabi/WebClients/ItBit/ItBitExchangeRateProvider.cs
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
using WalletWasabi.Interfaces;
@@ -9,13 +10,13 @@ namespace WalletWasabi.WebClients.ItBit;
public class ItBitExchangeRateProvider : IExchangeRateProvider
{
- public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync()
+ public async Task<IEnumerable<ExchangeRate>> GetExchangeRateAsync(CancellationToken cancellationToken)
{
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.itbit.com")
};
- using var response = await httpClient.GetAsync("v1/markets/XBTUSD/ticker").ConfigureAwait(false);
+ using var response = await httpClient.GetAsync("v1/markets/XBTUSD/ticker", cancellationToken).ConfigureAwait(false);
using var content = response.Content;
var data = await content.ReadAsJsonAsync<ItBitExchangeRateInfo>().ConfigureAwait(false);

make exchange fee rate providers support cancellation token