From 49cbc37e492e2c8a43b993b837e15adba3bd147e Mon Sep 17 00:00:00 2001 From: Kukks Date: Tue, 31 Oct 2023 14:35:47 +0100 Subject: [PATCH] Support onchain for prism --- .../BTCPayServer.Plugins.Prism.csproj | 2 +- .../Components/PrismEdit.razor | 50 ++--- .../LNURLPrismClaimCreate.cs | 49 +++++ .../LNURLPrismDestinationValidator.cs | 49 +++++ .../OnChainPrismClaimCreate.cs | 62 ++++++ .../OnChainPrismDestinationValidator.cs | 59 ++++++ .../BTCPayServer.Plugins.Prism/PrismPlugin.cs | 4 + .../BTCPayServer.Plugins.Prism/SatBreaker.cs | 197 ++++++++++++------ .../PrismClaimCreate.cs | 2 +- .../PrismSideshiftDestination.cs | 1 + .../Shared/SideShift/PrismEnhance.cshtml | 12 +- 11 files changed, 382 insertions(+), 105 deletions(-) create mode 100644 Plugins/BTCPayServer.Plugins.Prism/LNURLPrismClaimCreate.cs create mode 100644 Plugins/BTCPayServer.Plugins.Prism/LNURLPrismDestinationValidator.cs create mode 100644 Plugins/BTCPayServer.Plugins.Prism/OnChainPrismClaimCreate.cs create mode 100644 Plugins/BTCPayServer.Plugins.Prism/OnChainPrismDestinationValidator.cs diff --git a/Plugins/BTCPayServer.Plugins.Prism/BTCPayServer.Plugins.Prism.csproj b/Plugins/BTCPayServer.Plugins.Prism/BTCPayServer.Plugins.Prism.csproj index 5a0ba24..b210668 100644 --- a/Plugins/BTCPayServer.Plugins.Prism/BTCPayServer.Plugins.Prism.csproj +++ b/Plugins/BTCPayServer.Plugins.Prism/BTCPayServer.Plugins.Prism.csproj @@ -11,7 +11,7 @@ LN Prism Automated value splits for lightning. - 1.1.19 + 1.2.0 diff --git a/Plugins/BTCPayServer.Plugins.Prism/Components/PrismEdit.razor b/Plugins/BTCPayServer.Plugins.Prism/Components/PrismEdit.razor index a898c3e..e1ab88b 100644 --- a/Plugins/BTCPayServer.Plugins.Prism/Components/PrismEdit.razor +++ b/Plugins/BTCPayServer.Plugins.Prism/Components/PrismEdit.razor @@ -29,24 +29,19 @@ else @if (NoPayoutProcessors) { } -@if (Users?.Any() is not true) -{ - -} + + @foreach (var user in Users) { - + } @@ -63,7 +58,7 @@ else

- The prism plugin allows automated value splits for your lightning payments. You can set up multiple prisms, each with their own source (which is a lightning address username, or use * as a catch-all for all invoices settled through Lightning, excluding ones which Prism can handle explicitly) and destinations (which are other lightning addresses or lnurls). The plugin will automatically credit the configured percentage of the payment to the destination (while also making sure there is 2% reserved to cater for fees, don't worry, once the lightning node tells us the exact fee amount, we credit/debit the balance after the payment), and once the configured threshold is reached, a payout will be created. Then, a payout processor will run at intervals and process the payout. + The prism plugin allows automated value splits for your lightning and onchain payments. You can set up multiple prisms, each with their own source (which is a lightning address username, or use *, *Onchain or *All as catch-all for all payments made against invoices, excluding ones which Prism can handle explicitly) and destinations (which are other lightning addresses,, lnurls, bitcoin addresses, an xpub, or a custom formaty provided by other plugins). The plugin will automatically credit the configured percentage of the payment to the destination (while also making sure there is 2% reserved to cater for fees, don't worry, once the lightning node tells us the exact fee amount, we credit/debit the balance after the payment), and once the configured threshold is reached, a payout will be created. Then, a payout processor will run at intervals and process the payout.

@@ -150,7 +145,7 @@ else @StatusMessageModel.Message } -
+
@if (SelectedDestinationId is null or "null") { @@ -203,6 +198,7 @@ else public bool Loading { get; set; } = true; public List Users { get; set; } = new(); public PaymentMethodId pmi { get; set; } = new("BTC", LightningPaymentType.Instance); + public PaymentMethodId pmichain { get; set; } = new("BTC", PaymentTypes.BTCLike); public bool NoPayoutProcessors { get; set; } private string PrismEditButtonsFilter { get; set; } @@ -224,7 +220,7 @@ else var fetchProcessors = PayoutProcessorService.GetProcessors(new PayoutProcessorService.PayoutProcessorQuery() { Stores = new[] {StoreId}, - PaymentMethods = new[] {pmi.ToString()} + PaymentMethods = new[] {pmi.ToString(), pmichain.ToString()} }); var tasks = new Task[] @@ -241,7 +237,10 @@ else EditContext.OnValidationRequested += Validate; EditContext.OnFieldChanged += FieldChanged; SatBreaker.PrismUpdated += SatBreakerOnPrismUpdated; - NoPayoutProcessors = PayoutProcessorFactories.Any(factory => factory.GetSupportedPaymentMethods().Contains(pmi)) && !(await fetchProcessors).Any(); + //set NoPayoutProcessors to true if there are no configured payout processores for pmi and pmichain + NoPayoutProcessors = PayoutProcessorFactories.Any(factory => factory.GetSupportedPaymentMethods().Contains(pmi)) && (await fetchProcessors).All(data => + !new[] {pmi, pmichain}.Contains(data.GetPaymentMethodId())); + Loading = false; await InvokeAsync(StateHasChanged); } @@ -300,7 +299,6 @@ else MessageStore.Add(() => destination.Destination, "Destination is required"); continue; } - if (!ValidateDestination(dest, true)) { MessageStore.Add(() => destination.Destination, "Destination is not valid"); @@ -317,26 +315,8 @@ else { return true; } - try - { - LNURL.LNURL.ExtractUriFromInternetIdentifier(dest); - return true; - } - catch (Exception e) - { - try - { - LNURL.LNURL.Parse(dest, out var tag); - return true; - } - catch (Exception exception) - { - var result = PluginHookService.ApplyFilter("prism-destination-validate", dest).Result; - if (result is true) - return true; - } - } - return false; + var result = PluginHookService.ApplyFilter("prism-destination-validate", dest).Result; + return result is true or PrismDestinationValidationResult {Success: true }; } public ValidationMessageStore MessageStore { get; set; } @@ -547,4 +527,4 @@ else } } -} +} \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Prism/LNURLPrismClaimCreate.cs b/Plugins/BTCPayServer.Plugins.Prism/LNURLPrismClaimCreate.cs new file mode 100644 index 0000000..5df55e7 --- /dev/null +++ b/Plugins/BTCPayServer.Plugins.Prism/LNURLPrismClaimCreate.cs @@ -0,0 +1,49 @@ +using System; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using BTCPayServer.Data.Payouts.LightningLike; +using BTCPayServer.HostedServices; + +namespace BTCPayServer.Plugins.Prism; + +public class LNURLPrismClaimCreate : IPluginHookFilter +{ + private readonly BTCPayNetworkProvider _networkProvider; + public string Hook => "prism-claim-create"; + + public LNURLPrismClaimCreate(BTCPayNetworkProvider networkProvider) + { + _networkProvider = networkProvider; + } + public async Task Execute(object args) + { + var network = _networkProvider.GetNetwork("BTC"); + if (args is not ClaimRequest claimRequest || network is null) + { + return args; + } + + if (claimRequest.Destination?.ToString() is not { } potentialLnurl) return args; + + try + { + LNURL.LNURL.ExtractUriFromInternetIdentifier(potentialLnurl); + claimRequest.Destination = new LNURLPayClaimDestinaton(potentialLnurl); + return claimRequest; + } + catch (Exception e) + { + try + { + LNURL.LNURL.Parse(potentialLnurl, out _); + claimRequest.Destination = new LNURLPayClaimDestinaton(potentialLnurl); + return claimRequest; + } + catch (Exception) + { + } + } + + return args; + } +} \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Prism/LNURLPrismDestinationValidator.cs b/Plugins/BTCPayServer.Plugins.Prism/LNURLPrismDestinationValidator.cs new file mode 100644 index 0000000..8a70d69 --- /dev/null +++ b/Plugins/BTCPayServer.Plugins.Prism/LNURLPrismDestinationValidator.cs @@ -0,0 +1,49 @@ +using System; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using BTCPayServer.Payments; + +namespace BTCPayServer.Plugins.Prism; + +public class LNURLPrismDestinationValidator : IPluginHookFilter +{ + public string Hook => "prism-destination-validate"; + + public Task Execute(object args) + { + if (args is not string args1) return Task.FromResult(args); + + try + { + LNURL.LNURL.ExtractUriFromInternetIdentifier(args1); + return Task.FromResult(new PrismDestinationValidationResult() + { + Success = true, + PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.LNURLPay) + }); + } + catch (Exception e) + { + try + { + LNURL.LNURL.Parse(args1, out var tag); + return Task.FromResult(new PrismDestinationValidationResult() + { + Success = true, + PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.LNURLPay) + }); + } + catch (Exception) + { + } + } + + return Task.FromResult(args); + } +} + +public class PrismDestinationValidationResult +{ + public bool Success { get; set; } + public PaymentMethodId PaymentMethod { get; set; } +} \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Prism/OnChainPrismClaimCreate.cs b/Plugins/BTCPayServer.Plugins.Prism/OnChainPrismClaimCreate.cs new file mode 100644 index 0000000..09d90a4 --- /dev/null +++ b/Plugins/BTCPayServer.Plugins.Prism/OnChainPrismClaimCreate.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using BTCPayServer.Data; +using BTCPayServer.HostedServices; +using BTCPayServer.Payments; +using NBitcoin; +using NBXplorer.DerivationStrategy; + +namespace BTCPayServer.Plugins.Prism; + +public class OnChainPrismClaimCreate : IPluginHookFilter +{ + private readonly BTCPayNetworkProvider _networkProvider; + private readonly ExplorerClientProvider _explorerClientProvider; + public string Hook => "prism-claim-create"; + + public OnChainPrismClaimCreate(BTCPayNetworkProvider networkProvider, ExplorerClientProvider explorerClientProvider) + { + _networkProvider = networkProvider; + _explorerClientProvider = explorerClientProvider; + } + + public async Task Execute(object args) + { + var network = _networkProvider.GetNetwork("BTC"); + if (args is not ClaimRequest claimRequest || network is null) + { + return args; + } + + if (claimRequest.Destination?.Id is not { } destStr) return args; + try + { + claimRequest.Destination = + new AddressClaimDestination(BitcoinAddress.Create(destStr, network.NBitcoinNetwork)); + claimRequest.PaymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance); + return args; + } + catch (Exception) + { + try + { + var ds = new DerivationSchemeParser(network).Parse(destStr); + var ec = _explorerClientProvider.GetExplorerClient(network); + var add = await ec.GetUnusedAsync(ds, DerivationFeature.Deposit, 0, true); + + claimRequest.Destination = + new AddressClaimDestination(add.Address); + claimRequest.PaymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance); + } + catch (Exception exception) + { + Console.WriteLine(exception); + throw; + } + } + + + return args; + } +} \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Prism/OnChainPrismDestinationValidator.cs b/Plugins/BTCPayServer.Plugins.Prism/OnChainPrismDestinationValidator.cs new file mode 100644 index 0000000..a815eed --- /dev/null +++ b/Plugins/BTCPayServer.Plugins.Prism/OnChainPrismDestinationValidator.cs @@ -0,0 +1,59 @@ +using System; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using BTCPayServer.Data; +using BTCPayServer.Payments; +using NBitcoin; +using NBXplorer; + +namespace BTCPayServer.Plugins.Prism; + +public class OnChainPrismDestinationValidator : IPluginHookFilter +{ + private readonly BTCPayNetworkProvider _networkProvider; + public string Hook => "prism-destination-validate"; + + public OnChainPrismDestinationValidator(BTCPayNetworkProvider networkProvider) + { + _networkProvider = networkProvider; + } + + public Task Execute(object args) + { + if (args is not string args1) return Task.FromResult(args); + var network = _networkProvider.GetNetwork("BTC"); + if (network is null) + { + return Task.FromResult(args); + } + + try + { + + BitcoinAddress.Create(args1, network.NBitcoinNetwork); + return Task.FromResult(new PrismDestinationValidationResult() + { + Success = true, + PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike) + }); + } + catch (Exception e) + { + try + { + var parser = new DerivationSchemeParser(network); + var dsb = parser.Parse(args1); + return Task.FromResult(new PrismDestinationValidationResult() + { + Success = true, + PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike) + }); + } + catch (Exception) + { + } + } + + return Task.FromResult(args); + } +} \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Prism/PrismPlugin.cs b/Plugins/BTCPayServer.Plugins.Prism/PrismPlugin.cs index 9cb89cf..e974f56 100644 --- a/Plugins/BTCPayServer.Plugins.Prism/PrismPlugin.cs +++ b/Plugins/BTCPayServer.Plugins.Prism/PrismPlugin.cs @@ -22,6 +22,10 @@ public class PrismPlugin : BaseBTCPayServerPlugin "store-integrations-nav")); applicationBuilder.AddSingleton(); applicationBuilder.AddHostedService(provider => provider.GetRequiredService()); + applicationBuilder.AddSingleton(); + applicationBuilder.AddSingleton(); + applicationBuilder.AddSingleton(); + applicationBuilder.AddSingleton(); base.Execute(applicationBuilder); } diff --git a/Plugins/BTCPayServer.Plugins.Prism/SatBreaker.cs b/Plugins/BTCPayServer.Plugins.Prism/SatBreaker.cs index 68dd5ef..6a04205 100644 --- a/Plugins/BTCPayServer.Plugins.Prism/SatBreaker.cs +++ b/Plugins/BTCPayServer.Plugins.Prism/SatBreaker.cs @@ -14,6 +14,7 @@ using BTCPayServer.Lightning; using BTCPayServer.Payments; using BTCPayServer.Payments.Lightning; using BTCPayServer.Services; +using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Stores; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -23,6 +24,17 @@ using LightningAddressData = BTCPayServer.Data.LightningAddressData; namespace BTCPayServer.Plugins.Prism { + internal class PrismPlaceholderClaimDestination:IClaimDestination + { + public PrismPlaceholderClaimDestination(string id) + { + Id = id; + } + + public string Id { get; } + public decimal? Amount { get; } = null; + } + /// /// monitors stores that have prism enabled and detects incoming payments based on the lightning address splits the funds to the destinations once the threshold is reached /// @@ -293,6 +305,102 @@ namespace BTCPayServer.Plugins.Prism return true; // Indicate that the update succeeded } + + private (Split, LightMoney)[] DetermineMatches(PrismSettings prismSettings, InvoiceEntity entity) + { + //first check the primary thing - ln address + var explicitPMI = new PaymentMethodId("BTC", LNURLPayPaymentType.Instance); + var pm = entity.GetPaymentMethod(explicitPMI); + var pmd = pm?.GetPaymentMethodDetails() as LNURLPayPaymentMethodDetails; + List<(Split, LightMoney)> result = new(); + + var payments = entity.GetPayments(true).GroupBy(paymentEntity => paymentEntity.GetPaymentMethodId()).ToArray(); + if (pmd?.ConsumedLightningAddress is not null) + { + var address = pmd.ConsumedLightningAddress.Split("@")[0]; + var matchedExplicit = prismSettings.Splits.FirstOrDefault(s => + s.Source.Equals(address, StringComparison.InvariantCultureIgnoreCase)); + + if (matchedExplicit is not null) + { + var explicitPayments = payments.FirstOrDefault(grouping => + grouping.Key == explicitPMI)?.Sum(paymentEntity => paymentEntity.PaidAmount.Net); + payments = payments.Where(grouping => grouping.Key != explicitPMI).ToArray(); + + if (explicitPayments > 0) + { + result.Add((matchedExplicit, LightMoney.FromUnit(explicitPayments.Value, LightMoneyUnit.BTC))); + } + } + } + + var catchAlls = prismSettings.Splits.Where(split => split.Source.StartsWith("*")).Select(split => + { + PaymentMethodId pmi = null; + var valid = true; + + switch (split.Source) + { + case "*": + pmi = new PaymentMethodId("BTC", PaymentTypes.LightningLike); + break; + case "*All": + break; + case var s when PaymentTypes.TryParse(s.Substring(1), out var pType): + + pmi = new PaymentMethodId("BTC", pType); + break; + case var s when !PaymentMethodId.TryParse(s.Substring(1), out pmi): + valid = false; + break; + } + + if (pmi is not null && pmi.CryptoCode != "BTC") + { + valid = false; + } + + return (pmi, valid, split); + }).Where(tuple => tuple.valid).ToDictionary(split => split.pmi, split => split.split); + + while(payments.Any() || catchAlls.Any()) + { + decimal paymentSum; + Split catchAllSplit; + //check if all catachalls do not match to all payments.key and then check if there is a catch all with a null key, that will take all the payments + if(catchAlls.All(catchAll => payments.All(payment => payment.Key != catchAll.Key)) && catchAlls.TryGetValue(null, out catchAllSplit)) + { + + paymentSum = payments.Sum(paymentEntity => + paymentEntity.Sum(paymentEntity => paymentEntity.PaidAmount.Net)); + + payments = Array.Empty>(); + } + else + { + + var paymentGroup = payments.First(); + if (!catchAlls.Remove(paymentGroup.Key, out catchAllSplit)) + { + //shift the paymentgroup to bottom of the list + payments = payments.Where(grouping => grouping.Key != paymentGroup.Key).Append(paymentGroup).ToArray(); + continue; + } + + paymentSum = paymentGroup.Sum(paymentEntity => paymentEntity.PaidAmount.Net); + payments = payments.Where(grouping => grouping.Key != paymentGroup.Key).ToArray(); + } + + + if (paymentSum > 0) + { + result.Add((catchAllSplit, LightMoney.FromUnit(paymentSum, LightMoneyUnit.BTC))); + } + } + + return result.ToArray(); + } + /// /// if an invoice is completed, check if it was created through a lightning address, and if the store has prism enabled and one of the splits' source is the same lightning address, grab the paid amount, split it based on the destination percentages, and credit it inside the prism destbalances. /// When the threshold is reached (plus a 2% reserve fee to account for fees), create a payout and deduct the balance. @@ -320,71 +428,30 @@ namespace BTCPayServer.Plugins.Prism return; } - var onChainCatchAllIdentifier = "*" + PaymentTypes.BTCLike.ToStringNormalized(); - var catchAllPrism = prismSettings.Splits.FirstOrDefault(split => - split.Source == "*" || split.Source == onChainCatchAllIdentifier); - Split prism = null; - LightningAddressData address = null; + var prisms = DetermineMatches(prismSettings, invoiceEvent.Invoice); + foreach (var prism in prisms) + { + if (prism.Item2 is not { } msats || msats<= 0) + continue; + var splits = prism.Item1?.Destinations; + if (splits?.Any() is not true) + continue; - var pm = invoiceEvent.Invoice.GetPaymentMethod(new PaymentMethodId("BTC", - LNURLPayPaymentType.Instance)); - var pmd = pm?.GetPaymentMethodDetails() as LNURLPayPaymentMethodDetails; - if (string.IsNullOrEmpty(pmd?.ConsumedLightningAddress) && catchAllPrism is null) - { - return; - } - else if (!string.IsNullOrEmpty(pmd?.ConsumedLightningAddress)) - { - address = await _lightningAddressService.ResolveByAddress( - pmd.ConsumedLightningAddress.Split("@")[0]); - if (address is null) + //compute the sats for each destination based on splits percentage + var msatsPerDestination = + splits.ToDictionary(s => s.Destination, s => (long) (msats.MilliSatoshi * (s.Percentage / 100))); + + prismSettings.DestinationBalance ??= new Dictionary(); + foreach (var (destination, splitMSats) in msatsPerDestination) { - return; - } - - prism = prismSettings.Splits.FirstOrDefault(s => - s.Source.Equals(address.Username, StringComparison.InvariantCultureIgnoreCase)); - } - else if (catchAllPrism?.Source == onChainCatchAllIdentifier) - { - pm = invoiceEvent.Invoice.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike)); - prism = catchAllPrism; - } - else - { - pm = invoiceEvent.Invoice.GetPaymentMethod(invoiceEvent.Invoice.GetPayments(true) - .FirstOrDefault()?.GetPaymentMethodId()); - prism = catchAllPrism; - } - - var splits = prism?.Destinations; - if (splits?.Any() is not true || pm is null) - { - return; - } - - - var msats = LightMoney.FromUnit(pm.Calculate().CryptoPaid, LightMoneyUnit.BTC) - .ToUnit(LightMoneyUnit.MilliSatoshi); - if (msats <= 0) - { - return; - } - - //compute the sats for each destination based on splits percentage - var msatsPerDestination = - splits.ToDictionary(s => s.Destination, s => (long) (msats * (s.Percentage / 100))); - - prismSettings.DestinationBalance ??= new Dictionary(); - foreach (var (destination, splitMSats) in msatsPerDestination) - { - if (prismSettings.DestinationBalance.TryGetValue(destination, out var currentBalance)) - { - prismSettings.DestinationBalance[destination] = currentBalance + splitMSats; - } - else if (splitMSats > 0) - { - prismSettings.DestinationBalance.Add(destination, splitMSats); + if (prismSettings.DestinationBalance.TryGetValue(destination, out var currentBalance)) + { + prismSettings.DestinationBalance[destination] = currentBalance + splitMSats; + } + else if (splitMSats > 0) + { + prismSettings.DestinationBalance.Add(destination, splitMSats); + } } } @@ -393,7 +460,6 @@ namespace BTCPayServer.Plugins.Prism { await UpdatePrismSettingsForStore(invoiceEvent.Invoice.StoreId, prismSettings, true); } - break; } case CheckPayoutsEvt: @@ -416,7 +482,6 @@ namespace BTCPayServer.Plugins.Prism } } - private async Task CreatePayouts(string storeId, PrismSettings prismSettings) { if (!prismSettings.Enabled) @@ -454,7 +519,7 @@ namespace BTCPayServer.Plugins.Prism } var claimRequest = new ClaimRequest() { - Destination = new LNURLPayClaimDestinaton(destinationSettings?.Destination ?? destination), + Destination = new PrismPlaceholderClaimDestination(destinationSettings?.Destination ?? destination), PreApprove = true, StoreId = storeId, PaymentMethodId = pmi, diff --git a/Plugins/BTCPayServer.Plugins.SideShift/PrismClaimCreate.cs b/Plugins/BTCPayServer.Plugins.SideShift/PrismClaimCreate.cs index 51770e7..2865265 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/PrismClaimCreate.cs +++ b/Plugins/BTCPayServer.Plugins.SideShift/PrismClaimCreate.cs @@ -43,7 +43,7 @@ public class PrismClaimCreate : IPluginHookFilter affiliateId = "qg0OrfHJV", settleMemo = request.ShiftMemo, depositCoin = "BTC", - depositNetwork = "lightning", + depositNetwork = request.SourceNetwork?? "lightning", settleCoin = request.ShiftCoin, settleNetwork = request.ShiftNetwork, } diff --git a/Plugins/BTCPayServer.Plugins.SideShift/PrismSideshiftDestination.cs b/Plugins/BTCPayServer.Plugins.SideShift/PrismSideshiftDestination.cs index a4eb247..37d571c 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/PrismSideshiftDestination.cs +++ b/Plugins/BTCPayServer.Plugins.SideShift/PrismSideshiftDestination.cs @@ -6,6 +6,7 @@ public class PrismSideshiftDestination public string ShiftNetwork { get; set; } public string ShiftDestination { get; set; } public string ShiftMemo { get; set; } + public string SourceNetwork { get; set; } public bool Valid() { diff --git a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml index eee01f7..0e30300 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml +++ b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml @@ -49,6 +49,7 @@ document.addEventListener('DOMContentLoaded', (event) => { // sideshiftDestinationButton.addEventListener("click", ev => modal.show()); const selectedSideShiftCoin = document.getElementById("sscoin"); const specifiedSideShiftDestination = document.getElementById("ssdest"); + const specifiedSideShiftDepositNetwork = document.getElementById("ssdepositNetwork"); const specifiedSideShiftMemo= document.getElementById("ssmemo"); const shiftButton = document.getElementById("ssshift"); let selectedCoin = null; @@ -106,7 +107,7 @@ document.addEventListener('DOMContentLoaded', (event) => { settleMemo: specifiedSideShiftMemo.value, affiliateId: "qg0OrfHJV", depositCoin : "BTC", - depositNetwork : "lightning", + depositNetwork : specifiedSideShiftDepositNetwork.value, settleCoin: selectedCoin.code, settleNetwork: selectedCoin.network, permanent: true @@ -135,7 +136,8 @@ document.addEventListener('DOMContentLoaded', (event) => { shiftCoin:selectedCoin.code, shiftNetwork: selectedCoin.network, shiftDestination: specifiedSideShiftDestination.value, - shiftMemo: specifiedSideShiftMemo.value + shiftMemo: specifiedSideShiftMemo.value, + shiftDepositNetwork: specifiedSideShiftDepositNetwork.value }); shiftButton.removeAttribute("disabled"); } @@ -164,6 +166,12 @@ document.addEventListener('DOMContentLoaded', (event) => {

This will generate a piece of code based on Sideshift configuration that can work as a valid destination in prism. Prism will then generate a "shift" on Sideshift and send the funds through LN to it, and Sideshift will send you the conversion.

+ + +