mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
Plugins: Add hook for resolving Lightning Address (#5322)
This commit is contained in:
@@ -48,7 +48,7 @@ public class LightningAddressService
|
|||||||
{
|
{
|
||||||
return await _memoryCache.GetOrCreateAsync(GetKey(username), async entry =>
|
return await _memoryCache.GetOrCreateAsync(GetKey(username), async entry =>
|
||||||
{
|
{
|
||||||
var result = await Get(new LightningAddressQuery() { Usernames = new[] { username } });
|
var result = await Get(new LightningAddressQuery { Usernames = new[] { username } });
|
||||||
return result.FirstOrDefault();
|
return result.FirstOrDefault();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ public class LightningAddressService
|
|||||||
{
|
{
|
||||||
data.Username = NormalizeUsername(data.Username);
|
data.Username = NormalizeUsername(data.Username);
|
||||||
await using var context = _applicationDbContextFactory.CreateContext();
|
await using var context = _applicationDbContextFactory.CreateContext();
|
||||||
var result = (await GetCore(context, new LightningAddressQuery() { Usernames = new[] { data.Username } }))
|
var result = (await GetCore(context, new LightningAddressQuery { Usernames = new[] { data.Username } }))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
if (result is not null)
|
if (result is not null)
|
||||||
{
|
{
|
||||||
@@ -84,7 +84,7 @@ public class LightningAddressService
|
|||||||
{
|
{
|
||||||
username = NormalizeUsername(username);
|
username = NormalizeUsername(username);
|
||||||
await using var context = _applicationDbContextFactory.CreateContext();
|
await using var context = _applicationDbContextFactory.CreateContext();
|
||||||
var x = (await GetCore(context, new LightningAddressQuery() { Usernames = new[] { username } })).FirstOrDefault();
|
var x = (await GetCore(context, new LightningAddressQuery { Usernames = new[] { username } })).FirstOrDefault();
|
||||||
if (x is null)
|
if (x is null)
|
||||||
return true;
|
return true;
|
||||||
if (storeId is not null && x.StoreDataId != storeId)
|
if (storeId is not null && x.StoreDataId != storeId)
|
||||||
@@ -100,7 +100,7 @@ public class LightningAddressService
|
|||||||
|
|
||||||
public async Task Set(LightningAddressData data, ApplicationDbContext context)
|
public async Task Set(LightningAddressData data, ApplicationDbContext context)
|
||||||
{
|
{
|
||||||
var result = (await GetCore(context, new LightningAddressQuery() { Usernames = new[] { data.Username } }))
|
var result = (await GetCore(context, new LightningAddressQuery { Usernames = new[] { data.Username } }))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
if (result is not null)
|
if (result is not null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.Collections.Concurrent;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
@@ -18,9 +17,9 @@ using BTCPayServer.Data.Payouts.LightningLike;
|
|||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Logging;
|
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Plugins;
|
||||||
using BTCPayServer.Plugins.Crowdfund;
|
using BTCPayServer.Plugins.Crowdfund;
|
||||||
using BTCPayServer.Plugins.PointOfSale;
|
using BTCPayServer.Plugins.PointOfSale;
|
||||||
using BTCPayServer.Plugins.PointOfSale.Models;
|
using BTCPayServer.Plugins.PointOfSale.Models;
|
||||||
@@ -32,7 +31,6 @@ using BTCPayServer.Services.Stores;
|
|||||||
using LNURL;
|
using LNURL;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -368,41 +366,56 @@ namespace BTCPayServer
|
|||||||
[IgnoreAntiforgeryToken]
|
[IgnoreAntiforgeryToken]
|
||||||
public async Task<IActionResult> ResolveLightningAddress(string username)
|
public async Task<IActionResult> ResolveLightningAddress(string username)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(username))
|
||||||
|
return NotFound("Unknown username");
|
||||||
|
|
||||||
|
LNURLPayRequest lnurlRequest = null;
|
||||||
|
|
||||||
|
// Check core and fall back to lookup Lightning Address via plugins
|
||||||
var lightningAddressSettings = await _lightningAddressService.ResolveByAddress(username);
|
var lightningAddressSettings = await _lightningAddressService.ResolveByAddress(username);
|
||||||
if (lightningAddressSettings is null || username is null)
|
if (lightningAddressSettings is null)
|
||||||
return NotFound("Unknown username");
|
|
||||||
|
|
||||||
var store = await _storeRepository.FindStore(lightningAddressSettings.StoreDataId);
|
|
||||||
var cryptoCode = "BTC";
|
|
||||||
if (store is null)
|
|
||||||
return NotFound("Unknown username");
|
|
||||||
if (GetLNUrlPaymentMethodId(cryptoCode, store, out var lnUrlMethod) is null)
|
|
||||||
return NotFound("LNUrl not available for store");
|
|
||||||
|
|
||||||
var blob = lightningAddressSettings.GetBlob();
|
|
||||||
|
|
||||||
var lnurlRequest = new LNURLPayRequest()
|
|
||||||
{
|
{
|
||||||
Tag = "payRequest",
|
var resolver = (LightningAddressResolver)await _pluginHookService.ApplyFilter("resolve-lnurlp-request-for-lightning-address",
|
||||||
MinSendable = blob?.Min is decimal min ? new LightMoney(min, LightMoneyUnit.Satoshi) : null,
|
new LightningAddressResolver(username));
|
||||||
MaxSendable = blob?.Max is decimal max ? new LightMoney(max, LightMoneyUnit.Satoshi) : null,
|
|
||||||
CommentAllowed = lnUrlMethod.LUD12Enabled ? 2000 : 0
|
lnurlRequest = resolver.LNURLPayRequest;
|
||||||
};
|
if (lnurlRequest is null)
|
||||||
|
return NotFound("Unknown username");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var store = await _storeRepository.FindStore(lightningAddressSettings.StoreDataId);
|
||||||
|
if (store is null)
|
||||||
|
return NotFound("Unknown username");
|
||||||
|
|
||||||
|
var cryptoCode = "BTC";
|
||||||
|
if (GetLNUrlPaymentMethodId(cryptoCode, store, out var lnUrlMethod) is null)
|
||||||
|
return NotFound("LNURL not available for store");
|
||||||
|
|
||||||
|
var blob = lightningAddressSettings.GetBlob();
|
||||||
|
lnurlRequest = new LNURLPayRequest
|
||||||
|
{
|
||||||
|
Tag = "payRequest",
|
||||||
|
MinSendable = blob?.Min is decimal min ? new LightMoney(min, LightMoneyUnit.Satoshi) : null,
|
||||||
|
MaxSendable = blob?.Max is decimal max ? new LightMoney(max, LightMoneyUnit.Satoshi) : null,
|
||||||
|
CommentAllowed = lnUrlMethod.LUD12Enabled ? 2000 : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var lnUrlMetadata = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["text/identifier"] = $"{username}@{Request.Host}"
|
||||||
|
};
|
||||||
|
SetLNUrlDescriptionMetadata(lnUrlMetadata, store, store.GetStoreBlob(), null);
|
||||||
|
lnurlRequest.Metadata =
|
||||||
|
JsonConvert.SerializeObject(lnUrlMetadata.Select(kv => new[] { kv.Key, kv.Value }));
|
||||||
|
|
||||||
|
lnurlRequest.Callback = new Uri(_linkGenerator.GetUriByAction(
|
||||||
|
action: nameof(GetLNURLForLightningAddress),
|
||||||
|
controller: "UILNURL",
|
||||||
|
values: new { cryptoCode, username }, Request.Scheme, Request.Host, Request.PathBase));
|
||||||
|
}
|
||||||
|
|
||||||
NormalizeSendable(lnurlRequest);
|
NormalizeSendable(lnurlRequest);
|
||||||
|
|
||||||
var lnUrlMetadata = new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
["text/identifier"] = $"{username}@{Request.Host}"
|
|
||||||
};
|
|
||||||
SetLNUrlDescriptionMetadata(lnUrlMetadata, store, store.GetStoreBlob(), null);
|
|
||||||
lnurlRequest.Metadata =
|
|
||||||
JsonConvert.SerializeObject(lnUrlMetadata.Select(kv => new[] { kv.Key, kv.Value }));
|
|
||||||
|
|
||||||
lnurlRequest.Callback = new Uri(_linkGenerator.GetUriByAction(
|
|
||||||
action: nameof(GetLNURLForLightningAddress),
|
|
||||||
controller: "UILNURL",
|
|
||||||
values: new { cryptoCode, username }, Request.Scheme, Request.Host, Request.PathBase));
|
|
||||||
|
|
||||||
lnurlRequest = await _pluginHookService.ApplyFilter("modify-lnurlp-request", lnurlRequest) as LNURLPayRequest;
|
lnurlRequest = await _pluginHookService.ApplyFilter("modify-lnurlp-request", lnurlRequest) as LNURLPayRequest;
|
||||||
return Ok(lnurlRequest);
|
return Ok(lnurlRequest);
|
||||||
}
|
}
|
||||||
@@ -417,21 +430,23 @@ namespace BTCPayServer
|
|||||||
return NotFound("Unknown username");
|
return NotFound("Unknown username");
|
||||||
var blob = lightningAddressSettings.GetBlob();
|
var blob = lightningAddressSettings.GetBlob();
|
||||||
var store = await _storeRepository.FindStore(lightningAddressSettings.StoreDataId);
|
var store = await _storeRepository.FindStore(lightningAddressSettings.StoreDataId);
|
||||||
|
if (store is null)
|
||||||
|
return NotFound("Unknown username");
|
||||||
var result = await GetLNURLRequest(
|
var result = await GetLNURLRequest(
|
||||||
cryptoCode,
|
cryptoCode,
|
||||||
store,
|
store,
|
||||||
store.GetStoreBlob(),
|
store.GetStoreBlob(),
|
||||||
new CreateInvoiceRequest()
|
new CreateInvoiceRequest
|
||||||
{
|
{
|
||||||
Currency = blob?.CurrencyCode,
|
Currency = blob?.CurrencyCode,
|
||||||
Metadata = blob?.InvoiceMetadata
|
Metadata = blob?.InvoiceMetadata
|
||||||
},
|
},
|
||||||
new LNURLPayRequest()
|
new LNURLPayRequest
|
||||||
{
|
{
|
||||||
MinSendable = blob?.Min is decimal min ? new LightMoney(min, LightMoneyUnit.Satoshi) : null,
|
MinSendable = blob?.Min is decimal min ? new LightMoney(min, LightMoneyUnit.Satoshi) : null,
|
||||||
MaxSendable = blob?.Max is decimal max ? new LightMoney(max, LightMoneyUnit.Satoshi) : null,
|
MaxSendable = blob?.Max is decimal max ? new LightMoney(max, LightMoneyUnit.Satoshi) : null,
|
||||||
},
|
},
|
||||||
new Dictionary<string, string>()
|
new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "text/identifier", $"{username}@{Request.Host}" }
|
{ "text/identifier", $"{username}@{Request.Host}" }
|
||||||
});
|
});
|
||||||
|
|||||||
14
BTCPayServer/Plugins/LightningAddresssResolver.cs
Normal file
14
BTCPayServer/Plugins/LightningAddresssResolver.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using LNURL;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins;
|
||||||
|
|
||||||
|
public class LightningAddressResolver
|
||||||
|
{
|
||||||
|
public string Username { get; set; }
|
||||||
|
public LNURLPayRequest LNURLPayRequest { get; set; }
|
||||||
|
|
||||||
|
public LightningAddressResolver(string username)
|
||||||
|
{
|
||||||
|
Username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user