Remove dependency on Common from Rating

replaces #1591 and #1592 , closes #1571 Replaces the Currencies.txt to a json format which includes the networks too ( there is also a test to check now) Also makes CurrencyPair not depend on network and instead use CurrencyNameTable
This commit is contained in:
Kukks 2020-05-31 12:18:29 +02:00
parent 379e5741e7
commit 587f244f1d
15 changed files with 1347 additions and 377 deletions

View File

@ -6,12 +6,14 @@
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
<PackageReference Include="NBitcoin" Version="5.0.40" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.6.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BTCPayServer.Common\BTCPayServer.Common.csproj" />
<EmbeddedResource Include="Currencies.json" />
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -6,35 +6,22 @@ using System.Reflection;
using System.Linq;
using System.Text;
using System.Globalization;
using BTCPayServer.Rating;
using Newtonsoft.Json;
namespace BTCPayServer.Services.Rates
{
public class CurrencyData
{
public string Name
{
get;
internal set;
}
public string Code
{
get;
internal set;
}
public int Divisibility
{
get;
internal set;
}
public string Symbol
{
get;
internal set;
}
public string Name { get; set; }
public string Code { get; set; }
public int Divisibility { get; set; }
public string Symbol { get; set; }
public bool Crypto { get; set; }
}
public class CurrencyNameTable
{
public static CurrencyNameTable Instance = new CurrencyNameTable();
public CurrencyNameTable()
{
_Currencies = LoadCurrency().ToDictionary(k => k.Code);
@ -94,16 +81,10 @@ namespace BTCPayServer.Services.Rates
catch { }
}
foreach (var network in new BTCPayNetworkProvider(NetworkType.Mainnet).GetAll())
foreach (var curr in _Currencies.Where(pair => pair.Value.Crypto))
{
AddCurrency(_CurrencyProviders, network.CryptoCode, network.Divisibility, network.CryptoCode);
AddCurrency(_CurrencyProviders, curr.Key, curr.Value.Divisibility, curr.Value.Symbol?? curr.Value.Code);
}
_CurrencyProviders.TryAdd("SATS",
new NumberFormatInfo()
{
CurrencySymbol = "sats", CurrencyDecimalDigits = 0, CurrencyPositivePattern = 3
});
}
return _CurrencyProviders.TryGet(currency.ToUpperInvariant());
}
@ -153,58 +134,15 @@ namespace BTCPayServer.Services.Rates
static CurrencyData[] LoadCurrency()
{
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BTCPayServer.Currencies.txt");
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BTCPayServer.Rating.Currencies.json");
string content = null;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
content = reader.ReadToEnd();
}
var currencies = content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, CurrencyData> dico = new Dictionary<string, CurrencyData>();
foreach (var currency in currencies)
{
var splitted = currency.Split(new[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (splitted.Length < 3)
continue;
CurrencyData info = new CurrencyData();
info.Name = splitted[0];
info.Code = splitted[1];
int divisibility;
if (!int.TryParse(splitted[2], out divisibility))
continue;
info.Divisibility = divisibility;
if (!dico.ContainsKey(info.Code))
dico.Add(info.Code, info);
if (splitted.Length >= 4)
{
info.Symbol = splitted[3];
}
}
foreach (var network in new BTCPayNetworkProvider(NetworkType.Mainnet).GetAll())
{
if (!dico.TryAdd(network.CryptoCode, new CurrencyData()
{
Code = network.CryptoCode,
Divisibility = network.Divisibility,
Name = network.CryptoCode,
Crypto = true
}))
{
dico[network.CryptoCode].Crypto = true;
}
}
dico.TryAdd("SATS", new CurrencyData()
{
Code = "SATS",
Crypto = true,
Divisibility = 0,
Name = "Satoshis",
Symbol = "Sats",
});
return dico.Values.ToArray();
var currencies = JsonConvert.DeserializeObject<CurrencyData[]>(content);
return currencies;
}
public CurrencyData GetCurrencyData(string currency, bool useFallback)

View File

@ -1,10 +1,10 @@
using System;
using BTCPayServer.Services.Rates;
namespace BTCPayServer.Rating
{
public class CurrencyPair
{
static readonly BTCPayNetworkProvider _NetworkProvider = new BTCPayNetworkProvider(NBitcoin.NetworkType.Mainnet);
public CurrencyPair(string left, string right)
{
if (right == null)
@ -47,13 +47,14 @@ namespace BTCPayServer.Rating
value = new CurrencyPair(currencyPair.Substring(0,3), currencyPair.Substring(3, 3));
return true;
}
for (int i = 3; i < 5; i++)
{
var potentialCryptoName = currencyPair.Substring(0, i);
var network = _NetworkProvider.GetNetwork<BTCPayNetworkBase>(potentialCryptoName);
if (network != null)
var currency = CurrencyNameTable.Instance.GetCurrencyData(potentialCryptoName, false);
if (currency != null)
{
value = new CurrencyPair(network.CryptoCode, currencyPair.Substring(i));
value = new CurrencyPair(currency.Code, currencyPair.Substring(i));
return true;
}
}

View File

@ -0,0 +1,25 @@
using System;
namespace BTCPayServer.Rating
{
public static class Extensions
{
public static decimal RoundToSignificant(this decimal value, ref int divisibility)
{
if (value != 0m)
{
while (true)
{
var rounded = decimal.Round(value, divisibility, MidpointRounding.AwayFromZero);
if ((Math.Abs(rounded - value) / value) < 0.001m)
{
value = rounded;
break;
}
divisibility++;
}
}
return value;
}
}
}

View File

@ -1,13 +1,10 @@
using System;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using BTCPayServer.Rating;
using System.Threading;
using Microsoft.Extensions.Logging.Abstractions;
using BTCPayServer.Logging;
using Newtonsoft.Json;
using System.Reflection;
using System.Globalization;

View File

@ -530,7 +530,10 @@ namespace BTCPayServer.Rating
var rewriter = new ReplaceExchangeRateRewriter();
rewriter.Rates = ExchangeRates;
var result = rewriter.Visit(this.expression);
Errors.AddRange(rewriter.Errors);
foreach (var item in rewriter.Errors)
{
Errors.Add(item);
}
_Evaluated = result.NormalizeWhitespace("", "\n").ToString();
if (HasError)
return false;
@ -539,7 +542,10 @@ namespace BTCPayServer.Rating
calculate.Visit(result);
if (calculate.Values.Count != 1 || calculate.Errors.Count != 0)
{
Errors.AddRange(calculate.Errors);
foreach (var item in calculate.Errors)
{
Errors.Add(item);
}
return false;
}
_BidAsk = calculate.Values.Pop();

View File

@ -632,7 +632,7 @@ namespace BTCPayServer.Tests
(1000.0001m, "₹ 1,000.00 (INR)", "INR")
})
{
var actual = new CurrencyNameTable().DisplayFormatCurrency(test.Item1, test.Item3);
var actual = CurrencyNameTable.Instance.DisplayFormatCurrency(test.Item1, test.Item3);
actual = actual.Replace("¥", "¥"); // Hack so JPY test pass on linux as well
Assert.Equal(test.Item2, actual);
}
@ -1910,6 +1910,20 @@ namespace BTCPayServer.Tests
}
}
[Fact]
[Trait("Fast", "Fast")]
public void HasCurrencyDataForNetworks()
{
var btcPayNetworkProvider = new BTCPayNetworkProvider(NetworkType.Regtest);
foreach (var network in btcPayNetworkProvider.GetAll())
{
var cd = CurrencyNameTable.Instance.GetCurrencyData(network.CryptoCode, false);
Assert.NotNull(cd);
Assert.Equal(network.Divisibility, cd.Divisibility);
Assert.True(cd.Crypto);
}
}
[Fact]
[Trait("Fast", "Fast")]
public void CanParseCurrencyValue()

View File

@ -27,7 +27,6 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="bundleconfig.json" />
<EmbeddedResource Include="Currencies.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BTCPayServer.Hwi" Version="1.1.3" />

View File

@ -1,270 +0,0 @@
Afghani AFN 2
Bitcoin BTC 8 Ƀ
Euro EUR 2 €
Lek ALL 2
Algerian Dinar DZD 2
US Dollar USD 2 $
Euro EUR 2
Kwanza AOA 2
East Caribbean Dollar XCD 2
No universal currency
East Caribbean Dollar XCD 2
Argentine Peso ARS 2
Armenian Dram AMD 2
Aruban Florin AWG 2
Australian Dollar AUD 2 A$
Euro EUR 2
Azerbaijanian Manat AZN 2
Bahamian Dollar BSD 2
Bahraini Dinar BHD 3
Taka BDT 2
Barbados Dollar BBD 2
Belarusian Ruble BYN 2
Belarusian Ruble BYR 0
Euro EUR 2
Belize Dollar BZD 2
CFA Franc BCEAO XOF 0
Bermudian Dollar BMD 2
Indian Rupee INR 2
Ngultrum BTN 2
Boliviano BOB 2
Mvdol BOV 2
US Dollar USD 2
Convertible Mark BAM 2
Pula BWP 2
Norwegian Krone NOK 2
Brazilian Real BRL 2
US Dollar USD 2
Brunei Dollar BND 2
Bulgarian Lev BGN 2
CFA Franc BCEAO XOF 0
Burundi Franc BIF 0
Cabo Verde Escudo CVE 2
Riel KHR 2
CFA Franc BEAC XAF 0
Canadian Dollar CAD 2 CA$
Cayman Islands Dollar KYD 2
CFA Franc BEAC XAF 0
CFA Franc BEAC XAF 0
Chilean Peso CLP 0
Unidad de Fomento CLF 4
Yuan Renminbi CNY 2 CN¥
Australian Dollar AUD 2 A$
Colombian Peso COP 2
Unidad de Valor Real COU 2
Comoro Franc KMF 0
Congolese Franc CDF 2
CFA Franc BEAC XAF 0
New Zealand Dollar NZD 2 NZ$
Costa Rican Colon CRC 2
CFA Franc BCEAO XOF 0
Kuna HRK 2
Cuban Peso CUP 2
Peso Convertible CUC 2
Netherlands Antillean Guilder ANG 2
Euro EUR 2
Czech Koruna CZK 2
Danish Krone DKK 2
Djibouti Franc DJF 0
East Caribbean Dollar XCD 2
Dominican Peso DOP 2
US Dollar USD 2
Egyptian Pound EGP 2
El Salvador Colon SVC 2
US Dollar USD 2
CFA Franc BEAC XAF 0
Nakfa ERN 2
Euro EUR 2
Ethiopian Birr ETB 2
Euro EUR 2
Falkland Islands Pound FKP 2
Danish Krone DKK 2
Fiji Dollar FJD 2
Euro EUR 2
Euro EUR 2
Euro EUR 2
CFP Franc XPF 0
Euro EUR 2
CFA Franc BEAC XAF 0
Dalasi GMD 2
Lari GEL 2
Euro EUR 2
Ghana Cedi GHS 2
Gibraltar Pound GIP 2
Euro EUR 2
Danish Krone DKK 2
East Caribbean Dollar XCD 2
Euro EUR 2
US Dollar USD 2
Quetzal GTQ 2
Pound Sterling GBP 2 £
Guinea Franc GNF 0
CFA Franc BCEAO XOF 0
Guyana Dollar GYD 2
Gourde HTG 2
US Dollar USD 2
Australian Dollar AUD 2
Euro EUR 2
Lempira HNL 2
Hong Kong Dollar HKD 2
Forint HUF 2
Iceland Krona ISK 0
Indian Rupee INR 2
Rupiah IDR 2
SDR (Special Drawing Right) XDR N.A.
Iranian Rial IRR 2
Iraqi Dinar IQD 3
Euro EUR 2
Pound Sterling GBP 2
New Israeli Sheqel ILS 2
Euro EUR 2
Jamaican Dollar JMD 2
Yen JPY 0 ¥
Pound Sterling GBP 2
Jordanian Dinar JOD 3
Tenge KZT 2
Kenyan Shilling KES 2
Australian Dollar AUD 2
North Korean Won KPW 2
Won KRW 0 ₩
Kuwaiti Dinar KWD 3
Som KGS 2
Kip LAK 2
Euro EUR 2
Lebanese Pound LBP 2
Loti LSL 2
Rand ZAR 2
Liberian Dollar LRD 2
Libyan Dinar LYD 3
Swiss Franc CHF 2
Euro EUR 2
Euro EUR 2
Pataca MOP 2
Denar MKD 2
Malagasy Ariary MGA 2
Malawi Kwacha MWK 2
Malaysian Ringgit MYR 2
Rufiyaa MVR 2
CFA Franc BCEAO XOF 0
Euro EUR 2
US Dollar USD 2
Euro EUR 2
Ouguiya MRO 2
Mauritius Rupee MUR 2
Euro EUR 2
ADB Unit of Account XUA N.A.
Mexican Peso MXN 2
Mexican Unidad de Inversion (UDI) MXV 2
US Dollar USD 2
Moldovan Leu MDL 2
Euro EUR 2
Tugrik MNT 2
Euro EUR 2
East Caribbean Dollar XCD 2
Moroccan Dirham MAD 2
Mozambique Metical MZN 2
Kyat MMK 2
Namibia Dollar NAD 2
Rand ZAR 2
Australian Dollar AUD 2
Nepalese Rupee NPR 2
Euro EUR 2
CFP Franc XPF 0
New Zealand Dollar NZD 2
Cordoba Oro NIO 2
CFA Franc BCEAO XOF 0
Naira NGN 2
New Zealand Dollar NZD 2
Australian Dollar AUD 2
US Dollar USD 2
Norwegian Krone NOK 2
Rial Omani OMR 3
Pakistan Rupee PKR 2
US Dollar USD 2
No universal currency
Balboa PAB 2
US Dollar USD 2
Kina PGK 2
Guarani PYG 0
Sol PEN 2
Philippine Peso PHP 2
New Zealand Dollar NZD 2
Zloty PLN 2
Euro EUR 2
US Dollar USD 2
Qatari Rial QAR 2
Euro EUR 2
Romanian Leu RON 2
Russian Ruble RUB 2
Rwanda Franc RWF 0
Euro EUR 2
Saint Helena Pound SHP 2
East Caribbean Dollar XCD 2
East Caribbean Dollar XCD 2
Euro EUR 2
Euro EUR 2
East Caribbean Dollar XCD 2
Tala WST 2
Euro EUR 2
Dobra STD 2
Saudi Riyal SAR 2
CFA Franc BCEAO XOF 0
Serbian Dinar RSD 2
Seychelles Rupee SCR 2
Leone SLL 2
Singapore Dollar SGD 2
Netherlands Antillean Guilder ANG 2
Sucre XSU N.A.
Euro EUR 2
Euro EUR 2
Solomon Islands Dollar SBD 2
Somali Shilling SOS 2
Rand ZAR 2
No universal currency
South Sudanese Pound SSP 2
Euro EUR 2
Sri Lanka Rupee LKR 2
Sudanese Pound SDG 2
Surinam Dollar SRD 2
Norwegian Krone NOK 2
Lilangeni SZL 2
Swedish Krona SEK 2
Swiss Franc CHF 2
WIR Euro CHE 2
WIR Franc CHW 2
Syrian Pound SYP 2
New Taiwan Dollar TWD 2
Somoni TJS 2
Tanzanian Shilling TZS 2
Baht THB 2
US Dollar USD 2
CFA Franc BCEAO XOF 0
New Zealand Dollar NZD 2
Paanga TOP 2
Trinidad and Tobago Dollar TTD 2
Tunisian Dinar TND 3
Turkish Lira TRY 2
Turkmenistan New Manat TMT 2
US Dollar USD 2
Australian Dollar AUD 2
Uganda Shilling UGX 0
Hryvnia UAH 2
UAE Dirham AED 2
Pound Sterling GBP 2
US Dollar USD 2
US Dollar USD 2
US Dollar (Next day) USN 2
Peso Uruguayo UYU 2
Uruguay Peso en Unidades Indexadas (URUIURUI) UYI 0
Uzbekistan Sum UZS 2
Vatu VUV 0
Bolívar VEF 2
Dong VND 0
US Dollar USD 2
US Dollar USD 2
CFP Franc XPF 0
Moroccan Dirham MAD 2
Yemeni Rial YER 2
Zambian Kwacha ZMW 2
Zimbabwe Dollar ZWL 2
Indonesian Rupiah RP 2

View File

@ -11,7 +11,6 @@ namespace BTCPayServer
public class CurrencyValue
{
static Regex _Regex = new Regex("^([0-9]+(\\.[0-9]+)?)\\s*([a-zA-Z]+)$");
static CurrencyNameTable _CurrencyTable = new CurrencyNameTable();
public static bool TryParse(string str, out CurrencyValue value)
{
value = null;
@ -21,7 +20,7 @@ namespace BTCPayServer
return false;
var currency = match.Groups[match.Groups.Count - 1].Value.ToUpperInvariant();
var currencyData = _CurrencyTable.GetCurrencyData(currency, false);
var currencyData = CurrencyNameTable.Instance.GetCurrencyData(currency, false);
if (currencyData == null)
return false;
v = Math.Round(v, currencyData.Divisibility);

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

View File

@ -103,23 +103,6 @@ namespace BTCPayServer
}
return value;
}
public static decimal RoundToSignificant(this decimal value, ref int divisibility)
{
if (value != 0m)
{
while (true)
{
var rounded = decimal.Round(value, divisibility, MidpointRounding.AwayFromZero);
if ((Math.Abs(rounded - value) / value) < 0.001m)
{
value = rounded;
break;
}
divisibility++;
}
}
return value;
}
public static bool HasStatusMessage(this ITempDataDictionary tempData)
{

View File

@ -171,7 +171,7 @@ namespace BTCPayServer.Hosting
services.TryAddSingleton<PaymentRequestRepository>();
services.TryAddSingleton<BTCPayWalletProvider>();
services.TryAddSingleton<WalletReceiveStateService>();
services.TryAddSingleton<CurrencyNameTable>();
services.TryAddSingleton<CurrencyNameTable>(CurrencyNameTable.Instance);
services.TryAddSingleton<IFeeProviderFactory>(o => new NBXplorerFeeProviderFactory(o.GetRequiredService<ExplorerClientProvider>())
{
Fallback = new FeeRate(100L, 1)