using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using System.Windows;
using Prism.Mvvm;
using Newtonsoft.Json;
// https://coinmarketcap.com/
// https://coinmarketcap.com/api/
// https://pro.coinmarketcap.com/account
// https://coinmarketcap.com/api/documentation/v1/#section/Quick-Start-Guide
namespace CryptoSentiment
{
#region Models
public class ResponseStatus
{
public DateTime timestamp;
public int error_code;
public string error_message;
public int elapsed;
public int credit_count;
public string notice;
}
public class Platform
{
public int id;
public string name;
public string symbol;
public string slug;
public string token_address;
}
public class QuoteData
{
public double price;
public double volume_24h;
public double percent_change_1h;
public double percent_change_24h;
public double percent_change_7d;
public double percent_change_30d;
public double percent_change_60d;
public double percent_change_90d;
public double market_cap;
public double market_cap_dominance;
public double fully_diluted_market_cap;
public DateTime last_updated;
}
public class LatestQuoteResp
{
public int id;
public string name;
public string symbol;
public string slug;
public int num_market_pairs;
public DateTime date_added;
// tags
public double? max_supply;
public double? circulating_supply;
public double? total_supply;
public Platform platform;
public int is_active;
public int cmc_rank;
public DateTime last_updated;
public Dictionary<string, QuoteData> quote = new Dictionary<string, QuoteData>();
}
public class LatestQuoteAsyncResponse
{
public ResponseStatus status;
public Dictionary<string, LatestQuoteResp> data = new Dictionary<string, LatestQuoteResp>();
}
public class DataGridQuoteData : BindableBase
{
private string name;
public string Name
{
get { return name; }
set { SetProperty(ref name, value); }
}
private string longName;
public string LongName
{
get { return longName; }
set { SetProperty(ref longName, value); }
}
private double price;
public double Price
{
get { return price; }
set { SetProperty(ref price, value); }
}
private double marketCap;
public double MarketCap
{
get { return marketCap; }
set { SetProperty(ref marketCap, value); }
}
private double percentShare;
public double PercentShare
{
get { return percentShare; }
set { SetProperty(ref percentShare, value); }
}
private double volumn24h;
public double Volumn24h
{
get { return volumn24h; }
set { SetProperty(ref volumn24h, value); }
}
private double accumulativeMarketCap;
public double AccumulativeMarketCap
{
get { return accumulativeMarketCap; }
set { SetProperty(ref accumulativeMarketCap, value); }
}
}
#endregion
public partial class StableCoin : CrytoUserControl
{
private static readonly Lazy<StableCoin> lazy = new Lazy<StableCoin>(() => new StableCoin());
public static StableCoin Instance { get { return lazy.Value; } }
private readonly string CoinMarketCapApiKey = "31941fbb-01b9-4bad-bd52-d5aa9d875792";
private UriBuilder url = null;
private WebClient client = null;
public ObservableCollection<DataGridQuoteData> DataGridQuoteData = new ObservableCollection<DataGridQuoteData>();
public StableCoin()
{
InitializeComponent();
DataContext = this;
LoadStableCoinMarketShare();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{ }
public override void OnInitChanged(object sender, DependencyPropertyChangedEventArgs e)
{
DataGridQuoteData.Clear();
LoadStableCoinMarketShare();
}
// public static void Sort<T>(this ObservableCollection<T> collection, Comparison<T> comparison)
public void Sort<T>(ObservableCollection<T> collection, Comparison<T> comparison)
{
var sortableList = new List<T>(collection);
sortableList.Sort(comparison);
for (int i = 0; i < sortableList.Count; i++)
{
collection.Move(collection.IndexOf(sortableList[i]), i);
}
}
// Binds data to properties in XAML
private void CalculateLatestStableCoinMarketShare(LatestQuoteAsyncResponse resp)
{
var data = resp.data;
double totalmc = 0.0;
// populate our observable collection
foreach (var d in data)
{
var dg = new DataGridQuoteData();
dg.Name = d.Key;
dg.LongName = d.Value.name;
var qd = new QuoteData();
d.Value.quote.TryGetValue("USD", out qd);
dg.MarketCap = qd.market_cap;
dg.Price = qd.price;
dg.Volumn24h = qd.volume_24h;
totalmc += dg.MarketCap;
dg.AccumulativeMarketCap = totalmc;
DataGridQuoteData.Add(dg);
}
// calculate percent share
foreach (var dg in DataGridQuoteData) {
dg.PercentShare = dg.MarketCap / totalmc;
}
// update bindable sources
Sort(DataGridQuoteData, (a, b) => { return a.Name.CompareTo(b.Name); });
dgStableCoin.ItemsSource = DataGridQuoteData;
}
// Testing list
private void LoadTestStableCoinMarketShare()
{
Dictionary<string, LatestQuoteResp> data = new Dictionary<string, LatestQuoteResp>();
data.Add("USDC", new LatestQuoteResp
{
name = "USDC",
quote = new Dictionary<string, QuoteData> {
{ "USD", new QuoteData { market_cap = 5000.0 } }
}
});
data.Add("DAI", new LatestQuoteResp
{
name = "DAI MONEY",
quote = new Dictionary<string, QuoteData> {
{ "USD", new QuoteData { market_cap = 205.4 } }
}
});
data.Add("USDT", new LatestQuoteResp
{
name = "Tether",
quote = new Dictionary<string, QuoteData> {
{ "USD", new QuoteData { market_cap = 10000.0 } }
}
});
LatestQuoteAsyncResponse resp = new LatestQuoteAsyncResponse() { data = data };
CalculateLatestStableCoinMarketShare(resp);
}
// The real stable coin list
private void LoadStableCoinMarketShare()
{
url = new UriBuilder("https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest");
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString["symbol"] = "PAX,UST,DAI,GUSD,TUSD,BUSD,USDC,USDT";
url.Query = queryString.ToString();
client = new WebClient();
client.Headers.Add("X-CMC_PRO_API_KEY", CoinMarketCapApiKey);
client.Headers.Add("Accepts", "application/json");
var json = client.DownloadString(url.ToString());
var resp = JsonConvert.DeserializeObject<LatestQuoteAsyncResponse>(json);
CalculateLatestStableCoinMarketShare(resp);
}
}
}
//////////////////////////// XAML CODE ///////////////////////////////////////
/**
<local:CrytoUserControl x:Class="CryptoSentiment.StableCoin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CryptoSentiment"
mc:Ignorable="d" Loaded="OnLoaded">
<UserControl.Resources>
<Style x:Key="DataGridStyle1" TargetType="DataGrid">
<Setter Property="ColumnHeaderStyle" Value="{DynamicResource ColumnHeaderStyle}"/>
</Style>
<Style x:Key="CellAlignRight">
<Setter Property="Control.HorizontalAlignment" Value="Right" />
</Style>
<Style x:Key="ColumnHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightSteelBlue" />
<Setter Property="BorderThickness" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="DataGridRowStyle" TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Lavender" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<DataGrid x:Name="dgStableCoin"
AutoGenerateColumns="False" FontSize="18"
CellStyle="{StaticResource DataGridCellStyle}"
RowStyle="{StaticResource DataGridRowStyle}"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
AlternatingRowBackground="LightCyan">
<DataGrid.Columns>
<DataGridTextColumn Header="Stable Coin" Binding="{Binding Name}" Foreground="Blue" Width="150" />
<DataGridTextColumn Header="Coin Name" Binding="{Binding LongName}" Foreground="DarkSlateGray" Width="200" />
<DataGridTextColumn Header="Price" Binding="{Binding Price, StringFormat=N2}" Foreground="Sienna" Width="100" />
<DataGridTextColumn Header="Market Cap" Binding="{Binding MarketCap, StringFormat=N2}"
Foreground="Purple" Width="300" ElementStyle="{StaticResource CellAlignRight}" />
<DataGridTextColumn Header="Percent Share" Binding="{Binding PercentShare, StringFormat=P2}"
Foreground="Red" Width="200" ElementStyle="{StaticResource CellAlignRight}" />
<DataGridTextColumn Header="Volumn 24H" Binding="{Binding Volumn24h, StringFormat=N2}"
Foreground="Chocolate" Width="300" ElementStyle="{StaticResource CellAlignRight}" />
<DataGridTextColumn Header="Accumulative Market Cap" Binding="{Binding AccumulativeMarketCap, StringFormat=N2}"
Foreground="Magenta" Width="300" ElementStyle="{StaticResource CellAlignRight}" />
</DataGrid.Columns>
</DataGrid>
</local:CrytoUserControl>
*/