diff --git a/BTCPayServer/Controllers/WalletsController.PSBT.cs b/BTCPayServer/Controllers/WalletsController.PSBT.cs index d4cab9b3a..781488129 100644 --- a/BTCPayServer/Controllers/WalletsController.PSBT.cs +++ b/BTCPayServer/Controllers/WalletsController.PSBT.cs @@ -20,6 +20,10 @@ namespace BTCPayServer.Controllers { var nbx = ExplorerClientProvider.GetExplorerClient(network); CreatePSBTRequest psbtRequest = new CreatePSBTRequest(); + if (sendModel.InputSelection) + { + psbtRequest.IncludeOnlyOutpoints = sendModel.SelectedInputs?.Select(OutPoint.Parse)?.ToList()?? new List(); + } foreach (var transactionOutput in sendModel.Outputs) { var psbtDestination = new CreatePSBTDestination(); diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index e4dc74e6d..1c4ca1580 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -463,7 +463,36 @@ namespace BTCPayServer.Controllers } decimal transactionAmountSum = 0; - + if (command == "toggle-input-selection") + { + vm.InputSelection = !vm.InputSelection; + } + if (vm.InputSelection) + { + var schemeSettings = GetDerivationSchemeSettings(walletId); + var walletBlobAsync = await WalletRepository.GetWalletInfo(walletId); + var walletTransactionsInfoAsync = await WalletRepository.GetWalletTransactionsInfo(walletId); + + var utxos = await _walletProvider.GetWallet(network).GetUnspentCoins(schemeSettings.AccountDerivation, cancellation); + vm.InputsAvailable = utxos.Select(coin => + { + walletTransactionsInfoAsync.TryGetValue(coin.OutPoint.Hash.ToString(), out var info); + return new WalletSendModel.InputSelectionOption() + { + Outpoint = coin.OutPoint.ToString(), + Amount = coin.Value.GetValue(network), + Comment = info?.Comment, + Labels = info == null? null :walletBlobAsync.GetLabels(info), + Link = string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, coin.OutPoint.Hash.ToString()) + }; + }).ToArray(); + } + + if (command == "toggle-input-selection") + { + ModelState.Clear(); + return View(vm); + } if (command == "add-output") { ModelState.Clear(); diff --git a/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs b/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs index 73c72e121..55ec9ca4f 100644 --- a/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs +++ b/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Data; +using NBXplorer.Models; namespace BTCPayServer.Models.WalletViewModels { @@ -47,5 +49,17 @@ namespace BTCPayServer.Models.WalletViewModels public bool DisableRBF { get; set; } public bool NBXSeedAvailable { get; set; } + public bool InputSelection { get; set; } + public InputSelectionOption[] InputsAvailable { get; set; } + public IEnumerable SelectedInputs { get; set; } + + public class InputSelectionOption + { + public IEnumerable