Mass update

This commit is contained in:
Kukks
2023-04-24 10:11:08 +02:00
parent c9a5dbc7d1
commit 6617b13941
12 changed files with 127 additions and 111 deletions

View File

@@ -16,8 +16,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Rating", "subm
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Common", "submodules\btcpayserver\BTCPayServer.Common\BTCPayServer.Common.csproj", "{3F2E0BA0-9EA7-490F-894D-F9703F35B174}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Common", "submodules\btcpayserver\BTCPayServer.Common\BTCPayServer.Common.csproj", "{3F2E0BA0-9EA7-490F-894D-F9703F35B174}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.Custodians.FakeCustodian", "submodules\btcpayserver\Plugins\BTCPayServer.Plugins.Custodians.FakeCustodian\BTCPayServer.Plugins.Custodians.FakeCustodian.csproj", "{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BTCPay", "BTCPay", "{9E04ECE9-E304-4FF2-9CBC-83256E6C6962}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BTCPay", "BTCPay", "{9E04ECE9-E304-4FF2-9CBC-83256E6C6962}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
submodules\btcpayserver\Build\Common.csproj = submodules\btcpayserver\Build\Common.csproj submodules\btcpayserver\Build\Common.csproj = submodules\btcpayserver\Build\Common.csproj
@@ -127,14 +125,6 @@ Global
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU {3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.Build.0 = Debug|Any CPU {3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Release|Any CPU.Build.0 = Release|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Altcoins-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Altcoins-Debug|Any CPU.Build.0 = Debug|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Altcoins-Release|Any CPU.ActiveCfg = Release|Any CPU
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD}.Altcoins-Release|Any CPU.Build.0 = Release|Any CPU
{6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.Build.0 = Debug|Any CPU {6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6295533A-F941-40CA-B889-FE6C0432ED53}.Release|Any CPU.ActiveCfg = Release|Any CPU {6295533A-F941-40CA-B889-FE6C0432ED53}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -270,7 +260,6 @@ Global
{8F158B88-0FEE-44FF-8552-7C0F17D5C508} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962} {8F158B88-0FEE-44FF-8552-7C0F17D5C508} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962}
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962} {D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962}
{3F2E0BA0-9EA7-490F-894D-F9703F35B174} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962} {3F2E0BA0-9EA7-490F-894D-F9703F35B174} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962}
{CCDE6E23-60B7-4B12-95AA-91CB40DBC3BD} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962}
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962} {2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21} = {9E04ECE9-E304-4FF2-9CBC-83256E6C6962}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -11,7 +11,7 @@
<PropertyGroup> <PropertyGroup>
<Product>Nostr </Product> <Product>Nostr </Product>
<Description>Allows you to verify your nostr account with NIP5 and zap like the rest of the crazies</Description> <Description>Allows you to verify your nostr account with NIP5 and zap like the rest of the crazies</Description>
<Version>1.0.10</Version> <Version>1.0.11</Version>
</PropertyGroup> </PropertyGroup>
<!-- Plugin development properties --> <!-- Plugin development properties -->
<PropertyGroup> <PropertyGroup>

View File

@@ -34,7 +34,6 @@ public class LnurlDescriptionFilter : PluginHookFilter<string>
public override async Task<string> Execute(string arg) public override async Task<string> Execute(string arg)
{ {
if (_httpContextAccessor.HttpContext.Request.Query.TryGetValue("nostr", out var nostr) && if (_httpContextAccessor.HttpContext.Request.Query.TryGetValue("nostr", out var nostr) &&
_httpContextAccessor.HttpContext.Request.RouteValues.TryGetValue("invoiceId", out var invoiceId)) _httpContextAccessor.HttpContext.Request.RouteValues.TryGetValue("invoiceId", out var invoiceId))
{ {
@@ -87,8 +86,6 @@ public class LnurlDescriptionFilter : PluginHookFilter<string>
} }
} }
return arg; return arg;
} }
} }

View File

@@ -9,12 +9,14 @@ public class LnurlFilter : PluginHookFilter<LNURLPayRequest>
{ {
private readonly Nip5Controller _nip5Controller; private readonly Nip5Controller _nip5Controller;
private readonly LightningAddressService _lightningAddressService; private readonly LightningAddressService _lightningAddressService;
private readonly Zapper _zapper;
public override string Hook => "modify-lnurlp-request"; public override string Hook => "modify-lnurlp-request";
public LnurlFilter(Nip5Controller nip5Controller, LightningAddressService lightningAddressService) public LnurlFilter(Nip5Controller nip5Controller, LightningAddressService lightningAddressService, Zapper zapper)
{ {
_nip5Controller = nip5Controller; _nip5Controller = nip5Controller;
_lightningAddressService = lightningAddressService; _lightningAddressService = lightningAddressService;
_zapper = zapper;
} }
public override async Task<LNURLPayRequest> Execute(LNURLPayRequest arg) public override async Task<LNURLPayRequest> Execute(LNURLPayRequest arg)
@@ -32,13 +34,9 @@ public class LnurlFilter : PluginHookFilter<LNURLPayRequest>
return arg; return arg;
} }
var nip5 = await _nip5Controller.Get(name); var nip5 = await _nip5Controller.GetForStore(lnAddress.StoreDataId);
if (nip5.storeId != lnAddress.StoreDataId)
{
return arg;
}
arg.NostrPubkey = nip5.settings.PubKey; arg.NostrPubkey = nip5?.PubKey ?? (await _zapper.GetSettings()).ZappingPublicKeyHex;
arg.AllowsNostr = true; arg.AllowsNostr = true;
return arg; return arg;
} }

View File

@@ -19,7 +19,8 @@ namespace BTCPayServer.Plugins.NIP05
"store-integrations-nav")); "store-integrations-nav"));
applicationBuilder.AddSingleton<IPluginHookFilter, LnurlDescriptionFilter>(); applicationBuilder.AddSingleton<IPluginHookFilter, LnurlDescriptionFilter>();
applicationBuilder.AddSingleton<IPluginHookFilter, LnurlFilter>(); applicationBuilder.AddSingleton<IPluginHookFilter, LnurlFilter>();
applicationBuilder.AddHostedService<Zapper>(); applicationBuilder.AddSingleton<Zapper>();
applicationBuilder.AddHostedService(sp => sp.GetRequiredService<Zapper>());
base.Execute(applicationBuilder); base.Execute(applicationBuilder);
} }

View File

@@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using NBitcoin.DataEncoders; using NBitcoin.DataEncoders;
using NBitcoin.Secp256k1;
using NNostr.Client; using NNostr.Client;
using NNostr.Client.Protocols; using NNostr.Client.Protocols;
@@ -40,11 +41,12 @@ public class Nip5Controller : Controller
var settings = await GetForStore(storeId); var settings = await GetForStore(storeId);
return View(settings ?? new()); return View(settings ?? new());
} }
[NonAction]
[NonAction]
public async Task<Nip5StoreSettings?> GetForStore(string storeId) public async Task<Nip5StoreSettings?> GetForStore(string storeId)
{ {
return await _memoryCache.GetOrCreateAsync("NIP05_" + storeId, async entry => await _storeRepository.GetSettingAsync<Nip5StoreSettings>(storeId, "NIP05")); return await _memoryCache.GetOrCreateAsync("NIP05_" + storeId,
async entry => await _storeRepository.GetSettingAsync<Nip5StoreSettings>(storeId, "NIP05"));
} }
[NonAction] [NonAction]
@@ -58,7 +60,6 @@ public class Nip5Controller : Controller
[HttpPost] [HttpPost]
public async Task<IActionResult> Edit(string storeId, Nip5StoreSettings settings, string command) public async Task<IActionResult> Edit(string storeId, Nip5StoreSettings settings, string command)
{ {
var existingSettings = await GetForStore(storeId); var existingSettings = await GetForStore(storeId);
if (command == "remove") if (command == "remove")
{ {
@@ -82,11 +83,9 @@ public class Nip5Controller : Controller
{ {
if (!HexEncoder.IsWellFormed(settings.PubKey)) if (!HexEncoder.IsWellFormed(settings.PubKey))
{ {
var note = (NIP19.NosteProfileNote) settings.PubKey.FromNIP19Note(); var note = (NIP19.NosteProfileNote) settings.PubKey.FromNIP19Note();
settings.PubKey = note.PubKey; settings.PubKey = note.PubKey;
settings.Relays = (settings.Relays ?? Array.Empty<string>())?.Concat(note.Relays).ToArray(); settings.Relays = (settings.Relays ?? Array.Empty<string>())?.Concat(note.Relays).ToArray();
} }
} }
catch (Exception) catch (Exception)
@@ -100,7 +99,6 @@ public class Nip5Controller : Controller
} }
catch (Exception e) catch (Exception e)
{ {
ModelState.AddModelError(nameof(settings.PubKey), "invalid public key"); ModelState.AddModelError(nameof(settings.PubKey), "invalid public key");
} }
@@ -111,27 +109,25 @@ public class Nip5Controller : Controller
ECPrivKey k; ECPrivKey k;
try try
{ {
k = settings.PrivateKey.FromNIP19Nsec(); k = settings.PrivateKey.FromNIP19Nsec();
} }
catch (Exception e) catch (Exception e)
{ {
k = NostrExtensions.ParseKey(settings.PrivateKey); k = NostrExtensions.ParseKey(settings.PrivateKey);
} }
settings.PrivateKey = k.ToHex(); settings.PrivateKey = k.ToHex();
if (string.IsNullOrEmpty(settings.PubKey)) if (string.IsNullOrEmpty(settings.PubKey))
{ {
settings.PubKey = k.CreateXOnlyPubKey().ToHex(); settings.PubKey = k.CreateXOnlyPubKey().ToHex();
ModelState.Remove(nameof(settings.PubKey)); ModelState.Remove(nameof(settings.PubKey));
} }
else if(settings.PubKey != k.CreateXOnlyPubKey().ToHex()) else if (settings.PubKey != k.CreateXOnlyPubKey().ToHex())
ModelState.AddModelError(nameof(settings.PrivateKey), "private key does not match public key provided. Clear the public key to generate it from the private key."); ModelState.AddModelError(nameof(settings.PrivateKey),
"private key does not match public key provided. Clear the public key to generate it from the private key.");
} }
catch (Exception e) catch (Exception e)
{ {
ModelState.AddModelError(nameof(settings.PrivateKey), "invalid private key"); ModelState.AddModelError(nameof(settings.PrivateKey), "invalid private key");
} }
} }
@@ -160,7 +156,8 @@ k = settings.PrivateKey.FromNIP19Nsec();
await UpdateStore(storeId, settings); await UpdateStore(storeId, settings);
return RedirectToAction("Edit", new {storeId}); return RedirectToAction("Edit", new {storeId});
} }
[NonAction]
[NonAction]
public async Task<(string? storeId, Nip5StoreSettings? settings)> Get(string name) public async Task<(string? storeId, Nip5StoreSettings? settings)> Get(string name)
{ {
var rex = await _memoryCache.GetOrCreateAsync<(string? storeId, Nip5StoreSettings? settings)>( var rex = await _memoryCache.GetOrCreateAsync<(string? storeId, Nip5StoreSettings? settings)>(

View File

@@ -12,25 +12,33 @@
<h2 class="mb-4">@ViewData["Title"]</h2> <h2 class="mb-4">@ViewData["Title"]</h2>
<p>You'll also need to <a asp-action="EditLightningAddress" asp-controller="UILNURL" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()">enable a lightning address</a> with the same name.</p> <p class="alert alert-info">For Zaps, just <a class="alert-link" asp-action="EditLightningAddress" asp-controller="UILNURL" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()">enable a lightning address</a>. None of the nostr settings on this page are needed for zaps anymore.</p>
<div class="row"> <div class="row">
<div class="col-md-10"> <div class="col-md-10">
<form method="post"> <form method="post">
<div class="form-group"> <div class="form-group">
<div class="form-group pt-2">
<label asp-for="Name" class="form-label"></label> <label asp-for="Name" class="form-label"></label>
<div class="input-group">
<input asp-for="Name" class="form-control"/> <input asp-for="Name" class="form-control"/>
<span class="input-group-text">@@@Context.Request.Host.ToUriComponent()@Context.Request.PathBase</span>
</div>
<span asp-validation-for="Name" class="text-danger"></span> <span asp-validation-for="Name" class="text-danger"></span>
</div> </div>
</div>
<div class="form-group"> <div class="form-group">
<label asp-for="PubKey" class="form-label"></label> <label asp-for="PubKey" class="form-label">Nostr Public Key</label>
<input asp-for="PubKey" class="form-control"/> <input asp-for="PubKey" class="form-control"/>
<span asp-validation-for="PubKey" class="text-danger"></span> <span asp-validation-for="PubKey" class="text-danger"></span>
<p class="text-muted pt-2">Supports hex, npub or nprofile. Will be converted to hex once saved. If nprofile is provided, the relays will be added as well.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label asp-for="PrivateKey" class="form-label">Private key for zaps</label> <label asp-for="PrivateKey" class="form-label">Private key for zaps</label>
<input asp-for="PrivateKey" class="form-control" type="password"/> <input asp-for="PrivateKey" class="form-control" type="password"/>
<span asp-validation-for="PrivateKey" class="text-danger"></span> <span asp-validation-for="PrivateKey" class="text-danger"></span>
<p class="text-muted pt-2">OPTIONALLY, provide the private key to your pubkey so that zaps are signed directly by you as proof of receipt. Supports hex and nsec. Will be converted to hex once saved. </p>
</div> </div>
<table class="table table-responsive col-12"> <table class="table table-responsive col-12">
<thead> <thead>

View File

@@ -2,7 +2,6 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Events; using BTCPayServer.Events;
@@ -15,16 +14,36 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using NBitcoin; using NBitcoin;
using NBitcoin.Secp256k1; using NBitcoin.Secp256k1;
using Newtonsoft.Json;
using NNostr.Client; using NNostr.Client;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace BTCPayServer.Plugins.NIP05; namespace BTCPayServer.Plugins.NIP05;
public record ZapperSettings(string ZapperPrivateKey) public class ZapperSettings
{ {
public ECPrivKey ZappingKey => NostrExtensions.ParseKey(ZapperPrivateKey); public ZapperSettings(string ZapperPrivateKey)
public ECXOnlyPubKey ZappingPublicKey => ZappingKey.CreateXOnlyPubKey(); {
public string ZappingPublicKeyHex => ZappingPublicKey.ToHex(); this.ZapperPrivateKey = ZapperPrivateKey;
}
public ZapperSettings()
{
}
[JsonIgnore]
public ECPrivKey ZappingKey => NostrExtensions.ParseKey(ZapperPrivateKey);
[JsonIgnore]
public ECXOnlyPubKey ZappingPublicKey => ZappingKey.CreateXOnlyPubKey();
[JsonIgnore]
public string ZappingPublicKeyHex => ZappingPublicKey.ToHex();
public string ZapperPrivateKey { get; init; }
public void Deconstruct(out string ZapperPrivateKey)
{
ZapperPrivateKey = this.ZapperPrivateKey;
}
} }
public class Zapper : IHostedService public class Zapper : IHostedService
{ {
@@ -38,7 +57,7 @@ public class Zapper : IHostedService
private IEventAggregatorSubscription _subscription; private IEventAggregatorSubscription _subscription;
private ConcurrentBag<PendingZapEvent> _pendingZapEvents = new(); private ConcurrentBag<PendingZapEvent> _pendingZapEvents = new();
private async Task<ZapperSettings> GetSettings() public async Task<ZapperSettings> GetSettings()
{ var result = await _settingsRepository.GetSettingAsync<ZapperSettings>( "Zapper"); { var result = await _settingsRepository.GetSettingAsync<ZapperSettings>( "Zapper");
if (result is not null) return result; if (result is not null) return result;
result = new ZapperSettings(Convert.ToHexString(RandomUtils.GetBytes(32))); result = new ZapperSettings(Convert.ToHexString(RandomUtils.GetBytes(32)));
@@ -192,18 +211,25 @@ public class Zapper : IHostedService
Data = new() {zapRequest} Data = new() {zapRequest}
}); });
var userNostrSettings = await _nip5Controller.GetForStore(arg.Invoice.StoreId);
var key = userNostrSettings?.PrivateKey is not null
? NostrExtensions.ParseKey(userNostrSettings?.PrivateKey)
: settings.ZappingKey;
var pubkey = userNostrSettings?.PubKey is not null
? userNostrSettings?.PubKey
: settings.ZappingPublicKeyHex;
var zapReceipt = new NostrEvent() var zapReceipt = new NostrEvent()
{ {
Kind = 9735, Kind = 9735,
CreatedAt = DateTimeOffset.UtcNow, CreatedAt = DateTimeOffset.UtcNow,
PublicKey = settings.ZappingPublicKeyHex, PublicKey = pubkey,
Content = zapRequestEvent.Content, Content = zapRequestEvent.Content,
Tags = tags Tags = tags
}; };
await zapReceipt.ComputeIdAndSignAsync(settings.ZappingKey); await zapReceipt.ComputeIdAndSignAsync(key);
var userNostrSettings = await _nip5Controller.GetForStore(arg.Invoice.StoreId);
_pendingZapEvents.Add(new PendingZapEvent(relays.Concat(userNostrSettings?.Relays?? Array.Empty<string>()).Distinct().ToArray(), zapReceipt)); _pendingZapEvents.Add(new PendingZapEvent(relays.Concat(userNostrSettings?.Relays?? Array.Empty<string>()).Distinct().ToArray(), zapReceipt));
} }

View File

@@ -11,7 +11,7 @@
<PropertyGroup> <PropertyGroup>
<Product>LN Prism</Product> <Product>LN Prism</Product>
<Description>Automated value splits for lightning.</Description> <Description>Automated value splits for lightning.</Description>
<Version>1.0.6</Version> <Version>1.0.7</Version>
</PropertyGroup> </PropertyGroup>
<!-- Plugin development properties --> <!-- Plugin development properties -->
<PropertyGroup> <PropertyGroup>

View File

@@ -94,7 +94,7 @@
<span asp-validation-for="Splits[i].Destinations" class="text-danger w-100"></span> <span asp-validation-for="Splits[i].Destinations" class="text-danger w-100"></span>
</div> </div>
<table class="table"> <table class="table table-responsive">
<thead> <thead>
<tr> <tr>
<th> <th>
@@ -153,7 +153,7 @@
{ {
<div class="col-sm-12 col-md-5 col-xxl-constrain border border-light"> <div class="col-sm-12 col-md-5 col-xxl-constrain border border-light">
<h4 class="text-center p-2">Destination Balances</h4> <h4 class="text-center p-2">Destination Balances</h4>
<table class="table"> <table class="table table-responsive">
<tr> <tr>
<th>Destination</th> <th>Destination</th>
<th>Sats</th> <th>Sats</th>

View File

@@ -13,7 +13,7 @@
<PropertyGroup> <PropertyGroup>
<Product>Wabisabi Coinjoin</Product> <Product>Wabisabi Coinjoin</Product>
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description> <Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
<Version>1.0.32</Version> <Version>1.0.33</Version>
</PropertyGroup> </PropertyGroup>
<!-- Plugin development properties --> <!-- Plugin development properties -->