Add Gemini, Coinbase & itBit
MODIFY
MagicalCryptoWallet.Backend/Controllers/BlockchainController.cs
MagicalCryptoWallet.Backend/Controllers/BlockchainController.cs
@@ -25,10 +25,12 @@ namespace MagicalCryptoWallet.Backend.Controllers
public class BlockchainController : Controller
{
private readonly IMemoryCache _cache;
+ private readonly IExchangeRateProvider _exchangeRateProvider;
- public BlockchainController(IMemoryCache memoryCache)
+ public BlockchainController(IMemoryCache memoryCache, IExchangeRateProvider exchangeRateProvider)
{
_cache = memoryCache;
+ _exchangeRateProvider = exchangeRateProvider;
}
private static RPCClient RpcClient => Global.RpcClient;
@@ -161,21 +163,10 @@ namespace MagicalCryptoWallet.Backend.Controllers
if (!_cache.TryGetValue(nameof(GetExchangeRatesAsync), out exchangeRates))
{
- var exchangeRateProviders = new IExchangeRateProvider[]{
- new SmartBitExchangeRateProvider(new SmartBitClient(Network.Main, disposeHandler: true)),
- new BlockchainInfoExchangeRateProvider()
- // TODO: More Providers. Which ones?
- };
+ exchangeRates = await _exchangeRateProvider.GetExchangeRateAsync();
- foreach(var provider in exchangeRateProviders)
- {
- try
- {
- exchangeRates = await provider.GetExchangeRateAsync();
- break;
- }catch(Exception){
- // Ignore it and try with the next one
- }
+ if(exchangeRates == null){
+ throw new HttpRequestException("BTC/USD exchange rate is not available.");
}
var cacheEntryOptions = new MemoryCacheEntryOptions()

MODIFY
MagicalCryptoWallet.Backend/Global.cs
MagicalCryptoWallet.Backend/Global.cs
@@ -54,7 +54,7 @@ namespace MagicalCryptoWallet.Backend
{
UserPassword = new NetworkCredential(Config.BitcoinRpcUser, Config.BitcoinRpcPassword)
},
- host: "http://127.0.0.1:18443/",
+ host: "http://127.0.0.1:18332/",
network: Config.Network);
}

MODIFY
MagicalCryptoWallet.Backend/Startup.cs
MagicalCryptoWallet.Backend/Startup.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using MagicalCryptoWallet.WebClients;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
@@ -38,6 +39,8 @@ namespace MagicalCryptoWallet.Backend
var xmlPath = Path.Combine(basePath, "MagicalCryptoWallet.Backend.xml");
c.IncludeXmlComments(xmlPath);
});
+
+ services.AddSingleton<IExchangeRateProvider>(new ExchangeRateProvider() );
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

MODIFY
MagicalCryptoWallet/WebClients/ExchangeRateProviders.cs
MagicalCryptoWallet/WebClients/ExchangeRateProviders.cs
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using MagicalCryptoWallet;
using MagicalCryptoWallet.Backend.Models;
using MagicalCryptoWallet.WebClients.SmartBit;
+using NBitcoin;
using Newtonsoft.Json;
namespace MagicalCryptoWallet.WebClients
@@ -17,7 +18,7 @@ namespace MagicalCryptoWallet.WebClients
}
- public class SmartBitExchangeRateProvider : IExchangeRateProvider
+ class SmartBitExchangeRateProvider : IExchangeRateProvider
{
private SmartBitClient _client;
@@ -40,7 +41,7 @@ namespace MagicalCryptoWallet.WebClients
}
}
- public class BlockchainInfoExchangeRateProvider : IExchangeRateProvider
+ class BlockchainInfoExchangeRateProvider : IExchangeRateProvider
{
class BlockchainInfoExchangeRate{
public decimal Last { get; set; }
@@ -70,6 +71,111 @@ namespace MagicalCryptoWallet.WebClients
}
}
+ class CoinbaseExchangeRateProvider : IExchangeRateProvider
+ {
+ class DataWrapper{
+ public class CoinbaseExchangeRate{
+ public class ExchangeRates{
+ public decimal USD { get; set; }
+ }
+ public ExchangeRates Rates { get; set; }
+ }
+ public CoinbaseExchangeRate Data {get; set;}
+ }
+
+ public async Task<List<ExchangeRate>> GetExchangeRateAsync()
+ {
+ using(var httpClient = new HttpClient())
+ {
+ httpClient.BaseAddress = new Uri("https://api.coinbase.com");
+ var response = await httpClient.GetAsync("/v2/exchange-rates?currency=BTC");
+ var wrapper = await response.ReadAsAsync<DataWrapper>();
+
+ var exchangeRates = new List<ExchangeRate>
+ {
+ new ExchangeRate() { Rate = wrapper.Data.Rates.USD, Ticker = "USD" },
+ };
+
+ return exchangeRates;
+ }
+ }
+ }
+
+
+ public class ItBitExchangeRateProvider : IExchangeRateProvider
+ {
+ class ItBitExchangeRateInfo{
+ public decimal Bid { get; set; }
+ }
+ public async Task<List<ExchangeRate>> GetExchangeRateAsync()
+ {
+ using(var httpClient = new HttpClient())
+ {
+ httpClient.BaseAddress = new Uri("https://api.itbit.com");
+ var response = await httpClient.GetAsync("v1/markets/XBTUSD/ticker");
+ var data = await response.ReadAsAsync<ItBitExchangeRateInfo>();
+
+ var exchangeRates = new List<ExchangeRate>
+ {
+ new ExchangeRate() { Rate = data.Bid, Ticker = "USD" },
+ };
+
+ return exchangeRates;
+ }
+ }
+ }
+
+ public class GeminiExchangeRateProvider : IExchangeRateProvider
+ {
+ class GeminiExchangeRateInfo{
+ public decimal Bid { get; set; }
+ }
+ public async Task<List<ExchangeRate>> GetExchangeRateAsync()
+ {
+ using(var httpClient = new HttpClient())
+ {
+ httpClient.BaseAddress = new Uri("https://api.gemini.com");
+ var response = await httpClient.GetAsync("/v1/pubticker/btcusd");
+ var data = await response.ReadAsAsync<GeminiExchangeRateInfo>();
+
+ var exchangeRates = new List<ExchangeRate>
+ {
+ new ExchangeRate() { Rate = data.Bid, Ticker = "USD" },
+ };
+
+ return exchangeRates;
+ }
+ }
+ }
+
+ public class ExchangeRateProvider : IExchangeRateProvider
+ {
+ private readonly IExchangeRateProvider[] _exchangeRateProviders = new IExchangeRateProvider[]{
+ new SmartBitExchangeRateProvider(new SmartBitClient(Network.Main, disposeHandler: true)),
+ new BlockchainInfoExchangeRateProvider(),
+ new CoinbaseExchangeRateProvider(),
+ new GeminiExchangeRateProvider(),
+ new ItBitExchangeRateProvider()
+ };
+
+ public async Task<List<ExchangeRate>> GetExchangeRateAsync()
+ {
+ List<ExchangeRate> exchangeRates = null;
+
+ foreach(var provider in _exchangeRateProviders)
+ {
+ try
+ {
+ exchangeRates = await provider.GetExchangeRateAsync();
+ break;
+ }catch(Exception){
+ // Ignore it and try with the next one
+ }
+ }
+ return exchangeRates;
+ }
+ }
+
static class HttpResponseMessageExtensions
{
public static async Task<T> ReadAsAsync<T>(this HttpResponseMessage me)

Add Gemini, Coinbase & itBit