mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Remove the concept of "Rate multiplier" and replace it with the concept of "Spread"
This commit is contained in:
@@ -46,8 +46,8 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
Assert.Equal(test.Expected, rules.GetRuleFor(CurrencyPair.Parse(test.Pair)).ToString());
|
Assert.Equal(test.Expected, rules.GetRuleFor(CurrencyPair.Parse(test.Pair)).ToString());
|
||||||
}
|
}
|
||||||
rules.GlobalMultiplier = 2.32m;
|
rules.Spread = 0.2m;
|
||||||
Assert.Equal("(bittrex(DOGE_BTC) * gdax(BTC_USD) * 1.1) * 2.32", rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD")).ToString());
|
Assert.Equal("(bittrex(DOGE_BTC) * gdax(BTC_USD) * 1.1) * (0.8, 1.2)", rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD")).ToString());
|
||||||
////////////////
|
////////////////
|
||||||
|
|
||||||
// Check errors conditions
|
// Check errors conditions
|
||||||
@@ -113,22 +113,22 @@ namespace BTCPayServer.Tests
|
|||||||
builder.AppendLine("BTC_USD = -3 + coinbase(BTC_CAD) + 50 - 5");
|
builder.AppendLine("BTC_USD = -3 + coinbase(BTC_CAD) + 50 - 5");
|
||||||
builder.AppendLine("DOGE_BTC = 2000");
|
builder.AppendLine("DOGE_BTC = 2000");
|
||||||
Assert.True(RateRules.TryParse(builder.ToString(), out rules));
|
Assert.True(RateRules.TryParse(builder.ToString(), out rules));
|
||||||
rules.GlobalMultiplier = 1.1m;
|
rules.Spread = 0.1m;
|
||||||
|
|
||||||
rule2 = rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD"));
|
rule2 = rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD"));
|
||||||
Assert.Equal("(2000 * (-3 + coinbase(BTC_CAD) + 50 - 5)) * 1.1", rule2.ToString());
|
Assert.Equal("(2000 * (-3 + coinbase(BTC_CAD) + 50 - 5)) * (0.9, 1.1)", rule2.ToString());
|
||||||
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), new BidAsk(1000m));
|
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), new BidAsk(1000m));
|
||||||
Assert.True(rule2.Reevaluate());
|
Assert.True(rule2.Reevaluate());
|
||||||
Assert.Equal("(2000 * (-3 + 1000 + 50 - 5)) * 1.1", rule2.ToString(true));
|
Assert.Equal("(2000 * (-3 + 1000 + 50 - 5)) * (0.9, 1.1)", rule2.ToString(true));
|
||||||
Assert.Equal((2000m * (-3m + 1000m + 50m - 5m)) * 1.1m, rule2.BidAsk.Bid);
|
Assert.Equal((2000m * (-3m + 1000m + 50m - 5m)) * 0.9m, rule2.BidAsk.Bid);
|
||||||
|
|
||||||
// Test inverse
|
// Test inverse
|
||||||
rule2 = rules.GetRuleFor(CurrencyPair.Parse("USD_DOGE"));
|
rule2 = rules.GetRuleFor(CurrencyPair.Parse("USD_DOGE"));
|
||||||
Assert.Equal("(1 / (2000 * (-3 + coinbase(BTC_CAD) + 50 - 5))) * 1.1", rule2.ToString());
|
Assert.Equal("(1 / (2000 * (-3 + coinbase(BTC_CAD) + 50 - 5))) * (0.9, 1.1)", rule2.ToString());
|
||||||
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), new BidAsk(1000m));
|
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), new BidAsk(1000m));
|
||||||
Assert.True(rule2.Reevaluate());
|
Assert.True(rule2.Reevaluate());
|
||||||
Assert.Equal("(1 / (2000 * (-3 + 1000 + 50 - 5))) * 1.1", rule2.ToString(true));
|
Assert.Equal("(1 / (2000 * (-3 + 1000 + 50 - 5))) * (0.9, 1.1)", rule2.ToString(true));
|
||||||
Assert.Equal((1.0m / (2000m * (-3m + 1000m + 50m - 5m))) * 1.1m, rule2.BidAsk.Bid);
|
Assert.Equal((1.0m / (2000m * (-3m + 1000m + 50m - 5m))) * 0.9m, rule2.BidAsk.Bid);
|
||||||
////////
|
////////
|
||||||
|
|
||||||
// Make sure kraken is not converted to CurrencyPair
|
// Make sure kraken is not converted to CurrencyPair
|
||||||
|
|||||||
@@ -982,8 +982,8 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
var storeController = user.GetController<StoresController>();
|
var storeController = user.GetController<StoresController>();
|
||||||
var vm = (RatesViewModel)((ViewResult)storeController.Rates()).Model;
|
var vm = (RatesViewModel)((ViewResult)storeController.Rates()).Model;
|
||||||
Assert.Equal(1.0, vm.RateMultiplier);
|
Assert.Equal(0.0, vm.Spread);
|
||||||
vm.RateMultiplier = 0.5;
|
vm.Spread = 40;
|
||||||
storeController.Rates(vm).Wait();
|
storeController.Rates(vm).Wait();
|
||||||
|
|
||||||
|
|
||||||
@@ -997,7 +997,11 @@ namespace BTCPayServer.Tests
|
|||||||
FullNotifications = true
|
FullNotifications = true
|
||||||
}, Facade.Merchant);
|
}, Facade.Merchant);
|
||||||
|
|
||||||
Assert.True(invoice2.BtcPrice.Almost(invoice1.BtcPrice * 2, 0.00001m));
|
// The rate was 5000 USD per BTC
|
||||||
|
// Now it should be 3000 USD per BTC
|
||||||
|
// So the expected price should be
|
||||||
|
var expected = Money.Coins(5000m / 3000m);
|
||||||
|
Assert.True(invoice2.BtcPrice.Almost(expected, 0.00001m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,7 +1083,7 @@ namespace BTCPayServer.Tests
|
|||||||
var rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates()).Model);
|
var rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates()).Model);
|
||||||
Assert.False(rateVm.ShowScripting);
|
Assert.False(rateVm.ShowScripting);
|
||||||
Assert.Equal("coinaverage", rateVm.PreferredExchange);
|
Assert.Equal("coinaverage", rateVm.PreferredExchange);
|
||||||
Assert.Equal(1.0, rateVm.RateMultiplier);
|
Assert.Equal(0.0, rateVm.Spread);
|
||||||
Assert.Null(rateVm.TestRateRules);
|
Assert.Null(rateVm.TestRateRules);
|
||||||
|
|
||||||
rateVm.PreferredExchange = "bitflyer";
|
rateVm.PreferredExchange = "bitflyer";
|
||||||
@@ -1088,13 +1092,13 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal("bitflyer", rateVm.PreferredExchange);
|
Assert.Equal("bitflyer", rateVm.PreferredExchange);
|
||||||
|
|
||||||
rateVm.ScriptTest = "BTC_JPY,BTC_CAD";
|
rateVm.ScriptTest = "BTC_JPY,BTC_CAD";
|
||||||
rateVm.RateMultiplier = 1.1;
|
rateVm.Spread = 10;
|
||||||
store = user.GetController<StoresController>();
|
store = user.GetController<StoresController>();
|
||||||
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates(rateVm, "Test").Result).Model);
|
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates(rateVm, "Test").Result).Model);
|
||||||
Assert.NotNull(rateVm.TestRateRules);
|
Assert.NotNull(rateVm.TestRateRules);
|
||||||
Assert.Equal(2, rateVm.TestRateRules.Count);
|
Assert.Equal(2, rateVm.TestRateRules.Count);
|
||||||
Assert.False(rateVm.TestRateRules[0].Error);
|
Assert.False(rateVm.TestRateRules[0].Error);
|
||||||
Assert.StartsWith("(bitflyer(BTC_JPY)) * 1.10 =", rateVm.TestRateRules[0].Rule, StringComparison.OrdinalIgnoreCase);
|
Assert.StartsWith("(bitflyer(BTC_JPY)) * (0.9, 1.1) =", rateVm.TestRateRules[0].Rule, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.True(rateVm.TestRateRules[1].Error);
|
Assert.True(rateVm.TestRateRules[1].Error);
|
||||||
Assert.IsType<RedirectToActionResult>(store.Rates(rateVm, "Save").Result);
|
Assert.IsType<RedirectToActionResult>(store.Rates(rateVm, "Save").Result);
|
||||||
|
|
||||||
@@ -1107,19 +1111,19 @@ namespace BTCPayServer.Tests
|
|||||||
rateVm.ScriptTest = "BTC_JPY";
|
rateVm.ScriptTest = "BTC_JPY";
|
||||||
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates(rateVm, "Test").Result).Model);
|
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates(rateVm, "Test").Result).Model);
|
||||||
Assert.True(rateVm.ShowScripting);
|
Assert.True(rateVm.ShowScripting);
|
||||||
Assert.Contains("(bitflyer(BTC_JPY)) * 1.10 = ", rateVm.TestRateRules[0].Rule, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("(bitflyer(BTC_JPY)) * (0.9, 1.1) = ", rateVm.TestRateRules[0].Rule, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
rateVm.ScriptTest = "BTC_USD,BTC_CAD,DOGE_USD,DOGE_CAD";
|
rateVm.ScriptTest = "BTC_USD,BTC_CAD,DOGE_USD,DOGE_CAD";
|
||||||
rateVm.Script = "DOGE_X = bittrex(DOGE_BTC) * BTC_X;\n" +
|
rateVm.Script = "DOGE_X = bittrex(DOGE_BTC) * BTC_X;\n" +
|
||||||
"X_CAD = quadrigacx(X_CAD);\n" +
|
"X_CAD = quadrigacx(X_CAD);\n" +
|
||||||
"X_X = gdax(X_X);";
|
"X_X = gdax(X_X);";
|
||||||
rateVm.RateMultiplier = 0.5;
|
rateVm.Spread = 50;
|
||||||
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates(rateVm, "Test").Result).Model);
|
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates(rateVm, "Test").Result).Model);
|
||||||
Assert.True(rateVm.TestRateRules.All(t => !t.Error));
|
Assert.True(rateVm.TestRateRules.All(t => !t.Error));
|
||||||
Assert.IsType<RedirectToActionResult>(store.Rates(rateVm, "Save").Result);
|
Assert.IsType<RedirectToActionResult>(store.Rates(rateVm, "Save").Result);
|
||||||
store = user.GetController<StoresController>();
|
store = user.GetController<StoresController>();
|
||||||
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates()).Model);
|
rateVm = Assert.IsType<RatesViewModel>(Assert.IsType<ViewResult>(store.Rates()).Model);
|
||||||
Assert.Equal(0.5, rateVm.RateMultiplier);
|
Assert.Equal(50, rateVm.Spread);
|
||||||
Assert.True(rateVm.ShowScripting);
|
Assert.True(rateVm.ShowScripting);
|
||||||
Assert.Contains("DOGE_X", rateVm.Script, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("DOGE_X", rateVm.Script, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<Version>1.0.2.82</Version>
|
<Version>1.0.2.83</Version>
|
||||||
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
|
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ namespace BTCPayServer.Controllers
|
|||||||
var storeBlob = StoreData.GetStoreBlob();
|
var storeBlob = StoreData.GetStoreBlob();
|
||||||
var vm = new RatesViewModel();
|
var vm = new RatesViewModel();
|
||||||
vm.SetExchangeRates(GetSupportedExchanges(), storeBlob.PreferredExchange ?? CoinAverageRateProvider.CoinAverageName);
|
vm.SetExchangeRates(GetSupportedExchanges(), storeBlob.PreferredExchange ?? CoinAverageRateProvider.CoinAverageName);
|
||||||
vm.RateMultiplier = (double)storeBlob.GetRateMultiplier();
|
vm.Spread = (double)(storeBlob.Spread * 100m);
|
||||||
vm.Script = storeBlob.GetRateRules(_NetworkProvider).ToString();
|
vm.Script = storeBlob.GetRateRules(_NetworkProvider).ToString();
|
||||||
vm.DefaultScript = storeBlob.GetDefaultRateRules(_NetworkProvider).ToString();
|
vm.DefaultScript = storeBlob.GetDefaultRateRules(_NetworkProvider).ToString();
|
||||||
vm.AvailableExchanges = GetSupportedExchanges();
|
vm.AvailableExchanges = GetSupportedExchanges();
|
||||||
@@ -204,7 +204,7 @@ namespace BTCPayServer.Controllers
|
|||||||
model.AvailableExchanges = GetSupportedExchanges();
|
model.AvailableExchanges = GetSupportedExchanges();
|
||||||
|
|
||||||
blob.PreferredExchange = model.PreferredExchange;
|
blob.PreferredExchange = model.PreferredExchange;
|
||||||
blob.SetRateMultiplier(model.RateMultiplier);
|
blob.Spread = (decimal)model.Spread / 100.0m;
|
||||||
|
|
||||||
if (!model.ShowScripting)
|
if (!model.ShowScripting)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
var storeData = store.GetStoreBlob();
|
var storeData = store.GetStoreBlob();
|
||||||
var rateRules = store.GetStoreBlob().GetRateRules(_NetworkProvider);
|
var rateRules = store.GetStoreBlob().GetRateRules(_NetworkProvider);
|
||||||
rateRules.GlobalMultiplier = 1.0m;
|
rateRules.Spread = 0.0m;
|
||||||
var currencyPair = new Rating.CurrencyPair(paymentMethod.PaymentId.CryptoCode, GetCurrencyCode(storeData.DefaultLang) ?? "USD");
|
var currencyPair = new Rating.CurrencyPair(paymentMethod.PaymentId.CryptoCode, GetCurrencyCode(storeData.DefaultLang) ?? "USD");
|
||||||
WalletModel model = new WalletModel();
|
WalletModel model = new WalletModel();
|
||||||
model.ServerUrl = GetLedgerWebsocketUrl(this.HttpContext, walletId.CryptoCode, paymentMethod.DerivationStrategyBase);
|
model.ServerUrl = GetLedgerWebsocketUrl(this.HttpContext, walletId.CryptoCode, paymentMethod.DerivationStrategyBase);
|
||||||
|
|||||||
@@ -281,23 +281,9 @@ namespace BTCPayServer.Data
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetRateMultiplier(double rate)
|
public decimal Spread { get; set; } = 0.0m;
|
||||||
{
|
|
||||||
RateRules = new List<RateRule_Obsolete>();
|
|
||||||
RateRules.Add(new RateRule_Obsolete() { Multiplier = rate });
|
|
||||||
}
|
|
||||||
public decimal GetRateMultiplier()
|
|
||||||
{
|
|
||||||
decimal rate = 1.0m;
|
|
||||||
if (RateRules == null || RateRules.Count == 0)
|
|
||||||
return rate;
|
|
||||||
foreach (var rule in RateRules)
|
|
||||||
{
|
|
||||||
rate = rule.Apply(null, rate);
|
|
||||||
}
|
|
||||||
return rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
public List<RateRule_Obsolete> RateRules { get; set; } = new List<RateRule_Obsolete>();
|
public List<RateRule_Obsolete> RateRules { get; set; } = new List<RateRule_Obsolete>();
|
||||||
public string PreferredExchange { get; set; }
|
public string PreferredExchange { get; set; }
|
||||||
|
|
||||||
@@ -344,7 +330,7 @@ namespace BTCPayServer.Data
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rules.GlobalMultiplier = GetRateMultiplier();
|
rules.Spread = Spread;
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,7 +356,7 @@ namespace BTCPayServer.Data
|
|||||||
builder.AppendLine($"X_X = {preferredExchange}(X_X);");
|
builder.AppendLine($"X_X = {preferredExchange}(X_X);");
|
||||||
|
|
||||||
BTCPayServer.Rating.RateRules.TryParse(builder.ToString(), out var rules);
|
BTCPayServer.Rating.RateRules.TryParse(builder.ToString(), out var rules);
|
||||||
rules.GlobalMultiplier = GetRateMultiplier();
|
rules.Spread = Spread;
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ namespace BTCPayServer.HostedServices
|
|||||||
settings.UnreachableStoreCheck = true;
|
settings.UnreachableStoreCheck = true;
|
||||||
await _Settings.UpdateSetting(settings);
|
await _Settings.UpdateSetting(settings);
|
||||||
}
|
}
|
||||||
|
if (!settings.ConvertMultiplierToSpread)
|
||||||
|
{
|
||||||
|
await ConvertMultiplierToSpread();
|
||||||
|
settings.ConvertMultiplierToSpread = true;
|
||||||
|
await _Settings.UpdateSetting(settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -61,6 +67,30 @@ namespace BTCPayServer.HostedServices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ConvertMultiplierToSpread()
|
||||||
|
{
|
||||||
|
using (var ctx = _DBContextFactory.CreateContext())
|
||||||
|
{
|
||||||
|
foreach (var store in await ctx.Stores.ToArrayAsync())
|
||||||
|
{
|
||||||
|
var blob = store.GetStoreBlob();
|
||||||
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
|
decimal multiplier = 1.0m;
|
||||||
|
if (blob.RateRules != null && blob.RateRules.Count != 0)
|
||||||
|
{
|
||||||
|
foreach (var rule in blob.RateRules)
|
||||||
|
{
|
||||||
|
multiplier = rule.Apply(null, multiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blob.RateRules = null;
|
||||||
|
blob.Spread = Math.Min(1.0m, Math.Max(0m, -(multiplier - 1.0m)));
|
||||||
|
#pragma warning restore CS0612 // Type or member is obsolete
|
||||||
|
}
|
||||||
|
await ctx.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Task UnreachableStoreCheck()
|
private Task UnreachableStoreCheck()
|
||||||
{
|
{
|
||||||
return _StoreRepository.CleanUnreachableStores();
|
return _StoreRepository.CleanUnreachableStores();
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
public string ScriptTest { get; set; }
|
public string ScriptTest { get; set; }
|
||||||
public CoinAverageExchange[] AvailableExchanges { get; set; }
|
public CoinAverageExchange[] AvailableExchanges { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Multiply the rate by... (Setting to 1.01 would apply a discount of 1% to the purchase)")]
|
[Display(Name = "Add a spread on exchange rate of ... %")]
|
||||||
[Range(0.01, 10.0)]
|
[Range(0.0, 100.0)]
|
||||||
public double RateMultiplier
|
public double Spread
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
|||||||
@@ -99,7 +99,20 @@ namespace BTCPayServer.Rating
|
|||||||
SyntaxNode root;
|
SyntaxNode root;
|
||||||
RuleList ruleList;
|
RuleList ruleList;
|
||||||
|
|
||||||
public decimal GlobalMultiplier { get; set; } = 1.0m;
|
decimal _Spread;
|
||||||
|
public decimal Spread
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _Spread;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value > 1.0m || value < 0.0m)
|
||||||
|
throw new ArgumentOutOfRangeException(paramName: nameof(value), message: "The spread should be between 0 and 1");
|
||||||
|
_Spread = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RateRules(SyntaxNode root)
|
RateRules(SyntaxNode root)
|
||||||
{
|
{
|
||||||
@@ -136,9 +149,9 @@ namespace BTCPayServer.Rating
|
|||||||
if (currencyPair.Left == currencyPair.Right)
|
if (currencyPair.Left == currencyPair.Right)
|
||||||
return new RateRule(this, currencyPair, CreateExpression("1.0"));
|
return new RateRule(this, currencyPair, CreateExpression("1.0"));
|
||||||
var candidate = FindBestCandidate(currencyPair);
|
var candidate = FindBestCandidate(currencyPair);
|
||||||
if (GlobalMultiplier != decimal.One)
|
if (Spread != decimal.Zero)
|
||||||
{
|
{
|
||||||
candidate = CreateExpression($"({candidate}) * {GlobalMultiplier.ToString(CultureInfo.InvariantCulture)}");
|
candidate = CreateExpression($"({candidate}) * ({(1.0m - Spread).ToString(CultureInfo.InvariantCulture)}, {(1.0m + Spread).ToString(CultureInfo.InvariantCulture)})");
|
||||||
}
|
}
|
||||||
return new RateRule(this, currencyPair, candidate);
|
return new RateRule(this, currencyPair, candidate);
|
||||||
}
|
}
|
||||||
@@ -257,7 +270,7 @@ namespace BTCPayServer.Rating
|
|||||||
{
|
{
|
||||||
case SyntaxKind.UnaryMinusExpression:
|
case SyntaxKind.UnaryMinusExpression:
|
||||||
var v = Values.Pop();
|
var v = Values.Pop();
|
||||||
if(v.Bid == v.Ask)
|
if (v.Bid == v.Ask)
|
||||||
{
|
{
|
||||||
Values.Push(-v);
|
Values.Push(-v);
|
||||||
}
|
}
|
||||||
@@ -338,7 +351,7 @@ namespace BTCPayServer.Rating
|
|||||||
{
|
{
|
||||||
_TupleValues = new Stack<decimal>();
|
_TupleValues = new Stack<decimal>();
|
||||||
base.VisitTupleExpression(node);
|
base.VisitTupleExpression(node);
|
||||||
if(_TupleValues.Count != 2)
|
if (_TupleValues.Count != 2)
|
||||||
{
|
{
|
||||||
Errors.Add(RateRulesErrors.MissingArgument);
|
Errors.Add(RateRulesErrors.MissingArgument);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ namespace BTCPayServer.Services
|
|||||||
{
|
{
|
||||||
public bool UnreachableStoreCheck { get; set; }
|
public bool UnreachableStoreCheck { get; set; }
|
||||||
public bool DeprecatedLightningConnectionStringCheck { get; set; }
|
public bool DeprecatedLightningConnectionStringCheck { get; set; }
|
||||||
|
public bool ConvertMultiplierToSpread { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,9 +132,9 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="RateMultiplier"></label>
|
<label asp-for="Spread"></label>
|
||||||
<input asp-for="RateMultiplier" class="form-control" />
|
<input asp-for="Spread" class="form-control" />
|
||||||
<span asp-validation-for="RateMultiplier" class="text-danger"></span>
|
<span asp-validation-for="Spread" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h5>Testing</h5>
|
<h5>Testing</h5>
|
||||||
|
|||||||
Reference in New Issue
Block a user