diff --git a/src/CoinMarketCap/Currencies.cs b/src/CoinMarketCap/Currencies.cs
new file mode 100644
index 0000000..121134f
--- /dev/null
+++ b/src/CoinMarketCap/Currencies.cs
@@ -0,0 +1,16 @@
+namespace Kalakoi.Crypto.CoinMarketCap
+{
+ ///
+ /// Fiat currencies available for price conversions.
+ ///
+ public enum Currencies
+ {
+ USD, AUD, BRL, CAD, CHF,
+ CLP, CNY, CZK, DKK, EUR,
+ GBP, HKD, HUF, IDR, ILS,
+ INR, JPY, KRW, MXN, MYR,
+ NOK, NZD, PHP, PKR, PLN,
+ RUB, SEK, SGD, THB, TRY,
+ TWD, ZAR
+ }
+}
diff --git a/src/CoinMarketCap/GlobalData.cs b/src/CoinMarketCap/GlobalData.cs
new file mode 100644
index 0000000..373721f
--- /dev/null
+++ b/src/CoinMarketCap/GlobalData.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Kalakoi.Crypto.CoinMarketCap
+{
+ ///
+ /// Provides access to global data provided by CoinMarketCap
+ ///
+ public class GlobalData
+ {
+ ///
+ /// Market capitalization in USD.
+ ///
+ public double TotalMarketCapUSD { get; private set; }
+ ///
+ /// 24 Hour trade volume in USD.
+ ///
+ public double Total24HourVolumeUSD { get; private set; }
+ ///
+ /// Bitcoin percentage dominance.
+ ///
+ public double BitcoinPercentageOfMarketCap { get; private set; }
+ ///
+ /// Number of active currencies on CoinMarketCap.
+ ///
+ public int ActiveCurrencies { get; private set; }
+ ///
+ /// Number of active assets on CoinMarketCap.
+ ///
+ public int ActiveAssets { get; private set; }
+ ///
+ /// Number of active markets on CoinMarketCap.
+ ///
+ public int ActiveMarkets { get; private set; }
+ ///
+ /// Timestamp for when API was last updated.
+ ///
+ public int LastUpdated { get; private set; }
+ ///
+ /// Currency specified for value conversions.
+ ///
+ public Currencies Currency { get; private set; }
+ ///
+ /// Market capitalization in specified currency.
+ ///
+ public double TotalMarketCap { get; private set; }
+ ///
+ /// 24 hour trade volume in specified currency.
+ ///
+ public double Total24HourVolume { get; private set; }
+
+ private GlobalData() { }
+
+ internal static async Task GetDataAsync(Currencies currency = Currencies.USD)
+ {
+ Uri uri = GetUri(currency);
+ string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
+ return await ParseResponseAsync(response, currency).ConfigureAwait(false);
+ }
+
+ private static Uri GetUri(Currencies currency)
+ {
+ string BaseUrl = @"https://api.coinmarketcap.com/v1/global/{0}";
+ string AdditionFormat = "?convert={0}";
+ string Addition = string.Empty;
+ if (currency != Currencies.USD)
+ Addition = string.Format(AdditionFormat, currency.ToString());
+ return new Uri(string.Format(BaseUrl, Addition));
+ }
+
+ private static async Task ParseResponseAsync(string response, Currencies currency)
+ {
+ GlobalData data = new GlobalData();
+ data.Currency = currency;
+ using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
+ {
+ while (await jtr.ReadAsync().ConfigureAwait(false))
+ {
+ if (jtr.Value != null)
+ {
+ if (jtr.Value.ToString() == "total_market_cap_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.TotalMarketCapUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "total_24h_volume_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.Total24HourVolumeUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "bitcoin_percentage_of_market_cap")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.BitcoinPercentageOfMarketCap = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "active_currencies")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.ActiveCurrencies = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "active_assets")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.ActiveAssets = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "active_markets")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.ActiveMarkets = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "last_updated")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.LastUpdated = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("total_market_cap_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.TotalMarketCap = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("total_24h_volume_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ data.Total24HourVolume = Convert.ToDouble(jtr.Value.ToString());
+ }
+ }
+ else continue;
+ }
+ }
+ if (currency == Currencies.USD)
+ {
+ data.TotalMarketCap = data.TotalMarketCapUSD;
+ data.Total24HourVolume = data.Total24HourVolumeUSD;
+ }
+ return data;
+ }
+ }
+}
diff --git a/src/CoinMarketCap/Ticker.cs b/src/CoinMarketCap/Ticker.cs
new file mode 100644
index 0000000..3410050
--- /dev/null
+++ b/src/CoinMarketCap/Ticker.cs
@@ -0,0 +1,384 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Kalakoi.Crypto.CoinMarketCap
+{
+ ///
+ /// Provides access to ticker data provided by CoinMarketCap
+ ///
+ public class Ticker
+ {
+ ///
+ /// ID specific to CoinMarketCap.
+ ///
+ public string ID { get; private set; }
+ ///
+ /// Currency name.
+ ///
+ public string Name { get; private set; }
+ ///
+ /// Ticker symbol.
+ ///
+ public string Symbol { get; private set; }
+ ///
+ /// Rank among all active assets by market capitalization.
+ ///
+ public int Rank { get; private set; }
+ ///
+ /// Price per unit in USD.
+ ///
+ public double PriceUSD { get; private set; }
+ ///
+ /// Price per unit in BTC.
+ ///
+ public double PriceBTC { get; private set; }
+ ///
+ /// 24 hour trade volume in USD.
+ ///
+ public double Volume24HourUSD { get; private set; }
+ ///
+ /// Market capitalization in USD.
+ ///
+ public double MarketCapUSD { get; private set; }
+ ///
+ /// Available coin supply.
+ ///
+ public double AvailableSupply { get; private set; }
+ ///
+ /// Total coin supply.
+ ///
+ public double TotalSupply { get; private set; }
+ ///
+ /// Maximum coin supply, if applicable.
+ ///
+ public double MaxSupply { get; private set; }
+ ///
+ /// Percentage price change in last hour.
+ ///
+ public double PercentChange1Hour { get; private set; }
+ ///
+ /// Percentage price change in last 24 hours.
+ ///
+ public double PercentChange24Hour { get; private set; }
+ ///
+ /// Percentage price change in last 7 days.
+ ///
+ public double PercentChange7Day { get; private set; }
+ ///
+ /// Timestamp of when API was last updated.
+ ///
+ public int LastUpdated { get; private set; }
+ ///
+ /// Fiat currency to convert values to.
+ ///
+ public Currencies Currency { get; private set; }
+ ///
+ /// Price per unit in specified currency.
+ ///
+ public double Price { get; private set; }
+ ///
+ /// 24 hour trade volume in specified currency.
+ ///
+ public double Volume24Hour { get; private set; }
+ ///
+ /// Market capitalization in specified currency.
+ ///
+ public double MarketCap { get; private set; }
+
+ private Ticker() { }
+
+ internal static async Task> GetTickersAsync(Currencies currency = Currencies.USD, int start = 0, int limit = 100)
+ {
+ Uri uri = GetListUri(currency, start, limit);
+ string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
+ return await ParseListResponseAsync(response, currency).ConfigureAwait(false);
+ }
+
+ internal static async Task GetTickerAsync(string id, Currencies currency = Currencies.USD)
+ {
+ Uri uri = GetSingleUri(currency, id);
+ string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
+ return await ParseSingleResponseAsync(response, currency).ConfigureAwait(false);
+ }
+
+ private static Uri GetListUri(Currencies currency, int start, int limit)
+ {
+ string BaseUrl = @"https://api.coinmarketcap.com/v1/ticker/";
+ string AdditionFormat = "{0}{1}={2}";
+ string UrlAddition = string.Empty;
+ bool HasFirstAddition = false;
+ if (currency != Currencies.USD)
+ {
+ UrlAddition += string.Format(AdditionFormat, HasFirstAddition ? "&" : "?", "convert", currency.ToString());
+ HasFirstAddition = true;
+ }
+ if (start != 0)
+ {
+ UrlAddition += string.Format(AdditionFormat, HasFirstAddition ? "&" : "?", "start", start.ToString());
+ HasFirstAddition = true;
+ }
+ if (limit != 100)
+ {
+ UrlAddition += string.Format(AdditionFormat, HasFirstAddition ? "&" : "?", "limit", limit.ToString());
+ HasFirstAddition = true;
+ }
+ return new Uri(BaseUrl + UrlAddition);
+ }
+
+ private static Uri GetSingleUri(Currencies currency, string id)
+ {
+ string BaseUrl = @"https://api.coinmarketcap.com/v1/ticker/{0}/{1}";
+ string AdditionFormat = "?convert={0}";
+ string Addition = string.Empty;
+ if (currency != Currencies.USD)
+ Addition = string.Format(AdditionFormat, currency.ToString());
+ return new Uri(string.Format(BaseUrl, id, Addition));
+ }
+
+ private static async Task> ParseListResponseAsync(string response, Currencies currency)
+ {
+ List TickerList = new List();
+ Ticker ToAdd = new Ticker();
+ ToAdd.Currency = currency;
+ using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
+ {
+ while (await jtr.ReadAsync().ConfigureAwait(false))
+ {
+ if (jtr.TokenType.ToString() == "StartObject")
+ {
+ if (!string.IsNullOrEmpty(ToAdd.Name))
+ {
+ if (currency == Currencies.USD)
+ {
+ ToAdd.Price = ToAdd.PriceUSD;
+ ToAdd.Volume24Hour = ToAdd.Volume24HourUSD;
+ ToAdd.MarketCap = ToAdd.MarketCapUSD;
+ }
+ TickerList.Add(ToAdd);
+ }
+ ToAdd = new Ticker();
+ ToAdd.Currency = currency;
+ continue;
+ }
+ if (jtr.Value != null)
+ {
+ if (jtr.Value.ToString() == "id")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.ID = jtr.Value.ToString();
+ }
+ else if (jtr.Value.ToString() == "name")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Name = jtr.Value.ToString();
+ }
+ else if (jtr.Value.ToString() == "symbol")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Symbol = jtr.Value.ToString();
+ }
+ else if (jtr.Value.ToString() == "rank")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Rank = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "price_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PriceUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "price_btc")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PriceBTC = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "24h_volume_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Volume24HourUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "market_cap_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.MarketCapUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "available_supply")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.AvailableSupply = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "total_supply")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.TotalSupply = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "max_supply")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.MaxSupply = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "percent_change_1h")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PercentChange1Hour = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "percent_change_24h")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PercentChange24Hour = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "percent_change_7d")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PercentChange7Day = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "last_updated")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.LastUpdated = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("price_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Price = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("24h_volume_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Volume24Hour = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("market_cap_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.MarketCap = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else continue;
+ }
+ else continue;
+ }
+ }
+ if (!string.IsNullOrEmpty(ToAdd.Name))
+ {
+ if (currency == Currencies.USD)
+ {
+ ToAdd.Price = ToAdd.PriceUSD;
+ ToAdd.Volume24Hour = ToAdd.Volume24HourUSD;
+ ToAdd.MarketCap = ToAdd.MarketCapUSD;
+ }
+ TickerList.Add(ToAdd);
+ }
+ return TickerList;
+ }
+
+ private static async Task ParseSingleResponseAsync(string response, Currencies currency)
+ {
+ Ticker ToAdd = new Ticker();
+ ToAdd.Currency = currency;
+ using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
+ {
+ while (await jtr.ReadAsync().ConfigureAwait(false))
+ {
+ if (jtr.Value != null)
+ {
+ if (jtr.Value.ToString() == "id")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.ID = jtr.Value.ToString();
+ }
+ else if (jtr.Value.ToString() == "name")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Name = jtr.Value.ToString();
+ }
+ else if (jtr.Value.ToString() == "symbol")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Symbol = jtr.Value.ToString();
+ }
+ else if (jtr.Value.ToString() == "rank")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Rank = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "price_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PriceUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "price_btc")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PriceBTC = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "24h_volume_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Volume24HourUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "market_cap_usd")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.MarketCapUSD = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "available_supply")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.AvailableSupply = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "total_supply")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.TotalSupply = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "max_supply")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.MaxSupply = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "percent_change_1h")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PercentChange1Hour = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "percent_change_24h")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PercentChange24Hour = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "percent_change_7d")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.PercentChange7Day = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == "last_updated")
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.LastUpdated = Convert.ToInt32(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("price_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Price = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("24h_volume_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.Volume24Hour = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else if (jtr.Value.ToString() == string.Format("market_cap_{0}", currency.ToString().ToLower()))
+ {
+ await jtr.ReadAsync().ConfigureAwait(false);
+ ToAdd.MarketCap = Convert.ToDouble(jtr.Value.ToString());
+ }
+ else continue;
+ }
+ else continue;
+ }
+ }
+ return ToAdd;
+ }
+ }
+}