mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
Validation of Nostr connection shouldn't be in CreateClient
This commit is contained in:
@@ -8,6 +8,7 @@ using System.Threading;
|
|||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
|
using BTCPayServer.Payments.Lightning;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.Secp256k1;
|
using NBitcoin.Secp256k1;
|
||||||
using NNostr.Client;
|
using NNostr.Client;
|
||||||
@@ -16,24 +17,28 @@ using SHA256 = System.Security.Cryptography.SHA256;
|
|||||||
|
|
||||||
namespace BTCPayServer.Plugins.NIP05;
|
namespace BTCPayServer.Plugins.NIP05;
|
||||||
|
|
||||||
public class NostrWalletConnectLightningClient : ILightningClient
|
public class NostrWalletConnectLightningClient : IExtendedLightningClient
|
||||||
{
|
{
|
||||||
|
|
||||||
[Display] public string DisplayLabel => $"Nostr Wallet Connect {_connectParams.lud16} {_connectParams.relays.First()} ";
|
[Display] public string DisplayLabel => $"Nostr Wallet Connect {_connectParams.lud16} {_connectParams.relays.First()} ";
|
||||||
private readonly NostrClientPool _nostrClientPool;
|
|
||||||
|
public string? DisplayName => "Nostr Wallet Connect (NwC)";
|
||||||
|
|
||||||
|
public Uri? ServerUri => _serverUri;
|
||||||
|
|
||||||
|
private readonly NostrClientPool _nostrClientPool;
|
||||||
private readonly Uri _uri;
|
private readonly Uri _uri;
|
||||||
private readonly Network _network;
|
private readonly Network _network;
|
||||||
private readonly (string[] Commands, string[] Notifications) _commands;
|
|
||||||
private readonly (ECXOnlyPubKey pubkey, ECPrivKey secret, Uri[] relays, string lud16) _connectParams;
|
private readonly (ECXOnlyPubKey pubkey, ECPrivKey secret, Uri[] relays, string lud16) _connectParams;
|
||||||
|
private readonly Uri? _serverUri;
|
||||||
|
|
||||||
public NostrWalletConnectLightningClient(NostrClientPool nostrClientPool, Uri uri, Network network,
|
public NostrWalletConnectLightningClient(NostrClientPool nostrClientPool, Uri uri, Network network)
|
||||||
(string[] Commands, string[] Notifications) commands)
|
|
||||||
{
|
{
|
||||||
_nostrClientPool = nostrClientPool;
|
_nostrClientPool = nostrClientPool;
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
_network = network;
|
_network = network;
|
||||||
_commands = commands;
|
|
||||||
_connectParams = NIP47.ParseUri(uri);
|
_connectParams = NIP47.ParseUri(uri);
|
||||||
|
_serverUri = _connectParams.relays.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@@ -245,15 +250,19 @@ public class NostrWalletConnectLightningClient : ILightningClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ILightningInvoiceListener> Listen(CancellationToken cancellation = new())
|
public async Task<ILightningInvoiceListener> Listen(CancellationToken cancellation = default)
|
||||||
{
|
{
|
||||||
var x = await _nostrClientPool.GetClientAndConnect(_connectParams.relays, cancellation);
|
var x = await _nostrClientPool.GetClientAndConnect(_connectParams.relays, cancellation);
|
||||||
if (_commands.Notifications?.Contains("payment_received") is true)
|
var commands = await x.Item1.FetchNIP47AvailableCommands(_connectParams.Item1, cancellationToken: cancellation);
|
||||||
|
bool? hasNotification = commands?.Notifications?.Contains("payment_received");
|
||||||
|
if (hasNotification is false)
|
||||||
{
|
{
|
||||||
return new NotificationListener(_network, x, _connectParams);
|
var response = await x.Item1.SendNIP47Request<NIP47.GetInfoResponse>(_connectParams.pubkey, _connectParams.secret, new NIP47.GetInfoRequest(), cancellationToken: cancellation);
|
||||||
}
|
hasNotification = response?.Notifications?.Contains("payment_received");
|
||||||
|
}
|
||||||
return new PollListener(_network, x, _connectParams);
|
return hasNotification is true
|
||||||
|
? new NotificationListener(_network, x, _connectParams)
|
||||||
|
: new PollListener(_network, x, _connectParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -513,4 +522,36 @@ public class NostrWalletConnectLightningClient : ILightningClient
|
|||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ValidationResult?> Validate()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||||
|
var (client, disposable) = await _nostrClientPool.GetClientAndConnect(_connectParams.relays, cts.Token).ConfigureAwait(false);
|
||||||
|
using (disposable)
|
||||||
|
{
|
||||||
|
var commands = await client.FetchNIP47AvailableCommands(_connectParams.Item1, cancellationToken: cts.Token);
|
||||||
|
var requiredCommands = new[] { "get_info", "make_invoice", "lookup_invoice", "list_transactions" };
|
||||||
|
if (commands?.Commands is null || requiredCommands.Any(c => !commands.Value.Commands.Contains(c)))
|
||||||
|
{
|
||||||
|
return new ValidationResult("No commands available or not all required commands are available (get_info, make_invoice, lookup_invoice, list_transactions)");
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await client
|
||||||
|
.SendNIP47Request<NIP47.GetInfoResponse>(_connectParams.pubkey, _connectParams.secret,
|
||||||
|
new NIP47.GetInfoRequest(), cancellationToken: cts.Token);
|
||||||
|
|
||||||
|
var walletNetwork = response.Network;
|
||||||
|
if (!_network.ChainName.ToString().Equals(walletNetwork,
|
||||||
|
StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
return new ValidationResult($"The network of the wallet ({walletNetwork}) does not match the network of the server ({_network.ChainName})");
|
||||||
|
}
|
||||||
|
if (response?.Methods is null || requiredCommands.Any(c => !response.Methods.Contains(c)))
|
||||||
|
{
|
||||||
|
return new ValidationResult("No commands available or not all required commands are available (get_info, make_invoice, lookup_invoice, list_transactions)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ValidationResult.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -39,55 +39,8 @@ public class NostrWalletConnectLightningConnectionStringHandler : ILightningConn
|
|||||||
error = "Invalid nostr wallet connect uri";
|
error = "Invalid nostr wallet connect uri";
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try
|
|
||||||
{
|
|
||||||
var connectParams = NIP47.ParseUri(uri);
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
|
||||||
var (client, disposable) = _nostrClientPool.GetClientAndConnect(connectParams.relays, cts.Token).ConfigureAwait(false).GetAwaiter().GetResult();
|
|
||||||
using (disposable)
|
|
||||||
{
|
|
||||||
var commands = client.FetchNIP47AvailableCommands(connectParams.Item1, cancellationToken: cts.Token)
|
|
||||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
|
||||||
var requiredCommands = new[] {"get_info", "make_invoice", "lookup_invoice", "list_transactions"};
|
|
||||||
if (commands?.Commands is null || requiredCommands.Any(c => !commands.Value.Commands.Contains(c)))
|
|
||||||
{
|
|
||||||
error =
|
|
||||||
"No commands available or not all required commands are available (get_info, make_invoice, lookup_invoice, list_transactions)";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = client
|
error = null;
|
||||||
.SendNIP47Request<NIP47.GetInfoResponse>(connectParams.pubkey, connectParams.secret,
|
return new NostrWalletConnectLightningClient(_nostrClientPool, uri, network);
|
||||||
new NIP47.GetInfoRequest(), cancellationToken: cts.Token).ConfigureAwait(false).GetAwaiter()
|
}
|
||||||
.GetResult();
|
|
||||||
|
|
||||||
var walletNetwork = response.Network;
|
|
||||||
if (!network.ChainName.ToString().Equals(walletNetwork,
|
|
||||||
StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
error =
|
|
||||||
$"The network of the wallet ({walletNetwork}) does not match the network of the server ({network.ChainName})";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (response?.Methods is null || requiredCommands.Any(c => !response.Methods.Contains(c)))
|
|
||||||
{
|
|
||||||
error =
|
|
||||||
"No commands available or not all required commands are available (get_info, make_invoice, lookup_invoice, list_transactions)";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
(string[] Commands, string[] Notifications) values = (response.Methods ?? commands.Value.Commands,
|
|
||||||
response.Notifications ?? commands.Value.Notifications);
|
|
||||||
|
|
||||||
error = null;
|
|
||||||
return new NostrWalletConnectLightningClient(_nostrClientPool, uri, network, values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
error = "Invalid nostr wallet connect uri: " + e.Message;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Submodule submodules/btcpayserver updated: 540fb6c9f6...5534ddeb28
Reference in New Issue
Block a user