mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Wallet transactions: Add label manager (#4796)
* Wallet transactions: Add label manager * Update BTCPayServer/Views/UIWallets/WalletTransactions.cshtml Co-authored-by: Andrew Camilleri <evilkukka@gmail.com> * Add rich label info * Fixes * support labels in wallet send * add labels to tx info page * Remove noscript parts * Allow click on transaction label info * update psbt info labelstyling * revert red pixel fix as it broke all --------- Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
This commit is contained in:
@@ -7,6 +7,7 @@ using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.BIP78.Sender;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.ModelBinders;
|
||||
using BTCPayServer.Models;
|
||||
@@ -266,7 +267,7 @@ namespace BTCPayServer.Controllers
|
||||
ModelState.Remove(nameof(vm.PSBT));
|
||||
ModelState.Remove(nameof(vm.FileName));
|
||||
ModelState.Remove(nameof(vm.UploadedPSBTFile));
|
||||
await FetchTransactionDetails(derivationSchemeSettings, vm, network);
|
||||
await FetchTransactionDetails(walletId,derivationSchemeSettings, vm, network);
|
||||
return View("WalletPSBTDecoded", vm);
|
||||
|
||||
case "save-psbt":
|
||||
@@ -320,7 +321,7 @@ namespace BTCPayServer.Controllers
|
||||
return await _payjoinClient.RequestPayjoin(bip21, new PayjoinWallet(derivationSchemeSettings), psbt, cts.Token);
|
||||
}
|
||||
|
||||
private async Task FetchTransactionDetails(DerivationSchemeSettings derivationSchemeSettings, WalletPSBTReadyViewModel vm, BTCPayNetwork network)
|
||||
private async Task FetchTransactionDetails(WalletId walletId, DerivationSchemeSettings derivationSchemeSettings, WalletPSBTReadyViewModel vm, BTCPayNetwork network)
|
||||
{
|
||||
var psbtObject = PSBT.Parse(vm.SigningContext.PSBT, network.NBitcoinNetwork);
|
||||
if (!psbtObject.IsAllFinalized())
|
||||
@@ -371,17 +372,29 @@ namespace BTCPayServer.Controllers
|
||||
vm.Positive = balanceChange >= Money.Zero;
|
||||
}
|
||||
vm.Inputs = new List<WalletPSBTReadyViewModel.InputViewModel>();
|
||||
var inputToObjects = new Dictionary<uint, ObjectTypeId[]>();
|
||||
var outputToObjects = new Dictionary<string, ObjectTypeId>();
|
||||
foreach (var input in psbtObject.Inputs)
|
||||
{
|
||||
var inputVm = new WalletPSBTReadyViewModel.InputViewModel();
|
||||
vm.Inputs.Add(inputVm);
|
||||
var txOut = input.GetTxOut();
|
||||
var mine = input.HDKeysFor(derivationSchemeSettings.AccountDerivation, signingKey, signingKeyPath).Any();
|
||||
var balanceChange2 = input.GetTxOut()?.Value ?? Money.Zero;
|
||||
var balanceChange2 = txOut?.Value ?? Money.Zero;
|
||||
if (mine)
|
||||
balanceChange2 = -balanceChange2;
|
||||
inputVm.BalanceChange = ValueToString(balanceChange2, network);
|
||||
inputVm.Positive = balanceChange2 >= Money.Zero;
|
||||
inputVm.Index = (int)input.Index;
|
||||
|
||||
var walletObjectIds = new List<ObjectTypeId>();
|
||||
walletObjectIds.Add(new ObjectTypeId(WalletObjectData.Types.Utxo, input.PrevOut.ToString()));
|
||||
walletObjectIds.Add(new ObjectTypeId(WalletObjectData.Types.Tx, input.PrevOut.Hash.ToString()));
|
||||
var address = txOut?.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork)?.ToString();
|
||||
if(address != null)
|
||||
walletObjectIds.Add(new ObjectTypeId(WalletObjectData.Types.Address, address));
|
||||
inputToObjects.Add(input.Index, walletObjectIds.ToArray());
|
||||
|
||||
}
|
||||
vm.Destinations = new List<WalletPSBTReadyViewModel.DestinationViewModel>();
|
||||
foreach (var output in psbtObject.Outputs)
|
||||
@@ -395,6 +408,10 @@ namespace BTCPayServer.Controllers
|
||||
dest.Balance = ValueToString(balanceChange2, network);
|
||||
dest.Positive = balanceChange2 >= Money.Zero;
|
||||
dest.Destination = output.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork)?.ToString() ?? output.ScriptPubKey.ToString();
|
||||
var address = output.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork)?.ToString();
|
||||
if(address != null)
|
||||
outputToObjects.Add(dest.Destination, new ObjectTypeId(WalletObjectData.Types.Address, address));
|
||||
|
||||
}
|
||||
|
||||
if (psbtObject.TryGetFee(out var fee))
|
||||
@@ -420,6 +437,38 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
vm.SetErrors(errors);
|
||||
}
|
||||
|
||||
var combinedTypeIds = inputToObjects.Values.SelectMany(ids => ids).Concat(outputToObjects.Values)
|
||||
.DistinctBy(id => $"{id.Type}:{id.Id}").ToArray();
|
||||
|
||||
var labelInfo = await WalletRepository.GetWalletTransactionsInfo(walletId, combinedTypeIds);
|
||||
foreach (KeyValuePair<uint,ObjectTypeId[]> inputToObject in inputToObjects)
|
||||
{
|
||||
var keys = inputToObject.Value.Select(id => id.Id).ToArray();
|
||||
WalletTransactionInfo ix = null;
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (!labelInfo.TryGetValue(key, out var i)) continue;
|
||||
if (ix is null)
|
||||
{
|
||||
ix = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
ix.Merge(i);
|
||||
}
|
||||
}
|
||||
if (ix is null) continue;
|
||||
var input = vm.Inputs.First(model => model.Index == inputToObject.Key);
|
||||
input.Labels = ix.LabelColors;
|
||||
}
|
||||
foreach (var outputToObject in outputToObjects)
|
||||
{
|
||||
if (!labelInfo.TryGetValue(outputToObject.Value.Id, out var ix)) continue;
|
||||
var destination = vm.Destinations.First(model => model.Destination == outputToObject.Key);
|
||||
destination.Labels = ix.LabelColors;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[HttpPost("{walletId}/psbt/ready")]
|
||||
@@ -439,7 +488,7 @@ namespace BTCPayServer.Controllers
|
||||
if (derivationSchemeSettings == null)
|
||||
return NotFound();
|
||||
|
||||
await FetchTransactionDetails(derivationSchemeSettings, vm, network);
|
||||
await FetchTransactionDetails(walletId,derivationSchemeSettings, vm, network);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
@@ -570,7 +619,7 @@ namespace BTCPayServer.Controllers
|
||||
BackUrl = vm.BackUrl
|
||||
});
|
||||
case "decode":
|
||||
await FetchTransactionDetails(derivationSchemeSettings, vm, network);
|
||||
await FetchTransactionDetails(walletId,derivationSchemeSettings, vm, network);
|
||||
return View("WalletPSBTDecoded", vm);
|
||||
default:
|
||||
vm.Errors.Add("Unknown command");
|
||||
|
||||
Reference in New Issue
Block a user