This commit is contained in:
nicolas.dorier
2019-07-12 23:34:10 +09:00
parent e488f93b17
commit dc97982fad
6 changed files with 81 additions and 68 deletions

View File

@@ -70,61 +70,73 @@ namespace BTCPayServer.Services.Rates
//} //}
//b.AppendLine("}.ToArray()"); //b.AppendLine("}.ToArray()");
AvailableExchanges = new CoinAverageExchanges(); AvailableExchanges = new CoinAverageExchanges();
foreach(var item in foreach (var item in
new[] { new[] {
(DisplayName: "BitBargain", Name: "bitbargain"), (DisplayName: "Idex", Name: "idex"),
(DisplayName: "Tidex", Name: "tidex"),
(DisplayName: "LocalBitcoins", Name: "localbitcoins"),
(DisplayName: "EtherDelta", Name: "etherdelta"),
(DisplayName: "Kraken", Name: "kraken"),
(DisplayName: "BitBay", Name: "bitbay"),
(DisplayName: "Independent Reserve", Name: "independentreserve"),
(DisplayName: "Exmoney", Name: "exmoney"),
(DisplayName: "Bitcoin.co.id", Name: "bitcoin_co_id"),
(DisplayName: "Huobi", Name: "huobi"),
(DisplayName: "GDAX", Name: "gdax"),
(DisplayName: "Coincheck", Name: "coincheck"),
(DisplayName: "Bittylicious", Name: "bittylicious"),
(DisplayName: "Gemini", Name: "gemini"),
(DisplayName: "Bit2C", Name: "bit2c"),
(DisplayName: "Luno", Name: "luno"),
(DisplayName: "Negocie Coins", Name: "negociecoins"),
(DisplayName: "FYB-SE", Name: "fybse"),
(DisplayName: "Hitbtc", Name: "hitbtc"),
(DisplayName: "Bitex.la", Name: "bitex"),
(DisplayName: "Korbit", Name: "korbit"),
(DisplayName: "itBit", Name: "itbit"),
(DisplayName: "Okex", Name: "okex"),
(DisplayName: "Bitsquare", Name: "bitsquare"),
(DisplayName: "Bitfinex", Name: "bitfinex"),
(DisplayName: "CoinMate", Name: "coinmate"),
(DisplayName: "Bitstamp", Name: "bitstamp"),
(DisplayName: "Cryptonit", Name: "cryptonit"),
(DisplayName: "Foxbit", Name: "foxbit"),
(DisplayName: "QuickBitcoin", Name: "quickbitcoin"),
(DisplayName: "Poloniex", Name: "poloniex"),
(DisplayName: "Bit-Z", Name: "bitz"),
(DisplayName: "Liqui", Name: "liqui"),
(DisplayName: "BitKonan", Name: "bitkonan"),
(DisplayName: "Kucoin", Name: "kucoin"),
(DisplayName: "Binance", Name: "binance"),
(DisplayName: "Rock Trading", Name: "rocktrading"),
(DisplayName: "Mercado Bitcoin", Name: "mercado"),
(DisplayName: "Coinsecure", Name: "coinsecure"),
(DisplayName: "Coinfloor", Name: "coinfloor"), (DisplayName: "Coinfloor", Name: "coinfloor"),
(DisplayName: "bitFlyer", Name: "bitflyer"), (DisplayName: "Okex", Name: "okex"),
(DisplayName: "BTCTurk", Name: "btcturk"), (DisplayName: "Bitfinex", Name: "bitfinex"),
(DisplayName: "Bittrex", Name: "bittrex"), (DisplayName: "Bittylicious", Name: "bittylicious"),
(DisplayName: "CampBX", Name: "campbx"),
(DisplayName: "Zaif", Name: "zaif"),
(DisplayName: "FYB-SG", Name: "fybsg"),
(DisplayName: "Quoine", Name: "quoine"),
(DisplayName: "BTC Markets", Name: "btcmarkets"), (DisplayName: "BTC Markets", Name: "btcmarkets"),
(DisplayName: "Kucoin", Name: "kucoin"),
(DisplayName: "IDAX", Name: "idax"),
(DisplayName: "Kraken", Name: "kraken"),
(DisplayName: "Bit2C", Name: "bit2c"),
(DisplayName: "Mercado Bitcoin", Name: "mercado"),
(DisplayName: "CEX.IO", Name: "cex"),
(DisplayName: "Bitex.la", Name: "bitex"),
(DisplayName: "Quoine", Name: "quoine"),
(DisplayName: "Stex", Name: "stex"),
(DisplayName: "CoinTiger", Name: "cointiger"),
(DisplayName: "Poloniex", Name: "poloniex"),
(DisplayName: "Zaif", Name: "zaif"),
(DisplayName: "Huobi", Name: "huobi"),
(DisplayName: "QuickBitcoin", Name: "quickbitcoin"),
(DisplayName: "Tidex", Name: "tidex"),
(DisplayName: "Tokenomy", Name: "tokenomy"),
(DisplayName: "Bitcoin.co.id", Name: "bitcoin_co_id"),
(DisplayName: "Kryptono", Name: "kryptono"),
(DisplayName: "Bitso", Name: "bitso"), (DisplayName: "Bitso", Name: "bitso"),
(DisplayName: "Korbit", Name: "korbit"),
(DisplayName: "Yobit", Name: "yobit"),
(DisplayName: "BitBargain", Name: "bitbargain"),
(DisplayName: "Livecoin", Name: "livecoin"),
(DisplayName: "Hotbit", Name: "hotbit"),
(DisplayName: "Coincheck", Name: "coincheck"),
(DisplayName: "Binance", Name: "binance"),
(DisplayName: "Bit-Z", Name: "bitz"),
(DisplayName: "Coinbase Pro", Name: "coinbasepro"),
(DisplayName: "Rock Trading", Name: "rocktrading"),
(DisplayName: "Bittrex", Name: "bittrex"),
(DisplayName: "BitBay", Name: "bitbay"),
(DisplayName: "Tokenize", Name: "tokenize"),
(DisplayName: "Hitbtc", Name: "hitbtc"),
(DisplayName: "Upbit", Name: "upbit"),
(DisplayName: "Bitstamp", Name: "bitstamp"),
(DisplayName: "Luno", Name: "luno"),
(DisplayName: "Trade.io", Name: "tradeio"),
(DisplayName: "LocalBitcoins", Name: "localbitcoins"),
(DisplayName: "Independent Reserve", Name: "independentreserve"),
(DisplayName: "Coinsquare", Name: "coinsquare"),
(DisplayName: "Exmoney", Name: "exmoney"),
(DisplayName: "Coinegg", Name: "coinegg"),
(DisplayName: "FYB-SG", Name: "fybsg"),
(DisplayName: "Cryptonit", Name: "cryptonit"),
(DisplayName: "BTCTurk", Name: "btcturk"),
(DisplayName: "bitFlyer", Name: "bitflyer"),
(DisplayName: "Negocie Coins", Name: "negociecoins"),
(DisplayName: "OasisDEX", Name: "oasisdex"),
(DisplayName: "CoinMate", Name: "coinmate"),
(DisplayName: "BitForex", Name: "bitforex"),
(DisplayName: "Bitsquare", Name: "bitsquare"),
(DisplayName: "FYB-SE", Name: "fybse"),
(DisplayName: "itBit", Name: "itbit"),
}) })
{ {
AvailableExchanges.TryAdd(item.Name, new CoinAverageExchange(item.Name, item.DisplayName, $"https://apiv2.bitcoinaverage.com/exchanges/{item.Name}")); AvailableExchanges.TryAdd(item.Name, new CoinAverageExchange(item.Name, item.DisplayName, $"https://apiv2.bitcoinaverage.com/exchanges/{item.Name}"));
} }
// Keep back-compat
AvailableExchanges.Add(new CoinAverageExchange("gdax", string.Empty, $"https://apiv2.bitcoinaverage.com/exchanges/coinbasepro"));
} }
public Task AddHeader(HttpRequestMessage message) public Task AddHeader(HttpRequestMessage message)

View File

@@ -116,7 +116,6 @@ namespace BTCPayServer.Services.Rates
Providers.Add("bitbank", new BitbankRateProvider(_httpClientFactory?.CreateClient("EXCHANGE_BITBANK"))); Providers.Add("bitbank", new BitbankRateProvider(_httpClientFactory?.CreateClient("EXCHANGE_BITBANK")));
// Those exchanges make multiple requests when calling GetTickers so we remove them // Those exchanges make multiple requests when calling GetTickers so we remove them
//DirectProviders.Add("gdax", new ExchangeSharpRateProvider("gdax", new ExchangeGdaxAPI()));
//DirectProviders.Add("gemini", new ExchangeSharpRateProvider("gemini", new ExchangeGeminiAPI())); //DirectProviders.Add("gemini", new ExchangeSharpRateProvider("gemini", new ExchangeGeminiAPI()));
//DirectProviders.Add("bitfinex", new ExchangeSharpRateProvider("bitfinex", new ExchangeBitfinexAPI())); //DirectProviders.Add("bitfinex", new ExchangeSharpRateProvider("bitfinex", new ExchangeBitfinexAPI()));
//DirectProviders.Add("okex", new ExchangeSharpRateProvider("okex", new ExchangeOkexAPI())); //DirectProviders.Add("okex", new ExchangeSharpRateProvider("okex", new ExchangeOkexAPI()));

View File

@@ -34,7 +34,7 @@ namespace BTCPayServer.Tests
builder.AppendLine("DOGE_X = DOGE_BTC * BTC_X * 1.1"); builder.AppendLine("DOGE_X = DOGE_BTC * BTC_X * 1.1");
builder.AppendLine("DOGE_BTC = Bittrex(DOGE_BTC)"); builder.AppendLine("DOGE_BTC = Bittrex(DOGE_BTC)");
builder.AppendLine("// Some other cool comments"); builder.AppendLine("// Some other cool comments");
builder.AppendLine("BTC_usd = GDax(BTC_USD)"); builder.AppendLine("BTC_usd = kraken(BTC_USD)");
builder.AppendLine("BTC_X = Coinbase(BTC_X);"); builder.AppendLine("BTC_X = Coinbase(BTC_X);");
builder.AppendLine("X_X = CoinAverage(X_X) * 1.02"); builder.AppendLine("X_X = CoinAverage(X_X) * 1.02");
@@ -45,14 +45,14 @@ namespace BTCPayServer.Tests
"DOGE_X = DOGE_BTC * BTC_X * 1.1;\n" + "DOGE_X = DOGE_BTC * BTC_X * 1.1;\n" +
"DOGE_BTC = bittrex(DOGE_BTC);\n" + "DOGE_BTC = bittrex(DOGE_BTC);\n" +
"// Some other cool comments\n" + "// Some other cool comments\n" +
"BTC_USD = gdax(BTC_USD);\n" + "BTC_USD = kraken(BTC_USD);\n" +
"BTC_X = coinbase(BTC_X);\n" + "BTC_X = coinbase(BTC_X);\n" +
"X_X = coinaverage(X_X) * 1.02;", "X_X = coinaverage(X_X) * 1.02;",
rules.ToString()); rules.ToString());
var tests = new[] var tests = new[]
{ {
(Pair: "DOGE_USD", Expected: "bittrex(DOGE_BTC) * gdax(BTC_USD) * 1.1"), (Pair: "DOGE_USD", Expected: "bittrex(DOGE_BTC) * kraken(BTC_USD) * 1.1"),
(Pair: "BTC_USD", Expected: "gdax(BTC_USD)"), (Pair: "BTC_USD", Expected: "kraken(BTC_USD)"),
(Pair: "BTC_CAD", Expected: "coinbase(BTC_CAD)"), (Pair: "BTC_CAD", Expected: "coinbase(BTC_CAD)"),
(Pair: "DOGE_CAD", Expected: "bittrex(DOGE_BTC) * coinbase(BTC_CAD) * 1.1"), (Pair: "DOGE_CAD", Expected: "bittrex(DOGE_BTC) * coinbase(BTC_CAD) * 1.1"),
(Pair: "LTC_CAD", Expected: "coinaverage(LTC_CAD) * 1.02"), (Pair: "LTC_CAD", Expected: "coinaverage(LTC_CAD) * 1.02"),
@@ -62,14 +62,14 @@ 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.Spread = 0.2m; rules.Spread = 0.2m;
Assert.Equal("(bittrex(DOGE_BTC) * gdax(BTC_USD) * 1.1) * (0.8, 1.2)", rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD")).ToString()); Assert.Equal("(bittrex(DOGE_BTC) * kraken(BTC_USD) * 1.1) * (0.8, 1.2)", rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD")).ToString());
//////////////// ////////////////
// Check errors conditions // Check errors conditions
builder = new StringBuilder(); builder = new StringBuilder();
builder.AppendLine("DOGE_X = LTC_CAD * BTC_X * 1.1"); builder.AppendLine("DOGE_X = LTC_CAD * BTC_X * 1.1");
builder.AppendLine("DOGE_BTC = Bittrex(DOGE_BTC)"); builder.AppendLine("DOGE_BTC = Bittrex(DOGE_BTC)");
builder.AppendLine("BTC_usd = GDax(BTC_USD)"); builder.AppendLine("BTC_usd = kraken(BTC_USD)");
builder.AppendLine("LTC_CHF = LTC_CHF * 1.01"); builder.AppendLine("LTC_CHF = LTC_CHF * 1.01");
builder.AppendLine("BTC_X = Coinbase(BTC_X)"); builder.AppendLine("BTC_X = Coinbase(BTC_X)");
Assert.True(RateRules.TryParse(builder.ToString(), out rules)); Assert.True(RateRules.TryParse(builder.ToString(), out rules));
@@ -77,7 +77,7 @@ namespace BTCPayServer.Tests
tests = new[] tests = new[]
{ {
(Pair: "LTC_CAD", Expected: "ERR_NO_RULE_MATCH(LTC_CAD)"), (Pair: "LTC_CAD", Expected: "ERR_NO_RULE_MATCH(LTC_CAD)"),
(Pair: "DOGE_USD", Expected: "ERR_NO_RULE_MATCH(LTC_CAD) * gdax(BTC_USD) * 1.1"), (Pair: "DOGE_USD", Expected: "ERR_NO_RULE_MATCH(LTC_CAD) * kraken(BTC_USD) * 1.1"),
(Pair: "LTC_CHF", Expected: "ERR_TOO_MUCH_NESTED_CALLS(LTC_CHF) * 1.01"), (Pair: "LTC_CHF", Expected: "ERR_TOO_MUCH_NESTED_CALLS(LTC_CHF) * 1.01"),
}; };
foreach (var test in tests) foreach (var test in tests)
@@ -90,15 +90,15 @@ namespace BTCPayServer.Tests
builder = new StringBuilder(); builder = new StringBuilder();
builder.AppendLine("DOGE_X = DOGE_BTC * BTC_X * 1.1"); builder.AppendLine("DOGE_X = DOGE_BTC * BTC_X * 1.1");
builder.AppendLine("DOGE_BTC = Bittrex(DOGE_BTC)"); builder.AppendLine("DOGE_BTC = Bittrex(DOGE_BTC)");
builder.AppendLine("BTC_usd = GDax(BTC_USD)"); builder.AppendLine("BTC_usd = kraken(BTC_USD)");
builder.AppendLine("BTC_X = Coinbase(BTC_X)"); builder.AppendLine("BTC_X = Coinbase(BTC_X)");
builder.AppendLine("X_X = CoinAverage(X_X) * 1.02"); builder.AppendLine("X_X = CoinAverage(X_X) * 1.02");
Assert.True(RateRules.TryParse(builder.ToString(), out rules)); Assert.True(RateRules.TryParse(builder.ToString(), out rules));
var tests2 = new[] var tests2 = new[]
{ {
(Pair: "DOGE_USD", Expected: "bittrex(DOGE_BTC) * gdax(BTC_USD) * 1.1", ExpectedExchangeRates: "bittrex(DOGE_BTC),gdax(BTC_USD)"), (Pair: "DOGE_USD", Expected: "bittrex(DOGE_BTC) * kraken(BTC_USD) * 1.1", ExpectedExchangeRates: "bittrex(DOGE_BTC),kraken(BTC_USD)"),
(Pair: "BTC_USD", Expected: "gdax(BTC_USD)", ExpectedExchangeRates: "gdax(BTC_USD)"), (Pair: "BTC_USD", Expected: "kraken(BTC_USD)", ExpectedExchangeRates: "kraken(BTC_USD)"),
(Pair: "BTC_CAD", Expected: "coinbase(BTC_CAD)", ExpectedExchangeRates: "coinbase(BTC_CAD)"), (Pair: "BTC_CAD", Expected: "coinbase(BTC_CAD)", ExpectedExchangeRates: "coinbase(BTC_CAD)"),
(Pair: "DOGE_CAD", Expected: "bittrex(DOGE_BTC) * coinbase(BTC_CAD) * 1.1", ExpectedExchangeRates: "bittrex(DOGE_BTC),coinbase(BTC_CAD)"), (Pair: "DOGE_CAD", Expected: "bittrex(DOGE_BTC) * coinbase(BTC_CAD) * 1.1", ExpectedExchangeRates: "bittrex(DOGE_BTC),coinbase(BTC_CAD)"),
(Pair: "LTC_CAD", Expected: "coinaverage(LTC_CAD) * 1.02", ExpectedExchangeRates: "coinaverage(LTC_CAD)"), (Pair: "LTC_CAD", Expected: "coinaverage(LTC_CAD) * 1.02", ExpectedExchangeRates: "coinaverage(LTC_CAD)"),

View File

@@ -9,6 +9,7 @@ using NBitcoin.DataEncoders;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Xunit; using Xunit;
using System.IO; using System.IO;
using BTCPayServer.Services.Rates;
namespace BTCPayServer.Tests namespace BTCPayServer.Tests
{ {

View File

@@ -590,6 +590,7 @@ namespace BTCPayServer.Controllers
private CoinAverageExchange[] GetSupportedExchanges() private CoinAverageExchange[] GetSupportedExchanges()
{ {
return _RateFactory.RateProviderFactory.GetSupportedExchanges() return _RateFactory.RateProviderFactory.GetSupportedExchanges()
.Where(r => !string.IsNullOrWhiteSpace(r.Value.Display))
.Select(c => c.Value) .Select(c => c.Value)
.OrderBy(s => s.Name, StringComparer.OrdinalIgnoreCase) .OrderBy(s => s.Name, StringComparer.OrdinalIgnoreCase)
.ToArray(); .ToArray();

View File

@@ -58,25 +58,25 @@
<div id="help" class="collapse text-left"> <div id="help" class="collapse text-left">
<p> <p>
The script language is composed of several rules composed of a currency pair and a mathematic expression. The script language is composed of several rules composed of a currency pair and a mathematic expression.
The example below will use <code>gdax</code> for both <code>LTC_USD</code> and <code>BTC_USD</code> pairs. The example below will use <code>kraken</code> for both <code>LTC_USD</code> and <code>BTC_USD</code> pairs.
</p> </p>
<pre> <pre>
<code> <code>
LTC_USD = gdax(LTC_USD); LTC_USD = kraken(LTC_USD);
BTC_USD = gdax(BTC_USD); BTC_USD = kraken(BTC_USD);
</code> </code>
</pre> </pre>
<p>However, explicitely setting specific pairs like this can be a bit difficult. Instead, you can define a rule <code>X_X</code> which will match any currency pair. The following example will use <code>gdax</code> for getting the rate of any currency pair.</p> <p>However, explicitely setting specific pairs like this can be a bit difficult. Instead, you can define a rule <code>X_X</code> which will match any currency pair. The following example will use <code>kraken</code> for getting the rate of any currency pair.</p>
<pre> <pre>
<code> <code>
X_X = gdax(X_X); X_X = kraken(X_X);
</code> </code>
</pre> </pre>
<p>However, <code>gdax</code> does not support the <code>BTC_CAD</code> pair. For this reason you can add a rule mapping all <code>X_CAD</code> to <code>quadrigacx</code>, a Canadian exchange.</p> <p>However, <code>kraken</code> does not support the <code>BTC_CAD</code> pair. For this reason you can add a rule mapping all <code>X_CAD</code> to <code>quadrigacx</code>, a Canadian exchange.</p>
<pre> <pre>
<code> <code>
X_CAD = quadrigacx(X_CAD); X_CAD = quadrigacx(X_CAD);
X_X = gdax(X_X); X_X = kraken(X_X);
</code> </code>
</pre> </pre>
<p>A given currency pair match the most specific rule. If two rules are matching and are as specific, the first rule will be chosen.</p> <p>A given currency pair match the most specific rule. If two rules are matching and are as specific, the first rule will be chosen.</p>
@@ -88,11 +88,11 @@
<code> <code>
DOGE_X = bittrex(DOGE_BTC) * BTC_X DOGE_X = bittrex(DOGE_BTC) * BTC_X
X_CAD = quadrigacx(X_CAD); X_CAD = quadrigacx(X_CAD);
X_X = gdax(X_X); X_X = kraken(X_X);
</code> </code>
</pre> </pre>
<p> <p>
With <code>DOGE_USD</code> will be expanded to <code>bittrex(DOGE_BTC) * gdax(BTC_USD)</code>. And <code>DOGE_CAD</code> will be expanded to <code>bittrex(DOGE_BTC) * quadrigacx(BTC_CAD)</code>. <br /> With <code>DOGE_USD</code> will be expanded to <code>bittrex(DOGE_BTC) * kraken(BTC_USD)</code>. And <code>DOGE_CAD</code> will be expanded to <code>bittrex(DOGE_BTC) * quadrigacx(BTC_CAD)</code>. <br />
However, we advise you to write it that way to increase coverage so that <code>DOGE_BTC</code> is also supported: However, we advise you to write it that way to increase coverage so that <code>DOGE_BTC</code> is also supported:
</p> </p>
<pre> <pre>
@@ -100,7 +100,7 @@
DOGE_X = DOGE_BTC * BTC_X DOGE_X = DOGE_BTC * BTC_X
DOGE_BTC = bittrex(DOGE_BTC) DOGE_BTC = bittrex(DOGE_BTC)
X_CAD = quadrigacx(X_CAD); X_CAD = quadrigacx(X_CAD);
X_X = gdax(X_X); X_X = kraken(X_X);
</code> </code>
</pre> </pre>
<p> <p>