mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-21 14:04:12 +01:00
Show index of payment address for onchain payments
This commit is contained in:
parent
2711f2cb2f
commit
8e8415515d
15 changed files with 92 additions and 97 deletions
|
@ -600,7 +600,7 @@ namespace BTCPayServer.Controllers
|
|||
try
|
||||
{
|
||||
leases.Add(_EventAggregator.Subscribe<Events.InvoiceDataChangedEvent>(async o => await NotifySocket(webSocket, o.InvoiceId, invoiceId)));
|
||||
leases.Add(_EventAggregator.Subscribe<Events.InvoiceNewAddressEvent>(async o => await NotifySocket(webSocket, o.InvoiceId, invoiceId)));
|
||||
leases.Add(_EventAggregator.Subscribe<Events.InvoiceNewPaymentDetailsEvent>(async o => await NotifySocket(webSocket, o.InvoiceId, invoiceId)));
|
||||
leases.Add(_EventAggregator.Subscribe<Events.InvoiceEvent>(async o => await NotifySocket(webSocket, o.Invoice.Id, invoiceId)));
|
||||
while (true)
|
||||
{
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
namespace BTCPayServer.Events
|
||||
{
|
||||
public class InvoiceNewAddressEvent
|
||||
{
|
||||
public InvoiceNewAddressEvent(string invoiceId, string address, BTCPayNetworkBase network)
|
||||
{
|
||||
Address = address;
|
||||
InvoiceId = invoiceId;
|
||||
Network = network;
|
||||
}
|
||||
|
||||
public string Address { get; set; }
|
||||
public string InvoiceId { get; set; }
|
||||
public BTCPayNetworkBase Network { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Network.CryptoCode}: New address {Address} for invoice {InvoiceId}";
|
||||
}
|
||||
}
|
||||
}
|
24
BTCPayServer/Events/InvoiceNewPaymentDetailsEvent.cs
Normal file
24
BTCPayServer/Events/InvoiceNewPaymentDetailsEvent.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using BTCPayServer.Payments;
|
||||
|
||||
namespace BTCPayServer.Events
|
||||
{
|
||||
public class InvoiceNewPaymentDetailsEvent
|
||||
{
|
||||
|
||||
public InvoiceNewPaymentDetailsEvent(string invoiceId, IPaymentMethodDetails details, PaymentMethodId paymentMethodId)
|
||||
{
|
||||
InvoiceId = invoiceId;
|
||||
Details = details;
|
||||
PaymentMethodId = paymentMethodId;
|
||||
}
|
||||
|
||||
public string Address { get; set; }
|
||||
public string InvoiceId { get; set; }
|
||||
public IPaymentMethodDetails Details { get; }
|
||||
public PaymentMethodId PaymentMethodId { get; }
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{PaymentMethodId.ToPrettyString()}: New payment details {Details.GetPaymentDestination()} for invoice {InvoiceId}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using BTCPayServer.Client.Models;
|
||||
using NBitcoin;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -24,9 +25,10 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
return FeeRate.SatoshiPerByte;
|
||||
}
|
||||
|
||||
public void SetPaymentDestination(string newPaymentDestination)
|
||||
public void SetPaymentDetails(IPaymentMethodDetails newPaymentMethodDetails)
|
||||
{
|
||||
DepositAddress = newPaymentDestination;
|
||||
DepositAddress = newPaymentMethodDetails.GetPaymentDestination();
|
||||
KeyPath = (newPaymentMethodDetails as BitcoinLikeOnChainPaymentMethod)?.KeyPath;
|
||||
}
|
||||
public NetworkFeeMode NetworkFeeMode { get; set; }
|
||||
|
||||
|
@ -51,7 +53,9 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
[JsonIgnore]
|
||||
public Money NextNetworkFee { get; set; }
|
||||
[JsonIgnore]
|
||||
public String DepositAddress { get; set; }
|
||||
public String DepositAddress { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
|
||||
public KeyPath KeyPath { get; set; }
|
||||
|
||||
public BitcoinAddress GetDepositAddress(Network network)
|
||||
{
|
||||
|
|
|
@ -17,13 +17,14 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
|
||||
}
|
||||
|
||||
public BitcoinLikePaymentData(BitcoinAddress address, IMoney value, OutPoint outpoint, bool rbf)
|
||||
public BitcoinLikePaymentData(BitcoinAddress address, IMoney value, OutPoint outpoint, bool rbf, KeyPath keyPath)
|
||||
{
|
||||
Address = address;
|
||||
Value = value;
|
||||
Outpoint = outpoint;
|
||||
ConfirmationCount = 0;
|
||||
RBF = rbf;
|
||||
KeyPath = keyPath;
|
||||
}
|
||||
[JsonIgnore]
|
||||
public BTCPayNetworkBase Network { get; set; }
|
||||
|
@ -34,6 +35,8 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
public int ConfirmationCount { get; set; }
|
||||
public bool RBF { get; set; }
|
||||
public BitcoinAddress Address { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
|
||||
public KeyPath KeyPath { get; set; }
|
||||
public IMoney Value { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
|
|
|
@ -159,7 +159,9 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
break;
|
||||
}
|
||||
|
||||
onchainMethod.DepositAddress = (await prepare.ReserveAddress).Address.ToString();
|
||||
var reserved = await prepare.ReserveAddress;
|
||||
onchainMethod.DepositAddress = reserved.Address.ToString();
|
||||
onchainMethod.KeyPath = reserved.KeyPath;
|
||||
onchainMethod.PayjoinEnabled = blob.PayJoinEnabled &&
|
||||
PayjoinClient.SupportedFormats.Contains(supportedPaymentMethod
|
||||
.AccountDerivation.ScriptPubKeyType()) &&
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
|
||||
var paymentData = new BitcoinLikePaymentData(address,
|
||||
output.matchedOutput.Value, output.outPoint,
|
||||
evt.TransactionData.Transaction.RBF);
|
||||
evt.TransactionData.Transaction.RBF, output.Item1.KeyPath);
|
||||
|
||||
var alreadyExist = invoice.GetAllBitcoinPaymentData().Where(c => c.GetPaymentId() == paymentData.GetPaymentId()).Any();
|
||||
if (!alreadyExist)
|
||||
|
@ -363,7 +363,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
var address = network.NBXplorerNetwork.CreateAddress(strategy, coin.KeyPath, coin.ScriptPubKey);
|
||||
|
||||
var paymentData = new BitcoinLikePaymentData(address, coin.Value, coin.OutPoint,
|
||||
transaction.Transaction.RBF);
|
||||
transaction.Transaction.RBF, coin.KeyPath);
|
||||
|
||||
var payment = await _InvoiceRepository.AddPayment(invoice.Id, coin.Timestamp, paymentData, network).ConfigureAwait(false);
|
||||
alreadyAccounted.Add(coin.OutPoint);
|
||||
|
@ -400,8 +400,9 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||
{
|
||||
var address = await wallet.ReserveAddressAsync(strategy);
|
||||
btc.DepositAddress = address.Address.ToString();
|
||||
await _InvoiceRepository.NewAddress(invoice.Id, btc, wallet.Network);
|
||||
_Aggregator.Publish(new InvoiceNewAddressEvent(invoice.Id, btc.DepositAddress, wallet.Network));
|
||||
btc.KeyPath = address.KeyPath;
|
||||
await _InvoiceRepository.NewPaymentDetails(invoice.Id, btc, wallet.Network);
|
||||
_Aggregator.Publish(new InvoiceNewPaymentDetailsEvent(invoice.Id, btc, paymentMethod.GetId()));
|
||||
paymentMethod.SetPaymentMethodDetails(btc);
|
||||
invoice.SetPaymentMethod(paymentMethod);
|
||||
}
|
||||
|
|
|
@ -21,10 +21,5 @@ namespace BTCPayServer.Payments
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
decimal GetFeeRate();
|
||||
/// <summary>
|
||||
/// Change the payment destination (internal plumbing)
|
||||
/// </summary>
|
||||
/// <param name="newPaymentDestination"></param>
|
||||
void SetPaymentDestination(string newPaymentDestination);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace BTCPayServer.Payments.Lightning
|
|||
return 0.0m;
|
||||
}
|
||||
|
||||
public void SetPaymentDestination(string newPaymentDestination)
|
||||
public void SetPaymentDetails(IPaymentMethodDetails newPaymentMethodDetails)
|
||||
{
|
||||
BOLT11 = newPaymentDestination;
|
||||
BOLT11 = newPaymentMethodDetails.GetPaymentDestination();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,6 +238,7 @@ namespace BTCPayServer.Payments.PayJoin
|
|||
Dictionary<OutPoint, UTXO> selectedUTXOs = new Dictionary<OutPoint, UTXO>();
|
||||
PSBTOutput originalPaymentOutput = null;
|
||||
BitcoinAddress paymentAddress = null;
|
||||
KeyPath paymentAddressIndex = null;
|
||||
InvoiceEntity invoice = null;
|
||||
DerivationSchemeSettings derivationSchemeSettings = null;
|
||||
foreach (var output in psbt.Outputs)
|
||||
|
@ -300,6 +301,7 @@ namespace BTCPayServer.Payments.PayJoin
|
|||
ctx.LockedUTXOs = selectedUTXOs.Select(u => u.Key).ToArray();
|
||||
originalPaymentOutput = output;
|
||||
paymentAddress = paymentDetails.GetDepositAddress(network.NBitcoinNetwork);
|
||||
paymentAddressIndex = paymentDetails.KeyPath;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -440,7 +442,7 @@ namespace BTCPayServer.Payments.PayJoin
|
|||
var originalPaymentData = new BitcoinLikePaymentData(paymentAddress,
|
||||
originalPaymentOutput.Value,
|
||||
new OutPoint(ctx.OriginalTransaction.GetHash(), originalPaymentOutput.Index),
|
||||
ctx.OriginalTransaction.RBF);
|
||||
ctx.OriginalTransaction.RBF, paymentAddressIndex);
|
||||
originalPaymentData.ConfirmationCount = -1;
|
||||
originalPaymentData.PayjoinInformation = new PayjoinInformation()
|
||||
{
|
||||
|
|
|
@ -25,6 +25,11 @@ namespace BTCPayServer.Services.Altcoins.Ethereum.Payments
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void SetPaymentDetails(IPaymentMethodDetails newPaymentMethodDetails)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetPaymentDestination(string newPaymentDestination)
|
||||
{
|
||||
DepositAddress = newPaymentDestination;
|
||||
|
|
|
@ -25,10 +25,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments
|
|||
return 0.0m;
|
||||
}
|
||||
|
||||
public void SetPaymentDestination(string newPaymentDestination)
|
||||
{
|
||||
DepositAddress = newPaymentDestination;
|
||||
}
|
||||
public long AccountIndex { get; set; }
|
||||
public long AddressIndex { get; set; }
|
||||
public string DepositAddress { get; set; }
|
||||
|
|
|
@ -135,9 +135,9 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
|||
});
|
||||
monero.DepositAddress = address.Address;
|
||||
monero.AddressIndex = address.AddressIndex;
|
||||
await _invoiceRepository.NewAddress(invoice.Id, monero, payment.Network);
|
||||
await _invoiceRepository.NewPaymentDetails(invoice.Id, monero, payment.Network);
|
||||
_eventAggregator.Publish(
|
||||
new InvoiceNewAddressEvent(invoice.Id, address.Address, payment.Network));
|
||||
new InvoiceNewPaymentDetailsEvent(invoice.Id, monero, payment.GetPaymentMethodId()));
|
||||
paymentMethod.SetPaymentMethodDetails(monero);
|
||||
invoice.SetPaymentMethod(paymentMethod);
|
||||
}
|
||||
|
|
|
@ -245,67 +245,48 @@ retry:
|
|||
return paymentMethod.GetPaymentMethodDetails().GetPaymentDestination();
|
||||
}
|
||||
|
||||
public async Task<bool> NewAddress(string invoiceId, IPaymentMethodDetails paymentMethod, BTCPayNetworkBase network)
|
||||
public async Task<bool> NewPaymentDetails(string invoiceId, IPaymentMethodDetails paymentMethodDetails, BTCPayNetworkBase network)
|
||||
{
|
||||
using (var context = _ContextFactory.CreateContext())
|
||||
await using var context = _ContextFactory.CreateContext();
|
||||
var invoice = (await context.Invoices.Where(i => i.Id == invoiceId).ToListAsync()).FirstOrDefault();
|
||||
if (invoice == null)
|
||||
return false;
|
||||
|
||||
var invoiceEntity = invoice.GetBlob(_Networks);
|
||||
var paymentMethod = invoiceEntity.GetPaymentMethod(network, paymentMethodDetails.GetPaymentType());
|
||||
if (paymentMethod == null)
|
||||
return false;
|
||||
|
||||
var existingPaymentMethod = paymentMethod.GetPaymentMethodDetails();
|
||||
if (existingPaymentMethod.GetPaymentDestination() != null)
|
||||
{
|
||||
var invoice = (await context.Invoices.Where(i => i.Id == invoiceId).ToListAsync()).FirstOrDefault();
|
||||
if (invoice == null)
|
||||
return false;
|
||||
|
||||
var invoiceEntity = invoice.GetBlob(_Networks);
|
||||
var currencyData = invoiceEntity.GetPaymentMethod(network, paymentMethod.GetPaymentType());
|
||||
if (currencyData == null)
|
||||
return false;
|
||||
|
||||
var existingPaymentMethod = currencyData.GetPaymentMethodDetails();
|
||||
if (existingPaymentMethod.GetPaymentDestination() != null)
|
||||
{
|
||||
MarkUnassigned(invoiceId, invoiceEntity, context, currencyData.GetId());
|
||||
}
|
||||
|
||||
existingPaymentMethod.SetPaymentDestination(paymentMethod.GetPaymentDestination());
|
||||
currencyData.SetPaymentMethodDetails(existingPaymentMethod);
|
||||
MarkUnassigned(invoiceId, invoiceEntity, context, paymentMethod.GetId());
|
||||
}
|
||||
paymentMethod.SetPaymentMethodDetails(paymentMethodDetails);
|
||||
#pragma warning disable CS0618
|
||||
if (network.IsBTC)
|
||||
{
|
||||
invoiceEntity.DepositAddress = currencyData.DepositAddress;
|
||||
}
|
||||
if (network.IsBTC)
|
||||
{
|
||||
invoiceEntity.DepositAddress = paymentMethod.DepositAddress;
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
invoiceEntity.SetPaymentMethod(currencyData);
|
||||
invoice.Blob = ToBytes(invoiceEntity, network);
|
||||
invoiceEntity.SetPaymentMethod(paymentMethod);
|
||||
invoice.Blob = ToBytes(invoiceEntity, network);
|
||||
|
||||
context.AddressInvoices.Add(new AddressInvoiceData()
|
||||
await context.AddressInvoices.AddAsync(new AddressInvoiceData()
|
||||
{
|
||||
InvoiceDataId = invoiceId,
|
||||
CreatedTime = DateTimeOffset.UtcNow
|
||||
}
|
||||
.Set(GetDestination(currencyData), currencyData.GetId()));
|
||||
context.HistoricalAddressInvoices.Add(new HistoricalAddressInvoiceData()
|
||||
{
|
||||
InvoiceDataId = invoiceId,
|
||||
Assigned = DateTimeOffset.UtcNow
|
||||
}.SetAddress(paymentMethod.GetPaymentDestination(), network.CryptoCode));
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
AddToTextSearch(invoice.Id, paymentMethod.GetPaymentDestination());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateInvoicePaymentMethod(string invoiceId, PaymentMethod paymentMethod)
|
||||
{
|
||||
using (var context = _ContextFactory.CreateContext())
|
||||
.Set(GetDestination(paymentMethod), paymentMethod.GetId()));
|
||||
await context.HistoricalAddressInvoices.AddAsync(new HistoricalAddressInvoiceData()
|
||||
{
|
||||
var invoice = await context.Invoices.FindAsync(invoiceId);
|
||||
if (invoice == null)
|
||||
return;
|
||||
var network = paymentMethod.Network;
|
||||
var invoiceEntity = invoice.GetBlob(_Networks);
|
||||
invoiceEntity.SetPaymentMethod(paymentMethod);
|
||||
invoice.Blob = ToBytes(invoiceEntity, network);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
InvoiceDataId = invoiceId,
|
||||
Assigned = DateTimeOffset.UtcNow
|
||||
}.SetAddress(paymentMethodDetails.GetPaymentDestination(), network.CryptoCode));
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
AddToTextSearch(invoice.Id, paymentMethodDetails.GetPaymentDestination());
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task AddPendingInvoiceIfNotPresent(string invoiceId)
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<th>Crypto</th>
|
||||
<th>Index</th>
|
||||
<th>Deposit address</th>
|
||||
<th>Amount</th>
|
||||
<th>Transaction Id</th>
|
||||
|
@ -65,9 +66,10 @@
|
|||
{
|
||||
<tr style="@(payment.Replaced ? "text-decoration: line-through" : "")">
|
||||
<td>@payment.Crypto</td>
|
||||
<td>@payment.DepositAddress</td>
|
||||
<td>@(payment.CryptoPaymentData.Index?.ToString()?? "Unknown")</td>
|
||||
<td style="max-width:300px;" data-toggle="tooltip" class="text-truncate" title="@payment.DepositAddress">@payment.DepositAddress</td>
|
||||
<td class="payment-value">@payment.CryptoPaymentData.GetValue() @Safe.Raw(payment.AdditionalInformation is string i ? $"<br/>({i})" : string.Empty)</td>
|
||||
<td>
|
||||
<td style="max-width:300px;" data-toggle="tooltip" class="text-truncate" title="@payment.TransactionId">
|
||||
<div class="wraptextAuto">
|
||||
<a href="@payment.TransactionLink" target="_blank">
|
||||
@payment.TransactionId
|
||||
|
|
Loading…
Add table
Reference in a new issue