From 99dda66bbca022f6f962cf3473c12c496532047d Mon Sep 17 00:00:00 2001 From: Nicolas Dorier Date: Fri, 6 Sep 2024 10:34:10 +0900 Subject: [PATCH] Rename PayoutData.Destination (#6197) --- BTCPayServer.Data/Data/PayoutData.cs | 11 +++++-- .../Migrations/20240906010127_renamecol.cs | 32 +++++++++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 4 +-- .../BitcoinLike/BitcoinLikePayoutHandler.cs | 2 +- .../PullPaymentHostedService.cs | 5 ++- .../Webhooks/PayoutWebhookDeliveryRequest.cs | 7 ++-- BTCPayServer/Hosting/MigrationStartupTask.cs | 2 +- 7 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 BTCPayServer.Data/Migrations/20240906010127_renamecol.cs diff --git a/BTCPayServer.Data/Data/PayoutData.cs b/BTCPayServer.Data/Data/PayoutData.cs index 4df056132..415202524 100644 --- a/BTCPayServer.Data/Data/PayoutData.cs +++ b/BTCPayServer.Data/Data/PayoutData.cs @@ -44,7 +44,14 @@ namespace BTCPayServer.Data public string Blob { get; set; } public string Proof { get; set; } #nullable enable - public string? Destination { get; set; } + /// + /// For example, BTC-CHAIN needs to ensure that only a single address is tied to an active payout. + /// If `PayoutBlob.Destination` is `bitcoin://1BvBMSeYstWetqTFn5Au4m4GFg7xJaNVN2?amount=0.1` + /// Then `DedupId` is `1BvBMSeYstWetqTFn5Au4m4GFg7xJaNVN2` + /// For Lightning, Destination could be the lightning address, BOLT11 or LNURL + /// But the `DedupId` would be the `PaymentHash`. + /// + public string? DedupId { get; set; } #nullable restore public StoreData StoreData { get; set; } @@ -62,7 +69,7 @@ namespace BTCPayServer.Data builder.Entity() .HasIndex(o => o.State); builder.Entity() - .HasIndex(x => new { DestinationId = x.Destination, x.State }); + .HasIndex(x => new { DestinationId = x.DedupId, x.State }); builder.Entity() .Property(o => o.Blob) diff --git a/BTCPayServer.Data/Migrations/20240906010127_renamecol.cs b/BTCPayServer.Data/Migrations/20240906010127_renamecol.cs new file mode 100644 index 000000000..b3a72d536 --- /dev/null +++ b/BTCPayServer.Data/Migrations/20240906010127_renamecol.cs @@ -0,0 +1,32 @@ +using BTCPayServer.Data; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BTCPayServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240906010127_renamecol")] + public partial class renamecol : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Destination", + table: "Payouts", + newName: "DedupId"); + + migrationBuilder.RenameIndex( + name: "IX_Payouts_Destination_State", + table: "Payouts", + newName: "IX_Payouts_DedupId_State"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs index 051388eb6..2f615d2e0 100644 --- a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -565,7 +565,7 @@ namespace BTCPayServer.Migrations b.Property("Date") .HasColumnType("timestamp with time zone"); - b.Property("Destination") + b.Property("DedupId") .HasColumnType("text"); b.Property("OriginalAmount") @@ -601,7 +601,7 @@ namespace BTCPayServer.Migrations b.HasIndex("StoreDataId"); - b.HasIndex("Destination", "State"); + b.HasIndex("DedupId", "State"); b.ToTable("Payouts"); }); diff --git a/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs b/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs index 45465f14c..229b825fe 100644 --- a/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs +++ b/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs @@ -430,7 +430,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler, IHasNetwork .Where(p => p.State == PayoutState.AwaitingPayment) .Where(p => p.PayoutMethodId == paymentMethodId.ToString()) #pragma warning disable CA1307 // Specify StringComparison - .Where(p => destination.Equals(p.Destination)) + .Where(p => destination.Equals(p.DedupId)) #pragma warning restore CA1307 // Specify StringComparison .FirstOrDefaultAsync(); diff --git a/BTCPayServer/HostedServices/PullPaymentHostedService.cs b/BTCPayServer/HostedServices/PullPaymentHostedService.cs index dd99c7391..a8902116f 100644 --- a/BTCPayServer/HostedServices/PullPaymentHostedService.cs +++ b/BTCPayServer/HostedServices/PullPaymentHostedService.cs @@ -415,7 +415,6 @@ namespace BTCPayServer.HostedServices Date = DateTimeOffset.UtcNow, State = PayoutState.Completed, PullPaymentDataId = pp.Id, - Destination = topUp.InvoiceEntity.Id, StoreDataId = pp.StoreId }; if (topUp.InvoiceEntity.Currency != pp.Currency || @@ -649,7 +648,7 @@ namespace BTCPayServer.HostedServices if (req.ClaimRequest.Destination.Id != null) { if (await ctx.Payouts.AnyAsync(data => - data.Destination.Equals(req.ClaimRequest.Destination.Id) && + data.DedupId.Equals(req.ClaimRequest.Destination.Id) && data.State != PayoutState.Completed && data.State != PayoutState.Cancelled )) { @@ -693,7 +692,7 @@ namespace BTCPayServer.HostedServices State = PayoutState.AwaitingApproval, PullPaymentDataId = req.ClaimRequest.PullPaymentId, PayoutMethodId = req.ClaimRequest.PayoutMethodId.ToString(), - Destination = req.ClaimRequest.Destination.Id, + DedupId = req.ClaimRequest.Destination.Id, StoreDataId = req.ClaimRequest.StoreId ?? pp?.StoreId, Currency = payoutHandler.Currency, OriginalCurrency = pp?.Currency ?? payoutHandler.Currency diff --git a/BTCPayServer/HostedServices/Webhooks/PayoutWebhookDeliveryRequest.cs b/BTCPayServer/HostedServices/Webhooks/PayoutWebhookDeliveryRequest.cs index dc41dcbb2..569dcde1f 100644 --- a/BTCPayServer/HostedServices/Webhooks/PayoutWebhookDeliveryRequest.cs +++ b/BTCPayServer/HostedServices/Webhooks/PayoutWebhookDeliveryRequest.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System.Threading.Tasks; using BTCPayServer.Client.Models; using BTCPayServer.Controllers; @@ -23,13 +23,12 @@ public class PayoutWebhookDeliveryRequest(PayoutEvent evt, string? webhookId, We private string Interpolate(string str) { + var blob = evt.Payout.GetBlob(btcPayNetworkJsonSerializerSettings); var res = str.Replace("{Payout.Id}", evt.Payout.Id) .Replace("{Payout.PullPaymentId}", evt.Payout.PullPaymentDataId) - .Replace("{Payout.Destination}", evt.Payout.Destination) + .Replace("{Payout.Destination}", evt.Payout.DedupId ?? blob.Destination) .Replace("{Payout.State}", evt.Payout.State.ToString()); - var blob = evt.Payout.GetBlob(btcPayNetworkJsonSerializerSettings); - res = InterpolateJsonField(res, "Payout.Metadata", blob.Metadata); return res; } diff --git a/BTCPayServer/Hosting/MigrationStartupTask.cs b/BTCPayServer/Hosting/MigrationStartupTask.cs index 025956d16..067e91aaf 100644 --- a/BTCPayServer/Hosting/MigrationStartupTask.cs +++ b/BTCPayServer/Hosting/MigrationStartupTask.cs @@ -636,7 +636,7 @@ WHERE cte.""Id""=p.""Id"" continue; } var claim = await handler?.ParseClaimDestination(payoutData.GetBlob(_btcPayNetworkJsonSerializerSettings).Destination, default); - payoutData.Destination = claim.destination?.Id; + payoutData.DedupId = claim.destination?.Id; } await ctx.SaveChangesAsync(); }