mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-01-24 16:34:35 +01:00
150 lines
4.2 KiB
C#
150 lines
4.2 KiB
C#
#nullable enable
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using BTCPayServer.Data;
|
|
using BTCPayServer.Rating;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace BTCPayServer.Services.Invoices;
|
|
|
|
public class RateBook
|
|
{
|
|
public static RateBook Parse(string rates, string defaultCurrency)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(rates);
|
|
ArgumentNullException.ThrowIfNull(defaultCurrency);
|
|
if (rates == "")
|
|
return new(defaultCurrency, new());
|
|
var o = JObject.Parse(rates);
|
|
var ratesDict = new Dictionary<string, decimal>();
|
|
foreach (var property in o.Properties())
|
|
{
|
|
ratesDict.Add(property.Name, decimal.Parse(property.Value.ToString(), CultureInfo.InvariantCulture));
|
|
}
|
|
return new RateBook(defaultCurrency, ratesDict);
|
|
}
|
|
|
|
public RateBook()
|
|
{
|
|
Rates = new();
|
|
}
|
|
public RateBook(
|
|
string defaultCurrency,
|
|
Dictionary<string, decimal> rates
|
|
)
|
|
{
|
|
Rates = new(rates.Count);
|
|
foreach (var rate in rates)
|
|
{
|
|
if (!rate.Key.Contains('_', StringComparison.Ordinal))
|
|
Rates.Add(new CurrencyPair(rate.Key, defaultCurrency), rate.Value);
|
|
else
|
|
Rates.Add(CurrencyPair.Parse(rate.Key), rate.Value);
|
|
}
|
|
}
|
|
public Dictionary<CurrencyPair, decimal> Rates { get; }
|
|
|
|
public decimal? TryGetRate(CurrencyPair pair)
|
|
{
|
|
if (GetFastLaneRate(pair, out var tryGetRate)) return tryGetRate;
|
|
|
|
var rule = GetRateRules().GetRuleFor(pair);
|
|
rule.Reevaluate();
|
|
if (rule.BidAsk is null)
|
|
return null;
|
|
return rule.BidAsk.Bid;
|
|
}
|
|
|
|
private bool GetFastLaneRate(CurrencyPair pair, out decimal v)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(pair);
|
|
if (Rates.TryGetValue(pair, out var rate)) // Fast lane
|
|
{
|
|
v = rate;
|
|
return true;
|
|
}
|
|
v = 0m;
|
|
return false;
|
|
}
|
|
|
|
public decimal GetRate(CurrencyPair pair)
|
|
{
|
|
if (GetFastLaneRate(pair, out var v)) return v;
|
|
var rule = GetRateRules().GetRuleFor(pair);
|
|
rule.Reevaluate();
|
|
if (rule.BidAsk is null)
|
|
throw new InvalidOperationException($"Rate rule is not evaluated ({rule.Errors.First()})");
|
|
return rule.BidAsk.Bid;
|
|
}
|
|
|
|
public bool TryGetRate(CurrencyPair pair, out decimal rate)
|
|
{
|
|
if (GetFastLaneRate(pair, out rate)) return true;
|
|
var rule = GetRateRules().GetRuleFor(pair);
|
|
rule.Reevaluate();
|
|
if (rule.BidAsk is null)
|
|
{
|
|
rate = 0.0m;
|
|
return false;
|
|
}
|
|
|
|
rate = rule.BidAsk.Bid;
|
|
return true;
|
|
}
|
|
|
|
public RateRules GetRateRules()
|
|
{
|
|
var builder = new StringBuilder();
|
|
foreach (var r in Rates)
|
|
{
|
|
builder.AppendLine($"{r.Key} = {r.Value.ToString(CultureInfo.InvariantCulture)};");
|
|
}
|
|
|
|
if (RateRules.TryParse(builder.ToString(), out var rules))
|
|
return rules;
|
|
throw new FormatException("Invalid rate rules");
|
|
}
|
|
|
|
public void AddRates(RateBook? otherBook)
|
|
{
|
|
if (otherBook is null)
|
|
return;
|
|
foreach (var rate in otherBook.Rates)
|
|
{
|
|
this.Rates.TryAdd(rate.Key, rate.Value);
|
|
}
|
|
}
|
|
|
|
public static RateBook? FromTxWalletObject(WalletObjectData txObject)
|
|
{
|
|
var rates = txObject.GetData()?["rates"] as JObject;
|
|
if (rates is null)
|
|
return null;
|
|
var cryptoCode = WalletId.Parse(txObject.WalletId).CryptoCode;
|
|
return FromJObject(rates, cryptoCode);
|
|
}
|
|
|
|
public static RateBook? FromJObject(JObject rates, string cryptoCode)
|
|
{
|
|
var result = new RateBook();
|
|
foreach (var property in rates.Properties())
|
|
{
|
|
var rate = decimal.Parse(property.Value.ToString(), CultureInfo.InvariantCulture);
|
|
result.Rates.TryAdd(new CurrencyPair(cryptoCode, property.Name), rate);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void AddCurrencies(HashSet<string> trackedCurrencies)
|
|
{
|
|
foreach (var r in Rates)
|
|
{
|
|
trackedCurrencies.Add(r.Key.Left);
|
|
trackedCurrencies.Add(r.Key.Right);
|
|
}
|
|
}
|
|
}
|