mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 15:44:26 +01:00
wip
This commit is contained in:
@@ -4,7 +4,6 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Plugins.FixedFloat;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Breez.Sdk;
|
using Breez.Sdk;
|
||||||
|
using BTCPayServer.Lightning;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using Network = Breez.Sdk.Network;
|
using Network = Breez.Sdk.Network;
|
||||||
|
|
||||||
namespace BTCPayServer.Lightning.Breez;
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
|
|
||||||
public class BreezLightningClient: ILightningClient, IDisposable, EventListener
|
public class BreezLightningClient: ILightningClient, IDisposable, EventListener
|
||||||
@@ -22,7 +23,7 @@ public class BreezLightningClient: ILightningClient, IDisposable, EventListener
|
|||||||
new GreenlightNodeConfig(null, inviteCode)
|
new GreenlightNodeConfig(null, inviteCode)
|
||||||
);
|
);
|
||||||
var config = BreezSdkMethods.DefaultConfig(
|
var config = BreezSdkMethods.DefaultConfig(
|
||||||
EnvironmentType.PRODUCTION,
|
network ==NBitcoin.Network.Main ? EnvironmentType.PRODUCTION: EnvironmentType.STAGING,
|
||||||
apiKey,
|
apiKey,
|
||||||
nodeConfig
|
nodeConfig
|
||||||
) with {
|
) with {
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using System;
|
using BTCPayServer.Lightning;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using BTCPayServer.Plugins.FixedFloat;
|
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
|
||||||
namespace BTCPayServer.Lightning.Breez;
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
public class BreezLightningConnectionStringHandler : ILightningConnectionStringHandler
|
public class BreezLightningConnectionStringHandler : ILightningConnectionStringHandler
|
||||||
{
|
{
|
||||||
|
|||||||
33
Plugins/BTCPayServer.Plugins.Breez/BreezPlugin.cs
Normal file
33
Plugins/BTCPayServer.Plugins.Breez/BreezPlugin.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#nullable enable
|
||||||
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
|
using BTCPayServer.Abstractions.Models;
|
||||||
|
using BTCPayServer.Abstractions.Services;
|
||||||
|
using BTCPayServer.Lightning;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Breez
|
||||||
|
{
|
||||||
|
public class BreezPlugin : BaseBTCPayServerPlugin
|
||||||
|
{
|
||||||
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
|
{
|
||||||
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
|
{
|
||||||
|
applicationBuilder.AddSingleton<BreezService>();
|
||||||
|
applicationBuilder.AddSingleton<IHostedService>(provider => provider.GetRequiredService<BreezService>());
|
||||||
|
applicationBuilder.AddSingleton<BreezLightningConnectionStringHandler>();
|
||||||
|
applicationBuilder.AddSingleton<ILightningConnectionStringHandler>(provider => provider.GetRequiredService<BreezLightningConnectionStringHandler>());
|
||||||
|
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("Breez/BreezNav",
|
||||||
|
"store-integrations-nav"));
|
||||||
|
|
||||||
|
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("Breez/LNPaymentMethodSetupTabhead", "ln-payment-method-setup-tabhead"));
|
||||||
|
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("Breez/LNPaymentMethodSetupTab", "ln-payment-method-setup-tab"));
|
||||||
|
|
||||||
|
base.Execute(applicationBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
130
Plugins/BTCPayServer.Plugins.Breez/BreezService.cs
Normal file
130
Plugins/BTCPayServer.Plugins.Breez/BreezService.cs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Configuration;
|
||||||
|
using BTCPayServer.Services.Stores;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using NBitcoin;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
|
public class BreezService:IHostedService
|
||||||
|
{
|
||||||
|
private readonly StoreRepository _storeRepository;
|
||||||
|
private readonly IOptions<DataDirectories> _dataDirectories;
|
||||||
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private Dictionary<string, BreezSettings> _settings;
|
||||||
|
private Dictionary<string, BreezLightningClient> _clients = new();
|
||||||
|
|
||||||
|
public BreezService(StoreRepository storeRepository,
|
||||||
|
IOptions<DataDirectories> dataDirectories,
|
||||||
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
|
ILogger<BreezService> logger)
|
||||||
|
{
|
||||||
|
_storeRepository = storeRepository;
|
||||||
|
_dataDirectories = dataDirectories;
|
||||||
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetWorkDir()
|
||||||
|
{
|
||||||
|
var dir = _dataDirectories.Value.DataDir;
|
||||||
|
return Path.Combine(dir, "Plugins", "Breez");
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskCompletionSource tcs = new();
|
||||||
|
public async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_settings = (await _storeRepository.GetSettingsAsync<BreezSettings>("Breez")).Where(pair => pair.Value is not null).ToDictionary(pair => pair.Key, pair => pair.Value!);
|
||||||
|
foreach (var keyValuePair in _settings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
await Handle(keyValuePair.Key, keyValuePair.Value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tcs.TrySetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<BreezSettings?> Get(string storeId)
|
||||||
|
{
|
||||||
|
await tcs.Task;
|
||||||
|
_settings.TryGetValue(storeId, out var settings);
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<BreezLightningClient?> Handle(string? storeId, BreezSettings? settings)
|
||||||
|
{
|
||||||
|
if (settings is null)
|
||||||
|
{
|
||||||
|
if (storeId is not null && _clients.Remove(storeId, out var client))
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var network = Network.Main; // _btcPayNetworkProvider.BTC.NBitcoinNetwork;
|
||||||
|
Directory.CreateDirectory(GetWorkDir());
|
||||||
|
var client = new BreezLightningClient(settings.InviteCode, settings.ApiKey, GetWorkDir(),
|
||||||
|
network, settings.Mnemonic);
|
||||||
|
if (storeId is not null)
|
||||||
|
{
|
||||||
|
_clients.AddOrReplace(storeId, client);
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Could not create Breez client");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Set(string storeId, BreezSettings? settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
var result = await Handle(storeId, settings);
|
||||||
|
await _storeRepository.UpdateSetting(storeId, "Breez", settings!);
|
||||||
|
if (settings is null)
|
||||||
|
{
|
||||||
|
_settings.Remove(storeId);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(result is not null )
|
||||||
|
{
|
||||||
|
_settings.AddOrReplace(storeId, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_clients.Values.ToList().ForEach(c => c.Dispose());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BreezLightningClient? GetClient(string storeId)
|
||||||
|
{
|
||||||
|
_clients.TryGetValue(storeId, out var client);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Plugins/BTCPayServer.Plugins.Breez/BreezSettings.cs
Normal file
9
Plugins/BTCPayServer.Plugins.Breez/BreezSettings.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#nullable enable
|
||||||
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
|
public class BreezSettings
|
||||||
|
{
|
||||||
|
public string InviteCode { get; set; }
|
||||||
|
public string Mnemonic { get; set; }
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
}
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
|
||||||
using BTCPayServer.Abstractions.Services;
|
|
||||||
using BTCPayServer.Configuration;
|
|
||||||
using BTCPayServer.Lightning;
|
|
||||||
using BTCPayServer.Lightning.Breez;
|
|
||||||
using BTCPayServer.Services.Stores;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using NBitcoin;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.FixedFloat
|
|
||||||
{
|
|
||||||
public class BreezSettings
|
|
||||||
{
|
|
||||||
public string InviteCode { get; set; }
|
|
||||||
public string Mnemonic { get; set; }
|
|
||||||
public string ApiKey { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BreezService:IHostedService
|
|
||||||
{
|
|
||||||
private readonly StoreRepository _storeRepository;
|
|
||||||
private readonly IOptions<DataDirectories> _dataDirectories;
|
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
|
||||||
private readonly ILogger _logger;
|
|
||||||
private Dictionary<string, BreezSettings> _settings;
|
|
||||||
private Dictionary<string, BreezLightningClient> _clients = new();
|
|
||||||
|
|
||||||
public BreezService(StoreRepository storeRepository,
|
|
||||||
IOptions<DataDirectories> dataDirectories,
|
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
|
||||||
ILogger<BreezService> logger)
|
|
||||||
{
|
|
||||||
_storeRepository = storeRepository;
|
|
||||||
_dataDirectories = dataDirectories;
|
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetWorkDir()
|
|
||||||
{
|
|
||||||
var dir = _dataDirectories.Value.DataDir;
|
|
||||||
return Path.Combine(dir, "Plugins", "Breez");
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskCompletionSource tcs = new();
|
|
||||||
public async Task StartAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_settings = (await _storeRepository.GetSettingsAsync<BreezSettings>("Breez")).Where(pair => pair.Value is not null).ToDictionary(pair => pair.Key, pair => pair.Value!);
|
|
||||||
tcs.TrySetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<BreezSettings?> Get(string storeId)
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
_settings.TryGetValue(storeId, out var settings);
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<BreezLightningClient?> Handle(string? storeId, BreezSettings? settings)
|
|
||||||
{
|
|
||||||
if (settings is null)
|
|
||||||
{
|
|
||||||
if (storeId is not null && _clients.Remove(storeId, out var client))
|
|
||||||
{
|
|
||||||
client.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var client = new BreezLightningClient(settings.InviteCode, settings.ApiKey, GetWorkDir(),
|
|
||||||
_btcPayNetworkProvider.BTC.NBitcoinNetwork, settings.Mnemonic);
|
|
||||||
if (storeId is not null)
|
|
||||||
{
|
|
||||||
_clients.AddOrReplace(storeId, client);
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.LogError(e, "Could not create Breez client");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Set(string storeId, BreezSettings? settings)
|
|
||||||
{
|
|
||||||
|
|
||||||
var result = await Handle(storeId, settings);
|
|
||||||
await _storeRepository.UpdateSetting(storeId, "Breez", settings!);
|
|
||||||
if (settings is null)
|
|
||||||
{
|
|
||||||
_settings.Remove(storeId);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(result is not null )
|
|
||||||
{
|
|
||||||
_settings.AddOrReplace(storeId, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StopAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_clients.Values.ToList().ForEach(c => c.Dispose());
|
|
||||||
}
|
|
||||||
|
|
||||||
public BreezLightningClient? GetClient(string storeId)
|
|
||||||
{
|
|
||||||
_clients.TryGetValue(storeId, out var client);
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BreezPlugin : BaseBTCPayServerPlugin
|
|
||||||
{
|
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
|
||||||
{
|
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
|
||||||
};
|
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
|
||||||
{
|
|
||||||
applicationBuilder.AddSingleton<BreezService>();
|
|
||||||
applicationBuilder.AddSingleton<IHostedService>(provider => provider.GetRequiredService<BreezService>());
|
|
||||||
applicationBuilder.AddSingleton<BreezLightningConnectionStringHandler>();
|
|
||||||
applicationBuilder.AddSingleton<ILightningConnectionStringHandler>(provider => provider.GetRequiredService<BreezLightningConnectionStringHandler>());
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("Breez/BreezNav",
|
|
||||||
"store-integrations-nav"));
|
|
||||||
base.Execute(applicationBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
@using BTCPayServer.Plugins.FixedFloat
|
@using BTCPayServer.Plugins.Breez
|
||||||
@model BreezSettings?
|
@model BTCPayServer.Plugins.Breez.BreezSettings?
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage("Breez", "Breez", "Breez");
|
ViewData.SetActivePage("Breez", "Breez", "Breez");
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
@inject BreezService BreezService;
|
||||||
|
@using BTCPayServer.Plugins.Breez
|
||||||
|
@model BTCPayServer.Models.StoreViewModels.LightningNodeViewModel
|
||||||
|
@{
|
||||||
|
var storeId = Model.StoreId;
|
||||||
|
if(Model.CryptoCode != "BTC")
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var client = BreezService.GetClient(storeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
<div id="BreezSetup" class="pt-3 tab-pane fade" role="tabpanel" aria-labelledby="LightningNodeType-Breez">
|
||||||
|
@if (client is not null)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<a asp-action="Index" asp-controller="Breez" asp-route-storeId="@storeId">Breez needs to be configured beforehand.</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const typePrefix = 'type=breez;store=@Model.StoreId';
|
||||||
|
const triggerEl = document.getElementById('LightningNodeType-Breez')
|
||||||
|
const connStringEl = document.getElementById('ConnectionString')
|
||||||
|
const isBreez = connString.startsWith(typePrefix);
|
||||||
|
const setWallet = accessKey => connStringEl.value = accessKey.length
|
||||||
|
? `${typePrefix};`
|
||||||
|
: ''
|
||||||
|
|
||||||
|
if (isBreez) {
|
||||||
|
if (apiToken) {
|
||||||
|
walletEl.value = apiToken
|
||||||
|
} else if (walletId) {
|
||||||
|
const optionEl = document.querySelector(`option[data-wallet-id="${walletId}"]`)
|
||||||
|
if (optionEl) {
|
||||||
|
const accessKey = optionEl.getAttribute('value')
|
||||||
|
walletEl.value = accessKey
|
||||||
|
setWallet(accessKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deactivate currently active tab and activate Breez tab
|
||||||
|
const activeEl = document.querySelector('input[name="LightningNodeType"]:checked')
|
||||||
|
if (activeEl) {
|
||||||
|
activeEl.removeAttribute('checked')
|
||||||
|
activeEl.setAttribute('aria-selected', 'false')
|
||||||
|
document.querySelector('#LightningNodeTypeTabs .tab-pane.active').classList.remove('active', 'show')
|
||||||
|
triggerEl.setAttribute('checked', 'checked')
|
||||||
|
triggerEl.setAttribute('aria-selected', 'true')
|
||||||
|
document.getElementById('BreezSetup').classList.add('active', 'show')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
if (isBreez) {
|
||||||
|
const tabTrigger = new bootstrap.Tab(triggerEl)
|
||||||
|
triggerEl.checked = true
|
||||||
|
tabTrigger.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate('change', '#BreezWallet', e => {
|
||||||
|
const { value } = e.target
|
||||||
|
setWallet(value)
|
||||||
|
const tabTrigger = new bootstrap.Tab(triggerEl)
|
||||||
|
triggerEl.checked = true
|
||||||
|
tabTrigger.show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@inject BreezService BreezService;
|
||||||
|
@using BTCPayServer.Plugins.Breez
|
||||||
|
@model BTCPayServer.Models.StoreViewModels.LightningNodeViewModel
|
||||||
|
|
||||||
|
@if (Model.CryptoCode != "BTC")
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@{
|
||||||
|
var client = BreezService.GetClient(Model.StoreId);
|
||||||
|
}
|
||||||
|
<input value="Custom" type="radio" id="LightningNodeType-Breez" data-bs-toggle="pill" data-bs-target="#BreezSetup" role="tab" aria-controls="BreezSetup" aria-selected="false" name="LightningNodeType" disabled="@(client is null)">
|
||||||
|
<label for="LightningNodeType-Breez">Use Breez wallet</label>
|
||||||
Reference in New Issue
Block a user