mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-10 09:19:24 +01:00
Add the concept of RateDivisibility (#6278)
This commit is contained in:
parent
64ba8248d2
commit
b246beab3e
4 changed files with 18 additions and 13 deletions
|
@ -875,13 +875,7 @@ namespace BTCPayServer.Controllers
|
||||||
return extension?.Image ?? "";
|
return extension?.Image ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
var cd = this._CurrencyNameTable.GetCurrencyData(prompt.Currency, false);
|
string ShowMoney(decimal value) => MoneyExtensions.ShowMoney(value, prompt.RateDivisibility ?? prompt.Divisibility);
|
||||||
// Show the "Common divisibility" rather than the payment method disibility.
|
|
||||||
// For example, BTC has commonly 8 digits, but on lightning it has 11. In this case, pick 8.
|
|
||||||
if (cd?.Divisibility is not int divisibility)
|
|
||||||
divisibility = prompt.Divisibility;
|
|
||||||
|
|
||||||
string ShowMoney(decimal value) => MoneyExtensions.ShowMoney(value, divisibility);
|
|
||||||
var model = new PaymentModel
|
var model = new PaymentModel
|
||||||
{
|
{
|
||||||
Activated = prompt.Activated,
|
Activated = prompt.Activated,
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||||
context.Prompt.Inactive = false;
|
context.Prompt.Inactive = false;
|
||||||
context.Prompt.Currency = _network.CryptoCode;
|
context.Prompt.Currency = _network.CryptoCode;
|
||||||
context.Prompt.Divisibility = 11;
|
context.Prompt.Divisibility = 11;
|
||||||
|
context.Prompt.RateDivisibility = 8;
|
||||||
context.Prompt.PaymentMethodFee = 0.0m;
|
context.Prompt.PaymentMethodFee = 0.0m;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||||
context.Prompt.Currency = _Network.CryptoCode;
|
context.Prompt.Currency = _Network.CryptoCode;
|
||||||
context.Prompt.PaymentMethodFee = 0m;
|
context.Prompt.PaymentMethodFee = 0m;
|
||||||
context.Prompt.Divisibility = 11;
|
context.Prompt.Divisibility = 11;
|
||||||
|
context.Prompt.RateDivisibility = 8;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -870,8 +870,16 @@ namespace BTCPayServer.Services.Invoices
|
||||||
public string Currency { get; set; }
|
public string Currency { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public decimal Rate => Currency is null ? throw new InvalidOperationException("Currency of the payment prompt isn't set") : ParentEntity.GetInvoiceRate(Currency);
|
public decimal Rate => Currency is null ? throw new InvalidOperationException("Currency of the payment prompt isn't set") : ParentEntity.GetInvoiceRate(Currency);
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum divisibility supported by the underlying payment method
|
||||||
|
/// </summary>
|
||||||
public int Divisibility { get; set; }
|
public int Divisibility { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The divisibility to use when calculating the amount to pay.
|
||||||
|
/// If null, it will use the <see cref="Divisibility"/>.
|
||||||
|
/// </summary>
|
||||||
|
public int? RateDivisibility { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// Total additional fee imposed by this specific payment method.
|
/// Total additional fee imposed by this specific payment method.
|
||||||
/// It includes the <see cref="TweakFee"/>.
|
/// It includes the <see cref="TweakFee"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -909,24 +917,25 @@ namespace BTCPayServer.Services.Invoices
|
||||||
accounting.TxRequired = accounting.TxCount;
|
accounting.TxRequired = accounting.TxCount;
|
||||||
var grossDue = i.Price + i.PaidFee;
|
var grossDue = i.Price + i.PaidFee;
|
||||||
var rate = Rate;
|
var rate = Rate;
|
||||||
|
var divisibility = RateDivisibility ?? Divisibility;
|
||||||
if (i.MinimumNetDue > 0.0m)
|
if (i.MinimumNetDue > 0.0m)
|
||||||
{
|
{
|
||||||
accounting.TxRequired++;
|
accounting.TxRequired++;
|
||||||
grossDue += rate * PaymentMethodFee;
|
grossDue += rate * PaymentMethodFee;
|
||||||
}
|
}
|
||||||
accounting.TotalDue = Coins(grossDue / rate, Divisibility);
|
accounting.TotalDue = Coins(grossDue / rate, divisibility);
|
||||||
accounting.Paid = Coins(i.PaidAmount.Gross / rate, Divisibility);
|
accounting.Paid = Coins(i.PaidAmount.Gross / rate, divisibility);
|
||||||
accounting.PaymentMethodPaid = Coins(thisPaymentMethodPayments.Sum(p => p.PaidAmount.Gross), Divisibility);
|
accounting.PaymentMethodPaid = Coins(thisPaymentMethodPayments.Sum(p => p.PaidAmount.Gross), divisibility);
|
||||||
|
|
||||||
// This one deal with the fact where it might looks like a slight over payment due to the dust of another payment method.
|
// This one deal with the fact where it might looks like a slight over payment due to the dust of another payment method.
|
||||||
// So if we detect the NetDue is zero, just cap dueUncapped to 0
|
// So if we detect the NetDue is zero, just cap dueUncapped to 0
|
||||||
var dueUncapped = i.NetDue == 0.0m ? 0.0m : grossDue - i.PaidAmount.Gross;
|
var dueUncapped = i.NetDue == 0.0m ? 0.0m : grossDue - i.PaidAmount.Gross;
|
||||||
accounting.DueUncapped = Coins(dueUncapped / rate, Divisibility);
|
accounting.DueUncapped = Coins(dueUncapped / rate, divisibility);
|
||||||
accounting.Due = Max(accounting.DueUncapped, 0.0m);
|
accounting.Due = Max(accounting.DueUncapped, 0.0m);
|
||||||
|
|
||||||
accounting.PaymentMethodFee = Coins((grossDue - i.Price) / rate, Divisibility);
|
accounting.PaymentMethodFee = Coins((grossDue - i.Price) / rate, divisibility);
|
||||||
|
|
||||||
accounting.MinimumTotalDue = Max(Smallest(Divisibility), Coins((grossDue * (1.0m - ((decimal)i.PaymentTolerance / 100.0m))) / rate, Divisibility));
|
accounting.MinimumTotalDue = Max(Smallest(divisibility), Coins((grossDue * (1.0m - ((decimal)i.PaymentTolerance / 100.0m))) / rate, divisibility));
|
||||||
return accounting;
|
return accounting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue