Run dotnet format (#3244)

This commit is contained in:
Nicolas Dorier
2021-12-31 16:59:02 +09:00
committed by GitHub
parent e2d0b7c5f7
commit 04b8eafacb
259 changed files with 1613 additions and 1491 deletions

View File

@@ -2,8 +2,8 @@ namespace BTCPayServer.Configuration
{ {
public class DataDirectories public class DataDirectories
{ {
public string DataDir { get; set; } public string DataDir { get; set; }
public string PluginDir { get; set; } public string PluginDir { get; set; }
public string TempStorageDir { get; set; } public string TempStorageDir { get; set; }
public string StorageDir { get; set; } public string StorageDir { get; set; }
} }

View File

@@ -9,7 +9,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
namespace BTCPayServer.Abstractions.Contracts namespace BTCPayServer.Abstractions.Contracts
{ {
public abstract class BaseDbContextFactory<T> where T: DbContext public abstract class BaseDbContextFactory<T> where T : DbContext
{ {
private readonly IOptions<DatabaseOptions> _options; private readonly IOptions<DatabaseOptions> _options;
private readonly string _schemaPrefix; private readonly string _schemaPrefix;

View File

@@ -14,7 +14,7 @@ namespace BTCPayServer.Abstractions.Extensions
public static void SetActivePage<T>(this ViewDataDictionary viewData, T activePage, string title = null, string activeId = null) public static void SetActivePage<T>(this ViewDataDictionary viewData, T activePage, string title = null, string activeId = null)
where T : IConvertible where T : IConvertible
{ {
SetActivePage(viewData, activePage.ToString(), activePage.GetType().Name,title, activeId ); SetActivePage(viewData, activePage.ToString(), activePage.GetType().Name, title, activeId);
} }
public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null) public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null)
@@ -57,9 +57,9 @@ namespace BTCPayServer.Abstractions.Extensions
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null) public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
where T : IConvertible where T : IConvertible
{ {
return IsActivePage(viewData, page.ToString(), page.GetType().Name, id ); return IsActivePage(viewData, page.ToString(), page.GetType().Name, id);
} }
public static string IsActivePage(this ViewDataDictionary viewData, string page,string category, object id = null) public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{ {
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY)) if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
{ {
@@ -68,7 +68,7 @@ namespace BTCPayServer.Abstractions.Extensions
var activeId = viewData[ACTIVE_ID_KEY]; var activeId = viewData[ACTIVE_ID_KEY];
var activePage = viewData[ACTIVE_PAGE_KEY]?.ToString(); var activePage = viewData[ACTIVE_PAGE_KEY]?.ToString();
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString(); var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryAndPageMatch = ( category == null || activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase )) && page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase); var categoryAndPageMatch = (category == null || activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase)) && page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase);
var idMatch = id == null || activeId == null || id.Equals(activeId); var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryAndPageMatch && idMatch ? "active" : null; return categoryAndPageMatch && idMatch ? "active" : null;
} }

View File

@@ -3,7 +3,7 @@ using BTCPayServer.Abstractions.Contracts;
namespace BTCPayServer.Abstractions.Services namespace BTCPayServer.Abstractions.Services
{ {
public abstract class PluginAction<T>:IPluginHookAction public abstract class PluginAction<T> : IPluginHookAction
{ {
public abstract string Hook { get; } public abstract string Hook { get; }
public Task Execute(object args) public Task Execute(object args)

View File

@@ -3,7 +3,7 @@ using BTCPayServer.Abstractions.Contracts;
namespace BTCPayServer.Abstractions.Services namespace BTCPayServer.Abstractions.Services
{ {
public abstract class PluginHookFilter<T>:IPluginHookFilter public abstract class PluginHookFilter<T> : IPluginHookFilter
{ {
public abstract string Hook { get; } public abstract string Hook { get; }

View File

@@ -2,7 +2,7 @@ using BTCPayServer.Abstractions.Contracts;
namespace BTCPayServer.Abstractions.Services namespace BTCPayServer.Abstractions.Services
{ {
public class UIExtension: IUIExtension public class UIExtension : IUIExtension
{ {
public UIExtension(string partial, string location) public UIExtension(string partial, string location)
{ {

View File

@@ -35,13 +35,15 @@ namespace BTCPayServer.Client
if (textSearch != null) if (textSearch != null)
queryPayload.Add(nameof(textSearch), textSearch); queryPayload.Add(nameof(textSearch), textSearch);
if (status != null) if (status != null)
queryPayload.Add(nameof(status), status.Select(s=> s.ToString().ToLower()).ToArray()); queryPayload.Add(nameof(status), status.Select(s => s.ToString().ToLower()).ToArray());
if(skip != null) { if (skip != null)
{
queryPayload.Add(nameof(skip), skip); queryPayload.Add(nameof(skip), skip);
} }
if(take != null) { if (take != null)
{
queryPayload.Add(nameof(take), take); queryPayload.Add(nameof(take), take);
} }

View File

@@ -41,7 +41,7 @@ namespace BTCPayServer.Client
{ {
var response = await _httpClient.SendAsync( var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}", CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}",
method: HttpMethod.Put, bodyPayload: new UpdateNotification() {Seen = seen}), token); method: HttpMethod.Put, bodyPayload: new UpdateNotification() { Seen = seen }), token);
return await HandleResponse<NotificationData>(response); return await HandleResponse<NotificationData>(response);
} }

View File

@@ -63,7 +63,7 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync( var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview", CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview",
bodyPayload: paymentMethod, bodyPayload: paymentMethod,
queryPayload: new Dictionary<string, object>() {{"offset", offset}, {"amount", amount}}, queryPayload: new Dictionary<string, object>() { { "offset", offset }, { "amount", amount } },
method: HttpMethod.Post), token); method: HttpMethod.Post), token);
return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response); return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response);
} }
@@ -74,7 +74,7 @@ namespace BTCPayServer.Client
{ {
var response = await _httpClient.SendAsync( var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview", CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview",
queryPayload: new Dictionary<string, object>() {{"offset", offset}, {"amount", amount}}, queryPayload: new Dictionary<string, object>() { { "offset", offset }, { "amount", amount } },
method: HttpMethod.Get), token); method: HttpMethod.Get), token);
return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response); return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response);
} }

View File

@@ -25,7 +25,7 @@ namespace BTCPayServer.Client
Dictionary<string, object> queryParams = new Dictionary<string, object>(); Dictionary<string, object> queryParams = new Dictionary<string, object>();
if (blockTarget != null) if (blockTarget != null)
{ {
queryParams.Add("blockTarget",blockTarget); queryParams.Add("blockTarget", blockTarget);
} }
var response = var response =
await _httpClient.SendAsync( await _httpClient.SendAsync(
@@ -50,7 +50,7 @@ namespace BTCPayServer.Client
{ {
var response = var response =
await _httpClient.SendAsync( await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address",method:HttpMethod.Delete), token); CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address", method: HttpMethod.Delete), token);
await HandleResponse(response); await HandleResponse(response);
} }

View File

@@ -16,7 +16,7 @@ namespace BTCPayServer.Client
var response = var response =
await _httpClient.SendAsync( await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-requests", CreateHttpRequest($"api/v1/stores/{storeId}/payment-requests",
new Dictionary<string, object>() {{nameof(includeArchived), includeArchived}}), token); new Dictionary<string, object>() { { nameof(includeArchived), includeArchived } }), token);
return await HandleResponse<IEnumerable<PaymentRequestData>>(response); return await HandleResponse<IEnumerable<PaymentRequestData>>(response);
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using NBitcoin; using NBitcoin;
using NBitcoin.JsonConverters; using NBitcoin.JsonConverters;
using Newtonsoft.Json; using Newtonsoft.Json;

View File

@@ -29,7 +29,7 @@ namespace BTCPayServer.JsonConverters
throw new JsonSerializationException("Unexpected object type: " + objectType); throw new JsonSerializationException("Unexpected object type: " + objectType);
case JTokenType.Integer: case JTokenType.Integer:
case JTokenType.String: case JTokenType.String:
if (objectType == typeof(decimal) || objectType == typeof(decimal?) ) if (objectType == typeof(decimal) || objectType == typeof(decimal?))
return decimal.Parse(token.ToString(), CultureInfo.InvariantCulture); return decimal.Parse(token.ToString(), CultureInfo.InvariantCulture);
if (objectType == typeof(double) || objectType == typeof(double?)) if (objectType == typeof(double) || objectType == typeof(double?))
return double.Parse(token.ToString(), CultureInfo.InvariantCulture); return double.Parse(token.ToString(), CultureInfo.InvariantCulture);

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;

View File

@@ -18,7 +18,7 @@ namespace BTCPayServer.Client.Models
} }
[JsonConverter(typeof(FeeRateJsonConverter))] [JsonConverter(typeof(FeeRateJsonConverter))]
public FeeRate FeeRate { get; set; } public FeeRate FeeRate { get; set; }
public bool ProceedWithPayjoin { get; set; }= true; public bool ProceedWithPayjoin { get; set; } = true;
public bool ProceedWithBroadcast { get; set; } = true; public bool ProceedWithBroadcast { get; set; } = true;
public bool NoChange { get; set; } = false; public bool NoChange { get; set; } = false;
[JsonProperty(ItemConverterType = typeof(OutpointJsonConverter))] [JsonProperty(ItemConverterType = typeof(OutpointJsonConverter))]

View File

@@ -1,4 +1,4 @@
using BTCPayServer.Client.JsonConverters; using BTCPayServer.Client.JsonConverters;
using NBitcoin; using NBitcoin;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;

View File

@@ -1,4 +1,4 @@
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models
{ {
public class GenericPaymentMethodData public class GenericPaymentMethodData
{ {

View File

@@ -1,4 +1,4 @@
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models
{ {
public class LNURLPayPaymentMethodBaseData public class LNURLPayPaymentMethodBaseData
{ {

View File

@@ -1,6 +1,6 @@
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models
{ {
public class LNURLPayPaymentMethodData: LNURLPayPaymentMethodBaseData public class LNURLPayPaymentMethodData : LNURLPayPaymentMethodBaseData
{ {
/// <summary> /// <summary>
/// Whether the payment method is enabled /// Whether the payment method is enabled
@@ -16,7 +16,7 @@
{ {
} }
public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme, bool enableForStandardInvoices) public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme, bool enableForStandardInvoices)
{ {
Enabled = enabled; Enabled = enabled;
CryptoCode = cryptoCode; CryptoCode = cryptoCode;

View File

@@ -1,4 +1,4 @@
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models
{ {
public class LightningNetworkPaymentMethodBaseData public class LightningNetworkPaymentMethodBaseData
{ {

View File

@@ -1,6 +1,6 @@
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models
{ {
public class LightningNetworkPaymentMethodData: LightningNetworkPaymentMethodBaseData public class LightningNetworkPaymentMethodData : LightningNetworkPaymentMethodBaseData
{ {
/// <summary> /// <summary>
/// Whether the payment method is enabled /// Whether the payment method is enabled

View File

@@ -1,4 +1,4 @@
using NBitcoin; using NBitcoin;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models

View File

@@ -1,4 +1,4 @@
using BTCPayServer.Client.JsonConverters; using BTCPayServer.Client.JsonConverters;
using NBitcoin; using NBitcoin;
using Newtonsoft.Json; using Newtonsoft.Json;

View File

@@ -36,7 +36,7 @@ namespace BTCPayServer.Client.Models
public virtual bool Available { get; set; } public virtual bool Available { get; set; }
} }
public class ServerInfoSyncStatusData: SyncStatus public class ServerInfoSyncStatusData : SyncStatus
{ {
public int ChainHeight { get; set; } public int ChainHeight { get; set; }
public int? SyncHeight { get; set; } public int? SyncHeight { get; set; }

View File

@@ -1,6 +1,6 @@
namespace BTCPayServer.Client.Models namespace BTCPayServer.Client.Models
{ {
public class UpdateLightningNetworkPaymentMethodRequest: LightningNetworkPaymentMethodBaseData public class UpdateLightningNetworkPaymentMethodRequest : LightningNetworkPaymentMethodBaseData
{ {
/// <summary> /// <summary>
/// Whether the payment method is enabled /// Whether the payment method is enabled

View File

@@ -1,4 +1,4 @@
using NBXplorer; using NBXplorer;
namespace BTCPayServer.Common namespace BTCPayServer.Common
{ {

View File

@@ -37,7 +37,7 @@ namespace BTCPayServer.Data
builder.Entity<PayoutData>() builder.Entity<PayoutData>()
.HasIndex(o => o.State); .HasIndex(o => o.State);
builder.Entity<PayoutData>() builder.Entity<PayoutData>()
.HasIndex(x => new { DestinationId = x.Destination, x.State}); .HasIndex(x => new { DestinationId = x.Destination, x.State });
} }
// utility methods // utility methods

View File

@@ -20,7 +20,7 @@ namespace BTCPayServer.Migrations
name: "CurrentRefundId", name: "CurrentRefundId",
table: "Invoices", table: "Invoices",
nullable: true, nullable: true,
maxLength: maxLength); maxLength: maxLength);
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Notifications", name: "Notifications",

View File

@@ -1,4 +1,4 @@
using BTCPayServer.Data; using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;

View File

@@ -1,4 +1,4 @@
using System; using System;
using BTCPayServer.Data; using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;

View File

@@ -1,4 +1,4 @@
using BTCPayServer.Data; using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;

View File

@@ -1,4 +1,4 @@
using BTCPayServer.Data; using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;

View File

@@ -20,7 +20,7 @@ namespace BTCPayServer.Migrations
oldClrType: typeof(string)); oldClrType: typeof(string));
} }
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_Invoices_OrderId", name: "IX_Invoices_OrderId",
table: "Invoices", table: "Invoices",
column: "OrderId"); column: "OrderId");

View File

@@ -20,7 +20,7 @@ namespace BTCPayServer.Migrations
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGeneratedOnAdd", true) .Annotation("MySql:ValueGeneratedOnAdd", true)
.Annotation("Sqlite:Autoincrement", true), .Annotation("Sqlite:Autoincrement", true),
// eof manually added // eof manually added
InvoiceDataId = table.Column<string>(maxLength: 255, nullable: true), InvoiceDataId = table.Column<string>(maxLength: 255, nullable: true),
Value = table.Column<string>(maxLength: 512, nullable: true) Value = table.Column<string>(maxLength: 512, nullable: true)
}, },

View File

@@ -1,7 +1,7 @@
using System; using System;
using Microsoft.EntityFrameworkCore.Migrations;
using BTCPayServer.Data; using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace BTCPayServer.Migrations namespace BTCPayServer.Migrations
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using BTCPayServer.Data; using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
@@ -21,8 +21,8 @@ namespace BTCPayServer.PluginPacker
var name = args[1]; var name = args[1];
var outputDir = args[2]; var outputDir = args[2];
var outputFile = Path.Combine(outputDir, name); var outputFile = Path.Combine(outputDir, name);
var rootDLLPath = Path.Combine(directory, name +".dll"); var rootDLLPath = Path.Combine(directory, name + ".dll");
if (!File.Exists(rootDLLPath) ) if (!File.Exists(rootDLLPath))
{ {
throw new Exception($"{rootDLLPath} could not be found"); throw new Exception($"{rootDLLPath} could not be found");
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;

View File

@@ -19,7 +19,7 @@ namespace BTCPayServer.Plugins.Test.Services
{ {
await using var context = _testPluginDbContextFactory.CreateContext(); await using var context = _testPluginDbContextFactory.CreateContext();
await context.TestPluginRecords.AddAsync(new TestPluginData() {Timestamp = DateTimeOffset.UtcNow}); await context.TestPluginRecords.AddAsync(new TestPluginData() { Timestamp = DateTimeOffset.UtcNow });
await context.SaveChangesAsync(); await context.SaveChangesAsync();
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.Abstractions.Services; using BTCPayServer.Abstractions.Services;
@@ -9,11 +9,11 @@ using Microsoft.Extensions.DependencyInjection;
namespace BTCPayServer.Plugins.Test namespace BTCPayServer.Plugins.Test
{ {
public class TestPlugin: BaseBTCPayServerPlugin public class TestPlugin : BaseBTCPayServerPlugin
{ {
public override string Identifier { get; } = "BTCPayServer.Plugins.Test"; public override string Identifier { get; } = "BTCPayServer.Plugins.Test";
public override string Name { get; } = "Test Plugin!"; public override string Name { get; } = "Test Plugin!";
public override string Description { get; } = "This is a description of the loaded test extension!"; public override string Description { get; } = "This is a description of the loaded test extension!";
public override void Execute(IServiceCollection services) public override void Execute(IServiceCollection services)
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@@ -23,7 +23,7 @@ namespace BTCPayServer.Services.Rates
var data = jobj.ContainsKey("data") ? jobj["data"] : null; var data = jobj.ContainsKey("data") ? jobj["data"] : null;
if (jobj["success"]?.Value<int>() != 1) if (jobj["success"]?.Value<int>() != 1)
{ {
var errorCode = data is null? "Unknown": data["code"].Value<string>(); var errorCode = data is null ? "Unknown" : data["code"].Value<string>();
throw new Exception( throw new Exception(
$"BitBank Rates API Error: {errorCode}. See https://github.com/bitbankinc/bitbank-api-docs/blob/master/errors.md for more details."); $"BitBank Rates API Error: {errorCode}. See https://github.com/bitbankinc/bitbank-api-docs/blob/master/errors.md for more details.");
} }

View File

@@ -142,7 +142,7 @@ namespace BTCPayServer.Tests
(await apiKeyRepo.GetKey(accessToken)).GetBlob().Permissions); (await apiKeyRepo.GetKey(accessToken)).GetBlob().Permissions);
authUrl = BTCPayServerClient.GenerateAuthorizeUri(s.ServerUri, authUrl = BTCPayServerClient.GenerateAuthorizeUri(s.ServerUri,
new[] { Policies.CanModifyStoreSettings, Policies.CanModifyServerSettings }, false, true, applicationDetails: (null, new Uri(callbackUrl))).ToString(); new[] { Policies.CanModifyStoreSettings, Policies.CanModifyServerSettings }, false, true, applicationDetails: (null, new Uri(callbackUrl))).ToString();
s.Driver.Navigate().GoToUrl(authUrl); s.Driver.Navigate().GoToUrl(authUrl);
Assert.DoesNotContain("kukksappname", s.Driver.PageSource); Assert.DoesNotContain("kukksappname", s.Driver.PageSource);

View File

@@ -28,7 +28,8 @@ namespace BTCPayServer.Tests
public static void AssertNoError(this IWebDriver driver) public static void AssertNoError(this IWebDriver driver)
{ {
if (!driver.PageSource.Contains("alert-danger")) return; if (!driver.PageSource.Contains("alert-danger"))
return;
foreach (var dangerAlert in driver.FindElements(By.ClassName("alert-danger"))) foreach (var dangerAlert in driver.FindElements(By.ClassName("alert-danger")))
Assert.False(dangerAlert.Displayed, $"No alert should be displayed, but found this on {driver.Url}: {dangerAlert.Text}"); Assert.False(dangerAlert.Displayed, $"No alert should be displayed, but found this on {driver.Url}: {dangerAlert.Text}");
} }
@@ -50,7 +51,7 @@ namespace BTCPayServer.Tests
// Sometimes, selenium is flaky... // Sometimes, selenium is flaky...
public static IWebElement FindElementUntilNotStaled(this IWebDriver driver, By by, Action<IWebElement> act) public static IWebElement FindElementUntilNotStaled(this IWebDriver driver, By by, Action<IWebElement> act)
{ {
retry: retry:
try try
{ {
var el = driver.FindElement(by); var el = driver.FindElement(by);
@@ -91,8 +92,8 @@ namespace BTCPayServer.Tests
public static void UntilJsIsReady(this WebDriverWait wait) public static void UntilJsIsReady(this WebDriverWait wait)
{ {
wait.Until(d=>((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete")); wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete"));
wait.Until(d=>((IJavaScriptExecutor)d).ExecuteScript("return typeof(jQuery) === 'undefined' || jQuery.active === 0").Equals(true)); wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return typeof(jQuery) === 'undefined' || jQuery.active === 0").Equals(true));
} }
// Open collapse via JS, because if we click the link it triggers the toggle animation. // Open collapse via JS, because if we click the link it triggers the toggle animation.
@@ -135,7 +136,7 @@ namespace BTCPayServer.Tests
wait.UntilJsIsReady(); wait.UntilJsIsReady();
int retriesLeft = 4; int retriesLeft = 4;
retry: retry:
try try
{ {
var el = driver.FindElement(selector); var el = driver.FindElement(selector);

View File

@@ -1142,25 +1142,25 @@ namespace BTCPayServer.Tests
Assert.Empty(invoices); Assert.Empty(invoices);
//list Filtered //list Filtered
var invoicesFiltered = await viewOnly.GetInvoices(user.StoreId, var invoicesFiltered = await viewOnly.GetInvoices(user.StoreId,
orderId: null, status: null, startDate: DateTimeOffset.Now.AddHours(-1), orderId: null, status: null, startDate: DateTimeOffset.Now.AddHours(-1),
endDate: DateTimeOffset.Now.AddHours(1)); endDate: DateTimeOffset.Now.AddHours(1));
Assert.NotNull(invoicesFiltered); Assert.NotNull(invoicesFiltered);
Assert.Single(invoicesFiltered); Assert.Single(invoicesFiltered);
Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id); Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id);
Assert.NotNull(invoicesFiltered); Assert.NotNull(invoicesFiltered);
Assert.Single(invoicesFiltered); Assert.Single(invoicesFiltered);
Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id); Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id);
//list Yesterday //list Yesterday
var invoicesYesterday = await viewOnly.GetInvoices(user.StoreId, var invoicesYesterday = await viewOnly.GetInvoices(user.StoreId,
orderId: null, status: null, startDate: DateTimeOffset.Now.AddDays(-2), orderId: null, status: null, startDate: DateTimeOffset.Now.AddDays(-2),
endDate: DateTimeOffset.Now.AddDays(-1)); endDate: DateTimeOffset.Now.AddDays(-1));
Assert.NotNull(invoicesYesterday); Assert.NotNull(invoicesYesterday);
Assert.Empty(invoicesYesterday); Assert.Empty(invoicesYesterday);
// Error, startDate and endDate inverted // Error, startDate and endDate inverted
await AssertValidationError(new[] { "startDate", "endDate" }, await AssertValidationError(new[] { "startDate", "endDate" },
@@ -1177,29 +1177,29 @@ namespace BTCPayServer.Tests
//list Existing OrderId //list Existing OrderId
var invoicesExistingOrderId = var invoicesExistingOrderId =
await viewOnly.GetInvoices(user.StoreId, orderId: new []{newInvoice.Metadata["orderId"].ToString()}); await viewOnly.GetInvoices(user.StoreId, orderId: new[] { newInvoice.Metadata["orderId"].ToString() });
Assert.NotNull(invoicesExistingOrderId); Assert.NotNull(invoicesExistingOrderId);
Assert.Single(invoicesFiltered); Assert.Single(invoicesFiltered);
Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id); Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id);
//list NonExisting OrderId //list NonExisting OrderId
var invoicesNonExistingOrderId = var invoicesNonExistingOrderId =
await viewOnly.GetInvoices(user.StoreId, orderId: new []{"NonExistingOrderId"}); await viewOnly.GetInvoices(user.StoreId, orderId: new[] { "NonExistingOrderId" });
Assert.NotNull(invoicesNonExistingOrderId); Assert.NotNull(invoicesNonExistingOrderId);
Assert.Empty(invoicesNonExistingOrderId); Assert.Empty(invoicesNonExistingOrderId);
//list Existing Status //list Existing Status
var invoicesExistingStatus = var invoicesExistingStatus =
await viewOnly.GetInvoices(user.StoreId, status: new []{newInvoice.Status}); await viewOnly.GetInvoices(user.StoreId, status: new[] { newInvoice.Status });
Assert.NotNull(invoicesExistingStatus); Assert.NotNull(invoicesExistingStatus);
Assert.Single(invoicesExistingStatus); Assert.Single(invoicesExistingStatus);
Assert.Equal(newInvoice.Id, invoicesExistingStatus.First().Id); Assert.Equal(newInvoice.Id, invoicesExistingStatus.First().Id);
//list NonExisting Status //list NonExisting Status
var invoicesNonExistingStatus = await viewOnly.GetInvoices(user.StoreId, var invoicesNonExistingStatus = await viewOnly.GetInvoices(user.StoreId,
status: new []{BTCPayServer.Client.Models.InvoiceStatus.Invalid}); status: new[] { BTCPayServer.Client.Models.InvoiceStatus.Invalid });
Assert.NotNull(invoicesNonExistingStatus); Assert.NotNull(invoicesNonExistingStatus);
Assert.Empty(invoicesNonExistingStatus); Assert.Empty(invoicesNonExistingStatus);
//get //get
@@ -1216,8 +1216,8 @@ namespace BTCPayServer.Tests
//update //update
newInvoice = await client.CreateInvoice(user.StoreId, newInvoice = await client.CreateInvoice(user.StoreId,
new CreateInvoiceRequest() { Currency = "USD", Amount = 1 }); new CreateInvoiceRequest() { Currency = "USD", Amount = 1 });
Assert.Contains(InvoiceStatus.Settled, newInvoice.AvailableStatusesForManualMarking); Assert.Contains(InvoiceStatus.Settled, newInvoice.AvailableStatusesForManualMarking);
Assert.Contains(InvoiceStatus.Invalid, newInvoice.AvailableStatusesForManualMarking); Assert.Contains(InvoiceStatus.Invalid, newInvoice.AvailableStatusesForManualMarking);
await client.MarkInvoiceStatus(user.StoreId, newInvoice.Id, new MarkInvoiceStatusRequest() await client.MarkInvoiceStatus(user.StoreId, newInvoice.Id, new MarkInvoiceStatusRequest()
{ {
Status = InvoiceStatus.Settled Status = InvoiceStatus.Settled
@@ -1406,20 +1406,20 @@ namespace BTCPayServer.Tests
} }
}); });
var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)); var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
Assert.Equal(0.0001m, pm.Due); Assert.Equal(0.0001m, pm.Due);
await tester.WaitForEvent<NewOnChainTransactionEvent>(async () => await tester.WaitForEvent<NewOnChainTransactionEvent>(async () =>
{ {
await tester.ExplorerNode.SendToAddressAsync( await tester.ExplorerNode.SendToAddressAsync(
BitcoinAddress.Create(pm.Destination, tester.ExplorerClient.Network.NBitcoinNetwork), BitcoinAddress.Create(pm.Destination, tester.ExplorerClient.Network.NBitcoinNetwork),
new Money(0.0002m, MoneyUnit.BTC)); new Money(0.0002m, MoneyUnit.BTC));
}); });
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)); var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
Assert.Single(pm.Payments); Assert.Single(pm.Payments);
Assert.Equal(-0.0001m, pm.Due); Assert.Equal(-0.0001m, pm.Due);
}); });
} }
} }
@@ -1623,14 +1623,14 @@ namespace BTCPayServer.Tests
await viewOnlyClient.GenerateOnChainWallet(store.Id, "BTC", new GenerateOnChainWalletRequest() { }); await viewOnlyClient.GenerateOnChainWallet(store.Id, "BTC", new GenerateOnChainWalletRequest() { });
}); });
await AssertValidationError(new []{"SavePrivateKeys", "ImportKeysToRPC"}, async () => await AssertValidationError(new[] { "SavePrivateKeys", "ImportKeysToRPC" }, async () =>
{ {
await client2.GenerateOnChainWallet(user2.StoreId, "BTC", new GenerateOnChainWalletRequest() await client2.GenerateOnChainWallet(user2.StoreId, "BTC", new GenerateOnChainWalletRequest()
{ {
SavePrivateKeys = true, SavePrivateKeys = true,
ImportKeysToRPC = true ImportKeysToRPC = true
}); });
}); });
var allMnemonic = new Mnemonic("all all all all all all all all all all all all"); var allMnemonic = new Mnemonic("all all all all all all all all all all all all");
@@ -1638,7 +1638,7 @@ namespace BTCPayServer.Tests
await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC"); await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC");
var generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC", var generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC",
new GenerateOnChainWalletRequest() {ExistingMnemonic = allMnemonic,}); new GenerateOnChainWalletRequest() { ExistingMnemonic = allMnemonic, });
Assert.Equal(generateResponse.Mnemonic.ToString(), allMnemonic.ToString()); Assert.Equal(generateResponse.Mnemonic.ToString(), allMnemonic.ToString());
Assert.Equal(generateResponse.DerivationScheme, xpub); Assert.Equal(generateResponse.DerivationScheme, xpub);
@@ -1646,18 +1646,18 @@ namespace BTCPayServer.Tests
await AssertAPIError("already-configured", async () => await AssertAPIError("already-configured", async () =>
{ {
await client.GenerateOnChainWallet(store.Id, "BTC", await client.GenerateOnChainWallet(store.Id, "BTC",
new GenerateOnChainWalletRequest() {ExistingMnemonic = allMnemonic,}); new GenerateOnChainWalletRequest() { ExistingMnemonic = allMnemonic, });
}); });
await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC"); await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC");
generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC", generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC",
new GenerateOnChainWalletRequest() {}); new GenerateOnChainWalletRequest() { });
Assert.NotEqual(generateResponse.Mnemonic.ToString(), allMnemonic.ToString()); Assert.NotEqual(generateResponse.Mnemonic.ToString(), allMnemonic.ToString());
Assert.Equal(generateResponse.Mnemonic.DeriveExtKey().Derive(KeyPath.Parse("m/84'/1'/0'")).Neuter().ToString(Network.RegTest), generateResponse.DerivationScheme); Assert.Equal(generateResponse.Mnemonic.DeriveExtKey().Derive(KeyPath.Parse("m/84'/1'/0'")).Neuter().ToString(Network.RegTest), generateResponse.DerivationScheme);
await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC"); await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC");
generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC", generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC",
new GenerateOnChainWalletRequest() { ExistingMnemonic = allMnemonic, AccountNumber = 1}); new GenerateOnChainWalletRequest() { ExistingMnemonic = allMnemonic, AccountNumber = 1 });
Assert.Equal(generateResponse.Mnemonic.ToString(), allMnemonic.ToString()); Assert.Equal(generateResponse.Mnemonic.ToString(), allMnemonic.ToString());
@@ -1666,10 +1666,10 @@ namespace BTCPayServer.Tests
await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC"); await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC");
generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC", generateResponse = await client.GenerateOnChainWallet(store.Id, "BTC",
new GenerateOnChainWalletRequest() { WordList = Wordlist.Japanese, WordCount = WordCount.TwentyFour}); new GenerateOnChainWalletRequest() { WordList = Wordlist.Japanese, WordCount = WordCount.TwentyFour });
Assert.Equal(24,generateResponse.Mnemonic.Words.Length); Assert.Equal(24, generateResponse.Mnemonic.Words.Length);
Assert.Equal(Wordlist.Japanese,generateResponse.Mnemonic.WordList); Assert.Equal(Wordlist.Japanese, generateResponse.Mnemonic.WordList);
} }
@@ -1784,7 +1784,7 @@ namespace BTCPayServer.Tests
settings.AllowLightningInternalNodeForAll = true; settings.AllowLightningInternalNodeForAll = true;
await tester.PayTester.GetService<SettingsRepository>().UpdateSetting(settings); await tester.PayTester.GetService<SettingsRepository>().UpdateSetting(settings);
await nonAdminUserClient.UpdateStoreLightningNetworkPaymentMethod(nonAdminUser.StoreId, "BTC", new UpdateLightningNetworkPaymentMethodRequest() await nonAdminUserClient.UpdateStoreLightningNetworkPaymentMethod(nonAdminUser.StoreId, "BTC", new UpdateLightningNetworkPaymentMethodRequest()
{ {
Enabled = method.Enabled, Enabled = method.Enabled,
ConnectionString = method.ConnectionString ConnectionString = method.ConnectionString
@@ -2064,20 +2064,20 @@ namespace BTCPayServer.Tests
await adminClient.UpdateStoreLightningNetworkPaymentMethod(store.Id, "BTC", await adminClient.UpdateStoreLightningNetworkPaymentMethod(store.Id, "BTC",
new UpdateLightningNetworkPaymentMethodRequest( new UpdateLightningNetworkPaymentMethodRequest(
tester.GetLightningConnectionString(LightningConnectionType.CLightning, true), true)); tester.GetLightningConnectionString(LightningConnectionType.CLightning, true), true));
methods = await viewerOnlyClient.GetStorePaymentMethods(store.Id); methods = await viewerOnlyClient.GetStorePaymentMethods(store.Id);
Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out var item)); Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out var item));
var lightningNetworkPaymentMethodBaseData =Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>(); var lightningNetworkPaymentMethodBaseData = Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>();
Assert.Equal("*NEED CanModifyStoreSettings PERMISSION TO VIEW*", lightningNetworkPaymentMethodBaseData.ConnectionString); Assert.Equal("*NEED CanModifyStoreSettings PERMISSION TO VIEW*", lightningNetworkPaymentMethodBaseData.ConnectionString);
methods = await adminClient.GetStorePaymentMethods(store.Id); methods = await adminClient.GetStorePaymentMethods(store.Id);
Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out item)); Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out item));
lightningNetworkPaymentMethodBaseData =Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>(); lightningNetworkPaymentMethodBaseData = Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>();
Assert.NotEqual("*NEED CanModifyStoreSettings PERMISSION TO VIEW*", lightningNetworkPaymentMethodBaseData.ConnectionString); Assert.NotEqual("*NEED CanModifyStoreSettings PERMISSION TO VIEW*", lightningNetworkPaymentMethodBaseData.ConnectionString);

View File

@@ -4,6 +4,7 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Controllers; using BTCPayServer.Controllers;
using BTCPayServer.Data; using BTCPayServer.Data;
@@ -16,11 +17,10 @@ using BTCPayServer.Services;
using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Wallets; using BTCPayServer.Services.Wallets;
using BTCPayServer.Tests.Logging; using BTCPayServer.Tests.Logging;
using BTCPayServer.Views.Stores;
using BTCPayServer.Views.Wallets; using BTCPayServer.Views.Wallets;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Views.Stores;
using NBitcoin.Payment; using NBitcoin.Payment;
using NBitpayClient; using NBitpayClient;
using NBXplorer.DerivationStrategy; using NBXplorer.DerivationStrategy;
@@ -179,7 +179,7 @@ namespace BTCPayServer.Tests
var cashCow = tester.ExplorerNode; var cashCow = tester.ExplorerNode;
cashCow.Generate(2); // get some money in case cashCow.Generate(2); // get some money in case
var unsupportedFormats = new[] {ScriptPubKeyType.Legacy}; var unsupportedFormats = new[] { ScriptPubKeyType.Legacy };
foreach (ScriptPubKeyType senderAddressType in Enum.GetValues(typeof(ScriptPubKeyType))) foreach (ScriptPubKeyType senderAddressType in Enum.GetValues(typeof(ScriptPubKeyType)))
@@ -287,7 +287,7 @@ namespace BTCPayServer.Tests
var invoiceRepository = s.Server.PayTester.GetService<InvoiceRepository>(); var invoiceRepository = s.Server.PayTester.GetService<InvoiceRepository>();
s.RegisterNewUser(true); s.RegisterNewUser(true);
foreach (var format in new []{ScriptPubKeyType.Segwit, ScriptPubKeyType.SegwitP2SH}) foreach (var format in new[] { ScriptPubKeyType.Segwit, ScriptPubKeyType.SegwitP2SH })
{ {
var cryptoCode = "BTC"; var cryptoCode = "BTC";
var receiver = s.CreateNewStore(); var receiver = s.CreateNewStore();
@@ -867,7 +867,7 @@ retry:
//give the cow some cash //give the cow some cash
await cashCow.GenerateAsync(1); await cashCow.GenerateAsync(1);
//let's get some more utxos first //let's get some more utxos first
foreach (var m in new [] foreach (var m in new[]
{ {
Money.Coins(0.011m), Money.Coins(0.011m),
Money.Coins(0.012m), Money.Coins(0.012m),

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Lightning; using BTCPayServer.Lightning;
using BTCPayServer.Lightning.CLightning; using BTCPayServer.Lightning.CLightning;
using BTCPayServer.Views.Manage; using BTCPayServer.Views.Manage;
@@ -12,11 +13,10 @@ using BTCPayServer.Views.Stores;
using BTCPayServer.Views.Wallets; using BTCPayServer.Views.Wallets;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender;
using OpenQA.Selenium; using OpenQA.Selenium;
using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Chrome;
using Xunit;
using OpenQA.Selenium.Support.UI; using OpenQA.Selenium.Support.UI;
using Xunit;
namespace BTCPayServer.Tests namespace BTCPayServer.Tests
{ {
@@ -90,7 +90,7 @@ namespace BTCPayServer.Tests
public Uri ServerUri; public Uri ServerUri;
internal IWebElement FindAlertMessage(StatusMessageModel.StatusSeverity severity = StatusMessageModel.StatusSeverity.Success) internal IWebElement FindAlertMessage(StatusMessageModel.StatusSeverity severity = StatusMessageModel.StatusSeverity.Success)
{ {
return FindAlertMessage(new[] {severity}); return FindAlertMessage(new[] { severity });
} }
internal IWebElement FindAlertMessage(params StatusMessageModel.StatusSeverity[] severity) internal IWebElement FindAlertMessage(params StatusMessageModel.StatusSeverity[] severity)
{ {
@@ -240,7 +240,7 @@ namespace BTCPayServer.Tests
LightningConnectionType.Charge => LightningConnectionType.Charge =>
$"type=charge;server={Server.MerchantCharge.Client.Uri.AbsoluteUri};allowinsecure=true", $"type=charge;server={Server.MerchantCharge.Client.Uri.AbsoluteUri};allowinsecure=true",
LightningConnectionType.CLightning => LightningConnectionType.CLightning =>
$"type=clightning;server={((CLightningClient) Server.MerchantLightningD).Address.AbsoluteUri}", $"type=clightning;server={((CLightningClient)Server.MerchantLightningD).Address.AbsoluteUri}",
LightningConnectionType.LndREST => LightningConnectionType.LndREST =>
$"type=lnd-rest;server={Server.MerchantLnd.Swagger.BaseUrl};allowinsecure=true", $"type=lnd-rest;server={Server.MerchantLnd.Swagger.BaseUrl};allowinsecure=true",
_ => null _ => null

View File

@@ -1410,7 +1410,7 @@ namespace BTCPayServer.Tests
//even though we set DisableBolt11PaymentMethod to true, logic when saving it turns it back off as otherwise no lightning option is available at all! //even though we set DisableBolt11PaymentMethod to true, logic when saving it turns it back off as otherwise no lightning option is available at all!
Assert.False(s.Driver.FindElement(By.Id("DisableBolt11PaymentMethod")).Selected); Assert.False(s.Driver.FindElement(By.Id("DisableBolt11PaymentMethod")).Selected);
// Invoice creation should fail, because it is a standard invoice with amount, but DisableBolt11PaymentMethod = true and LNURLStandardInvoiceEnabled = false // Invoice creation should fail, because it is a standard invoice with amount, but DisableBolt11PaymentMethod = true and LNURLStandardInvoiceEnabled = false
s.CreateInvoice(storeId, 0.0000001m, cryptoCode,"",null, expectedSeverity: StatusMessageModel.StatusSeverity.Success); s.CreateInvoice(storeId, 0.0000001m, cryptoCode, "", null, expectedSeverity: StatusMessageModel.StatusSeverity.Success);
i = s.CreateInvoice(storeId, null, cryptoCode); i = s.CreateInvoice(storeId, null, cryptoCode);
s.GoToInvoiceCheckout(i); s.GoToInvoiceCheckout(i);
@@ -1437,7 +1437,7 @@ namespace BTCPayServer.Tests
// Check that pull payment has lightning option // Check that pull payment has lightning option
s.GoToStore(s.StoreId, StoreNavPages.PullPayments); s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click(); s.Driver.FindElement(By.Id("NewPullPayment")).Click();
Assert.Equal(new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike),PaymentMethodId.Parse(Assert.Single(s.Driver.FindElements(By.CssSelector("input[name='PaymentMethods']"))).GetAttribute("value"))); Assert.Equal(new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike), PaymentMethodId.Parse(Assert.Single(s.Driver.FindElements(By.CssSelector("input[name='PaymentMethods']"))).GetAttribute("value")));
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1"); s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.FindElement(By.Id("Amount")).Clear(); s.Driver.FindElement(By.Id("Amount")).Clear();
s.Driver.FindElement(By.Id("Amount")).SendKeys("0.0000001"); s.Driver.FindElement(By.Id("Amount")).SendKeys("0.0000001");
@@ -1534,7 +1534,7 @@ namespace BTCPayServer.Tests
var lnurl = new Uri(LNURL.LNURL.ExtractUriFromInternetIdentifier(value).ToString() var lnurl = new Uri(LNURL.LNURL.ExtractUriFromInternetIdentifier(value).ToString()
.Replace("https", "http")); .Replace("https", "http"));
var request =(LNURL.LNURLPayRequest) await LNURL.LNURL.FetchInformation(lnurl, new HttpClient()); var request = (LNURL.LNURLPayRequest)await LNURL.LNURL.FetchInformation(lnurl, new HttpClient());
switch (value) switch (value)
{ {

View File

@@ -5,6 +5,7 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Client; using BTCPayServer.Client;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Controllers; using BTCPayServer.Controllers;
@@ -14,6 +15,7 @@ using BTCPayServer.Lightning;
using BTCPayServer.Lightning.CLightning; using BTCPayServer.Lightning.CLightning;
using BTCPayServer.Models.AccountViewModels; using BTCPayServer.Models.AccountViewModels;
using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Payments.PayJoin.Sender; using BTCPayServer.Payments.PayJoin.Sender;
using BTCPayServer.Services; using BTCPayServer.Services;
using BTCPayServer.Services.Stores; using BTCPayServer.Services.Stores;
@@ -23,8 +25,6 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Operations;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Payments.Lightning;
using NBitcoin.Payment; using NBitcoin.Payment;
using NBitpayClient; using NBitpayClient;
using NBXplorer.DerivationStrategy; using NBXplorer.DerivationStrategy;
@@ -470,7 +470,7 @@ namespace BTCPayServer.Tests
public TEvent AssertHasWebhookEvent<TEvent>(WebhookEventType eventType, Action<TEvent> assert) where TEvent : class public TEvent AssertHasWebhookEvent<TEvent>(WebhookEventType eventType, Action<TEvent> assert) where TEvent : class
{ {
int retry = 0; int retry = 0;
retry: retry:
foreach (var evt in WebhookEvents) foreach (var evt in WebhookEvents)
{ {
if (evt.Type == eventType) if (evt.Type == eventType)

View File

@@ -371,7 +371,7 @@ namespace BTCPayServer.Tests
{ {
await tester.ExplorerNode.SendToAddressAsync( await tester.ExplorerNode.SendToAddressAsync(
BitcoinAddress.Create(invoice.BitcoinAddress, Network.RegTest), Money.Coins(0.00005m)); BitcoinAddress.Create(invoice.BitcoinAddress, Network.RegTest), Money.Coins(0.00005m));
}, e => e.InvoiceId == invoice.Id && e.PaymentMethodId.PaymentType == LightningPaymentType.Instance ); }, e => e.InvoiceId == invoice.Id && e.PaymentMethodId.PaymentType == LightningPaymentType.Instance);
await tester.ExplorerNode.GenerateAsync(1); await tester.ExplorerNode.GenerateAsync(1);
Invoice newInvoice = null; Invoice newInvoice = null;
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
@@ -1663,7 +1663,7 @@ namespace BTCPayServer.Tests
Assert.True($"bitcoin:{paymentMethodSecond.BtcAddress.ToUpperInvariant()}" == split); Assert.True($"bitcoin:{paymentMethodSecond.BtcAddress.ToUpperInvariant()}" == split);
// Fallback lightning invoice should be uppercase inside the QR code. // Fallback lightning invoice should be uppercase inside the QR code.
var lightningFallback = paymentMethodSecond.InvoiceBitcoinUrlQR.Split(new [] { "&lightning=" }, StringSplitOptions.None)[1]; var lightningFallback = paymentMethodSecond.InvoiceBitcoinUrlQR.Split(new[] { "&lightning=" }, StringSplitOptions.None)[1];
Assert.True(lightningFallback.ToUpperInvariant() == lightningFallback); Assert.True(lightningFallback.ToUpperInvariant() == lightningFallback);
} }
} }
@@ -2312,7 +2312,7 @@ namespace BTCPayServer.Tests
c => c =>
{ {
Assert.False(c.AfterExpiration); Assert.False(c.AfterExpiration);
Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(),c.PaymentMethod); Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(), c.PaymentMethod);
Assert.NotNull(c.Payment); Assert.NotNull(c.Payment);
Assert.Equal(invoice.BitcoinAddress, c.Payment.Destination); Assert.Equal(invoice.BitcoinAddress, c.Payment.Destination);
Assert.StartsWith(txId.ToString(), c.Payment.Id); Assert.StartsWith(txId.ToString(), c.Payment.Id);
@@ -2322,7 +2322,7 @@ namespace BTCPayServer.Tests
c => c =>
{ {
Assert.False(c.AfterExpiration); Assert.False(c.AfterExpiration);
Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(),c.PaymentMethod); Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(), c.PaymentMethod);
Assert.NotNull(c.Payment); Assert.NotNull(c.Payment);
Assert.Equal(invoice.BitcoinAddress, c.Payment.Destination); Assert.Equal(invoice.BitcoinAddress, c.Payment.Destination);
Assert.StartsWith(txId.ToString(), c.Payment.Id); Assert.StartsWith(txId.ToString(), c.Payment.Id);
@@ -2695,29 +2695,29 @@ namespace BTCPayServer.Tests
await settings.UpdateSetting(new PoliciesSettings() { DisableStoresToUseServerEmailSettings = false }); await settings.UpdateSetting(new PoliciesSettings() { DisableStoresToUseServerEmailSettings = false });
await settings.UpdateSetting(new EmailSettings() await settings.UpdateSetting(new EmailSettings()
{ {
From = "admin@admin.com", From = "admin@admin.com",
Login = "admin@admin.com", Login = "admin@admin.com",
Password = "admin@admin.com", Password = "admin@admin.com",
Port = 1234, Port = 1234,
Server = "admin.com", Server = "admin.com",
}); });
Assert.Equal("admin@admin.com",(await Assert.IsType<ServerEmailSender>(await emailSenderFactory.GetEmailSender()).GetEmailSettings()).Login); Assert.Equal("admin@admin.com", (await Assert.IsType<ServerEmailSender>(await emailSenderFactory.GetEmailSender()).GetEmailSettings()).Login);
Assert.Equal("admin@admin.com",(await Assert.IsType<StoreEmailSender>(await emailSenderFactory.GetEmailSender(acc.StoreId)).GetEmailSettings()).Login); Assert.Equal("admin@admin.com", (await Assert.IsType<StoreEmailSender>(await emailSenderFactory.GetEmailSender(acc.StoreId)).GetEmailSettings()).Login);
await settings.UpdateSetting(new PoliciesSettings() { DisableStoresToUseServerEmailSettings = true }); await settings.UpdateSetting(new PoliciesSettings() { DisableStoresToUseServerEmailSettings = true });
Assert.Equal("admin@admin.com",(await Assert.IsType<ServerEmailSender>(await emailSenderFactory.GetEmailSender()).GetEmailSettings()).Login); Assert.Equal("admin@admin.com", (await Assert.IsType<ServerEmailSender>(await emailSenderFactory.GetEmailSender()).GetEmailSettings()).Login);
Assert.Null(await Assert.IsType<StoreEmailSender>(await emailSenderFactory.GetEmailSender(acc.StoreId)).GetEmailSettings()); Assert.Null(await Assert.IsType<StoreEmailSender>(await emailSenderFactory.GetEmailSender(acc.StoreId)).GetEmailSettings());
Assert.IsType<RedirectToActionResult>(await acc.GetController<StoresController>().Emails(acc.StoreId, new EmailsViewModel(new EmailSettings() Assert.IsType<RedirectToActionResult>(await acc.GetController<StoresController>().Emails(acc.StoreId, new EmailsViewModel(new EmailSettings()
{ {
From = "store@store.com", From = "store@store.com",
Login = "store@store.com", Login = "store@store.com",
Password = "store@store.com", Password = "store@store.com",
Port = 1234, Port = 1234,
Server = "store.com" Server = "store.com"
}), "")); }), ""));
Assert.Equal("store@store.com",(await Assert.IsType<StoreEmailSender>(await emailSenderFactory.GetEmailSender(acc.StoreId)).GetEmailSettings()).Login); Assert.Equal("store@store.com", (await Assert.IsType<StoreEmailSender>(await emailSenderFactory.GetEmailSender(acc.StoreId)).GetEmailSettings()).Login);
} }
} }

View File

@@ -1,8 +1,8 @@
using System; using System;
using BTCPayServer.Configuration;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using BTCPayServer.Configuration;
using BTCPayServer.Logging; using BTCPayServer.Logging;
using BTCPayServer.SSH; using BTCPayServer.SSH;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@@ -72,7 +72,7 @@ namespace BTCPayServer.Configuration
TorrcFile = conf.GetOrDefault<string>("torrcfile", null); TorrcFile = conf.GetOrDefault<string>("torrcfile", null);
TorServices = conf.GetOrDefault<string>("torservices", null) TorServices = conf.GetOrDefault<string>("torservices", null)
?.Split(new[] {';', ','}, StringSplitOptions.RemoveEmptyEntries); ?.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
if (!string.IsNullOrEmpty(TorrcFile) && TorServices != null) if (!string.IsNullOrEmpty(TorrcFile) && TorServices != null)
throw new ConfigException($"torrcfile or torservices should be provided, but not both"); throw new ConfigException($"torrcfile or torservices should be provided, but not both");
@@ -145,7 +145,7 @@ namespace BTCPayServer.Configuration
DisableRegistration = conf.GetOrDefault<bool>("disable-registration", true); DisableRegistration = conf.GetOrDefault<bool>("disable-registration", true);
PluginRemote = conf.GetOrDefault("plugin-remote", "btcpayserver/btcpayserver-plugins"); PluginRemote = conf.GetOrDefault("plugin-remote", "btcpayserver/btcpayserver-plugins");
RecommendedPlugins = conf.GetOrDefault("recommended-plugins", "").ToLowerInvariant().Split('\r','\n','\t',' ').Where(s => !string.IsNullOrEmpty(s)).Distinct().ToArray(); RecommendedPlugins = conf.GetOrDefault("recommended-plugins", "").ToLowerInvariant().Split('\r', '\n', '\t', ' ').Where(s => !string.IsNullOrEmpty(s)).Distinct().ToArray();
CheatMode = conf.GetOrDefault("cheatmode", false); CheatMode = conf.GetOrDefault("cheatmode", false);
if (CheatMode && this.NetworkType == ChainName.Mainnet) if (CheatMode && this.NetworkType == ChainName.Mainnet)
throw new ConfigException($"cheatmode can't be used on mainnet"); throw new ConfigException($"cheatmode can't be used on mainnet");

View File

@@ -152,7 +152,7 @@ namespace BTCPayServer.Controllers
} }
var fido2Devices = await _fido2Service.HasCredentials(user.Id); var fido2Devices = await _fido2Service.HasCredentials(user.Id);
if (!await _userManager.IsLockedOutAsync(user) && fido2Devices) if (!await _userManager.IsLockedOutAsync(user) && fido2Devices)
{ {
if (await _userManager.CheckPasswordAsync(user, model.Password)) if (await _userManager.CheckPasswordAsync(user, model.Password))
{ {
@@ -171,7 +171,7 @@ namespace BTCPayServer.Controllers
return View("SecondaryLogin", new SecondaryLoginViewModel() return View("SecondaryLogin", new SecondaryLoginViewModel()
{ {
LoginWith2FaViewModel = twoFModel, LoginWith2FaViewModel = twoFModel,
LoginWithFido2ViewModel = fido2Devices? await BuildFido2ViewModel(model.RememberMe, user): null, LoginWithFido2ViewModel = fido2Devices ? await BuildFido2ViewModel(model.RememberMe, user) : null,
}); });
} }
else else
@@ -464,8 +464,13 @@ namespace BTCPayServer.Controllers
return RedirectToAction(nameof(HomeController.Index), "Home"); return RedirectToAction(nameof(HomeController.Index), "Home");
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
var user = new ApplicationUser { UserName = model.Email, Email = model.Email, RequiresEmailConfirmation = policies.RequiresConfirmedEmail, var user = new ApplicationUser
Created = DateTimeOffset.UtcNow }; {
UserName = model.Email,
Email = model.Email,
RequiresEmailConfirmation = policies.RequiresConfirmedEmail,
Created = DateTimeOffset.UtcNow
};
var result = await _userManager.CreateAsync(user, model.Password); var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded) if (result.Succeeded)
{ {
@@ -544,7 +549,7 @@ namespace BTCPayServer.Controllers
Severity = StatusMessageModel.StatusSeverity.Info, Severity = StatusMessageModel.StatusSeverity.Info,
Message = "Your email has been confirmed but you still need to set your password." Message = "Your email has been confirmed but you still need to set your password."
}); });
return RedirectToAction("SetPassword", new { email = user.Email, code= await _userManager.GeneratePasswordResetTokenAsync(user)}); return RedirectToAction("SetPassword", new { email = user.Email, code = await _userManager.GeneratePasswordResetTokenAsync(user) });
} }
if (result.Succeeded) if (result.Succeeded)
@@ -554,7 +559,7 @@ namespace BTCPayServer.Controllers
Severity = StatusMessageModel.StatusSeverity.Success, Severity = StatusMessageModel.StatusSeverity.Success,
Message = "Your email has been confirmed." Message = "Your email has been confirmed."
}); });
return RedirectToAction("Login", new {email = user.Email}); return RedirectToAction("Login", new { email = user.Email });
} }
return View("Error"); return View("Error");
@@ -583,7 +588,8 @@ namespace BTCPayServer.Controllers
} }
_eventAggregator.Publish(new UserPasswordResetRequestedEvent() _eventAggregator.Publish(new UserPasswordResetRequestedEvent()
{ {
User = user, RequestUri = Request.GetAbsoluteRootUri() User = user,
RequestUri = Request.GetAbsoluteRootUri()
}); });
return RedirectToAction(nameof(ForgotPasswordConfirmation)); return RedirectToAction(nameof(ForgotPasswordConfirmation));
} }
@@ -614,7 +620,7 @@ namespace BTCPayServer.Controllers
email = user?.Email; email = user?.Email;
} }
var model = new SetPasswordViewModel {Code = code, Email = email, EmailSetInternally = !string.IsNullOrEmpty(email)}; var model = new SetPasswordViewModel { Code = code, Email = email, EmailSetInternally = !string.IsNullOrEmpty(email) };
return View(model); return View(model);
} }
@@ -639,7 +645,8 @@ namespace BTCPayServer.Controllers
{ {
TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Severity = StatusMessageModel.StatusSeverity.Success, Message = "Password successfully set." Severity = StatusMessageModel.StatusSeverity.Success,
Message = "Password successfully set."
}); });
return RedirectToAction(nameof(Login)); return RedirectToAction(nameof(Login));
} }

View File

@@ -1,9 +1,9 @@
using System; using System;
using BTCPayServer.Data;
using System.Linq; 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.Data;
using BTCPayServer.Models; using BTCPayServer.Models;
using BTCPayServer.Models.AppViewModels; using BTCPayServer.Models.AppViewModels;
using BTCPayServer.Services.Apps; using BTCPayServer.Services.Apps;

View File

@@ -47,10 +47,10 @@ namespace BTCPayServer.Controllers
switch ((await _AppService.GetApp(appId, null)).AppType) switch ((await _AppService.GetApp(appId, null)).AppType)
{ {
case nameof(AppType.Crowdfund): case nameof(AppType.Crowdfund):
return RedirectToAction("ViewCrowdfund", new {appId}); return RedirectToAction("ViewCrowdfund", new { appId });
case nameof(AppType.PointOfSale): case nameof(AppType.PointOfSale):
return RedirectToAction("ViewPointOfSale", new {appId}); return RedirectToAction("ViewPointOfSale", new { appId });
} }
return NotFound(); return NotFound();
@@ -150,7 +150,7 @@ namespace BTCPayServer.Controllers
if (choice == null) if (choice == null)
return NotFound(); return NotFound();
title = choice.Title; title = choice.Title;
if (choice.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup) if (choice.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup)
{ {
price = null; price = null;
} }

View File

@@ -12,7 +12,7 @@ namespace BTCPayServer.Controllers.GreenField
{ {
private readonly NBXplorerDashboard _dashBoard; private readonly NBXplorerDashboard _dashBoard;
public HealthController(NBXplorerDashboard dashBoard ) public HealthController(NBXplorerDashboard dashBoard)
{ {
_dashBoard = dashBoard; _dashBoard = dashBoard;
} }

View File

@@ -82,7 +82,7 @@ namespace BTCPayServer.Controllers.GreenField
{ {
Skip = skip, Skip = skip,
Take = take, Take = take,
StoreId = new[] {store.Id}, StoreId = new[] { store.Id },
IncludeArchived = includeArchived, IncludeArchived = includeArchived,
StartDate = startDate, StartDate = startDate,
EndDate = endDate, EndDate = endDate,

View File

@@ -150,7 +150,7 @@ namespace BTCPayServer.Controllers.GreenField
_greenfieldPullPaymentController, _greenfieldPullPaymentController,
_homeController, _homeController,
_storePaymentMethodsController, _storePaymentMethodsController,
new HttpContextAccessor() {HttpContext = context} new HttpContextAccessor() { HttpContext = context }
); );
} }
} }
@@ -471,8 +471,8 @@ namespace BTCPayServer.Controllers.GreenField
switch (result) switch (result)
{ {
case JsonResult jsonResult: case JsonResult jsonResult:
return (T) jsonResult.Value; return (T)jsonResult.Value;
case OkObjectResult {Value: T res}: case OkObjectResult { Value: T res }:
return res; return res;
default: default:
return default; return default;
@@ -483,9 +483,9 @@ namespace BTCPayServer.Controllers.GreenField
{ {
switch (result) switch (result)
{ {
case UnprocessableEntityObjectResult {Value: List<GreenfieldValidationError> validationErrors}: case UnprocessableEntityObjectResult { Value: List<GreenfieldValidationError> validationErrors }:
throw new GreenFieldValidationException(validationErrors.ToArray()); throw new GreenFieldValidationException(validationErrors.ToArray());
case BadRequestObjectResult {Value: GreenfieldAPIError error}: case BadRequestObjectResult { Value: GreenfieldAPIError error }:
throw new GreenFieldAPIException(400, error); throw new GreenFieldAPIException(400, error);
case NotFoundResult _: case NotFoundResult _:
throw new GreenFieldAPIException(404, new GreenfieldAPIError("not-found", "")); throw new GreenFieldAPIException(404, new GreenfieldAPIError("not-found", ""));
@@ -632,7 +632,7 @@ namespace BTCPayServer.Controllers.GreenField
{ {
return GetFromActionResult<NotificationData>( return GetFromActionResult<NotificationData>(
await _notificationsController.UpdateNotification(notificationId, await _notificationsController.UpdateNotification(notificationId,
new UpdateNotification() {Seen = seen})); new UpdateNotification() { Seen = seen }));
} }
public override async Task RemoveNotification(string notificationId, CancellationToken token = default) public override async Task RemoveNotification(string notificationId, CancellationToken token = default)
@@ -832,7 +832,7 @@ namespace BTCPayServer.Controllers.GreenField
return GetFromActionResult<IEnumerable<InvoiceData>>( return GetFromActionResult<IEnumerable<InvoiceData>>(
await _greenFieldInvoiceController.GetInvoices(storeId, orderId, await _greenFieldInvoiceController.GetInvoices(storeId, orderId,
status?.Select(invoiceStatus => invoiceStatus.ToString())?.ToArray(), startDate, status?.Select(invoiceStatus => invoiceStatus.ToString())?.ToArray(), startDate,
endDate, textSearch, includeArchived,skip,take)); endDate, textSearch, includeArchived, skip, take));
} }
public override async Task<InvoiceData> GetInvoice(string storeId, string invoiceId, public override async Task<InvoiceData> GetInvoice(string storeId, string invoiceId,
@@ -928,7 +928,7 @@ namespace BTCPayServer.Controllers.GreenField
public override async Task<OnChainPaymentMethodDataWithSensitiveData> GenerateOnChainWallet(string storeId, string cryptoCode, GenerateOnChainWalletRequest request, public override async Task<OnChainPaymentMethodDataWithSensitiveData> GenerateOnChainWallet(string storeId, string cryptoCode, GenerateOnChainWalletRequest request,
CancellationToken token = default) CancellationToken token = default)
{ {
return GetFromActionResult<OnChainPaymentMethodDataWithSensitiveData>(await _chainPaymentMethodsController.GenerateOnChainWallet(storeId, cryptoCode, new GenerateWalletRequest() return GetFromActionResult<OnChainPaymentMethodDataWithSensitiveData>(await _chainPaymentMethodsController.GenerateOnChainWallet(storeId, cryptoCode, new GenerateWalletRequest()
{ {
Passphrase = request.Passphrase, Passphrase = request.Passphrase,
AccountNumber = request.AccountNumber, AccountNumber = request.AccountNumber,

View File

@@ -37,7 +37,10 @@ namespace BTCPayServer.Controllers.GreenField
{ {
var items = await _notificationManager.GetNotifications(new NotificationsQuery() var items = await _notificationManager.GetNotifications(new NotificationsQuery()
{ {
Seen = seen, UserId = _userManager.GetUserId(User), Skip = skip, Take = take Seen = seen,
UserId = _userManager.GetUserId(User),
Skip = skip,
Take = take
}); });
return Ok(items.Items.Select(ToModel)); return Ok(items.Items.Select(ToModel));
@@ -50,7 +53,8 @@ namespace BTCPayServer.Controllers.GreenField
{ {
var items = await _notificationManager.GetNotifications(new NotificationsQuery() var items = await _notificationManager.GetNotifications(new NotificationsQuery()
{ {
Ids = new[] {id}, UserId = _userManager.GetUserId(User) Ids = new[] { id },
UserId = _userManager.GetUserId(User)
}); });
if (items.Count == 0) if (items.Count == 0)
@@ -67,7 +71,7 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> UpdateNotification(string id, UpdateNotification request) public async Task<IActionResult> UpdateNotification(string id, UpdateNotification request)
{ {
var items = await _notificationManager.ToggleSeen( var items = await _notificationManager.ToggleSeen(
new NotificationsQuery() {Ids = new[] {id}, UserId = _userManager.GetUserId(User)}, request.Seen); new NotificationsQuery() { Ids = new[] { id }, UserId = _userManager.GetUserId(User) }, request.Seen);
if (items.Count == 0) if (items.Count == 0)
{ {
@@ -84,7 +88,8 @@ namespace BTCPayServer.Controllers.GreenField
{ {
await _notificationManager.Remove(new NotificationsQuery() await _notificationManager.Remove(new NotificationsQuery()
{ {
Ids = new[] {id}, UserId = _userManager.GetUserId(User) Ids = new[] { id },
UserId = _userManager.GetUserId(User)
}); });
return Ok(); return Ok();

View File

@@ -107,14 +107,14 @@ namespace BTCPayServer.Controllers.GreenField
PaymentMethodId.TryParse(s, out var pmi); PaymentMethodId.TryParse(s, out var pmi);
return pmi; return pmi;
}).ToArray(); }).ToArray();
var supported = (await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData())).ToArray(); var supported = (await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData())).ToArray();
for (int i = 0; i < paymentMethods.Length; i++) for (int i = 0; i < paymentMethods.Length; i++)
{ {
if (!supported.Contains(paymentMethods[i])) if (!supported.Contains(paymentMethods[i]))
{ {
request.AddModelError(paymentRequest => paymentRequest.PaymentMethods[i], "Invalid or unsupported payment method", this); request.AddModelError(paymentRequest => paymentRequest.PaymentMethods[i], "Invalid or unsupported payment method", this);
} }
} }
} }
else else
{ {
@@ -181,7 +181,7 @@ namespace BTCPayServer.Controllers.GreenField
var pp = await _pullPaymentService.GetPullPayment(pullPaymentId, true); var pp = await _pullPaymentService.GetPullPayment(pullPaymentId, true);
if (pp is null) if (pp is null)
return PullPaymentNotFound(); return PullPaymentNotFound();
var payouts = pp.Payouts .Where(p => p.State != PayoutState.Cancelled || includeCancelled).ToList(); var payouts = pp.Payouts.Where(p => p.State != PayoutState.Cancelled || includeCancelled).ToList();
var cd = _currencyNameTable.GetCurrencyData(pp.GetBlob().Currency, false); var cd = _currencyNameTable.GetCurrencyData(pp.GetBlob().Currency, false);
return base.Ok(payouts return base.Ok(payouts
.Select(p => ToModel(p, cd)).ToList()); .Select(p => ToModel(p, cd)).ToList());
@@ -198,7 +198,7 @@ namespace BTCPayServer.Controllers.GreenField
if (pp is null) if (pp is null)
return PullPaymentNotFound(); return PullPaymentNotFound();
var payout = pp.Payouts.FirstOrDefault(p => p.Id == payoutId); var payout = pp.Payouts.FirstOrDefault(p => p.Id == payoutId);
if(payout is null ) if (payout is null)
return PayoutNotFound(); return PayoutNotFound();
var cd = _currencyNameTable.GetCurrencyData(payout.PullPaymentData.GetBlob().Currency, false); var cd = _currencyNameTable.GetCurrencyData(payout.PullPaymentData.GetBlob().Currency, false);
return base.Ok(ToModel(payout, cd)); return base.Ok(ToModel(payout, cd));
@@ -248,7 +248,7 @@ namespace BTCPayServer.Controllers.GreenField
var destination = await payoutHandler.ParseClaimDestination(paymentMethodId, request!.Destination, true); var destination = await payoutHandler.ParseClaimDestination(paymentMethodId, request!.Destination, true);
if (destination.destination is null) if (destination.destination is null)
{ {
ModelState.AddModelError(nameof(request.Destination), destination.error??"The destination is invalid for the payment specified"); ModelState.AddModelError(nameof(request.Destination), destination.error ?? "The destination is invalid for the payment specified");
return this.CreateValidationError(ModelState); return this.CreateValidationError(ModelState);
} }

View File

@@ -23,7 +23,7 @@ namespace BTCPayServer.Controllers.GreenField
public GreenFieldServerInfoController( public GreenFieldServerInfoController(
BTCPayServerEnvironment env, BTCPayServerEnvironment env,
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary, PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
IEnumerable<ISyncSummaryProvider>summaryProviders) IEnumerable<ISyncSummaryProvider> summaryProviders)
{ {
_env = env; _env = env;
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary; _paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Client; using BTCPayServer.Client;

View File

@@ -179,12 +179,12 @@ namespace BTCPayServer.Controllers.GreenField
new new
OnChainPaymentMethodPreviewResultData. OnChainPaymentMethodPreviewResultData.
OnChainPaymentMethodPreviewResultAddressItem() OnChainPaymentMethodPreviewResultAddressItem()
{ {
KeyPath = deposit.GetKeyPath((uint)i).ToString(), KeyPath = deposit.GetKeyPath((uint)i).ToString(),
Address = strategy.Network.NBXplorerNetwork.CreateAddress(strategy.AccountDerivation, Address = strategy.Network.NBXplorerNetwork.CreateAddress(strategy.AccountDerivation,
line.KeyPathTemplate.GetKeyPath((uint)i), line.KeyPathTemplate.GetKeyPath((uint)i),
derivation.ScriptPubKey).ToString() derivation.ScriptPubKey).ToString()
}); });
} }
return Ok(result); return Ok(result);

View File

@@ -85,7 +85,8 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> ShowOnChainWalletOverview(string storeId, string cryptoCode) public async Task<IActionResult> ShowOnChainWalletOverview(string storeId, string cryptoCode)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
var balance = await wallet.GetBalance(derivationScheme.AccountDerivation); var balance = await wallet.GetBalance(derivationScheme.AccountDerivation);
@@ -94,8 +95,8 @@ namespace BTCPayServer.Controllers.GreenField
{ {
Label = derivationScheme.ToPrettyString(), Label = derivationScheme.ToPrettyString(),
Balance = balance.Total.GetValue(network), Balance = balance.Total.GetValue(network),
UnconfirmedBalance= balance.Unconfirmed.GetValue(network), UnconfirmedBalance = balance.Unconfirmed.GetValue(network),
ConfirmedBalance= balance.Confirmed.GetValue(network), ConfirmedBalance = balance.Confirmed.GetValue(network),
}); });
} }
@@ -104,12 +105,13 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null) public async Task<IActionResult> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var feeRateTarget = blockTarget?? Store.GetStoreBlob().RecommendedFeeBlockTarget; var feeRateTarget = blockTarget ?? Store.GetStoreBlob().RecommendedFeeBlockTarget;
return Ok(new OnChainWalletFeeRateData() return Ok(new OnChainWalletFeeRateData()
{ {
FeeRate = await _feeProviderFactory.CreateFeeProvider(network) FeeRate = await _feeProviderFactory.CreateFeeProvider(network)
.GetFeeRateAsync(feeRateTarget), .GetFeeRateAsync(feeRateTarget),
}); });
} }
@@ -119,7 +121,8 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false) public async Task<IActionResult> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var kpi = await _walletReceiveService.GetOrGenerate(new WalletId(storeId, cryptoCode), forceGenerate); var kpi = await _walletReceiveService.GetOrGenerate(new WalletId(storeId, cryptoCode), forceGenerate);
if (kpi is null) if (kpi is null)
@@ -146,7 +149,8 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode) public async Task<IActionResult> UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var addr = await _walletReceiveService.UnReserveAddress(new WalletId(storeId, cryptoCode)); var addr = await _walletReceiveService.UnReserveAddress(new WalletId(storeId, cryptoCode));
if (addr is null) if (addr is null)
@@ -168,7 +172,8 @@ namespace BTCPayServer.Controllers.GreenField
) )
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
var walletId = new WalletId(storeId, cryptoCode); var walletId = new WalletId(storeId, cryptoCode);
@@ -186,7 +191,7 @@ namespace BTCPayServer.Controllers.GreenField
filteredFlatList.AddRange(txs.UnconfirmedTransactions.Transactions); filteredFlatList.AddRange(txs.UnconfirmedTransactions.Transactions);
} }
if (statusFilter is null || !statusFilter.Any() ||statusFilter.Contains(TransactionStatus.Replaced)) if (statusFilter is null || !statusFilter.Any() || statusFilter.Contains(TransactionStatus.Replaced))
{ {
filteredFlatList.AddRange(txs.ReplacedTransactions.Transactions); filteredFlatList.AddRange(txs.ReplacedTransactions.Transactions);
} }
@@ -205,7 +210,8 @@ namespace BTCPayServer.Controllers.GreenField
string transactionId) string transactionId)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
var tx = await wallet.FetchTransaction(derivationScheme.AccountDerivation, uint256.Parse(transactionId)); var tx = await wallet.FetchTransaction(derivationScheme.AccountDerivation, uint256.Parse(transactionId));
@@ -216,7 +222,7 @@ namespace BTCPayServer.Controllers.GreenField
var walletId = new WalletId(storeId, cryptoCode); var walletId = new WalletId(storeId, cryptoCode);
var walletTransactionsInfoAsync = var walletTransactionsInfoAsync =
(await _walletRepository.GetWalletTransactionsInfo(walletId, new[] {transactionId})).Values (await _walletRepository.GetWalletTransactionsInfo(walletId, new[] { transactionId })).Values
.FirstOrDefault(); .FirstOrDefault();
return Ok(ToModel(walletTransactionsInfoAsync, tx, wallet)); return Ok(ToModel(walletTransactionsInfoAsync, tx, wallet));
@@ -227,7 +233,8 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> GetOnChainWalletUTXOs(string storeId, string cryptoCode) public async Task<IActionResult> GetOnChainWalletUTXOs(string storeId, string cryptoCode)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
@@ -248,7 +255,7 @@ namespace BTCPayServer.Controllers.GreenField
Timestamp = coin.Timestamp, Timestamp = coin.Timestamp,
KeyPath = coin.KeyPath, KeyPath = coin.KeyPath,
Confirmations = coin.Confirmations, Confirmations = coin.Confirmations,
Address = network.NBXplorerNetwork.CreateAddress(derivationScheme.AccountDerivation, coin.KeyPath, coin.ScriptPubKey).ToString() Address = network.NBXplorerNetwork.CreateAddress(derivationScheme.AccountDerivation, coin.KeyPath, coin.ScriptPubKey).ToString()
}; };
}).ToList() }).ToList()
); );
@@ -260,7 +267,8 @@ namespace BTCPayServer.Controllers.GreenField
[FromBody] CreateOnChainTransactionRequest request) [FromBody] CreateOnChainTransactionRequest request)
{ {
if (IsInvalidWalletRequest(cryptoCode, out var network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult)) return actionResult; out var derivationScheme, out var actionResult))
return actionResult;
if (network.ReadonlyWallet) if (network.ReadonlyWallet)
{ {
return this.CreateAPIError("not-available", return this.CreateAPIError("not-available",

View File

@@ -36,7 +36,8 @@ namespace BTCPayServer.Controllers.GreenField
var storeBlob = Store.GetStoreBlob(); var storeBlob = Store.GetStoreBlob();
var excludedPaymentMethods = storeBlob.GetExcludedPaymentMethods(); var excludedPaymentMethods = storeBlob.GetExcludedPaymentMethods();
var canModifyStore = (await _authorizationService.AuthorizeAsync(User, null, var canModifyStore = (await _authorizationService.AuthorizeAsync(User, null,
new PolicyRequirement(Policies.CanModifyStoreSettings))).Succeeded;; new PolicyRequirement(Policies.CanModifyStoreSettings))).Succeeded;
;
return Ok(Store.GetSupportedPaymentMethods(_btcPayNetworkProvider) return Ok(Store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
.Where(method => .Where(method =>
enabled is null || (enabled is false && excludedPaymentMethods.Match(method.PaymentId))) enabled is null || (enabled is false && excludedPaymentMethods.Match(method.PaymentId)))

View File

@@ -122,7 +122,7 @@ namespace BTCPayServer.Controllers.GreenField
{ {
Everything = aed.Everything, Everything = aed.Everything,
SpecificEvents = aed.SpecificEvents SpecificEvents = aed.SpecificEvents
}: } :
new AuthorizedWebhookEvents() { Everything = true }, new AuthorizedWebhookEvents() { Everything = true },
AutomaticRedelivery = create.AutomaticRedelivery, AutomaticRedelivery = create.AutomaticRedelivery,
}; };

View File

@@ -10,17 +10,17 @@ using BTCPayServer.Configuration;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events; using BTCPayServer.Events;
using BTCPayServer.HostedServices; using BTCPayServer.HostedServices;
using BTCPayServer.Logging;
using BTCPayServer.Security; using BTCPayServer.Security;
using BTCPayServer.Security.GreenField; using BTCPayServer.Security.GreenField;
using BTCPayServer.Services; using BTCPayServer.Services;
using BTCPayServer.Storage.Services;
using BTCPayServer.Services.Stores; using BTCPayServer.Services.Stores;
using BTCPayServer.Storage.Services;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NicolasDorier.RateLimits; using NicolasDorier.RateLimits;
using BTCPayServer.Logging;
namespace BTCPayServer.Controllers.GreenField namespace BTCPayServer.Controllers.GreenField
{ {
@@ -169,7 +169,8 @@ namespace BTCPayServer.Controllers.GreenField
if (!anyAdmin) if (!anyAdmin)
{ {
var settings = await _settingsRepository.GetSettingAsync<ThemeSettings>(); var settings = await _settingsRepository.GetSettingAsync<ThemeSettings>();
if (settings != null) { if (settings != null)
{
settings.FirstRun = false; settings.FirstRun = false;
await _settingsRepository.UpdateSetting(settings); await _settingsRepository.UpdateSetting(settings);
} }
@@ -234,7 +235,8 @@ namespace BTCPayServer.Controllers.GreenField
private async Task<bool> IsUserTheOnlyOneAdmin(ApplicationUser user) private async Task<bool> IsUserTheOnlyOneAdmin(ApplicationUser user)
{ {
var isUserAdmin = await _userService.IsAdminUser(user); var isUserAdmin = await _userService.IsAdminUser(user);
if (!isUserAdmin) { if (!isUserAdmin)
{
return false; return false;
} }

View File

@@ -4,9 +4,9 @@ using System.Threading.Tasks;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Filters; using BTCPayServer.Filters;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Services;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NBitcoin; using NBitcoin;
using BTCPayServer.Services;
namespace BTCPayServer.Controllers namespace BTCPayServer.Controllers
{ {
@@ -78,7 +78,7 @@ namespace BTCPayServer.Controllers
cheater.CashCow.GenerateToAddress(request.BlockCount, blockRewardBitcoinAddress); cheater.CashCow.GenerateToAddress(request.BlockCount, blockRewardBitcoinAddress);
return Ok(new return Ok(new
{ {
SuccessMessage = "Mined "+request.BlockCount+" blocks" SuccessMessage = "Mined " + request.BlockCount + " blocks"
}); });
} }
return BadRequest(new return BadRequest(new

View File

@@ -158,7 +158,7 @@ namespace BTCPayServer.Controllers
[HttpGet("invoices/{invoiceId}/refund")] [HttpGet("invoices/{invoiceId}/refund")]
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> Refund([FromServices]IEnumerable<IPayoutHandler> payoutHandlers, string invoiceId, CancellationToken cancellationToken) public async Task<IActionResult> Refund([FromServices] IEnumerable<IPayoutHandler> payoutHandlers, string invoiceId, CancellationToken cancellationToken)
{ {
await using var ctx = _dbContextFactory.CreateContext(); await using var ctx = _dbContextFactory.CreateContext();
ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
@@ -283,33 +283,34 @@ namespace BTCPayServer.Controllers
case RefundSteps.SelectRate: case RefundSteps.SelectRate:
createPullPayment = new CreatePullPayment createPullPayment = new CreatePullPayment
{ {
Name = $"Refund {invoice.Id}", PaymentMethodIds = new[] { paymentMethodId }, Name = $"Refund {invoice.Id}",
PaymentMethodIds = new[] { paymentMethodId },
StoreId = invoice.StoreId StoreId = invoice.StoreId
}; };
switch (model.SelectedRefundOption) switch (model.SelectedRefundOption)
{ {
case "RateThen": case "RateThen":
createPullPayment.Currency = paymentMethodId.CryptoCode; createPullPayment.Currency = paymentMethodId.CryptoCode;
createPullPayment.Amount = model.CryptoAmountThen; createPullPayment.Amount = model.CryptoAmountThen;
break; break;
case "CurrentRate": case "CurrentRate":
createPullPayment.Currency = paymentMethodId.CryptoCode; createPullPayment.Currency = paymentMethodId.CryptoCode;
createPullPayment.Amount = model.CryptoAmountNow; createPullPayment.Amount = model.CryptoAmountNow;
break; break;
case "Fiat": case "Fiat":
createPullPayment.Currency = invoice.Currency; createPullPayment.Currency = invoice.Currency;
createPullPayment.Amount = model.FiatAmount; createPullPayment.Amount = model.FiatAmount;
break; break;
case "Custom": case "Custom":
model.Title = "How much to refund?"; model.Title = "How much to refund?";
model.CustomCurrency = invoice.Currency; model.CustomCurrency = invoice.Currency;
model.CustomAmount = model.FiatAmount; model.CustomAmount = model.FiatAmount;
model.RefundStep = RefundSteps.SelectCustomAmount; model.RefundStep = RefundSteps.SelectCustomAmount;
return View(model); return View(model);
default: default:
ModelState.AddModelError(nameof(model.SelectedRefundOption), "Invalid choice"); ModelState.AddModelError(nameof(model.SelectedRefundOption), "Invalid choice");
return View(model); return View(model);
} }
break; break;
case RefundSteps.SelectCustomAmount: case RefundSteps.SelectCustomAmount:
@@ -343,7 +344,8 @@ namespace BTCPayServer.Controllers
createPullPayment = new CreatePullPayment createPullPayment = new CreatePullPayment
{ {
Name = $"Refund {invoice.Id}", PaymentMethodIds = new[] { paymentMethodId }, Name = $"Refund {invoice.Id}",
PaymentMethodIds = new[] { paymentMethodId },
StoreId = invoice.StoreId, StoreId = invoice.StoreId,
Currency = model.CustomCurrency, Currency = model.CustomCurrency,
Amount = model.CustomAmount Amount = model.CustomAmount
@@ -563,10 +565,10 @@ namespace BTCPayServer.Controllers
lang = _languageService.AutoDetectLanguageUsingHeader(HttpContext.Request.Headers, null).Code; lang = _languageService.AutoDetectLanguageUsingHeader(HttpContext.Request.Headers, null).Code;
break; break;
case { } langs when !string.IsNullOrEmpty(langs): case { } langs when !string.IsNullOrEmpty(langs):
{ {
lang = _languageService.FindLanguage(langs)?.Code; lang = _languageService.FindLanguage(langs)?.Code;
break; break;
} }
} }
lang ??= storeBlob.DefaultLang; lang ??= storeBlob.DefaultLang;
@@ -750,7 +752,7 @@ namespace BTCPayServer.Controllers
var store = model.StoreId == null || fs.ContainsFilter("storeid") ? null : HttpContext.GetStoreData(); var store = model.StoreId == null || fs.ContainsFilter("storeid") ? null : HttpContext.GetStoreData();
var storeIds = store == null var storeIds = store == null
? fs.GetFilterArray("storeid") != null ? fs.GetFilterArray("storeid") : new List<string>().ToArray() ? fs.GetFilterArray("storeid") != null ? fs.GetFilterArray("storeid") : new List<string>().ToArray()
: new []{ store.Id }; : new[] { store.Id };
model.StoreIds = storeIds; model.StoreIds = storeIds;

View File

@@ -29,7 +29,7 @@ namespace BTCPayServer.Controllers
{ {
Is2faEnabled = user.TwoFactorEnabled, Is2faEnabled = user.TwoFactorEnabled,
RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user), RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user),
Credentials = await _fido2Service.GetCredentials( _userManager.GetUserId(User)) Credentials = await _fido2Service.GetCredentials(_userManager.GetUserId(User))
}; };
return View(model); return View(model);
@@ -104,7 +104,7 @@ namespace BTCPayServer.Controllers
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
TempData[RecoveryCodesKey] = recoveryCodes.ToArray(); TempData[RecoveryCodesKey] = recoveryCodes.ToArray();
return RedirectToAction(nameof(GenerateRecoveryCodes), new {confirm = false}); return RedirectToAction(nameof(GenerateRecoveryCodes), new { confirm = false });
} }
public async Task<IActionResult> ResetAuthenticator() public async Task<IActionResult> ResetAuthenticator()
@@ -136,7 +136,7 @@ namespace BTCPayServer.Controllers
recoveryCodes = (await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10)).ToArray(); recoveryCodes = (await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10)).ToArray();
} }
var model = new GenerateRecoveryCodesViewModel {RecoveryCodes = recoveryCodes}; var model = new GenerateRecoveryCodesViewModel { RecoveryCodes = recoveryCodes };
return View(model); return View(model);
} }

View File

@@ -108,7 +108,7 @@ namespace BTCPayServer.Controllers
//check if there is an app identifier that matches and belongs to the current user //check if there is an app identifier that matches and belongs to the current user
var keys = await _apiKeyRepository.GetKeys(new APIKeyRepository.APIKeyQuery() var keys = await _apiKeyRepository.GetKeys(new APIKeyRepository.APIKeyQuery()
{ {
UserId = new[] {_userManager.GetUserId(User)} UserId = new[] { _userManager.GetUserId(User) }
}); });
foreach (var key in keys) foreach (var key in keys)
{ {
@@ -201,14 +201,19 @@ namespace BTCPayServer.Controllers
* Go over each permission and associated store IDs and * Go over each permission and associated store IDs and
* join them so that permission for a specific store is parsed correctly * join them so that permission for a specific store is parsed correctly
*/ */
for (var i = 0; i < permissions.Length; i++) { for (var i = 0; i < permissions.Length; i++)
{
var currPerm = permissions[i]; var currPerm = permissions[i];
var storeIds = vm.PermissionValues[i].SpecificStores.ToArray(); var storeIds = vm.PermissionValues[i].SpecificStores.ToArray();
if (storeIds.Length > 0) { if (storeIds.Length > 0)
for (var x = 0; x < storeIds.Length; x++) { {
for (var x = 0; x < storeIds.Length; x++)
{
permissionsWithStoreIDs.Add($"{currPerm}:{storeIds[x]}"); permissionsWithStoreIDs.Add($"{currPerm}:{storeIds[x]}");
} }
} else { }
else
{
permissionsWithStoreIDs.Add(currPerm); permissionsWithStoreIDs.Add(currPerm);
} }
} }
@@ -232,7 +237,8 @@ namespace BTCPayServer.Controllers
var command = commandParts.Length > 1 ? commandParts[1] : null; var command = commandParts.Length > 1 ? commandParts[1] : null;
var isPerformingAnAction = command == "change-store-mode" || command == "add-store"; var isPerformingAnAction = command == "change-store-mode" || command == "add-store";
// Don't want to accidentally change mode for the user if they are explicitly performing some action // Don't want to accidentally change mode for the user if they are explicitly performing some action
if (isPerformingAnAction) { if (isPerformingAnAction)
{
continue; continue;
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;

View File

@@ -19,7 +19,7 @@ namespace BTCPayServer.Controllers
var user = await _userManager.GetUserAsync(User); var user = await _userManager.GetUserAsync(User);
if (user.DisabledNotifications == "all") if (user.DisabledNotifications == "all")
{ {
return View(new NotificationSettingsViewModel() {All = true}); return View(new NotificationSettingsViewModel() { All = true });
} }
var disabledNotifications = var disabledNotifications =
user.DisabledNotifications?.Split(';', StringSplitOptions.RemoveEmptyEntries)?.ToList() ?? user.DisabledNotifications?.Split(';', StringSplitOptions.RemoveEmptyEntries)?.ToList() ??
@@ -29,7 +29,7 @@ namespace BTCPayServer.Controllers
disabledNotifications.Contains(tuple.identifier, StringComparer.InvariantCultureIgnoreCase)))) disabledNotifications.Contains(tuple.identifier, StringComparer.InvariantCultureIgnoreCase))))
.ToList(); .ToList();
return View(new NotificationSettingsViewModel() {DisabledNotifications = notifications}); return View(new NotificationSettingsViewModel() { DisabledNotifications = notifications });
} }
[HttpPost("notifications")] [HttpPost("notifications")]
@@ -56,7 +56,8 @@ namespace BTCPayServer.Controllers
await _userManager.UpdateAsync(user); await _userManager.UpdateAsync(user);
TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Message = "Updated successfully.", Severity = StatusMessageModel.StatusSeverity.Success Message = "Updated successfully.",
Severity = StatusMessageModel.StatusSeverity.Success
}); });
return RedirectToAction("NotificationSettings"); return RedirectToAction("NotificationSettings");
} }

View File

@@ -53,7 +53,7 @@ namespace BTCPayServer.Controllers
Fido2Service fido2Service, Fido2Service fido2Service,
LinkGenerator linkGenerator, LinkGenerator linkGenerator,
UserService userService, UserService userService,
UserLoginCodeService userLoginCodeService UserLoginCodeService userLoginCodeService
) )
{ {
_userManager = userManager; _userManager = userManager;

View File

@@ -110,10 +110,12 @@ namespace BTCPayServer.Controllers
var res = await _notificationManager.GetNotifications(new NotificationsQuery() var res = await _notificationManager.GetNotifications(new NotificationsQuery()
{ {
Skip = skip, Take = count, UserId = userId Skip = skip,
Take = count,
UserId = userId
}); });
var model = new IndexViewModel() {Skip = skip, Count = count, Items = res.Items, Total = res.Count}; var model = new IndexViewModel() { Skip = skip, Count = count, Items = res.Items, Total = res.Count };
return View(model); return View(model);
} }
@@ -133,7 +135,7 @@ namespace BTCPayServer.Controllers
{ {
if (ValidUserClaim(out var userId)) if (ValidUserClaim(out var userId))
{ {
await _notificationManager.ToggleSeen(new NotificationsQuery() {Ids = new[] {id}, UserId = userId}, null); await _notificationManager.ToggleSeen(new NotificationsQuery() { Ids = new[] { id }, UserId = userId }, null);
return RedirectToAction(nameof(Index)); return RedirectToAction(nameof(Index));
} }
@@ -148,7 +150,8 @@ namespace BTCPayServer.Controllers
var items = await var items = await
_notificationManager.ToggleSeen(new NotificationsQuery() _notificationManager.ToggleSeen(new NotificationsQuery()
{ {
Ids = new[] {id}, UserId = userId Ids = new[] { id },
UserId = userId
}, true); }, true);
var link = items.FirstOrDefault()?.ActionLink ?? ""; var link = items.FirstOrDefault()?.ActionLink ?? "";
@@ -185,21 +188,26 @@ namespace BTCPayServer.Controllers
case "delete": case "delete":
await _notificationManager.Remove(new NotificationsQuery() await _notificationManager.Remove(new NotificationsQuery()
{ {
UserId = userId, Ids = selectedItems UserId = userId,
Ids = selectedItems
}); });
break; break;
case "mark-seen": case "mark-seen":
await _notificationManager.ToggleSeen(new NotificationsQuery() await _notificationManager.ToggleSeen(new NotificationsQuery()
{ {
UserId = userId, Ids = selectedItems, Seen = false UserId = userId,
Ids = selectedItems,
Seen = false
}, true); }, true);
break; break;
case "mark-unseen": case "mark-unseen":
await _notificationManager.ToggleSeen(new NotificationsQuery() await _notificationManager.ToggleSeen(new NotificationsQuery()
{ {
UserId = userId, Ids = selectedItems, Seen = true UserId = userId,
Ids = selectedItems,
Seen = true
}, false); }, false);
break; break;
} }
@@ -217,7 +225,7 @@ namespace BTCPayServer.Controllers
{ {
return NotFound(); return NotFound();
} }
await _notificationManager.ToggleSeen(new NotificationsQuery() {Seen = false, UserId = userId}, true); await _notificationManager.ToggleSeen(new NotificationsQuery() { Seen = false, UserId = userId }, true);
return Redirect(returnUrl); return Redirect(returnUrl);
} }

View File

@@ -251,11 +251,11 @@ namespace BTCPayServer.Controllers
Metadata = invoiceMetadata.ToJObject(), Metadata = invoiceMetadata.ToJObject(),
Currency = blob.Currency, Currency = blob.Currency,
Amount = amount.Value, Amount = amount.Value,
Checkout = {RedirectURL = redirectUrl} Checkout = { RedirectURL = redirectUrl }
}; };
var additionalTags = new List<string> {PaymentRequestRepository.GetInternalTag(payReqId)}; var additionalTags = new List<string> { PaymentRequestRepository.GetInternalTag(payReqId) };
var newInvoice = await _InvoiceController.CreateInvoiceCoreRaw(invoiceRequest,store, Request.GetAbsoluteRoot(), additionalTags, cancellationToken); var newInvoice = await _InvoiceController.CreateInvoiceCoreRaw(invoiceRequest, store, Request.GetAbsoluteRoot(), additionalTags, cancellationToken);
if (redirectToInvoice) if (redirectToInvoice)
{ {
@@ -279,7 +279,8 @@ namespace BTCPayServer.Controllers
return NotFound(); return NotFound();
} }
if (!result.AllowCustomPaymentAmounts) { if (!result.AllowCustomPaymentAmounts)
{
return BadRequest("Not allowed to cancel this invoice"); return BadRequest("Not allowed to cancel this invoice");
} }

View File

@@ -109,7 +109,7 @@ namespace BTCPayServer.Controllers
var paymentMethodId = ppBlob.SupportedPaymentMethods.FirstOrDefault(id => vm.SelectedPaymentMethod == id.ToString()); var paymentMethodId = ppBlob.SupportedPaymentMethods.FirstOrDefault(id => vm.SelectedPaymentMethod == id.ToString());
var payoutHandler = paymentMethodId is null? null: _payoutHandlers.FindPayoutHandler(paymentMethodId); var payoutHandler = paymentMethodId is null ? null : _payoutHandlers.FindPayoutHandler(paymentMethodId);
if (payoutHandler is null) if (payoutHandler is null)
{ {
ModelState.AddModelError(nameof(vm.SelectedPaymentMethod), $"Invalid destination with selected payment method"); ModelState.AddModelError(nameof(vm.SelectedPaymentMethod), $"Invalid destination with selected payment method");
@@ -118,7 +118,7 @@ namespace BTCPayServer.Controllers
var destination = await payoutHandler?.ParseClaimDestination(paymentMethodId, vm.Destination, true); var destination = await payoutHandler?.ParseClaimDestination(paymentMethodId, vm.Destination, true);
if (destination.destination is null) if (destination.destination is null)
{ {
ModelState.AddModelError(nameof(vm.Destination), destination.error??"Invalid destination with selected payment method"); ModelState.AddModelError(nameof(vm.Destination), destination.error ?? "Invalid destination with selected payment method");
return await ViewPullPayment(pullPaymentId); return await ViewPullPayment(pullPaymentId);
} }

View File

@@ -83,7 +83,7 @@ namespace BTCPayServer.Controllers
[HttpPost("server/plugins/install")] [HttpPost("server/plugins/install")]
public async Task<IActionResult> InstallPlugin( public async Task<IActionResult> InstallPlugin(
[FromServices] PluginService pluginService, string plugin , bool update = false) [FromServices] PluginService pluginService, string plugin, bool update = false)
{ {
try try
{ {
@@ -107,7 +107,8 @@ namespace BTCPayServer.Controllers
{ {
TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Message = "The plugin could not be downloaded. Try again later.", Severity = StatusMessageModel.StatusSeverity.Error Message = "The plugin could not be downloaded. Try again later.",
Severity = StatusMessageModel.StatusSeverity.Error
}); });
} }
@@ -127,7 +128,7 @@ namespace BTCPayServer.Controllers
} }
return RedirectToAction("ListPlugins", return RedirectToAction("ListPlugins",
new {StatusMessage = "Files uploaded, restart server to load plugins"}); new { StatusMessage = "Files uploaded, restart server to load plugins" });
} }
} }
} }

View File

@@ -212,10 +212,10 @@ namespace BTCPayServer.Controllers
} }
this.TempData.SetStatusMessageModel(new StatusMessageModel() this.TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Message = statusMessage, Message = statusMessage,
Severity = statusMessageSeverity Severity = statusMessageSeverity
}); });
return RedirectToAction(nameof(Files), new return RedirectToAction(nameof(Files), new
{ {

View File

@@ -138,8 +138,14 @@ namespace BTCPayServer.Controllers
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
IdentityResult result; IdentityResult result;
var user = new ApplicationUser { UserName = model.Email, Email = model.Email, EmailConfirmed = model.EmailConfirmed, RequiresEmailConfirmation = requiresConfirmedEmail, var user = new ApplicationUser
Created = DateTimeOffset.UtcNow }; {
UserName = model.Email,
Email = model.Email,
EmailConfirmed = model.EmailConfirmed,
RequiresEmailConfirmation = requiresConfirmedEmail,
Created = DateTimeOffset.UtcNow
};
if (!string.IsNullOrEmpty(model.Password)) if (!string.IsNullOrEmpty(model.Password))
{ {
@@ -159,7 +165,10 @@ namespace BTCPayServer.Controllers
_eventAggregator.Publish(new UserRegisteredEvent() _eventAggregator.Publish(new UserRegisteredEvent()
{ {
RequestUri = Request.GetAbsoluteRootUri(), User = user, Admin = model.IsAdmin is true, CallbackUrlGenerated = tcs RequestUri = Request.GetAbsoluteRootUri(),
User = user,
Admin = model.IsAdmin is true,
CallbackUrlGenerated = tcs
}); });
var callbackUrl = await tcs.Task; var callbackUrl = await tcs.Task;
@@ -173,7 +182,8 @@ namespace BTCPayServer.Controllers
Html = Html =
$"Account created without a set password. An email will be sent (if configured) to set the password.<br/> You may alternatively share this link with them: <a class='alert-link' href='{callbackUrl}'>{callbackUrl}</a>" $"Account created without a set password. An email will be sent (if configured) to set the password.<br/> You may alternatively share this link with them: <a class='alert-link' href='{callbackUrl}'>{callbackUrl}</a>"
}); });
}else if (!await _UserManager.HasPasswordAsync(user)) }
else if (!await _UserManager.HasPasswordAsync(user))
{ {
TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {

View File

@@ -28,7 +28,7 @@ namespace BTCPayServer.Controllers
[Route("stores/{storeId}/pull-payments")] [Route("stores/{storeId}/pull-payments")]
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[AutoValidateAntiforgeryToken] [AutoValidateAntiforgeryToken]
public class StorePullPaymentsController: Controller public class StorePullPaymentsController : Controller
{ {
private readonly BTCPayNetworkProvider _btcPayNetworkProvider; private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
private readonly IEnumerable<IPayoutHandler> _payoutHandlers; private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
@@ -49,7 +49,7 @@ namespace BTCPayServer.Controllers
CurrencyNameTable currencyNameTable, CurrencyNameTable currencyNameTable,
PullPaymentHostedService pullPaymentHostedService, PullPaymentHostedService pullPaymentHostedService,
ApplicationDbContextFactory dbContextFactory, ApplicationDbContextFactory dbContextFactory,
BTCPayNetworkJsonSerializerSettings jsonSerializerSettings) BTCPayNetworkJsonSerializerSettings jsonSerializerSettings)
{ {
_btcPayNetworkProvider = btcPayNetworkProvider; _btcPayNetworkProvider = btcPayNetworkProvider;
_payoutHandlers = payoutHandlers; _payoutHandlers = payoutHandlers;
@@ -63,7 +63,7 @@ namespace BTCPayServer.Controllers
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> NewPullPayment(string storeId) public async Task<IActionResult> NewPullPayment(string storeId)
{ {
if (CurrentStore is null) if (CurrentStore is null)
return NotFound(); return NotFound();
var paymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(CurrentStore); var paymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(CurrentStore);
@@ -90,7 +90,7 @@ namespace BTCPayServer.Controllers
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> NewPullPayment(string storeId, NewPullPaymentModel model) public async Task<IActionResult> NewPullPayment(string storeId, NewPullPaymentModel model)
{ {
if (CurrentStore is null) if (CurrentStore is null)
return NotFound(); return NotFound();
var paymentMethodOptions = await _payoutHandlers.GetSupportedPaymentMethods(CurrentStore); var paymentMethodOptions = await _payoutHandlers.GetSupportedPaymentMethods(CurrentStore);
@@ -172,7 +172,9 @@ namespace BTCPayServer.Controllers
var vm = this.ParseListQuery(new PullPaymentsModel() var vm = this.ParseListQuery(new PullPaymentsModel()
{ {
Skip = skip, Count = count, Total = await ppsQuery.CountAsync() Skip = skip,
Count = count,
Total = await ppsQuery.CountAsync()
}); });
var pps = (await ppsQuery var pps = (await ppsQuery
.Skip(vm.Skip) .Skip(vm.Skip)
@@ -182,11 +184,12 @@ namespace BTCPayServer.Controllers
foreach (var pp in pps) foreach (var pp in pps)
{ {
var totalCompleted = pp.Payouts.Where(p => (p.State == PayoutState.Completed || var totalCompleted = pp.Payouts.Where(p => (p.State == PayoutState.Completed ||
p.State == PayoutState.InProgress) && p.IsInPeriod(pp, now)) p.State == PayoutState.InProgress) && p.IsInPeriod(pp, now))
.Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum(); .Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();
var totalAwaiting = pp.Payouts.Where(p => (p.State == PayoutState.AwaitingPayment || var totalAwaiting = pp.Payouts.Where(p => (p.State == PayoutState.AwaitingPayment ||
p.State == PayoutState.AwaitingApproval) && p.State == PayoutState.AwaitingApproval) &&
p.IsInPeriod(pp, now)).Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();; p.IsInPeriod(pp, now)).Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();
;
var ppBlob = pp.GetBlob(); var ppBlob = pp.GetBlob();
var ni = _currencyNameTable.GetCurrencyData(ppBlob.Currency, true); var ni = _currencyNameTable.GetCurrencyData(ppBlob.Currency, true);
var nfi = _currencyNameTable.GetNumberFormatInfo(ppBlob.Currency, true); var nfi = _currencyNameTable.GetNumberFormatInfo(ppBlob.Currency, true);
@@ -281,115 +284,120 @@ namespace BTCPayServer.Controllers
{ {
case "approve-pay": case "approve-pay":
case "approve": case "approve":
{
await using var ctx = this._dbContextFactory.CreateContext();
ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var payouts = await GetPayoutsForPaymentMethod(paymentMethodId, ctx, payoutIds, storeId, cancellationToken);
var failed = false;
for (int i = 0; i < payouts.Count; i++)
{ {
var payout = payouts[i]; await using var ctx = this._dbContextFactory.CreateContext();
if (payout.State != PayoutState.AwaitingApproval) ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
continue; var payouts = await GetPayoutsForPaymentMethod(paymentMethodId, ctx, payoutIds, storeId, cancellationToken);
var rateResult = await _pullPaymentService.GetRate(payout, null, cancellationToken);
if (rateResult.BidAsk == null) var failed = false;
for (int i = 0; i < payouts.Count; i++)
{ {
this.TempData.SetStatusMessageModel(new StatusMessageModel() var payout = payouts[i];
if (payout.State != PayoutState.AwaitingApproval)
continue;
var rateResult = await _pullPaymentService.GetRate(payout, null, cancellationToken);
if (rateResult.BidAsk == null)
{ {
Message = $"Rate unavailable: {rateResult.EvaluatedRule}", this.TempData.SetStatusMessageModel(new StatusMessageModel()
Severity = StatusMessageModel.StatusSeverity.Error {
Message = $"Rate unavailable: {rateResult.EvaluatedRule}",
Severity = StatusMessageModel.StatusSeverity.Error
});
failed = true;
break;
}
var approveResult = await _pullPaymentService.Approve(new HostedServices.PullPaymentHostedService.PayoutApproval()
{
PayoutId = payout.Id,
Revision = payout.GetBlob(_jsonSerializerSettings).Revision,
Rate = rateResult.BidAsk.Ask
}); });
failed = true; if (approveResult != PullPaymentHostedService.PayoutApproval.Result.Ok)
{
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = PullPaymentHostedService.PayoutApproval.GetErrorMessage(approveResult),
Severity = StatusMessageModel.StatusSeverity.Error
});
failed = true;
break;
}
}
if (failed)
{
break; break;
} }
var approveResult = await _pullPaymentService.Approve(new HostedServices.PullPaymentHostedService.PayoutApproval() if (command == "approve-pay")
{ {
PayoutId = payout.Id, goto case "pay";
Revision = payout.GetBlob(_jsonSerializerSettings).Revision, }
Rate = rateResult.BidAsk.Ask TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = "Payouts approved",
Severity = StatusMessageModel.StatusSeverity.Success
}); });
if (approveResult != PullPaymentHostedService.PayoutApproval.Result.Ok)
{
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = PullPaymentHostedService.PayoutApproval.GetErrorMessage(approveResult),
Severity = StatusMessageModel.StatusSeverity.Error
});
failed = true;
break;
}
}
if (failed)
{
break; break;
} }
if (command == "approve-pay")
{
goto case "pay";
}
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = "Payouts approved", Severity = StatusMessageModel.StatusSeverity.Success
});
break;
}
case "pay": case "pay":
{
if (handler is { }) return await handler?.InitiatePayment(paymentMethodId, payoutIds);
TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Message = "Paying via this payment method is not supported", Severity = StatusMessageModel.StatusSeverity.Error if (handler is { })
}); return await handler?.InitiatePayment(paymentMethodId, payoutIds);
break; TempData.SetStatusMessageModel(new StatusMessageModel()
}
case "mark-paid":
{
await using var ctx = this._dbContextFactory.CreateContext();
ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var payouts = await GetPayoutsForPaymentMethod(paymentMethodId, ctx, payoutIds, storeId, cancellationToken);
for (int i = 0; i < payouts.Count; i++)
{
var payout = payouts[i];
if (payout.State != PayoutState.AwaitingPayment)
continue;
var result = await _pullPaymentService.MarkPaid(new PayoutPaidRequest()
{ {
PayoutId = payout.Id Message = "Paying via this payment method is not supported",
Severity = StatusMessageModel.StatusSeverity.Error
}); });
if (result != PayoutPaidRequest.PayoutPaidResult.Ok) break;
{
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = PayoutPaidRequest.GetErrorMessage(result),
Severity = StatusMessageModel.StatusSeverity.Error
});
return RedirectToAction(nameof(Payouts), new
{
storeId = storeId,
pullPaymentId = vm.PullPaymentId,
paymentMethodId = paymentMethodId.ToString()
});
}
} }
TempData.SetStatusMessageModel(new StatusMessageModel() case "mark-paid":
{ {
Message = "Payouts marked as paid", Severity = StatusMessageModel.StatusSeverity.Success await using var ctx = this._dbContextFactory.CreateContext();
}); ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
break; var payouts = await GetPayoutsForPaymentMethod(paymentMethodId, ctx, payoutIds, storeId, cancellationToken);
} for (int i = 0; i < payouts.Count; i++)
{
var payout = payouts[i];
if (payout.State != PayoutState.AwaitingPayment)
continue;
var result = await _pullPaymentService.MarkPaid(new PayoutPaidRequest()
{
PayoutId = payout.Id
});
if (result != PayoutPaidRequest.PayoutPaidResult.Ok)
{
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = PayoutPaidRequest.GetErrorMessage(result),
Severity = StatusMessageModel.StatusSeverity.Error
});
return RedirectToAction(nameof(Payouts), new
{
storeId = storeId,
pullPaymentId = vm.PullPaymentId,
paymentMethodId = paymentMethodId.ToString()
});
}
}
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = "Payouts marked as paid",
Severity = StatusMessageModel.StatusSeverity.Success
});
break;
}
case "cancel": case "cancel":
await _pullPaymentService.Cancel( await _pullPaymentService.Cancel(
new PullPaymentHostedService.CancelRequest(payoutIds)); new PullPaymentHostedService.CancelRequest(payoutIds));
TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Message = "Payouts archived", Severity = StatusMessageModel.StatusSeverity.Success Message = "Payouts archived",
Severity = StatusMessageModel.StatusSeverity.Success
}); });
break; break;
} }
@@ -437,9 +445,9 @@ namespace BTCPayServer.Controllers
var vm = this.ParseListQuery(new PayoutsModel var vm = this.ParseListQuery(new PayoutsModel
{ {
PaymentMethods = paymentMethods, PaymentMethods = paymentMethods,
PaymentMethodId = paymentMethodId??paymentMethods.First().ToString(), PaymentMethodId = paymentMethodId ?? paymentMethods.First().ToString(),
PullPaymentId = pullPaymentId, PullPaymentId = pullPaymentId,
PayoutState = payoutState, PayoutState = payoutState,
Skip = skip, Skip = skip,
Count = count Count = count
}); });
@@ -459,11 +467,11 @@ namespace BTCPayServer.Controllers
} }
vm.PayoutStateCount = payoutRequest.GroupBy(data => data.State) vm.PayoutStateCount = payoutRequest.GroupBy(data => data.State)
.Select(e => new {e.Key, Count = e.Count()}) .Select(e => new { e.Key, Count = e.Count() })
.ToDictionary(arg => arg.Key, arg => arg.Count); .ToDictionary(arg => arg.Key, arg => arg.Count);
foreach (PayoutState value in Enum.GetValues(typeof(PayoutState))) foreach (PayoutState value in Enum.GetValues(typeof(PayoutState)))
{ {
if(vm.PayoutStateCount.ContainsKey(value)) if (vm.PayoutStateCount.ContainsKey(value))
continue; continue;
vm.PayoutStateCount.Add(value, 0); vm.PayoutStateCount.Add(value, 0);
} }

View File

@@ -1,10 +1,10 @@
#nullable enable #nullable enable
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Models; using BTCPayServer.Models;
using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Client.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NBitcoin; using NBitcoin;
using NBitcoin.DataEncoders; using NBitcoin.DataEncoders;
@@ -29,20 +29,21 @@ namespace BTCPayServer.Controllers
{ {
var webhooks = await _Repo.GetWebhooks(CurrentStore.Id); var webhooks = await _Repo.GetWebhooks(CurrentStore.Id);
return View(nameof(Webhooks), new WebhooksViewModel() return View(nameof(Webhooks), new WebhooksViewModel()
{
Webhooks = webhooks.Select(async w =>
{ {
Webhooks = webhooks.Select(async w => { var lastDelivery = await LastDeliveryForWebhook(w.Id);
var lastDelivery = await LastDeliveryForWebhook(w.Id); var lastDeliveryBlob = lastDelivery?.GetBlob();
var lastDeliveryBlob = lastDelivery?.GetBlob();
return new WebhooksViewModel.WebhookViewModel() return new WebhooksViewModel.WebhookViewModel()
{ {
Id = w.Id, Id = w.Id,
Url = w.GetBlob().Url, Url = w.GetBlob().Url,
LastDeliveryErrorMessage = lastDeliveryBlob?.ErrorMessage, LastDeliveryErrorMessage = lastDeliveryBlob?.ErrorMessage,
LastDeliveryTimeStamp = lastDelivery?.Timestamp, LastDeliveryTimeStamp = lastDelivery?.Timestamp,
LastDeliverySuccessful = lastDeliveryBlob == null ? true : lastDeliveryBlob.Status == WebhookDeliveryStatus.HttpSuccess, LastDeliverySuccessful = lastDeliveryBlob == null ? true : lastDeliveryBlob.Status == WebhookDeliveryStatus.HttpSuccess,
}; };
} }
).Select(t => t.Result).ToArray() ).Select(t => t.Result).ToArray()
}); });
} }
@@ -135,9 +136,12 @@ namespace BTCPayServer.Controllers
{ {
var result = await WebhookNotificationManager.TestWebhook(CurrentStore.Id, webhookId, viewModel.Type); var result = await WebhookNotificationManager.TestWebhook(CurrentStore.Id, webhookId, viewModel.Type);
if (result.Success) { if (result.Success)
{
TempData[WellKnownTempData.SuccessMessage] = $"{viewModel.Type.ToString()} event delivered successfully! Delivery ID is {result.DeliveryId}"; TempData[WellKnownTempData.SuccessMessage] = $"{viewModel.Type.ToString()} event delivered successfully! Delivery ID is {result.DeliveryId}";
} else { }
else
{
TempData[WellKnownTempData.ErrorMessage] = $"{viewModel.Type.ToString()} event could not be delivered. Error message received: {(result.ErrorMessage ?? "unknown")}"; TempData[WellKnownTempData.ErrorMessage] = $"{viewModel.Type.ToString()} event could not be delivered. Error message received: {(result.ErrorMessage ?? "unknown")}";
} }

View File

@@ -5,6 +5,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.HostedServices; using BTCPayServer.HostedServices;
using BTCPayServer.ModelBinders; using BTCPayServer.ModelBinders;
using BTCPayServer.Models; using BTCPayServer.Models;
@@ -13,7 +14,6 @@ using BTCPayServer.Payments.PayJoin.Sender;
using BTCPayServer.Services; using BTCPayServer.Services;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender;
using NBitcoin.Payment; using NBitcoin.Payment;
using NBXplorer; using NBXplorer;
using NBXplorer.Models; using NBXplorer.Models;

View File

@@ -7,13 +7,16 @@ using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Client; using BTCPayServer.Client;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.HostedServices; using BTCPayServer.HostedServices;
using BTCPayServer.ModelBinders; using BTCPayServer.ModelBinders;
using BTCPayServer.Models; using BTCPayServer.Models;
using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Models.WalletViewModels; using BTCPayServer.Models.WalletViewModels;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Payments.PayJoin;
using BTCPayServer.Services; using BTCPayServer.Services;
using BTCPayServer.Services.Labels; using BTCPayServer.Services.Labels;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
@@ -23,9 +26,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Payments.PayJoin;
using NBXplorer; using NBXplorer;
using NBXplorer.DerivationStrategy; using NBXplorer.DerivationStrategy;
using NBXplorer.Models; using NBXplorer.Models;
@@ -177,7 +177,8 @@ namespace BTCPayServer.Controllers
allColors allColors
.GroupBy(k => k) .GroupBy(k => k)
.OrderBy(k => k.Count()) .OrderBy(k => k.Count())
.ThenBy(k => { .ThenBy(k =>
{
var indexInColorScheme = Array.IndexOf(LabelColorScheme, k.Key); var indexInColorScheme = Array.IndexOf(LabelColorScheme, k.Key);
// Ensures that any label color which may not be in our label color scheme is given the least priority // Ensures that any label color which may not be in our label color scheme is given the least priority
@@ -492,7 +493,7 @@ namespace BTCPayServer.Controllers
.ToArray(); .ToArray();
var balance = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation); var balance = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation);
model.NBXSeedAvailable = await GetSeed(walletId, network) != null; model.NBXSeedAvailable = await GetSeed(walletId, network) != null;
var Balance= await balance; var Balance = await balance;
model.CurrentBalance = (Balance.Available ?? Balance.Total).GetValue(network); model.CurrentBalance = (Balance.Available ?? Balance.Total).GetValue(network);
if (Balance.Immature is null) if (Balance.Immature is null)
model.ImmatureBalance = 0; model.ImmatureBalance = 0;
@@ -777,9 +778,9 @@ namespace BTCPayServer.Controllers
try try
{ {
vm.Outputs.Add(new WalletSendModel.TransactionOutput() vm.Outputs.Add(new WalletSendModel.TransactionOutput()
{ {
DestinationAddress = BitcoinAddress.Create(bip21, network.NBitcoinNetwork).ToString() DestinationAddress = BitcoinAddress.Create(bip21, network.NBitcoinNetwork).ToString()
} }
); );
} }
catch catch
@@ -934,7 +935,7 @@ namespace BTCPayServer.Controllers
{ {
EnforceLowR = !(viewModel.SigningContext?.EnforceLowR is false) EnforceLowR = !(viewModel.SigningContext?.EnforceLowR is false)
}; };
var changed = psbt.PSBTChanged( () => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath)); var changed = psbt.PSBTChanged(() => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath));
if (!changed) if (!changed)
{ {
ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Impossible to sign the transaction. Probable causes: Incorrect account key path in wallet settings or PSBT already signed."); ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Impossible to sign the transaction. Probable causes: Incorrect account key path in wallet settings or PSBT already signed.");
@@ -1075,35 +1076,35 @@ namespace BTCPayServer.Controllers
switch (command) switch (command)
{ {
case "prune": case "prune":
{
var result = await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode).PruneAsync(derivationScheme.AccountDerivation, new PruneRequest(), cancellationToken);
if (result.TotalPruned == 0)
{ {
TempData[WellKnownTempData.SuccessMessage] = "The wallet is already pruned"; var result = await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode).PruneAsync(derivationScheme.AccountDerivation, new PruneRequest(), cancellationToken);
} if (result.TotalPruned == 0)
else {
{ TempData[WellKnownTempData.SuccessMessage] = "The wallet is already pruned";
TempData[WellKnownTempData.SuccessMessage] = }
$"The wallet has been successfully pruned ({result.TotalPruned} transactions have been removed from the history)"; else
} {
TempData[WellKnownTempData.SuccessMessage] =
$"The wallet has been successfully pruned ({result.TotalPruned} transactions have been removed from the history)";
}
return RedirectToAction(nameof(WalletTransactions), new { walletId }); return RedirectToAction(nameof(WalletTransactions), new { walletId });
} }
case "clear" when User.IsInRole(Roles.ServerAdmin): case "clear" when User.IsInRole(Roles.ServerAdmin):
{
if (Version.TryParse(_dashboard.Get(walletId.CryptoCode)?.Status?.Version ?? "0.0.0.0", out var v) &&
v < new Version(2, 2, 4))
{ {
TempData[WellKnownTempData.ErrorMessage] = "This version of NBXplorer doesn't support this operation, please upgrade to 2.2.4 or above"; if (Version.TryParse(_dashboard.Get(walletId.CryptoCode)?.Status?.Version ?? "0.0.0.0", out var v) &&
v < new Version(2, 2, 4))
{
TempData[WellKnownTempData.ErrorMessage] = "This version of NBXplorer doesn't support this operation, please upgrade to 2.2.4 or above";
}
else
{
await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode)
.WipeAsync(derivationScheme.AccountDerivation, cancellationToken);
TempData[WellKnownTempData.SuccessMessage] = "The transactions have been wiped out, to restore your balance, rescan the wallet.";
}
return RedirectToAction(nameof(WalletTransactions), new { walletId });
} }
else
{
await ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode)
.WipeAsync(derivationScheme.AccountDerivation, cancellationToken);
TempData[WellKnownTempData.SuccessMessage] = "The transactions have been wiped out, to restore your balance, rescan the wallet.";
}
return RedirectToAction(nameof(WalletTransactions), new { walletId });
}
default: default:
return NotFound(); return NotFound();
} }

View File

@@ -5,7 +5,7 @@ namespace BTCPayServer.Data
{ {
public class AddressClaimDestination : IBitcoinLikeClaimDestination public class AddressClaimDestination : IBitcoinLikeClaimDestination
{ {
public BitcoinAddress _bitcoinAddress; public BitcoinAddress _bitcoinAddress;
public AddressClaimDestination(BitcoinAddress bitcoinAddress) public AddressClaimDestination(BitcoinAddress bitcoinAddress)
{ {

View File

@@ -97,7 +97,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
{ {
return null; return null;
} }
var raw = JObject.Parse(Encoding.UTF8.GetString(payout.Proof)); var raw = JObject.Parse(Encoding.UTF8.GetString(payout.Proof));
if (raw.TryGetValue("proofType", StringComparison.InvariantCultureIgnoreCase, out var proofType) && if (raw.TryGetValue("proofType", StringComparison.InvariantCultureIgnoreCase, out var proofType) &&
proofType.Value<string>() == ManualPayoutProof.Type) proofType.Value<string>() == ManualPayoutProof.Type)
{ {
@@ -106,14 +106,15 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
var res = raw.ToObject<PayoutTransactionOnChainBlob>( var res = raw.ToObject<PayoutTransactionOnChainBlob>(
JsonSerializer.Create(_jsonSerializerSettings.GetSerializer(paymentMethodId.CryptoCode))); JsonSerializer.Create(_jsonSerializerSettings.GetSerializer(paymentMethodId.CryptoCode)));
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode); var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
if (res == null) return null; if (res == null)
return null;
res.LinkTemplate = network.BlockExplorerLink; res.LinkTemplate = network.BlockExplorerLink;
return res; return res;
} }
public void StartBackgroundCheck(Action<Type[]> subscribe) public void StartBackgroundCheck(Action<Type[]> subscribe)
{ {
subscribe(new[] {typeof(NewOnChainTransactionEvent), typeof(NewBlockEvent)}); subscribe(new[] { typeof(NewOnChainTransactionEvent), typeof(NewBlockEvent) });
} }
public async Task BackgroundCheck(object o) public async Task BackgroundCheck(object o)
@@ -172,7 +173,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
.ToListAsync()).Where(data => .ToListAsync()).Where(data =>
PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) && PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) &&
CanHandle(paymentMethodId)) CanHandle(paymentMethodId))
.Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple=> tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == false); .Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple => tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == false);
foreach (var valueTuple in payouts) foreach (var valueTuple in payouts)
{ {
valueTuple.Item2.Accounted = true; valueTuple.Item2.Accounted = true;
@@ -199,7 +200,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
.ToListAsync()).Where(data => .ToListAsync()).Where(data =>
PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) && PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) &&
CanHandle(paymentMethodId)) CanHandle(paymentMethodId))
.Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple=> tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == true); .Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple => tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == true);
foreach (var valueTuple in payouts) foreach (var valueTuple in payouts)
{ {
valueTuple.Item2.TransactionId = null; valueTuple.Item2.TransactionId = null;
@@ -225,7 +226,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
.Where(id => id.PaymentType == BitcoinPaymentType.Instance)); .Where(id => id.PaymentType == BitcoinPaymentType.Instance));
} }
public async Task<IActionResult> InitiatePayment(PaymentMethodId paymentMethodId ,string[] payoutIds) public async Task<IActionResult> InitiatePayment(PaymentMethodId paymentMethodId, string[] payoutIds)
{ {
await using var ctx = this._dbContextFactory.CreateContext(); await using var ctx = this._dbContextFactory.CreateContext();
ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
@@ -262,12 +263,12 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
break; break;
} }
} }
if(bip21.Any()) if (bip21.Any())
return new RedirectToActionResult("WalletSend", "Wallets", new {walletId = new WalletId(storeId, paymentMethodId.CryptoCode).ToString(), bip21}); return new RedirectToActionResult("WalletSend", "Wallets", new { walletId = new WalletId(storeId, paymentMethodId.CryptoCode).ToString(), bip21 });
return new RedirectToActionResult("Payouts", "Wallets", new return new RedirectToActionResult("Payouts", "Wallets", new
{ {
walletId = new WalletId(storeId, paymentMethodId.CryptoCode).ToString(), walletId = new WalletId(storeId, paymentMethodId.CryptoCode).ToString(),
pullPaymentId = pullPaymentIds.Length == 1? pullPaymentIds.First(): null pullPaymentId = pullPaymentIds.Length == 1 ? pullPaymentIds.First() : null
}); });
} }
@@ -390,9 +391,10 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
var isInternal = storeWalletMatched is { }; var isInternal = storeWalletMatched is { };
var proof = ParseProof(payout) as PayoutTransactionOnChainBlob ?? var proof = ParseProof(payout) as PayoutTransactionOnChainBlob ??
new PayoutTransactionOnChainBlob() {Accounted = isInternal}; new PayoutTransactionOnChainBlob() { Accounted = isInternal };
var txId = newTransaction.NewTransactionEvent.TransactionData.TransactionHash; var txId = newTransaction.NewTransactionEvent.TransactionData.TransactionHash;
if (!proof.Candidates.Add(txId)) return; if (!proof.Candidates.Add(txId))
return;
if (isInternal) if (isInternal)
{ {
payout.State = PayoutState.InProgress; payout.State = PayoutState.InProgress;

View File

@@ -5,7 +5,7 @@ using Newtonsoft.Json;
namespace BTCPayServer.Data namespace BTCPayServer.Data
{ {
public class PayoutTransactionOnChainBlob: IPayoutProof public class PayoutTransactionOnChainBlob : IPayoutProof
{ {
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))] [JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
public uint256 TransactionId { get; set; } public uint256 TransactionId { get; set; }

View File

@@ -5,8 +5,8 @@ using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using PayoutData = BTCPayServer.Data.PayoutData;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using PayoutData = BTCPayServer.Data.PayoutData;
using StoreData = BTCPayServer.Data.StoreData; using StoreData = BTCPayServer.Data.StoreData;
public interface IPayoutHandler public interface IPayoutHandler

View File

@@ -1,6 +1,6 @@
namespace BTCPayServer.Data.Payouts.LightningLike namespace BTCPayServer.Data.Payouts.LightningLike
{ {
public class LNURLPayClaimDestinaton: ILightningLikeLikeClaimDestination public class LNURLPayClaimDestinaton : ILightningLikeLikeClaimDestination
{ {
public LNURLPayClaimDestinaton(string lnurl) public LNURLPayClaimDestinaton(string lnurl)
{ {

View File

@@ -76,7 +76,8 @@ namespace BTCPayServer.Data.Payouts.LightningLike
.ToListAsync()) .ToListAsync())
.Where(payout => .Where(payout =>
{ {
if (approvedStores.TryGetValue(payout.PullPaymentData.StoreId, out var value)) return value; if (approvedStores.TryGetValue(payout.PullPaymentData.StoreId, out var value))
return value;
value = payout.PullPaymentData.StoreData.UserStores value = payout.PullPaymentData.StoreData.UserStores
.Any(store => store.Role == StoreRoles.Owner && store.ApplicationUserId == userId); .Any(store => store.Role == StoreRoles.Owner && store.ApplicationUserId == userId);
approvedStores.Add(payout.PullPaymentData.StoreId, value); approvedStores.Add(payout.PullPaymentData.StoreId, value);
@@ -98,7 +99,9 @@ namespace BTCPayServer.Data.Payouts.LightningLike
return new ConfirmVM() return new ConfirmVM()
{ {
Amount = blob.CryptoAmount.Value, Destination = blob.Destination, PayoutId = payoutData.Id Amount = blob.CryptoAmount.Value,
Destination = blob.Destination,
PayoutId = payoutData.Id
}; };
}).ToList(); }).ToList();
return View(vm); return View(vm);
@@ -136,7 +139,9 @@ namespace BTCPayServer.Data.Payouts.LightningLike
{ {
results.Add(new ResultVM() results.Add(new ResultVM()
{ {
PayoutId = payoutData.Id, Result = result.Result, Destination = payoutBlob.Destination PayoutId = payoutData.Id,
Result = result.Result,
Destination = payoutBlob.Destination
}); });
payoutData.State = PayoutState.Completed; payoutData.State = PayoutState.Completed;
} }
@@ -144,12 +149,14 @@ namespace BTCPayServer.Data.Payouts.LightningLike
{ {
results.Add(new ResultVM() results.Add(new ResultVM()
{ {
PayoutId = payoutData.Id, Result = result.Result, Destination = payoutBlob.Destination PayoutId = payoutData.Id,
Result = result.Result,
Destination = payoutBlob.Destination
}); });
} }
} }
var authorizedForInternalNode = (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded; var authorizedForInternalNode = (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded;
foreach (var payoutDatas in payouts) foreach (var payoutDatas in payouts)
{ {
var store = payoutDatas.First().PullPaymentData.StoreData; var store = payoutDatas.First().PullPaymentData.StoreData;
@@ -249,7 +256,9 @@ namespace BTCPayServer.Data.Payouts.LightningLike
{ {
results.Add(new ResultVM() results.Add(new ResultVM()
{ {
PayoutId = payoutData.Id, Result = PayResult.Error, Destination = blob.Destination PayoutId = payoutData.Id,
Result = PayResult.Error,
Destination = blob.Destination
}); });
} }
} }

View File

@@ -92,7 +92,8 @@ namespace BTCPayServer.Data.Payouts.LightningLike
? new BoltInvoiceClaimDestination(destination, invoice) ? new BoltInvoiceClaimDestination(destination, invoice)
: null; : null;
if (result == null) return (null, "A valid BOLT11 invoice (with 30+ day expiry) or LNURL Pay or Lightning address was not provided."); if (result == null)
return (null, "A valid BOLT11 invoice (with 30+ day expiry) or LNURL Pay or Lightning address was not provided.");
if (validate && (invoice.ExpiryDate.UtcDateTime - DateTime.UtcNow).Days < 30) if (validate && (invoice.ExpiryDate.UtcDateTime - DateTime.UtcNow).Days < 30)
{ {
return (null, return (null,
@@ -139,7 +140,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
public async Task<IEnumerable<PaymentMethodId>> GetSupportedPaymentMethods(StoreData storeData) public async Task<IEnumerable<PaymentMethodId>> GetSupportedPaymentMethods(StoreData storeData)
{ {
var result = new List<PaymentMethodId>(); var result = new List<PaymentMethodId>();
var methods = storeData.GetEnabledPaymentMethods(_btcPayNetworkProvider).Where(id => id.PaymentId.PaymentType == LightningPaymentType.Instance).OfType<LightningSupportedPaymentMethod>(); var methods = storeData.GetEnabledPaymentMethods(_btcPayNetworkProvider).Where(id => id.PaymentId.PaymentType == LightningPaymentType.Instance).OfType<LightningSupportedPaymentMethod>();
foreach (LightningSupportedPaymentMethod supportedPaymentMethod in methods) foreach (LightningSupportedPaymentMethod supportedPaymentMethod in methods)
{ {
if (!supportedPaymentMethod.IsInternalNode) if (!supportedPaymentMethod.IsInternalNode)
@@ -150,7 +151,8 @@ namespace BTCPayServer.Data.Payouts.LightningLike
foreach (UserStore storeDataUserStore in storeData.UserStores) foreach (UserStore storeDataUserStore in storeData.UserStores)
{ {
if (!await _userService.IsAdminUser(storeDataUserStore.ApplicationUserId)) continue; if (!await _userService.IsAdminUser(storeDataUserStore.ApplicationUserId))
continue;
result.Add(supportedPaymentMethod.PaymentId); result.Add(supportedPaymentMethod.PaymentId);
break; break;
} }

View File

@@ -1,6 +1,6 @@
namespace BTCPayServer.Data.Payouts.LightningLike namespace BTCPayServer.Data.Payouts.LightningLike
{ {
public class PayoutLightningBlob: IPayoutProof public class PayoutLightningBlob : IPayoutProof
{ {
public string Bolt11Invoice { get; set; } public string Bolt11Invoice { get; set; }
public string Preimage { get; set; } public string Preimage { get; set; }

View File

@@ -29,7 +29,7 @@ namespace BTCPayServer.Data
public static PaymentMethodId GetPaymentMethodId(this PayoutData data) public static PaymentMethodId GetPaymentMethodId(this PayoutData data)
{ {
return PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId)? paymentMethodId : null; return PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) ? paymentMethodId : null;
} }
public static PayoutBlob GetBlob(this PayoutData data, BTCPayNetworkJsonSerializerSettings serializers) public static PayoutBlob GetBlob(this PayoutData data, BTCPayNetworkJsonSerializerSettings serializers)
{ {
@@ -42,7 +42,7 @@ namespace BTCPayServer.Data
public static void SetProofBlob(this PayoutData data, ManualPayoutProof blob) public static void SetProofBlob(this PayoutData data, ManualPayoutProof blob)
{ {
if(blob is null) if (blob is null)
return; return;
var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(blob)); var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(blob));
// We only update the property if the bytes actually changed, this prevent from hammering the DB too much // We only update the property if the bytes actually changed, this prevent from hammering the DB too much

View File

@@ -4,11 +4,11 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
using NBitcoin; using NBitcoin;
using NBXplorer; using NBXplorer;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using BTCPayServer.Payments.Lightning;
namespace BTCPayServer.Data namespace BTCPayServer.Data
{ {

View File

@@ -37,7 +37,7 @@ namespace BTCPayServer
return (Parse($"{hd.Extkey}{suffix}"), null); return (Parse($"{hd.Extkey}{suffix}"), null);
case PubKeyProvider.Origin origin: case PubKeyProvider.Origin origin:
var innerResult = ExtractFromPkProvider(origin.Inner, suffix); var innerResult = ExtractFromPkProvider(origin.Inner, suffix);
return (innerResult.Item1, new[] {origin.KeyOriginInfo}); return (innerResult.Item1, new[] { origin.KeyOriginInfo });
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
@@ -46,7 +46,7 @@ namespace BTCPayServer
ArgumentNullException.ThrowIfNull(str); ArgumentNullException.ThrowIfNull(str);
str = str.Trim(); str = str.Trim();
var outputDescriptor = OutputDescriptor.Parse(str, Network); var outputDescriptor = OutputDescriptor.Parse(str, Network);
switch(outputDescriptor) switch (outputDescriptor)
{ {
case OutputDescriptor.PK _: case OutputDescriptor.PK _:
case OutputDescriptor.Raw _: case OutputDescriptor.Raw _:
@@ -58,7 +58,7 @@ namespace BTCPayServer
var xpubs = multi.PkProviders.Select(provider => ExtractFromPkProvider(provider)); var xpubs = multi.PkProviders.Select(provider => ExtractFromPkProvider(provider));
return ( return (
Parse( Parse(
$"{multi.Threshold}-of-{(string.Join('-', xpubs.Select(tuple => tuple.Item1.ToString())))}{(multi.IsSorted?"":"-[keeporder]")}"), $"{multi.Threshold}-of-{(string.Join('-', xpubs.Select(tuple => tuple.Item1.ToString())))}{(multi.IsSorted ? "" : "-[keeporder]")}"),
xpubs.SelectMany(tuple => tuple.Item2).ToArray()); xpubs.SelectMany(tuple => tuple.Item2).ToArray());
case OutputDescriptor.PKH pkh: case OutputDescriptor.PKH pkh:
return ExtractFromPkProvider(pkh.PkProvider, "-[legacy]"); return ExtractFromPkProvider(pkh.PkProvider, "-[legacy]");
@@ -82,7 +82,7 @@ namespace BTCPayServer
case OutputDescriptor.WSH wsh: case OutputDescriptor.WSH wsh:
if (wsh.Inner is OutputDescriptor.Multi) if (wsh.Inner is OutputDescriptor.Multi)
{ {
return ParseOutputDescriptor(wsh.Inner.ToString()); return ParseOutputDescriptor(wsh.Inner.ToString());
} }
throw new FormatException("wsh descriptors are only supported with multisig"); throw new FormatException("wsh descriptors are only supported with multisig");
default: default:

View File

@@ -115,7 +115,7 @@ namespace BTCPayServer
return Subscribe(eventType, s); return Subscribe(eventType, s);
} }
public IEventAggregatorSubscription Subscribe(Type eventType, Action<IEventAggregatorSubscription, object> subscription) public IEventAggregatorSubscription Subscribe(Type eventType, Action<IEventAggregatorSubscription, object> subscription)
{ {
var s = new Subscription(this, eventType); var s = new Subscription(this, eventType);
s.Act = (o) => subscription(s, o); s.Act = (o) => subscription(s, o);

View File

@@ -1,4 +1,4 @@
using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Invoices;
namespace BTCPayServer.Events namespace BTCPayServer.Events
{ {

View File

@@ -14,7 +14,7 @@ namespace BTCPayServer.Events
InvoiceEntity = invoiceEntity; InvoiceEntity = invoiceEntity;
} }
public string InvoiceId => InvoiceEntity.Id; public string InvoiceId => InvoiceEntity.Id;
public override string ToString() public override string ToString()
{ {

View File

@@ -12,6 +12,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.BIP78.Sender;
using BTCPayServer.Configuration; using BTCPayServer.Configuration;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Lightning; using BTCPayServer.Lightning;
@@ -29,7 +30,6 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender;
using NBitcoin.Payment; using NBitcoin.Payment;
using NBitpayClient; using NBitpayClient;
using NBXplorer.DerivationStrategy; using NBXplorer.DerivationStrategy;
@@ -564,7 +564,7 @@ namespace BTCPayServer
var defaultSettings = BTCPayDefaultSettings.GetDefaultSettings(networkType); var defaultSettings = BTCPayDefaultSettings.GetDefaultSettings(networkType);
dataDirectories.DataDir = configuration["datadir"] ?? defaultSettings.DefaultDataDirectory; dataDirectories.DataDir = configuration["datadir"] ?? defaultSettings.DefaultDataDirectory;
dataDirectories.PluginDir = configuration["plugindir"] ?? defaultSettings.DefaultPluginDirectory; dataDirectories.PluginDir = configuration["plugindir"] ?? defaultSettings.DefaultPluginDirectory;
dataDirectories.StorageDir = Path.Combine(dataDirectories.DataDir , Storage.Services.Providers.FileSystemStorage.FileSystemFileProviderService.LocalStorageDirectoryName); dataDirectories.StorageDir = Path.Combine(dataDirectories.DataDir, Storage.Services.Providers.FileSystemStorage.FileSystemFileProviderService.LocalStorageDirectoryName);
dataDirectories.TempStorageDir = Path.Combine(dataDirectories.StorageDir, "tmp"); dataDirectories.TempStorageDir = Path.Combine(dataDirectories.StorageDir, "tmp");
return dataDirectories; return dataDirectories;
} }

View File

@@ -38,7 +38,7 @@ namespace BTCPayServer
.Replace("-", "", StringComparison.InvariantCulture) .Replace("-", "", StringComparison.InvariantCulture)
.PadLeft(divisibility, '0'); .PadLeft(divisibility, '0');
amt = amt.Length == divisibility ? $"0.{amt}" : amt.Insert(amt.Length - divisibility, "."); amt = amt.Length == divisibility ? $"0.{amt}" : amt.Insert(amt.Length - divisibility, ".");
return decimal.Parse($"{(negative? "-": string.Empty)}{amt}", CultureInfo.InvariantCulture); return decimal.Parse($"{(negative ? "-" : string.Empty)}{amt}", CultureInfo.InvariantCulture);
} }
public static string ShowMoney(this IMoney money, BTCPayNetwork network) public static string ShowMoney(this IMoney money, BTCPayNetwork network)
{ {

Some files were not shown because too many files have changed in this diff Show More