diff --git a/Plugins/BTCPayServer.Plugins.NIP05/BTCPayServer.Plugins.NIP05.csproj b/Plugins/BTCPayServer.Plugins.NIP05/BTCPayServer.Plugins.NIP05.csproj index 506793b..732a5a2 100644 --- a/Plugins/BTCPayServer.Plugins.NIP05/BTCPayServer.Plugins.NIP05.csproj +++ b/Plugins/BTCPayServer.Plugins.NIP05/BTCPayServer.Plugins.NIP05.csproj @@ -11,7 +11,7 @@ Nostr Allows you to verify your nostr account with NIP5 and zap like the rest of the crazies - 1.0.16 + 1.1.0 diff --git a/Plugins/BTCPayServer.Plugins.NIP05/LnurlDescriptionFilter.cs b/Plugins/BTCPayServer.Plugins.NIP05/LnurlDescriptionFilter.cs index 67e2c0c..e135699 100644 --- a/Plugins/BTCPayServer.Plugins.NIP05/LnurlDescriptionFilter.cs +++ b/Plugins/BTCPayServer.Plugins.NIP05/LnurlDescriptionFilter.cs @@ -47,11 +47,7 @@ public class LnurlDescriptionFilter : PluginHookFilter var username = metadata .FirstOrDefault(strings => strings.FirstOrDefault()?.Equals("text/identifier") is true) ?.ElementAtOrDefault(1)?.ToLowerInvariant().Split("@")[0]; - if (string.IsNullOrEmpty(username)) - { - return arg; - } - else + if (!string.IsNullOrEmpty(username)) { var lnAddress = await _lightningAddressService.ResolveByAddress(username); if (lnAddress is null) @@ -59,9 +55,6 @@ public class LnurlDescriptionFilter : PluginHookFilter return arg; } } - - - var parsedNote = System.Text.Json.JsonSerializer.Deserialize(nostr); if (parsedNote?.Kind != 9734) { diff --git a/Plugins/BTCPayServer.Plugins.NIP05/LnurlFilter.cs b/Plugins/BTCPayServer.Plugins.NIP05/LnurlFilter.cs index bd40edc..682cf8e 100644 --- a/Plugins/BTCPayServer.Plugins.NIP05/LnurlFilter.cs +++ b/Plugins/BTCPayServer.Plugins.NIP05/LnurlFilter.cs @@ -23,20 +23,21 @@ public class LnurlFilter : PluginHookFilter { var name = arg.ParsedMetadata.FirstOrDefault(pair => pair.Key == "text/identifier").Value ?.ToLowerInvariant().Split("@")[0]; - if (string.IsNullOrEmpty(name)) + if (!string.IsNullOrEmpty(name)) { - return arg; + var lnAddress = await _lightningAddressService.ResolveByAddress(name); + if (lnAddress is null) + { + return arg; + } + var nip5 = await _nip5Controller.GetForStore(lnAddress.StoreDataId); + arg.NostrPubkey = nip5?.PubKey; } - var lnAddress = await _lightningAddressService.ResolveByAddress(name); - if (lnAddress is null) - { - return arg; - } + - var nip5 = await _nip5Controller.GetForStore(lnAddress.StoreDataId); - arg.NostrPubkey = nip5?.PubKey ?? (await _zapper.GetSettings()).ZappingPublicKeyHex; + arg.NostrPubkey ??= (await _zapper.GetSettings()).ZappingPublicKeyHex; arg.AllowsNostr = true; return arg; } diff --git a/Plugins/BTCPayServer.Plugins.NIP05/Nip5Controller.cs b/Plugins/BTCPayServer.Plugins.NIP05/Nip5Controller.cs index c354ed5..9ba3246 100644 --- a/Plugins/BTCPayServer.Plugins.NIP05/Nip5Controller.cs +++ b/Plugins/BTCPayServer.Plugins.NIP05/Nip5Controller.cs @@ -2,14 +2,18 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Client; +using BTCPayServer.Filters; using BTCPayServer.Services.Stores; +using LNURL; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; +using NBitcoin; using NBitcoin.DataEncoders; using NBitcoin.Secp256k1; using NNostr.Client; @@ -205,4 +209,33 @@ public class Nip5Controller : Controller : null }); } + + [CheatModeRoute] + [HttpGet("~/nostr-fake")] + [EnableCors(CorsPolicies.All)] + [IgnoreAntiforgeryToken] + [AllowAnonymous] + public async Task FakeNostr(string lnurl) + { + if (lnurl.Contains("@")) + { + lnurl = LNURL.LNURL.ExtractUriFromInternetIdentifier(lnurl).ToString(); + } + var lnurlRequest = (LNURLPayRequest) await LNURL.LNURL.FetchInformation(new Uri(lnurl), new HttpClient()); + var nKey = ECPrivKey.Create(RandomUtils.GetBytes(32)); + var nostrEvent = new NostrEvent() + { + Kind = 9734, + Content = "", + + }; + var lnurlBech32x = LNURL.LNURL.EncodeBech32(new Uri(lnurl)); + nostrEvent.SetTag("relays", "wss://btcpay.kukks.org/nostr"); + nostrEvent.SetTag("lnurl", lnurlBech32x); + nostrEvent.SetTag("amount", lnurlRequest.MinSendable.MilliSatoshi.ToString()); + nostrEvent = await nostrEvent.ComputeIdAndSignAsync(nKey); + var response = await new HttpClient().GetAsync(lnurlRequest.Callback + "?amount=" + lnurlRequest.MinSendable.MilliSatoshi + + "&nostr=" +System.Text.Json.JsonSerializer.Serialize(nostrEvent)); + return Content(await response.Content.ReadAsStringAsync()); + } } \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.NIP05/Zapper.cs b/Plugins/BTCPayServer.Plugins.NIP05/Zapper.cs index 503771d..ee6a490 100644 --- a/Plugins/BTCPayServer.Plugins.NIP05/Zapper.cs +++ b/Plugins/BTCPayServer.Plugins.NIP05/Zapper.cs @@ -5,8 +5,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Events; +using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; using BTCPayServer.Services; +using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Stores; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Hosting; @@ -49,6 +51,7 @@ public class Zapper : IHostedService private readonly IMemoryCache _memoryCache; private readonly ILogger _logger; private readonly SettingsRepository _settingsRepository; + private readonly InvoiceRepository _invoiceRepository; private IEventAggregatorSubscription _subscription; private readonly ConcurrentBag _pendingZapEvents = new(); @@ -70,13 +73,18 @@ public class Zapper : IHostedService public Zapper(EventAggregator eventAggregator, - Nip5Controller nip5Controller, IMemoryCache memoryCache, ILogger logger, SettingsRepository settingsRepository, StoreRepository storeRepository) + Nip5Controller nip5Controller, + IMemoryCache memoryCache, + ILogger logger, + SettingsRepository settingsRepository, + InvoiceRepository invoiceRepository) { _eventAggregator = eventAggregator; _nip5Controller = nip5Controller; _memoryCache = memoryCache; _logger = logger; _settingsRepository = settingsRepository; + _invoiceRepository = invoiceRepository; } public Task StartAsync(CancellationToken cancellationToken) @@ -202,9 +210,16 @@ public class Zapper : IHostedService Tags = tags }; - - await zapReceipt.ComputeIdAndSignAsync(key); - _pendingZapEvents.Add(new PendingZapEvent(relays.Concat(userNostrSettings?.Relays?? Array.Empty()).Distinct().ToArray(), zapReceipt)); + zapReceipt = await zapReceipt.ComputeIdAndSignAsync(key); + relays = relays.Concat(userNostrSettings?.Relays ?? Array.Empty()).Distinct().ToArray(); + arg.Invoice.Metadata.SetAdditionalData("Nostr", new Dictionary() + { + {"Zap Request", zapRequestEvent.Id}, + {"Zap Receipt", zapReceipt.Id}, + {"Relays", string.Join(',', relays)} + }); + await _invoiceRepository.UpdateInvoiceMetadata(arg.InvoiceId, arg.Invoice.StoreId, arg.Invoice.Metadata.ToJObject()); + _pendingZapEvents.Add(new PendingZapEvent(relays, zapReceipt)); } public Task StopAsync(CancellationToken cancellationToken)