From 67da6ee379732548c11060767a072e1defd48ad8 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Sun, 3 May 2020 18:04:34 +0200 Subject: [PATCH] Decimal precision and filter valid transaction (#1538) The liquid transactions list was showing all transactions to the wallet, even when it had nothing to do with the specific crypto code (e.g sending LBTC txs in USDT, LCAD in USDT, etc). This PR fixes that. It also uses the previously introduced checkout decimal precision fix to the Wallets screen, specifically the balance amount on wallet llist and balance change on transaction list. --- .../Liquid/ElementsLikeBtcPayNetwork.cs | 25 +++++++++++++++++++ BTCPayServer.Common/BTCPayNetwork.cs | 5 ++++ BTCPayServer.Tests/docker-elements.ps1 | 1 + .../Controllers/InvoiceController.UI.cs | 14 +++-------- BTCPayServer/Controllers/WalletsController.cs | 5 ++-- BTCPayServer/Extensions/MoneyExtensions.cs | 22 ++++++++++++++++ BTCPayServer/Services/Wallets/BTCPayWallet.cs | 4 +-- 7 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 BTCPayServer.Tests/docker-elements.ps1 diff --git a/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs b/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs index 9d059ec33..47321e83f 100644 --- a/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs +++ b/BTCPayServer.Common/Altcoins/Liquid/ElementsLikeBtcPayNetwork.cs @@ -23,6 +23,31 @@ namespace BTCPayServer }); } + public override GetTransactionsResponse FilterValidTransactions(GetTransactionsResponse response) + { + TransactionInformationSet Filter(TransactionInformationSet transactionInformationSet) + { + return new TransactionInformationSet() + { + Transactions = + transactionInformationSet.Transactions.FindAll(information => + information.Outputs.Any(output => + output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId) || + information.Inputs.Any(output => + output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId)) + }; + } + + return new GetTransactionsResponse() + { + Height = response.Height, + ConfirmedTransactions = Filter(response.ConfirmedTransactions), + ReplacedTransactions = Filter(response.ReplacedTransactions), + UnconfirmedTransactions = Filter(response.UnconfirmedTransactions) + }; + } + + public override string GenerateBIP21(string cryptoInfoAddress, Money cryptoInfoDue) { //precision 0: 10 = 0.00000010 diff --git a/BTCPayServer.Common/BTCPayNetwork.cs b/BTCPayServer.Common/BTCPayNetwork.cs index b7208ef5b..ecb71bc16 100644 --- a/BTCPayServer.Common/BTCPayNetwork.cs +++ b/BTCPayServer.Common/BTCPayNetwork.cs @@ -120,6 +120,11 @@ namespace BTCPayServer { return $"{UriScheme}:{cryptoInfoAddress}?amount={cryptoInfoDue.ToString(false, true)}"; } + + public virtual GetTransactionsResponse FilterValidTransactions(GetTransactionsResponse response) + { + return response; + } } public abstract class BTCPayNetworkBase diff --git a/BTCPayServer.Tests/docker-elements.ps1 b/BTCPayServer.Tests/docker-elements.ps1 new file mode 100644 index 000000000..4116d33dd --- /dev/null +++ b/BTCPayServer.Tests/docker-elements.ps1 @@ -0,0 +1 @@ +docker exec -ti btcpayserver_elementsd_liquid elements-cli -datadir="/data" $args diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index 689b7d4f0..3f14666f0 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -227,14 +227,6 @@ namespace BTCPayServer.Controllers var divisibility = _CurrencyNameTable.GetNumberFormatInfo(paymentMethod.GetId().CryptoCode, false)?.CurrencyDecimalDigits; - string ShowMoney(Money money) - { - if (!divisibility.HasValue) return money.ToString(); - var res = $"0{(divisibility.Value > 0 ? "." : string.Empty)}"; - var format = res.PadRight(divisibility.Value + res.Length, '0'); - return money.ToDecimal(MoneyUnit.BTC).ToString(format, CultureInfo.InvariantCulture); - } - var model = new PaymentModel() { CryptoCode = network.CryptoCode, @@ -247,8 +239,8 @@ namespace BTCPayServer.Controllers HtmlTitle = storeBlob.HtmlTitle ?? "BTCPay Invoice", CryptoImage = Request.GetRelativePathOrAbsolute(paymentMethodHandler.GetCryptoImage(paymentMethodId)), BtcAddress = paymentMethodDetails.GetPaymentDestination(), - BtcDue = ShowMoney(accounting.Due), - OrderAmount = ShowMoney(accounting.TotalDue - accounting.NetworkFee), + BtcDue = accounting.Due.ShowMoney(divisibility), + OrderAmount = (accounting.TotalDue - accounting.NetworkFee).ShowMoney(divisibility), OrderAmountFiat = OrderAmountFromInvoice(network.CryptoCode, invoice.ProductInformation), CustomerEmail = invoice.RefundMail, RequiresRefundEmail = storeBlob.RequiresRefundEmail, @@ -264,7 +256,7 @@ namespace BTCPayServer.Controllers StoreName = store.StoreName, PeerInfo = (paymentMethodDetails as LightningLikePaymentMethodDetails)?.NodeInfo, TxCount = accounting.TxRequired, - BtcPaid = ShowMoney(accounting.Paid), + BtcPaid = accounting.Paid.ShowMoney(divisibility), #pragma warning disable CS0618 // Type or member is obsolete Status = invoice.StatusString, #pragma warning restore CS0618 // Type or member is obsolete diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index c50c740f6..ce9d0a42a 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -285,7 +285,7 @@ namespace BTCPayServer.Controllers vm.Id); vm.Timestamp = tx.Timestamp; vm.Positive = tx.BalanceChange.GetValue(wallet.Network) >= 0; - vm.Balance = tx.BalanceChange.ToString(); + vm.Balance = tx.BalanceChange.ShowMoney(wallet.Network); vm.IsConfirmed = tx.Confirmations != 0; if (walletTransactionsInfo.TryGetValue(tx.TransactionId.ToString(), out var transactionInfo)) @@ -996,7 +996,8 @@ namespace BTCPayServer.Controllers { try { - return (await wallet.GetBalance(derivationStrategy, cts.Token)).ToString(CultureInfo.InvariantCulture); + return (await wallet.GetBalance(derivationStrategy, cts.Token)).ShowMoney(wallet.Network + .Divisibility); } catch { diff --git a/BTCPayServer/Extensions/MoneyExtensions.cs b/BTCPayServer/Extensions/MoneyExtensions.cs index 66b4e8b59..454640b80 100644 --- a/BTCPayServer/Extensions/MoneyExtensions.cs +++ b/BTCPayServer/Extensions/MoneyExtensions.cs @@ -36,5 +36,27 @@ namespace BTCPayServer return decimal.Parse(amt, CultureInfo.InvariantCulture); } + public static string ShowMoney(this IMoney money, BTCPayNetwork network) + { + return money.GetValue(network).ShowMoney(network.Divisibility); + } + + public static string ShowMoney(this Money money, int? divisibility) + { + return !divisibility.HasValue + ? money.ToString() + : money.ToDecimal(MoneyUnit.BTC).ShowMoney(divisibility.Value); + } + + public static string ShowMoney(this decimal d, int divisibility) + { + return d.ToString(GetDecimalFormat(divisibility), CultureInfo.InvariantCulture); + } + + private static string GetDecimalFormat(int divisibility) + { + var res = $"0{(divisibility > 0 ? "." : string.Empty)}"; + return res.PadRight(divisibility + res.Length, '0'); + } } } diff --git a/BTCPayServer/Services/Wallets/BTCPayWallet.cs b/BTCPayServer/Services/Wallets/BTCPayWallet.cs index 16abb602e..d741e0928 100644 --- a/BTCPayServer/Services/Wallets/BTCPayWallet.cs +++ b/BTCPayServer/Services/Wallets/BTCPayWallet.cs @@ -200,9 +200,9 @@ namespace BTCPayServer.Services.Wallets return await completionSource.Task; } - public Task FetchTransactions(DerivationStrategyBase derivationStrategyBase) + public async Task FetchTransactions(DerivationStrategyBase derivationStrategyBase) { - return _Client.GetTransactionsAsync(derivationStrategyBase); + return _Network.FilterValidTransactions(await _Client.GetTransactionsAsync(derivationStrategyBase)); } public Task BroadcastTransactionsAsync(List transactions)