mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 09:54:30 +01:00
Fix rate handling
This commit is contained in:
parent
7f01a12245
commit
0723eec508
@ -47,7 +47,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uri LTCNBXplorerUri { get; set; }
|
public Uri LTCNBXplorerUri { get; set; }
|
||||||
|
|
||||||
public Uri ServerUri
|
public Uri ServerUri
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@ -65,6 +65,9 @@ namespace BTCPayServer.Tests
|
|||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool MockRates { get; set; } = true;
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(_Directory))
|
if (!Directory.Exists(_Directory))
|
||||||
@ -101,12 +104,15 @@ namespace BTCPayServer.Tests
|
|||||||
.UseConfiguration(conf)
|
.UseConfiguration(conf)
|
||||||
.ConfigureServices(s =>
|
.ConfigureServices(s =>
|
||||||
{
|
{
|
||||||
var mockRates = new MockRateProviderFactory();
|
if (MockRates)
|
||||||
var btc = new MockRateProvider("BTC", new Rate("USD", 5000m), new Rate("CAD", 4500m));
|
{
|
||||||
var ltc = new MockRateProvider("LTC", new Rate("USD", 500m));
|
var mockRates = new MockRateProviderFactory();
|
||||||
mockRates.AddMock(btc);
|
var btc = new MockRateProvider("BTC", new Rate("USD", 5000m), new Rate("CAD", 4500m));
|
||||||
mockRates.AddMock(ltc);
|
var ltc = new MockRateProvider("LTC", new Rate("USD", 500m));
|
||||||
s.AddSingleton<IRateProviderFactory>(mockRates);
|
mockRates.AddMock(btc);
|
||||||
|
mockRates.AddMock(ltc);
|
||||||
|
s.AddSingleton<IRateProviderFactory>(mockRates);
|
||||||
|
}
|
||||||
s.AddLogging(l =>
|
s.AddLogging(l =>
|
||||||
{
|
{
|
||||||
l.SetMinimumLevel(LogLevel.Information)
|
l.SetMinimumLevel(LogLevel.Information)
|
||||||
@ -121,7 +127,7 @@ namespace BTCPayServer.Tests
|
|||||||
_Host.Start();
|
_Host.Start();
|
||||||
InvoiceRepository = (InvoiceRepository)_Host.Services.GetService(typeof(InvoiceRepository));
|
InvoiceRepository = (InvoiceRepository)_Host.Services.GetService(typeof(InvoiceRepository));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string HostName
|
public string HostName
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
@ -34,21 +34,11 @@ namespace BTCPayServer.Tests
|
|||||||
public ServerTester(string scope)
|
public ServerTester(string scope)
|
||||||
{
|
{
|
||||||
_Directory = scope;
|
_Directory = scope;
|
||||||
}
|
|
||||||
|
|
||||||
public bool Dockerized
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (Directory.Exists(_Directory))
|
if (Directory.Exists(_Directory))
|
||||||
Utils.DeleteDirectory(_Directory);
|
Utils.DeleteDirectory(_Directory);
|
||||||
if (!Directory.Exists(_Directory))
|
if (!Directory.Exists(_Directory))
|
||||||
Directory.CreateDirectory(_Directory);
|
Directory.CreateDirectory(_Directory);
|
||||||
|
|
||||||
|
|
||||||
NetworkProvider = new BTCPayNetworkProvider(ChainType.Regtest);
|
NetworkProvider = new BTCPayNetworkProvider(ChainType.Regtest);
|
||||||
ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("BTC").NBitcoinNetwork);
|
ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("BTC").NBitcoinNetwork);
|
||||||
LTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LTCRPCCONNECTION", "server=http://127.0.0.1:43783;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("LTC").NBitcoinNetwork);
|
LTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LTCRPCCONNECTION", "server=http://127.0.0.1:43783;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("LTC").NBitcoinNetwork);
|
||||||
@ -72,6 +62,15 @@ namespace BTCPayServer.Tests
|
|||||||
PayTester.Port = int.Parse(GetEnvironment("TESTS_PORT", Utils.FreeTcpPort().ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
PayTester.Port = int.Parse(GetEnvironment("TESTS_PORT", Utils.FreeTcpPort().ToString(CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);
|
||||||
PayTester.HostName = GetEnvironment("TESTS_HOSTNAME", "127.0.0.1");
|
PayTester.HostName = GetEnvironment("TESTS_HOSTNAME", "127.0.0.1");
|
||||||
PayTester.InContainer = bool.Parse(GetEnvironment("TESTS_INCONTAINER", "false"));
|
PayTester.InContainer = bool.Parse(GetEnvironment("TESTS_INCONTAINER", "false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Dockerized
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
PayTester.Start();
|
PayTester.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,12 +616,51 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanUseExchangeSpecificRate()
|
||||||
|
{
|
||||||
|
using (var tester = ServerTester.Create())
|
||||||
|
{
|
||||||
|
tester.PayTester.MockRates = false;
|
||||||
|
tester.Start();
|
||||||
|
var user = tester.NewAccount();
|
||||||
|
user.GrantAccess();
|
||||||
|
user.RegisterDerivationScheme("BTC");
|
||||||
|
List<decimal> rates = new List<decimal>();
|
||||||
|
rates.Add(CreateInvoice(tester, user, "coinaverage"));
|
||||||
|
rates.Add(CreateInvoice(tester, user, "bitflyer"));
|
||||||
|
|
||||||
|
foreach(var rate in rates)
|
||||||
|
{
|
||||||
|
Assert.Single(rates.Where(r => r == rate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static decimal CreateInvoice(ServerTester tester, TestAccount user, string exchange)
|
||||||
|
{
|
||||||
|
var storeController = tester.PayTester.GetController<StoresController>(user.UserId);
|
||||||
|
var vm = (StoreViewModel)((ViewResult)storeController.UpdateStore(user.StoreId).Result).Model;
|
||||||
|
vm.PreferredExchange = exchange;
|
||||||
|
storeController.UpdateStore(user.StoreId, vm).Wait();
|
||||||
|
var invoice2 = user.BitPay.CreateInvoice(new Invoice()
|
||||||
|
{
|
||||||
|
Price = 5000.0,
|
||||||
|
Currency = "USD",
|
||||||
|
PosData = "posData",
|
||||||
|
OrderId = "orderId",
|
||||||
|
ItemDesc = "Some description",
|
||||||
|
FullNotifications = true
|
||||||
|
}, Facade.Merchant);
|
||||||
|
return invoice2.CryptoInfo[0].Rate;
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanTweakRate()
|
public void CanTweakRate()
|
||||||
{
|
{
|
||||||
using (var tester = ServerTester.Create())
|
using (var tester = ServerTester.Create())
|
||||||
{
|
{
|
||||||
|
tester.PayTester.MockRates = false;
|
||||||
tester.Start();
|
tester.Start();
|
||||||
var user = tester.NewAccount();
|
var user = tester.NewAccount();
|
||||||
user.GrantAccess();
|
user.GrantAccess();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<Version>1.0.1.82</Version>
|
<Version>1.0.1.83</Version>
|
||||||
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
|
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -165,7 +165,7 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
var btc = _NetworkProvider.BTC;
|
var btc = _NetworkProvider.BTC;
|
||||||
var feeProvider = ((IFeeProviderFactory)_ServiceProvider.GetService(typeof(IFeeProviderFactory))).CreateFeeProvider(btc);
|
var feeProvider = ((IFeeProviderFactory)_ServiceProvider.GetService(typeof(IFeeProviderFactory))).CreateFeeProvider(btc);
|
||||||
var rateProvider = storeBlob.ApplyRateRules(btc, _RateProviders.GetRateProvider(btc));
|
var rateProvider = _RateProviders.GetRateProvider(btc, storeBlob.GetRateRules());
|
||||||
if (feeProvider != null && rateProvider != null)
|
if (feeProvider != null && rateProvider != null)
|
||||||
{
|
{
|
||||||
var gettingFee = feeProvider.GetFeeRateAsync();
|
var gettingFee = feeProvider.GetFeeRateAsync();
|
||||||
@ -186,7 +186,7 @@ namespace BTCPayServer.Controllers
|
|||||||
private async Task<PaymentMethod> CreatePaymentMethodAsync(IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, InvoiceEntity entity, StoreData store)
|
private async Task<PaymentMethod> CreatePaymentMethodAsync(IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, InvoiceEntity entity, StoreData store)
|
||||||
{
|
{
|
||||||
var storeBlob = store.GetStoreBlob();
|
var storeBlob = store.GetStoreBlob();
|
||||||
var rate = await storeBlob.ApplyRateRules(network, _RateProviders.GetRateProvider(network)).GetRateAsync(entity.ProductInformation.Currency);
|
var rate = await _RateProviders.GetRateProvider(network, storeBlob.GetRateRules()).GetRateAsync(entity.ProductInformation.Currency);
|
||||||
PaymentMethod paymentMethod = new PaymentMethod();
|
PaymentMethod paymentMethod = new PaymentMethod();
|
||||||
paymentMethod.ParentEntity = entity;
|
paymentMethod.ParentEntity = entity;
|
||||||
paymentMethod.Network = network;
|
paymentMethod.Network = network;
|
||||||
@ -221,7 +221,7 @@ namespace BTCPayServer.Controllers
|
|||||||
if (limitValue.Currency == entity.ProductInformation.Currency)
|
if (limitValue.Currency == entity.ProductInformation.Currency)
|
||||||
limitValueRate = paymentMethod.Rate;
|
limitValueRate = paymentMethod.Rate;
|
||||||
else
|
else
|
||||||
limitValueRate = await storeBlob.ApplyRateRules(network, _RateProviders.GetRateProvider(network)).GetRateAsync(limitValue.Currency);
|
limitValueRate = await _RateProviders.GetRateProvider(network, storeBlob.GetRateRules()).GetRateAsync(limitValue.Currency);
|
||||||
|
|
||||||
var limitValueCrypto = Money.Coins(limitValue.Value / limitValueRate);
|
var limitValueCrypto = Money.Coins(limitValue.Value / limitValueRate);
|
||||||
if (compare(paymentMethod.Calculate().Due, limitValueCrypto))
|
if (compare(paymentMethod.Calculate().Due, limitValueCrypto))
|
||||||
|
@ -49,18 +49,20 @@ namespace BTCPayServer.Controllers
|
|||||||
var network = _NetworkProvider.GetNetwork(cryptoCode);
|
var network = _NetworkProvider.GetNetwork(cryptoCode);
|
||||||
if (network == null)
|
if (network == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
var rateProvider = _RateProviderFactory.GetRateProvider(network);
|
|
||||||
if (rateProvider == null)
|
|
||||||
return NotFound();
|
|
||||||
|
|
||||||
|
RateRules rules = null;
|
||||||
if (storeId != null)
|
if (storeId != null)
|
||||||
{
|
{
|
||||||
var store = await _StoreRepo.FindStore(storeId);
|
var store = await _StoreRepo.FindStore(storeId);
|
||||||
if (store == null)
|
if (store == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
rateProvider = store.GetStoreBlob().ApplyRateRules(network, rateProvider);
|
rules = store.GetStoreBlob().GetRateRules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rateProvider = _RateProviderFactory.GetRateProvider(network, rules);
|
||||||
|
if (rateProvider == null)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
var allRates = (await rateProvider.GetRatesAsync());
|
var allRates = (await rateProvider.GetRatesAsync());
|
||||||
return Json(allRates.Select(r =>
|
return Json(allRates.Select(r =>
|
||||||
new NBitpayClient.Rate()
|
new NBitpayClient.Rate()
|
||||||
|
@ -284,30 +284,12 @@ namespace BTCPayServer.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRateProvider ApplyRateRules(BTCPayNetwork network, IRateProvider rateProvider)
|
public RateRules GetRateRules()
|
||||||
{
|
{
|
||||||
if (!PreferredExchange.IsCoinAverage())
|
return new RateRules(RateRules)
|
||||||
{
|
{
|
||||||
// If the original rateProvider is a cache, use the same inner provider as fallback, and same memory cache to wrap it all
|
PreferredExchange = PreferredExchange
|
||||||
if (rateProvider is CachedRateProvider cachedRateProvider)
|
};
|
||||||
{
|
|
||||||
rateProvider = new FallbackRateProvider(new IRateProvider[] {
|
|
||||||
new CoinAverageRateProvider(network.CryptoCode) { Exchange = PreferredExchange },
|
|
||||||
cachedRateProvider.Inner
|
|
||||||
});
|
|
||||||
rateProvider = new CachedRateProvider(network.CryptoCode, rateProvider, cachedRateProvider.MemoryCache) { AdditionalScope = PreferredExchange };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rateProvider = new FallbackRateProvider(new IRateProvider[] {
|
|
||||||
new CoinAverageRateProvider(network.CryptoCode) { Exchange = PreferredExchange },
|
|
||||||
rateProvider
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (RateRules == null || RateRules.Count == 0)
|
|
||||||
return rateProvider;
|
|
||||||
return new TweakRateProvider(network, rateProvider, RateRules.ToList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -6,24 +7,44 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using BTCPayServer.Logging;
|
||||||
|
|
||||||
namespace BTCPayServer.HostedServices
|
namespace BTCPayServer.HostedServices
|
||||||
{
|
{
|
||||||
public class RatesHostedService : IHostedService
|
public class RatesHostedService : IHostedService
|
||||||
{
|
{
|
||||||
private SettingsRepository _SettingsRepository;
|
private SettingsRepository _SettingsRepository;
|
||||||
private BTCPayRateProviderFactory _RateProviderFactory;
|
private IRateProviderFactory _RateProviderFactory;
|
||||||
public RatesHostedService(SettingsRepository repo, IRateProviderFactory rateProviderFactory)
|
public RatesHostedService(SettingsRepository repo,
|
||||||
|
IRateProviderFactory rateProviderFactory)
|
||||||
{
|
{
|
||||||
this._SettingsRepository = repo;
|
this._SettingsRepository = repo;
|
||||||
_RateProviderFactory = rateProviderFactory as BTCPayRateProviderFactory;
|
_RateProviderFactory = rateProviderFactory;
|
||||||
}
|
}
|
||||||
public async Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
async void Init()
|
||||||
{
|
{
|
||||||
if (_RateProviderFactory == null)
|
|
||||||
return;
|
|
||||||
var rates = (await _SettingsRepository.GetSettingAsync<RatesSetting>()) ?? new RatesSetting();
|
var rates = (await _SettingsRepository.GetSettingAsync<RatesSetting>()) ?? new RatesSetting();
|
||||||
_RateProviderFactory.CacheSpan = TimeSpan.FromMinutes(rates.CacheInMinutes);
|
_RateProviderFactory.CacheSpan = TimeSpan.FromMinutes(rates.CacheInMinutes);
|
||||||
|
|
||||||
|
//string[] availableExchanges = null;
|
||||||
|
//// So we don't run this in testing
|
||||||
|
//if(_RateProviderFactory is BTCPayRateProviderFactory)
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// await new CoinAverageRateProvider("BTC").GetExchangeTickersAsync();
|
||||||
|
// }
|
||||||
|
// catch(Exception ex)
|
||||||
|
// {
|
||||||
|
// Logs.PayServer.LogWarning(ex, "Failed to get exchange tickers");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
@ -51,9 +51,28 @@ namespace BTCPayServer.Services.Rates
|
|||||||
_Cache = new MemoryCache(_CacheOptions);
|
_Cache = new MemoryCache(_CacheOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRateProvider GetRateProvider(BTCPayNetwork network)
|
public IRateProvider GetRateProvider(BTCPayNetwork network, RateRules rules)
|
||||||
{
|
{
|
||||||
return new CachedRateProvider(network.CryptoCode, GetDefaultRateProvider(network), _Cache) { CacheSpan = CacheSpan };
|
rules = rules ?? new RateRules();
|
||||||
|
var rateProvider = GetDefaultRateProvider(network);
|
||||||
|
if (!rules.PreferredExchange.IsCoinAverage())
|
||||||
|
{
|
||||||
|
rateProvider = CreateExchangeRateProvider(network, rules.PreferredExchange);
|
||||||
|
}
|
||||||
|
rateProvider = CreateCachedRateProvider(network, rateProvider, rules.PreferredExchange);
|
||||||
|
return new TweakRateProvider(network, rateProvider, rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IRateProvider CreateExchangeRateProvider(BTCPayNetwork network, string exchange)
|
||||||
|
{
|
||||||
|
var coinAverage = new CoinAverageRateProviderDescription(network.CryptoCode).CreateRateProvider(serviceProvider);
|
||||||
|
coinAverage.Exchange = exchange;
|
||||||
|
return coinAverage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CachedRateProvider CreateCachedRateProvider(BTCPayNetwork network, IRateProvider rateProvider, string additionalScope)
|
||||||
|
{
|
||||||
|
return new CachedRateProvider(network.CryptoCode, rateProvider, _Cache) { CacheSpan = CacheSpan, AdditionalScope = additionalScope };
|
||||||
}
|
}
|
||||||
|
|
||||||
private IRateProvider GetDefaultRateProvider(BTCPayNetwork network)
|
private IRateProvider GetDefaultRateProvider(BTCPayNetwork network)
|
||||||
|
@ -30,13 +30,31 @@ namespace BTCPayServer.Services.Rates
|
|||||||
|
|
||||||
public string CryptoCode { get; set; }
|
public string CryptoCode { get; set; }
|
||||||
|
|
||||||
public IRateProvider CreateRateProvider(IServiceProvider serviceProvider)
|
public CoinAverageRateProvider CreateRateProvider(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
return new CoinAverageRateProvider(CryptoCode)
|
return new CoinAverageRateProvider(CryptoCode)
|
||||||
{
|
{
|
||||||
Authenticator = serviceProvider.GetService<ICoinAverageAuthenticator>()
|
Authenticator = serviceProvider.GetService<ICoinAverageAuthenticator>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRateProvider RateProviderDescription.CreateRateProvider(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
return CreateRateProvider(serviceProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetExchangeTickersResponse
|
||||||
|
{
|
||||||
|
public class Exchange
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonProperty("display_name")]
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
public string[] Symbols { get; set; }
|
||||||
|
}
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public Exchange[] Exchanges { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RatesSetting
|
public class RatesSetting
|
||||||
@ -181,5 +199,26 @@ namespace BTCPayServer.Services.Rates
|
|||||||
var resp = await _Client.SendAsync(request);
|
var resp = await _Client.SendAsync(request);
|
||||||
resp.EnsureSuccessStatusCode();
|
resp.EnsureSuccessStatusCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<GetExchangeTickersResponse> GetExchangeTickersAsync()
|
||||||
|
{
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get, "https://apiv2.bitcoinaverage.com/symbols/exchanges/ticker");
|
||||||
|
var resp = await _Client.SendAsync(request);
|
||||||
|
resp.EnsureSuccessStatusCode();
|
||||||
|
var jobj = JObject.Parse(await resp.Content.ReadAsStringAsync());
|
||||||
|
var response = new GetExchangeTickersResponse();
|
||||||
|
response.Success = jobj["success"].Value<bool>();
|
||||||
|
var exchanges = (JObject)jobj["exchanges"];
|
||||||
|
response.Exchanges = exchanges
|
||||||
|
.Properties()
|
||||||
|
.Select(p =>
|
||||||
|
{
|
||||||
|
var exchange = JsonConvert.DeserializeObject<GetExchangeTickersResponse.Exchange>(p.Value.ToString());
|
||||||
|
exchange.Name = p.Name;
|
||||||
|
return exchange;
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,40 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Data;
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Rates
|
namespace BTCPayServer.Services.Rates
|
||||||
{
|
{
|
||||||
|
public class RateRules : IEnumerable<RateRule>
|
||||||
|
{
|
||||||
|
private List<RateRule> rateRules;
|
||||||
|
|
||||||
|
public RateRules()
|
||||||
|
{
|
||||||
|
rateRules = new List<RateRule>();
|
||||||
|
}
|
||||||
|
public RateRules(List<RateRule> rateRules)
|
||||||
|
{
|
||||||
|
this.rateRules = rateRules?.ToList() ?? new List<RateRule>();
|
||||||
|
}
|
||||||
|
public string PreferredExchange { get; set; }
|
||||||
|
|
||||||
|
public IEnumerator<RateRule> GetEnumerator()
|
||||||
|
{
|
||||||
|
return rateRules.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
public interface IRateProviderFactory
|
public interface IRateProviderFactory
|
||||||
{
|
{
|
||||||
IRateProvider GetRateProvider(BTCPayNetwork network);
|
IRateProvider GetRateProvider(BTCPayNetwork network, RateRules rules);
|
||||||
|
TimeSpan CacheSpan { get; set; }
|
||||||
|
void InvalidateCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,21 @@ namespace BTCPayServer.Services.Rates
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSpan CacheSpan { get; set; }
|
||||||
|
|
||||||
public void AddMock(MockRateProvider mock)
|
public void AddMock(MockRateProvider mock)
|
||||||
{
|
{
|
||||||
_Mocks.Add(mock);
|
_Mocks.Add(mock);
|
||||||
}
|
}
|
||||||
public IRateProvider GetRateProvider(BTCPayNetwork network)
|
public IRateProvider GetRateProvider(BTCPayNetwork network, RateRules rules)
|
||||||
{
|
{
|
||||||
return _Mocks.FirstOrDefault(m => m.CryptoCode == network.CryptoCode);
|
return _Mocks.FirstOrDefault(m => m.CryptoCode == network.CryptoCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InvalidateCache()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public class MockRateProvider : IRateProvider
|
public class MockRateProvider : IRateProvider
|
||||||
{
|
{
|
||||||
|
@ -10,9 +10,9 @@ namespace BTCPayServer.Services.Rates
|
|||||||
{
|
{
|
||||||
private BTCPayNetwork network;
|
private BTCPayNetwork network;
|
||||||
private IRateProvider rateProvider;
|
private IRateProvider rateProvider;
|
||||||
private List<RateRule> rateRules;
|
private RateRules rateRules;
|
||||||
|
|
||||||
public TweakRateProvider(BTCPayNetwork network, IRateProvider rateProvider, List<RateRule> rateRules)
|
public TweakRateProvider(BTCPayNetwork network, IRateProvider rateProvider, RateRules rateRules)
|
||||||
{
|
{
|
||||||
if (network == null)
|
if (network == null)
|
||||||
throw new ArgumentNullException(nameof(network));
|
throw new ArgumentNullException(nameof(network));
|
||||||
|
Loading…
Reference in New Issue
Block a user