mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
update breez
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
<!-- Plugin specific properties -->
|
<!-- Plugin specific properties -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Breez / Greenlight</Product>
|
<Product>Breez / Greenlight</Product>
|
||||||
<Description>Lightwight lightning baby!</Description>
|
<Description>Lightweight lightning baby!</Description>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Breez.Sdk" Version="0.2.10" />
|
<PackageReference Include="Breez.Sdk" Version="0.3.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Breez.Sdk;
|
using Breez.Sdk;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@@ -17,21 +23,22 @@ using NBXplorer.DerivationStrategy;
|
|||||||
namespace BTCPayServer.Plugins.Breez;
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
||||||
[Route("plugins/{storeId}/Breez")]
|
[Route("plugins/{storeId}/Breez")]
|
||||||
public class BreezController : Controller
|
public class BreezController : Controller
|
||||||
{
|
{
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly BreezService _breezService;
|
private readonly BreezService _breezService;
|
||||||
private readonly BTCPayWalletProvider _btcWalletProvider;
|
private readonly BTCPayWalletProvider _btcWalletProvider;
|
||||||
|
private readonly StoreRepository _storeRepository;
|
||||||
|
|
||||||
public BreezController(BTCPayNetworkProvider btcPayNetworkProvider,
|
public BreezController(BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
BreezService breezService,
|
BreezService breezService,
|
||||||
BTCPayWalletProvider btcWalletProvider)
|
BTCPayWalletProvider btcWalletProvider, StoreRepository storeRepository)
|
||||||
{
|
{
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_breezService = breezService;
|
_breezService = breezService;
|
||||||
_btcWalletProvider = btcWalletProvider;
|
_btcWalletProvider = btcWalletProvider;
|
||||||
|
_storeRepository = storeRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -43,6 +50,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("swapin")]
|
[HttpGet("swapin")]
|
||||||
|
[Authorize(Policy = Policies.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> SwapIn(string storeId)
|
public async Task<IActionResult> SwapIn(string storeId)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -55,6 +63,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("info")]
|
[HttpGet("info")]
|
||||||
|
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Info(string storeId)
|
public async Task<IActionResult> Info(string storeId)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -67,6 +76,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("sweep")]
|
[HttpGet("sweep")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Sweep(string storeId)
|
public async Task<IActionResult> Sweep(string storeId)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -79,6 +89,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("sweep")]
|
[HttpPost("sweep")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Sweep(string storeId, string address, uint satPerByte)
|
public async Task<IActionResult> Sweep(string storeId, string address, uint satPerByte)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -98,7 +109,7 @@ public class BreezController : Controller
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = client.Sdk.Sweep(new SweepRequest(address, satPerByte));
|
var response = client.Sdk.RedeemOnchainFunds(new RedeemOnchainFundsRequest(address, satPerByte));
|
||||||
|
|
||||||
TempData[WellKnownTempData.SuccessMessage] = $"sweep successful: {response.txid}";
|
TempData[WellKnownTempData.SuccessMessage] = $"sweep successful: {response.txid}";
|
||||||
}
|
}
|
||||||
@@ -112,6 +123,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("send")]
|
[HttpGet("send")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Send(string storeId)
|
public async Task<IActionResult> Send(string storeId)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -122,6 +134,7 @@ public class BreezController : Controller
|
|||||||
|
|
||||||
return View((object) storeId);
|
return View((object) storeId);
|
||||||
}
|
}
|
||||||
|
[Authorize(Policy = Policies.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
[Route("receive")]
|
[Route("receive")]
|
||||||
public async Task<IActionResult> Receive(string storeId, ulong? amount)
|
public async Task<IActionResult> Receive(string storeId, ulong? amount)
|
||||||
{
|
{
|
||||||
@@ -130,11 +143,20 @@ public class BreezController : Controller
|
|||||||
{
|
{
|
||||||
return RedirectToAction(nameof(Configure), new {storeId});
|
return RedirectToAction(nameof(Configure), new {storeId});
|
||||||
}
|
}
|
||||||
if (amount is not null)
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var invoice = await client.CreateInvoice(LightMoney.FromUnit(amount.Value, LightMoneyUnit.Satoshi).MilliSatoshi, null, TimeSpan.Zero);
|
if (amount is not null)
|
||||||
TempData["bolt11"] = invoice.BOLT11;
|
{
|
||||||
return RedirectToAction("Payments", "Breez", new {storeId });
|
var invoice = await client.CreateInvoice(LightMoney.FromUnit(amount.Value, LightMoneyUnit.Satoshi).MilliSatoshi, null, TimeSpan.Zero);
|
||||||
|
TempData["bolt11"] = invoice.BOLT11;
|
||||||
|
return RedirectToAction("Payments", "Breez", new {storeId });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TempData[WellKnownTempData.ErrorMessage] = $"{e.Message}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +164,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("send")]
|
[HttpPost("send")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Send(string storeId, string address, ulong? amount)
|
public async Task<IActionResult> Send(string storeId, string address, ulong? amount)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -203,6 +226,7 @@ public class BreezController : Controller
|
|||||||
|
|
||||||
|
|
||||||
[HttpGet("swapout")]
|
[HttpGet("swapout")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> SwapOut(string storeId)
|
public async Task<IActionResult> SwapOut(string storeId)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -215,6 +239,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("swapout")]
|
[HttpPost("swapout")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> SwapOut(string storeId, string address, ulong amount, uint satPerByte,
|
public async Task<IActionResult> SwapOut(string storeId, string address, ulong amount, uint satPerByte,
|
||||||
string feesHash)
|
string feesHash)
|
||||||
{
|
{
|
||||||
@@ -247,6 +272,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("swapin/{address}/refund")]
|
[HttpGet("swapin/{address}/refund")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> SwapInRefund(string storeId, string address)
|
public async Task<IActionResult> SwapInRefund(string storeId, string address)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -259,6 +285,7 @@ public class BreezController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("swapin/{address}/refund")]
|
[HttpPost("swapin/{address}/refund")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> SwapInRefund(string storeId, string address, string refundAddress, uint satPerByte)
|
public async Task<IActionResult> SwapInRefund(string storeId, string address, string refundAddress, uint satPerByte)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -280,27 +307,100 @@ public class BreezController : Controller
|
|||||||
return RedirectToAction(nameof(SwapIn), new {storeId});
|
return RedirectToAction(nameof(SwapIn), new {storeId});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
[HttpGet("configure")]
|
[HttpGet("configure")]
|
||||||
public async Task<IActionResult> Configure(string storeId)
|
public async Task<IActionResult> Configure(string storeId)
|
||||||
{
|
{
|
||||||
return View(await _breezService.Get(storeId));
|
return View(await _breezService.Get(storeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task<byte[]> ReadAsByteArrayAsync( Stream source)
|
||||||
|
{
|
||||||
|
// Optimization
|
||||||
|
if (source is MemoryStream memorySource)
|
||||||
|
return memorySource.ToArray();
|
||||||
|
|
||||||
|
using var memoryStream = new MemoryStream();
|
||||||
|
await source.CopyToAsync(memoryStream);
|
||||||
|
return memoryStream.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("configure")]
|
[HttpPost("configure")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Configure(string storeId, string command, BreezSettings settings)
|
public async Task<IActionResult> Configure(string storeId, string command, BreezSettings settings)
|
||||||
{
|
{
|
||||||
|
var store = HttpContext.GetStoreData();
|
||||||
|
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider).OfType<LightningSupportedPaymentMethod>()
|
||||||
|
.FirstOrDefault(method =>
|
||||||
|
method.PaymentId.PaymentType == LightningPaymentType.Instance &&
|
||||||
|
method.PaymentId.CryptoCode == "BTC");
|
||||||
|
|
||||||
if (command == "clear")
|
if (command == "clear")
|
||||||
{
|
{
|
||||||
await _breezService.Set(storeId, null);
|
await _breezService.Set(storeId, null);
|
||||||
TempData[WellKnownTempData.SuccessMessage] = "Settings cleared successfully";
|
TempData[WellKnownTempData.SuccessMessage] = "Settings cleared successfully";
|
||||||
|
var client = _breezService.GetClient(storeId);
|
||||||
|
var isStoreSetToThisMicro = existing?.GetExternalLightningUrl() == client?.ToString();
|
||||||
|
if (client is not null && isStoreSetToThisMicro)
|
||||||
|
{
|
||||||
|
store.SetSupportedPaymentMethod(existing.PaymentId, null);
|
||||||
|
await _storeRepository.UpdateStore(store);
|
||||||
|
}
|
||||||
return RedirectToAction(nameof(Configure), new {storeId});
|
return RedirectToAction(nameof(Configure), new {storeId});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command == "save")
|
if (command == "save")
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _breezService.Set(storeId, settings);
|
if (string.IsNullOrEmpty(settings.Mnemonic))
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(settings.Mnemonic), "Mnemonic is required");
|
||||||
|
return View(settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new Mnemonic(settings.Mnemonic);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(settings.Mnemonic), "Invalid mnemonic");
|
||||||
|
return View(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.GreenlightCredentials is not null)
|
||||||
|
{
|
||||||
|
await using var stream = settings.GreenlightCredentials .OpenReadStream();
|
||||||
|
using var archive = new ZipArchive(stream);
|
||||||
|
var deviceClientArchiveEntry = archive.GetEntry("client.crt");
|
||||||
|
var deviceKeyArchiveEntry = archive.GetEntry("client-key.pem");
|
||||||
|
if(deviceClientArchiveEntry is null || deviceKeyArchiveEntry is null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(settings.GreenlightCredentials), "Invalid zip file (does not have client.crt or client-key.pem)");
|
||||||
|
return View(settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var deviceClient = await ReadAsByteArrayAsync(deviceClientArchiveEntry.Open());
|
||||||
|
var deviceKey = await ReadAsByteArrayAsync(deviceKeyArchiveEntry.Open());
|
||||||
|
var dir = _breezService.GetWorkDir(storeId);
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
await System.IO.File.WriteAllBytesAsync(Path.Combine(dir, "client.crt"), deviceClient);
|
||||||
|
await System.IO.File.WriteAllBytesAsync(Path.Combine(dir, "client-key.pem"), deviceKey);
|
||||||
|
|
||||||
|
await _breezService.Set(storeId, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
await _breezService.Set(storeId, settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -308,14 +408,27 @@ public class BreezController : Controller
|
|||||||
return View(settings);
|
return View(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(existing is null)
|
||||||
|
{
|
||||||
|
existing = new LightningSupportedPaymentMethod()
|
||||||
|
{
|
||||||
|
CryptoCode = "BTC"
|
||||||
|
};
|
||||||
|
var client = _breezService.GetClient(storeId);
|
||||||
|
existing.SetLightningUrl(client);
|
||||||
|
store.SetSupportedPaymentMethod(existing);
|
||||||
|
await _storeRepository.UpdateStore(store);
|
||||||
|
}
|
||||||
|
|
||||||
TempData[WellKnownTempData.SuccessMessage] = "Settings saved successfully";
|
TempData[WellKnownTempData.SuccessMessage] = "Settings saved successfully";
|
||||||
return RedirectToAction(nameof(Configure), new {storeId});
|
return RedirectToAction(nameof(Info), new {storeId});
|
||||||
}
|
}
|
||||||
|
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("payments")]
|
[Route("payments")]
|
||||||
|
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> Payments(string storeId, PaymentsViewModel viewModel)
|
public async Task<IActionResult> Payments(string storeId, PaymentsViewModel viewModel)
|
||||||
{
|
{
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
@@ -326,7 +439,7 @@ public class BreezController : Controller
|
|||||||
|
|
||||||
viewModel ??= new PaymentsViewModel();
|
viewModel ??= new PaymentsViewModel();
|
||||||
|
|
||||||
viewModel.Payments = client.Sdk.ListPayments(new ListPaymentsRequest(null, null, null, true,
|
viewModel.Payments = client.Sdk.ListPayments(new ListPaymentsRequest(null, null, null,null,true,
|
||||||
(uint?) viewModel.Skip, (uint?) viewModel.Count));
|
(uint?) viewModel.Skip, (uint?) viewModel.Count));
|
||||||
|
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -22,12 +23,21 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
public readonly string PaymentKey;
|
public readonly string PaymentKey;
|
||||||
|
|
||||||
public BreezLightningClient(string inviteCode, string apiKey, string workingDir, NBitcoin.Network network,
|
public BreezLightningClient(string inviteCode, string apiKey, string workingDir, NBitcoin.Network network,
|
||||||
string mnemonic, string paymentKey)
|
Mnemonic mnemonic, string paymentKey)
|
||||||
{
|
{
|
||||||
|
apiKey??= "99010c6f84541bf582899db6728f6098ba98ca95ea569f4c63f2c2c9205ace57";
|
||||||
_network = network;
|
_network = network;
|
||||||
PaymentKey = paymentKey;
|
PaymentKey = paymentKey;
|
||||||
|
GreenlightCredentials glCreds = null;
|
||||||
|
if (File.Exists(Path.Combine(workingDir, "client.crt")) && File.Exists(Path.Combine(workingDir, "client-key.pem")))
|
||||||
|
{
|
||||||
|
var deviceCert = File.ReadAllBytes(Path.Combine(workingDir, "client.crt"));
|
||||||
|
var deviceKey = File.ReadAllBytes(Path.Combine(workingDir, "client-key.pem"));
|
||||||
|
|
||||||
|
glCreds = new GreenlightCredentials(deviceKey.ToList(), deviceCert.ToList());
|
||||||
|
}
|
||||||
var nodeConfig = new NodeConfig.Greenlight(
|
var nodeConfig = new NodeConfig.Greenlight(
|
||||||
new GreenlightNodeConfig(null, inviteCode)
|
new GreenlightNodeConfig(glCreds, inviteCode)
|
||||||
);
|
);
|
||||||
var config = BreezSdkMethods.DefaultConfig(
|
var config = BreezSdkMethods.DefaultConfig(
|
||||||
network == NBitcoin.Network.Main ? EnvironmentType.PRODUCTION : EnvironmentType.STAGING,
|
network == NBitcoin.Network.Main ? EnvironmentType.PRODUCTION : EnvironmentType.STAGING,
|
||||||
@@ -40,8 +50,8 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
network == NBitcoin.Network.TestNet ? Network.TESTNET :
|
network == NBitcoin.Network.TestNet ? Network.TESTNET :
|
||||||
network == NBitcoin.Network.RegTest ? Network.REGTEST : Network.SIGNET
|
network == NBitcoin.Network.RegTest ? Network.REGTEST : Network.SIGNET
|
||||||
};
|
};
|
||||||
var seed = BreezSdkMethods.MnemonicToSeed(mnemonic);
|
var seed = mnemonic.DeriveSeed();
|
||||||
Sdk = BreezSdkMethods.Connect(config, seed, this);
|
Sdk = BreezSdkMethods.Connect(config, seed.ToList(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockingBreezServices Sdk { get; }
|
public BlockingBreezServices Sdk { get; }
|
||||||
@@ -137,7 +147,7 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
CancellationToken cancellation = default)
|
CancellationToken cancellation = default)
|
||||||
{
|
{
|
||||||
return Sdk.ListPayments(new ListPaymentsRequest(new List<PaymentTypeFilter>(){PaymentTypeFilter.RECEIVED}, null, null,
|
return Sdk.ListPayments(new ListPaymentsRequest(new List<PaymentTypeFilter>(){PaymentTypeFilter.RECEIVED}, null, null,
|
||||||
request?.PendingOnly is not true, (uint?) request?.OffsetIndex, null))
|
null, request?.PendingOnly is not true, (uint?) request?.OffsetIndex, null))
|
||||||
.Select(FromPayment).ToArray();
|
.Select(FromPayment).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +165,7 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
CancellationToken cancellation = default)
|
CancellationToken cancellation = default)
|
||||||
{
|
{
|
||||||
return Sdk.ListPayments(new ListPaymentsRequest(new List<PaymentTypeFilter>(){PaymentTypeFilter.RECEIVED}, null, null, null,
|
return Sdk.ListPayments(new ListPaymentsRequest(new List<PaymentTypeFilter>(){PaymentTypeFilter.RECEIVED}, null, null, null,
|
||||||
(uint?) request?.OffsetIndex, null))
|
null, (uint?) request?.OffsetIndex, null))
|
||||||
.Select(ToLightningPayment).ToArray();
|
.Select(ToLightningPayment).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +174,7 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
CancellationToken cancellation = default)
|
CancellationToken cancellation = default)
|
||||||
{
|
{
|
||||||
var expiryS = expiry == TimeSpan.Zero ? (uint?) null : Math.Max(0, (uint) expiry.TotalSeconds);
|
var expiryS = expiry == TimeSpan.Zero ? (uint?) null : Math.Max(0, (uint) expiry.TotalSeconds);
|
||||||
|
description??= "Invoice";
|
||||||
var p = Sdk.ReceivePayment(new ReceivePaymentRequest((ulong) amount.MilliSatoshi, description, null, null,
|
var p = Sdk.ReceivePayment(new ReceivePaymentRequest((ulong) amount.MilliSatoshi, description, null, null,
|
||||||
false, expiryS));
|
false, expiryS));
|
||||||
return FromPR(p);
|
return FromPR(p);
|
||||||
@@ -207,10 +218,6 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
{
|
{
|
||||||
PeersCount = ni.connectedPeers.Count,
|
PeersCount = ni.connectedPeers.Count,
|
||||||
Alias = $"greenlight {ni.id}",
|
Alias = $"greenlight {ni.id}",
|
||||||
NodeInfoList =
|
|
||||||
{
|
|
||||||
new NodeInfo(new PubKey(ni.id), "blockstrean.com", 69)
|
|
||||||
}, //we have to fake this as btcpay currently requires this to enable the payment method
|
|
||||||
BlockHeight = (int) ni.blockHeight
|
BlockHeight = (int) ni.blockHeight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class BreezLightningConnectionStringHandler : ILightningConnectionStringH
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!kv.TryGetValue("key", out var key))
|
if (!kv.TryGetValue("key", out var key))
|
||||||
{
|
{
|
||||||
error = $"The key 'key' is mandatory for breez connection strings";
|
error = $"The key 'key' is mandatory for breez connection strings";
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ public class BreezService:EventHostedServiceBase
|
|||||||
await base.ProcessEvent(evt, cancellationToken);
|
await base.ProcessEvent(evt, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetWorkDir()
|
public string GetWorkDir(string storeId)
|
||||||
{
|
{
|
||||||
var dir = _dataDirectories.Value.DataDir;
|
var dir = _dataDirectories.Value.DataDir;
|
||||||
return Path.Combine(dir, "Plugins", "Breez");
|
return Path.Combine(dir, "Plugins", "Breez",storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskCompletionSource tcs = new();
|
TaskCompletionSource tcs = new();
|
||||||
@@ -103,9 +103,11 @@ public class BreezService:EventHostedServiceBase
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var network = Network.Main; // _btcPayNetworkProvider.BTC.NBitcoinNetwork;
|
var network = Network.Main; // _btcPayNetworkProvider.BTC.NBitcoinNetwork;
|
||||||
Directory.CreateDirectory(GetWorkDir());
|
var dir = GetWorkDir(storeId);
|
||||||
var client = new BreezLightningClient(settings.InviteCode, settings.ApiKey, GetWorkDir(),
|
Directory.CreateDirectory(dir);
|
||||||
network, settings.Mnemonic, settings.PaymentKey);
|
settings.PaymentKey ??= Guid.NewGuid().ToString();
|
||||||
|
var client = new BreezLightningClient(settings.InviteCode, settings.ApiKey, dir,
|
||||||
|
network, new Mnemonic(settings.Mnemonic), settings.PaymentKey);
|
||||||
if (storeId is not null)
|
if (storeId is not null)
|
||||||
{
|
{
|
||||||
_clients.AddOrReplace(storeId, client);
|
_clients.AddOrReplace(storeId, client);
|
||||||
@@ -140,6 +142,7 @@ public class BreezService:EventHostedServiceBase
|
|||||||
data.SetSupportedPaymentMethod(new PaymentMethodId("BTC", LightningPaymentType.Instance), null );
|
data.SetSupportedPaymentMethod(new PaymentMethodId("BTC", LightningPaymentType.Instance), null );
|
||||||
await _storeRepository.UpdateStore(data);
|
await _storeRepository.UpdateStore(data);
|
||||||
}
|
}
|
||||||
|
Directory.Delete(GetWorkDir(storeId), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(result is not null )
|
else if(result is not null )
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Breez;
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
public class BreezSettings
|
public class BreezSettings
|
||||||
{
|
{
|
||||||
public string InviteCode { get; set; }
|
public string? InviteCode { get; set; }
|
||||||
public string Mnemonic { get; set; }
|
public string? Mnemonic { get; set; }
|
||||||
public string ApiKey { get; set; }
|
public string? ApiKey { get; set; }
|
||||||
|
|
||||||
public string PaymentKey { get; set; } = Guid.NewGuid().ToString();
|
public string PaymentKey { get; set; } = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IFormFile GreenlightCredentials { get; set; }
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,10 @@
|
|||||||
@{
|
@{
|
||||||
ViewData.SetActivePage("Breez", "Configure", "Configure");
|
ViewData.SetActivePage("Breez", "Configure", "Configure");
|
||||||
var storeId = Context.GetCurrentStoreId();
|
var storeId = Context.GetCurrentStoreId();
|
||||||
|
var showAdvancedOptions = !string.IsNullOrEmpty(Model?.ApiKey) || !string.IsNullOrEmpty(Model?.InviteCode);
|
||||||
|
var active = (await BreezService.Get(storeId)) is not null;
|
||||||
}
|
}
|
||||||
<form method="post" asp-action="Configure" asp-controller="Breez" asp-route-storeId="@storeId">
|
<form method="post" asp-action="Configure" asp-controller="Breez" asp-route-storeId="@storeId" enctype="multipart/form-data">
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||||
@@ -16,7 +18,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
||||||
<button name="command" type="submit" value="save" class="btn btn-primary">Save</button>
|
<button name="command" type="submit" value="save" class="btn btn-primary">Save</button>
|
||||||
@if (await BreezService.Get(storeId) is not null)
|
@if (active)
|
||||||
{
|
{
|
||||||
<button name="command" type="submit" value="clear" class="btn btn-danger">Clear</button>
|
<button name="command" type="submit" value="clear" class="btn btn-danger">Clear</button>
|
||||||
}
|
}
|
||||||
@@ -25,21 +27,55 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Mnemonic" class="form-label">Mnemonic</label>
|
<label asp-for="Mnemonic" class="form-label">Mnemonic</label>
|
||||||
<input asp-for="Mnemonic" class="form-control"/>
|
<input value="@Model?.Mnemonic" asp-for="Mnemonic" class="form-control" type="password" disabled="@active"/>
|
||||||
<span asp-validation-for="Mnemonic" class="text-danger"></span>
|
<span asp-validation-for="Mnemonic" class="text-danger"></span>
|
||||||
|
<span class="text-muted">A Bitcoin 12-word mnemonic seed phrase.<strong>BACK THIS UP SAFELY! GENERATE IT RANDOMLY! SERVER ADMINS HAVE ACCESS TO THIS!</strong></span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
@if (!active)
|
||||||
<label asp-for="ApiKey" class="form-label">ApiKey</label>
|
{
|
||||||
<input asp-for="ApiKey" class="form-control"/>
|
<div class="row">
|
||||||
<span asp-validation-for="ApiKey" class="text-danger"></span>
|
<div class="col-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="GreenlightCredentials" class="form-label">Greenlight credentials</label>
|
||||||
|
<input asp-for="GreenlightCredentials" type="file" class="form-control">
|
||||||
|
<span asp-validation-for="GreenlightCredentials" class="text-danger w-100 d-block"></span>
|
||||||
|
<a href="https://greenlight.blockstream.com/" target="_blank">Get Greenlight credentials directly from Blockstream</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="InviteCode" class="form-label">Invite Code</label>
|
||||||
|
<input asp-for="InviteCode" class="form-control"/>
|
||||||
|
<span asp-validation-for="InviteCode" class="text-danger"></span>
|
||||||
|
|
||||||
</div>
|
<span class="text-muted">Alternatively, you can use an invite code.</span>
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="InviteCode" class="form-label">InviteCode</label>
|
|
||||||
<input asp-for="InviteCode" class="form-control"/>
|
|
||||||
<span asp-validation-for="InviteCode" class="text-danger"></span>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<button class="d-inline-flex align-items-center btn btn-link text-primary fw-semibold p-0 mb-3" type="button" id="AdvancedSettingsButton" data-bs-toggle="collapse" data-bs-target="#AdvancedSettings" aria-expanded="false" aria-controls="AdvancedSettings">
|
||||||
|
<vc:icon symbol="caret-down"/>
|
||||||
|
<span class="ms-1">Advanced settings</span>
|
||||||
|
</button>
|
||||||
|
<div id="AdvancedSettings" class="collapse @(showAdvancedOptions ? "show" : "")">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="ApiKey" class="form-label">Breez API Key</label>
|
||||||
|
<input asp-for="ApiKey" class="form-control"/>
|
||||||
|
<span asp-validation-for="ApiKey" class="text-danger"></span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@if (active)
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="InviteCode" class="form-label">Invite Code</label>
|
||||||
|
<input asp-for="InviteCode" class="form-control"/>
|
||||||
|
<span asp-validation-for="InviteCode" class="text-danger"></span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" asp-for="PaymentKey"/>
|
<input type="hidden" asp-for="PaymentKey"/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
@using BTCPayServer.Models.StoreViewModels
|
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@model object
|
@model object
|
||||||
@{
|
@{
|
||||||
var storeId = Model switch
|
var storeId = Model switch
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
string s => s,
|
string s => s,
|
||||||
StoreDashboardViewModel dashboardModel => dashboardModel.StoreId,
|
StoreDashboardViewModel dashboardModel => dashboardModel.StoreId,
|
||||||
_ => Context.GetImplicitStoreId()
|
_ => Context.GetImplicitStoreId()
|
||||||
};
|
};
|
||||||
ViewData.SetActivePage("Breez", "Create Swapin Refund", "Info");
|
ViewData.SetActivePage("Breez", "Breez node info", "Info");
|
||||||
|
|
||||||
}
|
}
|
||||||
<partial name="Breez/BreezNodeInfo" model="@storeId"/>
|
<partial name="Breez/BreezNodeInfo" model="@storeId"/>
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
@using BTCPayServer.Components
|
@using BTCPayServer.Components
|
||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
|
@using BTCPayServer.Client
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
@using BTCPayServer.Components.QRCode
|
||||||
|
@using BTCPayServer.Components.TruncateCenter
|
||||||
@model BTCPayServer.Plugins.Breez.PaymentsViewModel
|
@model BTCPayServer.Plugins.Breez.PaymentsViewModel
|
||||||
@{
|
@{
|
||||||
var storeId = Context.GetCurrentStoreId();
|
var storeId = Context.GetCurrentStoreId();
|
||||||
@@ -17,8 +21,8 @@
|
|||||||
</h3>
|
</h3>
|
||||||
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
||||||
|
|
||||||
<a asp-action="Send" asp-controller="Breez" asp-route-storeId="@storeId" type="submit" class="btn btn-primary">Send</a>
|
<a permission="@Policies.CanModifyStoreSettings" asp-action="Send" asp-controller="Breez" asp-route-storeId="@storeId" type="submit" class="btn btn-primary">Send</a>
|
||||||
<a asp-action="Receive" asp-controller="Breez" asp-route-storeId="@storeId" type="submit" class="btn btn-primary">Receive</a>
|
<a permission="@Policies.CanCreateInvoice" asp-action="Receive" asp-controller="Breez" asp-route-storeId="@storeId" type="submit" class="btn btn-primary">Receive</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
@using BTCPayServer.Abstractions.Contracts
|
@using BTCPayServer.Abstractions.Contracts
|
||||||
|
@using BTCPayServer.Client
|
||||||
@using BTCPayServer.Components.QRCode
|
@using BTCPayServer.Components.QRCode
|
||||||
@using BTCPayServer.Components.TruncateCenter
|
@using BTCPayServer.Components.TruncateCenter
|
||||||
@using BTCPayServer.Models.StoreViewModels
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
@using BTCPayServer.Services
|
@using BTCPayServer.Services
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@using NBitcoin
|
@using NBitcoin
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
||||||
@@ -20,7 +22,7 @@
|
|||||||
string s => s,
|
string s => s,
|
||||||
StoreDashboardViewModel dashboardModel => dashboardModel.StoreId,
|
StoreDashboardViewModel dashboardModel => dashboardModel.StoreId,
|
||||||
_ => Context.GetImplicitStoreId()
|
_ => Context.GetImplicitStoreId()
|
||||||
};
|
};
|
||||||
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
||||||
if (sdk is null)
|
if (sdk is null)
|
||||||
return;
|
return;
|
||||||
@@ -34,13 +36,12 @@
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
var refundables = sdk.ListRefundables();
|
var refundables = sdk.ListRefundables();
|
||||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
||||||
var ni = sdk.NodeInfo();
|
var ni = sdk.NodeInfo();
|
||||||
var f = sdk.RecommendedFees();
|
var f = sdk.RecommendedFees();
|
||||||
var pmi = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
var pmi = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<datalist id="fees">
|
<datalist id="fees">
|
||||||
@@ -70,34 +71,35 @@
|
|||||||
<vc:truncate-center text="@inProgressSwap.bitcoinAddress" padding="15" elastic="true" classes="form-control-plaintext" id="Address"/>
|
<vc:truncate-center text="@inProgressSwap.bitcoinAddress" padding="15" elastic="true" classes="form-control-plaintext" id="Address"/>
|
||||||
<label for="Address">Address</label>
|
<label for="Address">Address</label>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-muted">Please send an amount between <br/> @Money.Satoshis(inProgressSwap.minAllowedDeposit).ToDecimal(MoneyUnit.BTC) and @Money.Satoshis(inProgressSwap.maxAllowedDeposit).ToDecimal(MoneyUnit.BTC)BTC </span>
|
<div>
|
||||||
@if (deriv is not null)
|
<span class="text-muted">Please send an amount between <br/> @Money.Satoshis(inProgressSwap.minAllowedDeposit).ToDecimal(MoneyUnit.BTC) and @Money.Satoshis(inProgressSwap.maxAllowedDeposit).ToDecimal(MoneyUnit.BTC)BTC </span>
|
||||||
{
|
@if (deriv is not null)
|
||||||
var wallet = new WalletId(storeId, "BTC");
|
|
||||||
<a class="btn btn-link w-100" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@wallet" asp-route-defaultDestination="@inProgressSwap.bitcoinAddress">Send using BTCPay Wallet</a>
|
|
||||||
}
|
|
||||||
@{
|
|
||||||
var onChainSats = ni.onchainBalanceMsat / 1000;
|
|
||||||
if (inProgressSwap.minAllowedDeposit <= (long) onChainSats)
|
|
||||||
{
|
{
|
||||||
<div class="w-100">
|
var wallet = new WalletId(storeId, "BTC");
|
||||||
<form asp-action="Sweep" asp-route-storeId="@storeId">
|
<a class="btn btn-link w-100" permission="@Policies.CanModifyStoreSettings" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@wallet" asp-route-defaultDestination="@inProgressSwap.bitcoinAddress">Send using BTCPay Wallet</a>
|
||||||
<input type="hidden" value="@inProgressSwap.bitcoinAddress" name="address"/>
|
|
||||||
<button class="btn btn-link w-100" type="submit"> Sweep onchain funds to swap in</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
@{
|
||||||
}
|
var onChainSats = ni.onchainBalanceMsat / 1000;
|
||||||
|
if (inProgressSwap.minAllowedDeposit <= (long) onChainSats)
|
||||||
|
{
|
||||||
|
<div class="w-100">
|
||||||
|
<form asp-action="Sweep" asp-route-storeId="@storeId">
|
||||||
|
<input type="hidden" value="@inProgressSwap.bitcoinAddress" name="address"/>
|
||||||
|
<button class="btn btn-link w-100" type="submit"> Sweep onchain funds to swap in</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (inProgressSwap.unconfirmedSats + inProgressSwap.confirmedSats + inProgressSwap.paidSats > 0)
|
@if (inProgressSwap.unconfirmedSats + inProgressSwap.confirmedSats + (inProgressSwap.paidMsat * 1000) > 0)
|
||||||
{
|
{
|
||||||
<div class="card truncate-center-id">
|
<div class="card truncate-center-id">
|
||||||
<span class="text-nowrap">@inProgressSwap.unconfirmedSats sats unconfirmed</span>
|
<span class="text-nowrap">@inProgressSwap.unconfirmedSats sats unconfirmed</span>
|
||||||
<span class="text-nowrap">@inProgressSwap.confirmedSats sats confirmed</span>
|
<span class="text-nowrap">@inProgressSwap.confirmedSats sats confirmed</span>
|
||||||
<span class="text-nowrap">@inProgressSwap.paidSats sats paid</span>
|
<span class="text-nowrap">@(inProgressSwap.paidMsat * 1000) sats paid</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (inProgressSwap.unconfirmedTxIds.Any())
|
@if (inProgressSwap.unconfirmedTxIds.Any())
|
||||||
@@ -144,12 +146,12 @@
|
|||||||
<td>@DateTimeOffset.FromUnixTimeSeconds(refund.createdAt)</td>
|
<td>@DateTimeOffset.FromUnixTimeSeconds(refund.createdAt)</td>
|
||||||
<td>@refund.bitcoinAddress</td>
|
<td>@refund.bitcoinAddress</td>
|
||||||
<td>
|
<td>
|
||||||
@if (refund.unconfirmedSats + refund.confirmedSats + refund.paidSats > 0)
|
@if (refund.unconfirmedSats + refund.confirmedSats + refund.paidMsat > 0)
|
||||||
{
|
{
|
||||||
<div class="card truncate-center-id">
|
<div class="card truncate-center-id">
|
||||||
<span class="text-nowrap">@refund.unconfirmedSats sats unconfirmed</span>
|
<span class="text-nowrap">@refund.unconfirmedSats sats unconfirmed</span>
|
||||||
<span class="text-nowrap">@refund.confirmedSats sats confirmed</span>
|
<span class="text-nowrap">@refund.confirmedSats sats confirmed</span>
|
||||||
<span class="text-nowrap">@refund.paidSats sats paid</span>
|
<span class="text-nowrap">@(refund.paidMsat * 1000) sats paid</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (refund.unconfirmedTxIds.Any())
|
@if (refund.unconfirmedTxIds.Any())
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
|
@using BTCPayServer.Client
|
||||||
@using BTCPayServer.Models.StoreViewModels
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@{
|
@{
|
||||||
@@ -22,12 +24,12 @@
|
|||||||
<div class="nav">
|
<div class="nav">
|
||||||
@if (sdk is not null)
|
@if (sdk is not null)
|
||||||
{
|
{
|
||||||
<a asp-action="Info" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Info")">Info</a>
|
<a permission="@Policies.CanViewStoreSettings" asp-action="Info" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Info")">Info</a>
|
||||||
<a asp-action="Payments" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Payments")">Payments</a>
|
<a permission="@Policies.CanViewStoreSettings" asp-action="Payments" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Payments")">Payments</a>
|
||||||
<a asp-action="SwapIn" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapIn")">Swap In</a>
|
<a permission="@Policies.CanCreateInvoice" asp-action="SwapIn" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapIn")">Swap In</a>
|
||||||
<a asp-action="SwapOut" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapOut")">Swap Out</a>
|
<a permission="@Policies.CanModifyStoreSettings" asp-action="SwapOut" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapOut")">Swap Out</a>
|
||||||
}
|
}
|
||||||
<a asp-action="Configure" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Configure")">Configuration</a>
|
<a permission="@Policies.CanModifyStoreSettings" asp-action="Configure" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Configure")">Configuration</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
@if (!string.IsNullOrEmpty(storeId))
|
@if (!string.IsNullOrEmpty(storeId))
|
||||||
{
|
{
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a permission="@Policies.CanModifyStoreSettings" asp-controller="Breez" asp-action="Index" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez")" id="Nav-Breez">
|
<a permission="@Policies.CanViewStoreSettings" asp-controller="Breez" asp-action="Index" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez")" id="Nav-Breez">
|
||||||
|
|
||||||
<svg style="width: 15px; margin-left: 3px; margin-right: 7px;" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg style="width: 15px; margin-left: 3px; margin-right: 7px;" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="favicon-64-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="favicon-64-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@using BTCPayServer.Models.StoreViewModels
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
|
@using BTCPayServer.Client
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@{
|
@{
|
||||||
string storeId = null;
|
string storeId = null;
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
{
|
{
|
||||||
<div class="d-flex w-100 align-items-center justify-content-start gap-3">
|
<div class="d-flex w-100 align-items-center justify-content-start gap-3">
|
||||||
<span class="btcpay-status btcpay-status--enabled"></span>
|
<span class="btcpay-status btcpay-status--enabled"></span>
|
||||||
<h6 class="text-truncate">@lspInfo.name connected</h6>
|
<h6 class="text-truncate">@lspInfo.name LSP connected</h6>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="store-number">
|
<div class="store-number">
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
<h6>On-Chain Balance</h6>
|
<h6>On-Chain Balance</h6>
|
||||||
@if (Model is StoreDashboardViewModel && nodeState.onchainBalanceMsat > 0)
|
@if (Model is StoreDashboardViewModel && nodeState.onchainBalanceMsat > 0)
|
||||||
{
|
{
|
||||||
<div>
|
<div permission="@Policies.CanModifyStoreSettings">
|
||||||
<a asp-action="Sweep" asp-controller="Breez" asp-route-storeId="@storeId">Sweep</a>
|
<a asp-action="Sweep" asp-controller="Breez" asp-route-storeId="@storeId">Sweep</a>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@
|
|||||||
<h6>Lightning Balance</h6>
|
<h6>Lightning Balance</h6>
|
||||||
@if (Model is StoreDashboardViewModel)
|
@if (Model is StoreDashboardViewModel)
|
||||||
{
|
{
|
||||||
<div>
|
<div permission="@Policies.CanModifyStoreSettings">
|
||||||
<a asp-action="SwapIn" asp-controller="Breez" asp-route-storeId="@storeId">Swap in</a>
|
<a asp-action="SwapIn" asp-controller="Breez" asp-route-storeId="@storeId">Swap in</a>
|
||||||
@if (nodeState.channelsBalanceMsat > 0)
|
@if (nodeState.channelsBalanceMsat > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
if (sdk is null)
|
if (sdk is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data = sdk.ListPayments(new ListPaymentsRequest(null, null, null, null, 0, 10));
|
data = sdk.ListPayments(new ListPaymentsRequest(null, null, null, null, true, 0, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
var isDashboard = Model is StoreDashboardViewModel;
|
var isDashboard = Model is StoreDashboardViewModel;
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<th class="w-125px">Id</th>
|
<th class="w-125px">Id</th>
|
||||||
<th class="w-125px">Timestamp</th>
|
<th class="w-125px">Timestamp</th>
|
||||||
<th class="w-125px">Type</th>
|
<th class="w-125px">Type</th>
|
||||||
<th class="w-125px">Amount</th>
|
<th class="w-125px">Amount</th>a
|
||||||
<th class="text-nowrap">Fee</th>
|
<th class="text-nowrap">Fee</th>
|
||||||
<th class="text-nowrap">Status</th>
|
<th class="text-nowrap">Status</th>
|
||||||
<th class="text-nowrap">Description</th>
|
<th class="text-nowrap">Description</th>
|
||||||
@@ -57,25 +57,25 @@
|
|||||||
@foreach (var payment in data)
|
@foreach (var payment in data)
|
||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td class="smMaxWidth text-truncate">
|
||||||
|
|
||||||
<span class="text-break">@payment.id</span>
|
<span >@payment.id</span>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="text-break">@DateTimeOffset.FromUnixTimeSeconds(payment.paymentTime).ToTimeAgo()</span>
|
<span >@DateTimeOffset.FromUnixTimeSeconds(payment.paymentTime).ToTimeAgo()</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="text-break">>@payment.paymentType.ToString().ToLowerInvariant().Replace("_", " ")</span>
|
<span >@payment.paymentType.ToString().ToLowerInvariant().Replace("_", " ")</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="text-break">>@LightMoney.MilliSatoshis(payment.amountMsat).ToDecimal(LightMoneyUnit.BTC) BTC</span>
|
<span >@LightMoney.MilliSatoshis(payment.amountMsat).ToDecimal(LightMoneyUnit.BTC) BTC</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="text-break">>@LightMoney.MilliSatoshis(payment.feeMsat).ToDecimal(LightMoneyUnit.BTC) BTC</span>
|
<span >@LightMoney.MilliSatoshis(payment.feeMsat).ToDecimal(LightMoneyUnit.BTC) BTC</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="text-break">@payment.status.ToString().ToLowerInvariant()</span>
|
<span >@payment.status.ToString().ToLowerInvariant()</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="text-break">@payment.description</span>
|
<span class="text-break">@payment.description</span>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@inject BreezService BreezService;
|
@inject BreezService BreezService;
|
||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
|
@using BTCPayServer.Client
|
||||||
@model BTCPayServer.Models.StoreViewModels.LightningNodeViewModel
|
@model BTCPayServer.Models.StoreViewModels.LightningNodeViewModel
|
||||||
|
|
||||||
@if (Model.CryptoCode != "BTC")
|
@if (Model.CryptoCode != "BTC")
|
||||||
@@ -9,5 +10,15 @@
|
|||||||
@{
|
@{
|
||||||
var client = BreezService.GetClient(Model.StoreId);
|
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>
|
@if (client is null)
|
||||||
|
{
|
||||||
|
<a asp-action="Configure" asp-controller="Breez" permission="@Policies.CanModifyStoreSettings" asp-route-storeId="@Model.StoreId" value="Custom" type="radio" id="LightningNodeType-Breez" role="tab" aria-controls="BreezSetup" aria-selected="false" name="LightningNodeType">
|
||||||
|
<label for="LightningNodeType-Breez">Configure Breez</label>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<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