mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Code formatting updates (#4502)
* Editorconfig: Add space_before_self_closing setting This was a difference between the way dotnet-format and Rider format code. See https://www.jetbrains.com/help/rider/EditorConfig_Index.html * Editorconfig: Keep 4 spaces indentation for Swagger JSON files They are all formatted that way, let's keep it like that. * Apply dotnet-format, mostly white-space related changes
This commit is contained in:
@@ -11,10 +11,14 @@ insert_final_newline = true
|
|||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
|
space_before_self_closing = true
|
||||||
|
|
||||||
[*.json]
|
[*.json]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[swagger*.json]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
# C# files
|
# C# files
|
||||||
[*.cs]
|
[*.cs]
|
||||||
# New line preferences
|
# New line preferences
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
namespace BTCPayServer.Abstractions.Contracts;
|
namespace BTCPayServer.Abstractions.Contracts;
|
||||||
|
|
||||||
public interface IScopeProvider
|
public interface IScopeProvider
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace BTCPayServer.Abstractions.Contracts;
|
namespace BTCPayServer.Abstractions.Contracts;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class AssetQuoteResult
|
|||||||
|
|
||||||
public AssetQuoteResult() { }
|
public AssetQuoteResult() { }
|
||||||
|
|
||||||
public AssetQuoteResult(string fromAsset, string toAsset,decimal bid, decimal ask)
|
public AssetQuoteResult(string fromAsset, string toAsset, decimal bid, decimal ask)
|
||||||
{
|
{
|
||||||
FromAsset = fromAsset;
|
FromAsset = fromAsset;
|
||||||
ToAsset = toAsset;
|
ToAsset = toAsset;
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ namespace BTCPayServer.Abstractions.Custodians;
|
|||||||
|
|
||||||
public class AssetBalancesUnavailableException : CustodianApiException
|
public class AssetBalancesUnavailableException : CustodianApiException
|
||||||
{
|
{
|
||||||
|
|
||||||
public AssetBalancesUnavailableException(System.Exception e) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {e.Message}", e)
|
public AssetBalancesUnavailableException(System.Exception e) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {e.Message}", e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
namespace BTCPayServer.Abstractions.Custodians;
|
namespace BTCPayServer.Abstractions.Custodians;
|
||||||
public class CustodianApiException: Exception {
|
public class CustodianApiException : Exception
|
||||||
|
{
|
||||||
public int HttpStatus { get; }
|
public int HttpStatus { get; }
|
||||||
public string Code { get; }
|
public string Code { get; }
|
||||||
|
|
||||||
@@ -9,7 +10,8 @@ public class CustodianApiException: Exception {
|
|||||||
HttpStatus = httpStatus;
|
HttpStatus = httpStatus;
|
||||||
Code = code;
|
Code = code;
|
||||||
}
|
}
|
||||||
public CustodianApiException( int httpStatus, string code, string message) : this(httpStatus, code, message, null)
|
|
||||||
|
public CustodianApiException(int httpStatus, string code, string message) : this(httpStatus, code, message, null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
namespace BTCPayServer.Abstractions.Custodians;
|
namespace BTCPayServer.Abstractions.Custodians;
|
||||||
|
|
||||||
public class CustodianFeatureNotImplementedException: CustodianApiException
|
public class CustodianFeatureNotImplementedException : CustodianApiException
|
||||||
{
|
{
|
||||||
public CustodianFeatureNotImplementedException(string message) : base(400, "not-implemented", message)
|
public CustodianFeatureNotImplementedException(string message) : base(400, "not-implemented", message)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,4 @@ public class InsufficientFundsException : CustodianApiException
|
|||||||
public InsufficientFundsException(string message) : base(400, "insufficient-funds", message)
|
public InsufficientFundsException(string message) : base(400, "insufficient-funds", message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ public class TradeNotFoundException : CustodianApiException
|
|||||||
{
|
{
|
||||||
private string tradeId { get; }
|
private string tradeId { get; }
|
||||||
|
|
||||||
public TradeNotFoundException(string tradeId) : base(404,"trade-not-found","Could not find trade ID " + tradeId)
|
public TradeNotFoundException(string tradeId) : base(404, "trade-not-found", "Could not find trade ID " + tradeId)
|
||||||
{
|
{
|
||||||
this.tradeId = tradeId;
|
this.tradeId = tradeId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace BTCPayServer.Abstractions.Custodians;
|
namespace BTCPayServer.Abstractions.Custodians;
|
||||||
|
|
||||||
public class WrongTradingPairException: CustodianApiException
|
public class WrongTradingPairException : CustodianApiException
|
||||||
{
|
{
|
||||||
public const int HttpCode = 404;
|
public const int HttpCode = 404;
|
||||||
public WrongTradingPairException(string fromAsset, string toAsset) : base(HttpCode, "wrong-trading-pair", $"Cannot find a trading pair for converting {fromAsset} into {toAsset}.")
|
public WrongTradingPairException(string fromAsset, string toAsset) : base(HttpCode, "wrong-trading-pair", $"Cannot find a trading pair for converting {fromAsset} into {toAsset}.")
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ namespace BTCPayServer.Abstractions.Custodians;
|
|||||||
|
|
||||||
public interface ICanTrade
|
public interface ICanTrade
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of tradable asset pairs, or NULL if the custodian cannot trade/convert assets. if thr asset pair contains fiat, fiat is always put last. If both assets are a cyrptocode or both are fiat, the pair is written alphabetically. Always in uppercase. Example: ["BTC/EUR","BTC/USD", "EUR/USD", "BTC/ETH",...]
|
* A list of tradable asset pairs, or NULL if the custodian cannot trade/convert assets. if thr asset pair contains fiat, fiat is always put last. If both assets are a cyrptocode or both are fiat, the pair is written alphabetically. Always in uppercase. Example: ["BTC/EUR","BTC/USD", "EUR/USD", "BTC/ETH",...]
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ namespace BTCPayServer.Abstractions.Extensions;
|
|||||||
|
|
||||||
public static class StringExtensions
|
public static class StringExtensions
|
||||||
{
|
{
|
||||||
|
|
||||||
public static bool IsValidFileName(this string fileName)
|
public static bool IsValidFileName(this string fileName)
|
||||||
{
|
{
|
||||||
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
|
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
|
||||||
@@ -41,5 +40,4 @@ public static class StringExtensions
|
|||||||
return str.Substring(0, str.Length - 1);
|
return str.Substring(0, str.Length - 1);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class Form
|
|||||||
|
|
||||||
if (field.Fields.Any())
|
if (field.Fields.Any())
|
||||||
{
|
{
|
||||||
names.AddRange(GetAllNames(field.Fields).Select(s => $"{prefix}{s}" ));
|
names.AddRange(GetAllNames(field.Fields).Select(s => $"{prefix}{s}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +139,9 @@ public class Form
|
|||||||
|
|
||||||
result.TryAdd(name, values);
|
result.TryAdd(name, values);
|
||||||
|
|
||||||
if (keylessValue is not Dictionary<string, object> dict) continue;
|
if (keylessValue is not Dictionary<string, object> dict)
|
||||||
foreach (KeyValuePair<string,object> keyValuePair in dict)
|
continue;
|
||||||
|
foreach (KeyValuePair<string, object> keyValuePair in dict)
|
||||||
{
|
{
|
||||||
result.TryAdd(keyValuePair.Key, keyValuePair.Value);
|
result.TryAdd(keyValuePair.Key, keyValuePair.Value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace BTCPayServer.Client
|
|||||||
parameters.Add("includeNeighbourData", v);
|
parameters.Add("includeNeighbourData", v);
|
||||||
var response =
|
var response =
|
||||||
await _httpClient.SendAsync(
|
await _httpClient.SendAsync(
|
||||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", parameters, method:HttpMethod.Get), token);
|
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", parameters, method: HttpMethod.Get), token);
|
||||||
return await HandleResponse<OnChainWalletObjectData[]>(response);
|
return await HandleResponse<OnChainWalletObjectData[]>(response);
|
||||||
}
|
}
|
||||||
public virtual async Task RemoveOnChainWalletObject(string storeId, string cryptoCode, OnChainWalletObjectId objectId,
|
public virtual async Task RemoveOnChainWalletObject(string storeId, string cryptoCode, OnChainWalletObjectId objectId,
|
||||||
@@ -47,7 +47,7 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
var response =
|
var response =
|
||||||
await _httpClient.SendAsync(
|
await _httpClient.SendAsync(
|
||||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}", method:HttpMethod.Delete), token);
|
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}", method: HttpMethod.Delete), token);
|
||||||
await HandleResponse(response);
|
await HandleResponse(response);
|
||||||
}
|
}
|
||||||
public virtual async Task<OnChainWalletObjectData> AddOrUpdateOnChainWalletObject(string storeId, string cryptoCode, AddOnChainWalletObjectRequest request,
|
public virtual async Task<OnChainWalletObjectData> AddOrUpdateOnChainWalletObject(string storeId, string cryptoCode, AddOnChainWalletObjectRequest request,
|
||||||
@@ -55,7 +55,7 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
var response =
|
var response =
|
||||||
await _httpClient.SendAsync(
|
await _httpClient.SendAsync(
|
||||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", method:HttpMethod.Post, bodyPayload: request), token);
|
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", method: HttpMethod.Post, bodyPayload: request), token);
|
||||||
return await HandleResponse<OnChainWalletObjectData>(response);
|
return await HandleResponse<OnChainWalletObjectData>(response);
|
||||||
}
|
}
|
||||||
public virtual async Task AddOrUpdateOnChainWalletLink(string storeId, string cryptoCode,
|
public virtual async Task AddOrUpdateOnChainWalletLink(string storeId, string cryptoCode,
|
||||||
@@ -65,7 +65,7 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
var response =
|
var response =
|
||||||
await _httpClient.SendAsync(
|
await _httpClient.SendAsync(
|
||||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links", method:HttpMethod.Post, bodyPayload: request), token);
|
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links", method: HttpMethod.Post, bodyPayload: request), token);
|
||||||
await HandleResponse(response);
|
await HandleResponse(response);
|
||||||
}
|
}
|
||||||
public virtual async Task RemoveOnChainWalletLinks(string storeId, string cryptoCode,
|
public virtual async Task RemoveOnChainWalletLinks(string storeId, string cryptoCode,
|
||||||
@@ -75,7 +75,7 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
var response =
|
var response =
|
||||||
await _httpClient.SendAsync(
|
await _httpClient.SendAsync(
|
||||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links/{link.Type}/{link.Id}", method:HttpMethod.Delete), token);
|
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links/{link.Type}/{link.Id}", method: HttpMethod.Delete), token);
|
||||||
await HandleResponse(response);
|
await HandleResponse(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
query.Add(nameof(statusFilter), statusFilter);
|
query.Add(nameof(statusFilter), statusFilter);
|
||||||
}
|
}
|
||||||
if (labelFilter != null) {
|
if (labelFilter != null)
|
||||||
|
{
|
||||||
query.Add(nameof(labelFilter), labelFilter);
|
query.Add(nameof(labelFilter), labelFilter);
|
||||||
}
|
}
|
||||||
var response =
|
var response =
|
||||||
|
|||||||
@@ -24,24 +24,24 @@ namespace BTCPayServer.Client
|
|||||||
public virtual async Task<IEnumerable<LightningAutomatedPayoutSettings>> GetStoreLightningAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
|
public virtual async Task<IEnumerable<LightningAutomatedPayoutSettings>> GetStoreLightningAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory{(paymentMethod is null? string.Empty: $"/{paymentMethod}")}"), token);
|
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory{(paymentMethod is null ? string.Empty : $"/{paymentMethod}")}"), token);
|
||||||
return await HandleResponse<IEnumerable<LightningAutomatedPayoutSettings>>(response);
|
return await HandleResponse<IEnumerable<LightningAutomatedPayoutSettings>>(response);
|
||||||
}
|
}
|
||||||
public virtual async Task<LightningAutomatedPayoutSettings> UpdateStoreLightningAutomatedPayoutProcessors(string storeId, string paymentMethod,LightningAutomatedPayoutSettings request, CancellationToken token = default)
|
public virtual async Task<LightningAutomatedPayoutSettings> UpdateStoreLightningAutomatedPayoutProcessors(string storeId, string paymentMethod, LightningAutomatedPayoutSettings request, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory/{paymentMethod}",null, request, HttpMethod.Put ), token);
|
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory/{paymentMethod}", null, request, HttpMethod.Put), token);
|
||||||
return await HandleResponse<LightningAutomatedPayoutSettings>(response);
|
return await HandleResponse<LightningAutomatedPayoutSettings>(response);
|
||||||
}
|
}
|
||||||
public virtual async Task<OnChainAutomatedPayoutSettings> UpdateStoreOnChainAutomatedPayoutProcessors(string storeId, string paymentMethod,OnChainAutomatedPayoutSettings request, CancellationToken token = default)
|
public virtual async Task<OnChainAutomatedPayoutSettings> UpdateStoreOnChainAutomatedPayoutProcessors(string storeId, string paymentMethod, OnChainAutomatedPayoutSettings request, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory/{paymentMethod}",null, request, HttpMethod.Put ), token);
|
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory/{paymentMethod}", null, request, HttpMethod.Put), token);
|
||||||
return await HandleResponse<OnChainAutomatedPayoutSettings>(response);
|
return await HandleResponse<OnChainAutomatedPayoutSettings>(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<IEnumerable<OnChainAutomatedPayoutSettings>> GetStoreOnChainAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
|
public virtual async Task<IEnumerable<OnChainAutomatedPayoutSettings>> GetStoreOnChainAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory{(paymentMethod is null? string.Empty: $"/{paymentMethod}")}"), token);
|
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory{(paymentMethod is null ? string.Empty : $"/{paymentMethod}")}"), token);
|
||||||
return await HandleResponse<IEnumerable<OnChainAutomatedPayoutSettings>>(response);
|
return await HandleResponse<IEnumerable<OnChainAutomatedPayoutSettings>>(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
using var response = await _httpClient.SendAsync(
|
using var response = await _httpClient.SendAsync(
|
||||||
CreateHttpRequest($"api/v1/stores/{storeId}/rates/configuration/preview", bodyPayload: request,
|
CreateHttpRequest($"api/v1/stores/{storeId}/rates/configuration/preview", bodyPayload: request,
|
||||||
queryPayload: new Dictionary<string, object>() {{"currencyPair", currencyPair}},
|
queryPayload: new Dictionary<string, object>() { { "currencyPair", currencyPair } },
|
||||||
method: HttpMethod.Post),
|
method: HttpMethod.Post),
|
||||||
token);
|
token);
|
||||||
return await HandleResponse<List<StoreRatePreviewResult>>(response);
|
return await HandleResponse<List<StoreRatePreviewResult>>(response);
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ namespace BTCPayServer.Client
|
|||||||
public virtual async Task<bool> LockUser(string idOrEmail, bool locked, CancellationToken token = default)
|
public virtual async Task<bool> LockUser(string idOrEmail, bool locked, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}/lock", null,
|
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}/lock", null,
|
||||||
new LockUserRequest {Locked = locked}, HttpMethod.Post), token);
|
new LockUserRequest { Locked = locked }, HttpMethod.Post), token);
|
||||||
await HandleResponse(response);
|
await HandleResponse(response);
|
||||||
return response.IsSuccessStatusCode;
|
return response.IsSuccessStatusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<ApplicationUserData[]> GetUsers( CancellationToken token = default)
|
public virtual async Task<ApplicationUserData[]> GetUsers(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/", null, HttpMethod.Get), token);
|
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/", null, HttpMethod.Get), token);
|
||||||
return await HandleResponse<ApplicationUserData[]>(response);
|
return await HandleResponse<ApplicationUserData[]>(response);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace BTCPayServer.Client.Models;
|
namespace BTCPayServer.Client.Models;
|
||||||
|
|
||||||
public class CustodianAccountResponse: CustodianAccountData
|
public class CustodianAccountResponse : CustodianAccountData
|
||||||
{
|
{
|
||||||
public IDictionary<string, decimal> AssetBalances { get; set; }
|
public IDictionary<string, decimal> AssetBalances { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using BTCPayServer.Client.JsonConverters;
|
using BTCPayServer.Client.JsonConverters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BTCPayServer.Client;
|
namespace BTCPayServer.Client;
|
||||||
|
|
||||||
public class LockUserRequest
|
public class LockUserRequest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using BTCPayServer.Client.JsonConverters;
|
using BTCPayServer.Client.JsonConverters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BTCPayServer.Client.Models;
|
namespace BTCPayServer.Client.Models;
|
||||||
|
|
||||||
public class RateSource
|
public class RateSource
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BTCPayServer.Client.Models;
|
namespace BTCPayServer.Client.Models;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BTCPayServer.Client.Models;
|
namespace BTCPayServer.Client.Models;
|
||||||
|
|
||||||
public class StoreRateResult
|
public class StoreRateResult
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace BTCPayServer
|
|||||||
internal Task ProcessTask;
|
internal Task ProcessTask;
|
||||||
public async Task Process(CancellationToken cancellationToken)
|
public async Task Process(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
while (Chan.Reader.TryRead(out var item))
|
while (Chan.Reader.TryRead(out var item))
|
||||||
{
|
{
|
||||||
await item(cancellationToken);
|
await item(cancellationToken);
|
||||||
@@ -52,7 +52,7 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
lock (_Queues)
|
lock (_Queues)
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
if (stopped)
|
if (stopped)
|
||||||
return;
|
return;
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace BTCPayServer.Data
|
|||||||
public DbSet<WalletTransactionData> WalletTransactions { get; set; }
|
public DbSet<WalletTransactionData> WalletTransactions { get; set; }
|
||||||
public DbSet<WebhookDeliveryData> WebhookDeliveries { get; set; }
|
public DbSet<WebhookDeliveryData> WebhookDeliveries { get; set; }
|
||||||
public DbSet<WebhookData> Webhooks { get; set; }
|
public DbSet<WebhookData> Webhooks { get; set; }
|
||||||
public DbSet<LightningAddressData> LightningAddresses{ get; set; }
|
public DbSet<LightningAddressData> LightningAddresses { get; set; }
|
||||||
public DbSet<PayoutProcessorData> PayoutProcessors { get; set; }
|
public DbSet<PayoutProcessorData> PayoutProcessors { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace BTCPayServer.Data;
|
namespace BTCPayServer.Data;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace BTCPayServer.Data.Data;
|
namespace BTCPayServer.Data.Data;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Rating;
|
using BTCPayServer.Rating;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace BTCPayServer.Services.Rates
|
|||||||
{
|
{
|
||||||
await new SynchronizationContextRemover();
|
await new SynchronizationContextRemover();
|
||||||
|
|
||||||
var exchangeAPI = (T) await ExchangeAPI.GetExchangeAPIAsync<T>();
|
var exchangeAPI = (T)await ExchangeAPI.GetExchangeAPIAsync<T>();
|
||||||
exchangeAPI.RequestMaker = new HttpClientRequestMaker(exchangeAPI, _httpClient, cancellationToken);
|
exchangeAPI.RequestMaker = new HttpClientRequestMaker(exchangeAPI, _httpClient, cancellationToken);
|
||||||
var rates = await exchangeAPI.GetTickersAsync();
|
var rates = await exchangeAPI.GetTickersAsync();
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ namespace BTCPayServer.Services.Rates
|
|||||||
var result = JsonConvert.DeserializeObject<T>(stringResult);
|
var result = JsonConvert.DeserializeObject<T>(stringResult);
|
||||||
if (result is JToken json)
|
if (result is JToken json)
|
||||||
{
|
{
|
||||||
if (!(json is JArray) && json["result"] is JObject {Count: > 0} pairResult)
|
if (!(json is JArray) && json["result"] is JObject { Count: > 0 } pairResult)
|
||||||
{
|
{
|
||||||
return (T)(object)(pairResult);
|
return (T)(object)(pairResult);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Rating;
|
using BTCPayServer.Rating;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Rates
|
namespace BTCPayServer.Services.Rates
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ retry:
|
|||||||
wait.UntilJsIsReady();
|
wait.UntilJsIsReady();
|
||||||
|
|
||||||
int retriesLeft = 4;
|
int retriesLeft = 4;
|
||||||
retry:
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var el = driver.FindElement(selector);
|
var el = driver.FindElement(selector);
|
||||||
@@ -176,7 +176,8 @@ retry:
|
|||||||
catch (NoSuchElementException) when (retriesLeft > 0)
|
catch (NoSuchElementException) when (retriesLeft > 0)
|
||||||
{
|
{
|
||||||
retriesLeft--;
|
retriesLeft--;
|
||||||
if (waitTime != null) Thread.Sleep(waitTime.Value);
|
if (waitTime != null)
|
||||||
|
Thread.Sleep(waitTime.Value);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
wait.UntilJsIsReady();
|
wait.UntilJsIsReady();
|
||||||
|
|||||||
@@ -1077,7 +1077,8 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
MultiProcessingQueueTest t = new MultiProcessingQueueTest();
|
MultiProcessingQueueTest t = new MultiProcessingQueueTest();
|
||||||
t.Tcs = new TaskCompletionSource();
|
t.Tcs = new TaskCompletionSource();
|
||||||
q.Enqueue(queueName, async (cancellationToken) => {
|
q.Enqueue(queueName, async (cancellationToken) =>
|
||||||
|
{
|
||||||
t.Started = true;
|
t.Started = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1774,10 +1775,10 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
foreach (var policy in Policies.AllPolicies)
|
foreach (var policy in Policies.AllPolicies)
|
||||||
{
|
{
|
||||||
Assert.True( UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.ContainsKey(policy));
|
Assert.True(UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.ContainsKey(policy));
|
||||||
if (Policies.IsStorePolicy(policy))
|
if (Policies.IsStorePolicy(policy))
|
||||||
{
|
{
|
||||||
Assert.True( UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.ContainsKey($"{policy}:"));
|
Assert.True(UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.ContainsKey($"{policy}:"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1804,8 +1805,8 @@ namespace BTCPayServer.Tests
|
|||||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var newBlob = new Serializer(null).ToString(blob).Replace( "paymentMethod\":\"BTC\"","paymentMethod\":\"ETH_ZYC\"");
|
var newBlob = new Serializer(null).ToString(blob).Replace("paymentMethod\":\"BTC\"", "paymentMethod\":\"ETH_ZYC\"");
|
||||||
Assert.Empty(StoreDataExtensions.GetStoreBlob(new StoreData() {StoreBlob = newBlob}).PaymentMethodCriteria);
|
Assert.Empty(StoreDataExtensions.GetStoreBlob(new StoreData() { StoreBlob = newBlob }).PaymentMethodCriteria);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ using BTCPayServer.Lightning;
|
|||||||
using BTCPayServer.Models.InvoicingModels;
|
using BTCPayServer.Models.InvoicingModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
using BTCPayServer.Services.Custodian.Client.MockCustodian;
|
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Custodian.Client.MockCustodian;
|
||||||
using BTCPayServer.Services.Notifications;
|
using BTCPayServer.Services.Notifications;
|
||||||
using BTCPayServer.Services.Notifications.Blobs;
|
using BTCPayServer.Services.Notifications.Blobs;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
@@ -206,7 +206,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
// Test validation for creating the app
|
// Test validation for creating the app
|
||||||
await AssertValidationError(new[] { "AppName" },
|
await AssertValidationError(new[] { "AppName" },
|
||||||
async () => await client.CreatePointOfSaleApp(user.StoreId, new CreatePointOfSaleAppRequest() {}));
|
async () => await client.CreatePointOfSaleApp(user.StoreId, new CreatePointOfSaleAppRequest() { }));
|
||||||
await AssertValidationError(new[] { "AppName" },
|
await AssertValidationError(new[] { "AppName" },
|
||||||
async () => await client.CreatePointOfSaleApp(
|
async () => await client.CreatePointOfSaleApp(
|
||||||
user.StoreId,
|
user.StoreId,
|
||||||
@@ -261,7 +261,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal("PointOfSale", app.AppType);
|
Assert.Equal("PointOfSale", app.AppType);
|
||||||
|
|
||||||
// Make sure we return a 404 if we try to get an app that doesn't exist
|
// Make sure we return a 404 if we try to get an app that doesn't exist
|
||||||
await AssertHttpError(404, async () => {
|
await AssertHttpError(404, async () =>
|
||||||
|
{
|
||||||
await client.GetApp("some random ID lol");
|
await client.GetApp("some random ID lol");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -284,7 +285,8 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
// Test deleting the newly created app
|
// Test deleting the newly created app
|
||||||
await client.DeleteApp(retrievedApp.Id);
|
await client.DeleteApp(retrievedApp.Id);
|
||||||
await AssertHttpError(404, async () => {
|
await AssertHttpError(404, async () =>
|
||||||
|
{
|
||||||
await client.GetApp(retrievedApp.Id);
|
await client.GetApp(retrievedApp.Id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -301,7 +303,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
// Test validation for creating the app
|
// Test validation for creating the app
|
||||||
await AssertValidationError(new[] { "AppName" },
|
await AssertValidationError(new[] { "AppName" },
|
||||||
async () => await client.CreateCrowdfundApp(user.StoreId, new CreateCrowdfundAppRequest() {}));
|
async () => await client.CreateCrowdfundApp(user.StoreId, new CreateCrowdfundAppRequest() { }));
|
||||||
await AssertValidationError(new[] { "AppName" },
|
await AssertValidationError(new[] { "AppName" },
|
||||||
async () => await client.CreateCrowdfundApp(
|
async () => await client.CreateCrowdfundApp(
|
||||||
user.StoreId,
|
user.StoreId,
|
||||||
@@ -347,7 +349,7 @@ namespace BTCPayServer.Tests
|
|||||||
new CreateCrowdfundAppRequest()
|
new CreateCrowdfundAppRequest()
|
||||||
{
|
{
|
||||||
AppName = "good name",
|
AppName = "good name",
|
||||||
AnimationColors = new string[] {}
|
AnimationColors = new string[] { }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -461,8 +463,8 @@ namespace BTCPayServer.Tests
|
|||||||
var adminClient = await adminUser.CreateClient(Policies.Unrestricted);
|
var adminClient = await adminUser.CreateClient(Policies.Unrestricted);
|
||||||
|
|
||||||
// Should be 404 if user doesn't exist
|
// Should be 404 if user doesn't exist
|
||||||
await AssertHttpError(404,async () => await adminClient.GetUserByIdOrEmail("non_existing_id"));
|
await AssertHttpError(404, async () => await adminClient.GetUserByIdOrEmail("non_existing_id"));
|
||||||
await AssertHttpError(404,async () => await adminClient.GetUserByIdOrEmail("doesnotexist@example.com"));
|
await AssertHttpError(404, async () => await adminClient.GetUserByIdOrEmail("doesnotexist@example.com"));
|
||||||
|
|
||||||
// Try listing all users, should be fine
|
// Try listing all users, should be fine
|
||||||
await adminClient.GetUsers();
|
await adminClient.GetUsers();
|
||||||
@@ -487,8 +489,8 @@ namespace BTCPayServer.Tests
|
|||||||
await goodClient.GetUsers();
|
await goodClient.GetUsers();
|
||||||
|
|
||||||
// Should be 404 if user doesn't exist
|
// Should be 404 if user doesn't exist
|
||||||
await AssertHttpError(404,async () => await goodClient.GetUserByIdOrEmail("non_existing_id"));
|
await AssertHttpError(404, async () => await goodClient.GetUserByIdOrEmail("non_existing_id"));
|
||||||
await AssertHttpError(404,async () => await goodClient.GetUserByIdOrEmail("doesnotexist@example.com"));
|
await AssertHttpError(404, async () => await goodClient.GetUserByIdOrEmail("doesnotexist@example.com"));
|
||||||
|
|
||||||
// Try listing all users, should be fine
|
// Try listing all users, should be fine
|
||||||
await goodClient.GetUsers();
|
await goodClient.GetUsers();
|
||||||
@@ -510,20 +512,20 @@ namespace BTCPayServer.Tests
|
|||||||
var badClient = await goodUser.CreateClient(Policies.CanCreateInvoice);
|
var badClient = await goodUser.CreateClient(Policies.CanCreateInvoice);
|
||||||
|
|
||||||
// Try listing all users, should be fine
|
// Try listing all users, should be fine
|
||||||
await AssertHttpError(403,async () => await badClient.GetUsers());
|
await AssertHttpError(403, async () => await badClient.GetUsers());
|
||||||
|
|
||||||
// Should be 404 if user doesn't exist
|
// Should be 404 if user doesn't exist
|
||||||
await AssertHttpError(403,async () => await badClient.GetUserByIdOrEmail("non_existing_id"));
|
await AssertHttpError(403, async () => await badClient.GetUserByIdOrEmail("non_existing_id"));
|
||||||
await AssertHttpError(403,async () => await badClient.GetUserByIdOrEmail("doesnotexist@example.com"));
|
await AssertHttpError(403, async () => await badClient.GetUserByIdOrEmail("doesnotexist@example.com"));
|
||||||
|
|
||||||
// Try listing all users, should be fine
|
// Try listing all users, should be fine
|
||||||
await AssertHttpError(403,async () => await badClient.GetUsers());
|
await AssertHttpError(403, async () => await badClient.GetUsers());
|
||||||
|
|
||||||
// Try loading 1 user by ID. Loading myself.
|
// Try loading 1 user by ID. Loading myself.
|
||||||
await AssertHttpError(403,async () => await badClient.GetUserByIdOrEmail(badUser.UserId));
|
await AssertHttpError(403, async () => await badClient.GetUserByIdOrEmail(badUser.UserId));
|
||||||
|
|
||||||
// Try loading 1 user by email. Loading myself.
|
// Try loading 1 user by email. Loading myself.
|
||||||
await AssertHttpError(403,async () => await badClient.GetUserByIdOrEmail(badUser.Email));
|
await AssertHttpError(403, async () => await badClient.GetUserByIdOrEmail(badUser.Email));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -929,21 +931,21 @@ namespace BTCPayServer.Tests
|
|||||||
});
|
});
|
||||||
await AssertAPIError("invalid-state", async () =>
|
await AssertAPIError("invalid-state", async () =>
|
||||||
{
|
{
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = PayoutState.Completed});
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() { State = PayoutState.Completed });
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await client.ApprovePayout(storeId, payout.Id, new ApprovePayoutRequest());
|
await client.ApprovePayout(storeId, payout.Id, new ApprovePayoutRequest());
|
||||||
|
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = PayoutState.Completed});
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() { State = PayoutState.Completed });
|
||||||
Assert.Equal(PayoutState.Completed,(await client.GetStorePayouts(storeId,false)).Single(data => data.Id == payout.Id ).State );
|
Assert.Equal(PayoutState.Completed, (await client.GetStorePayouts(storeId, false)).Single(data => data.Id == payout.Id).State);
|
||||||
Assert.Null((await client.GetStorePayouts(storeId,false)).Single(data => data.Id == payout.Id ).PaymentProof );
|
Assert.Null((await client.GetStorePayouts(storeId, false)).Single(data => data.Id == payout.Id).PaymentProof);
|
||||||
|
|
||||||
foreach (var state in new []{ PayoutState.AwaitingApproval, PayoutState.Cancelled, PayoutState.Completed, PayoutState.AwaitingApproval, PayoutState.InProgress})
|
foreach (var state in new[] { PayoutState.AwaitingApproval, PayoutState.Cancelled, PayoutState.Completed, PayoutState.AwaitingApproval, PayoutState.InProgress })
|
||||||
{
|
{
|
||||||
await AssertAPIError("invalid-state", async () =>
|
await AssertAPIError("invalid-state", async () =>
|
||||||
{
|
{
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = state});
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() { State = state });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
payout = await client.CreatePayout(storeId, new CreatePayoutThroughStoreRequest()
|
payout = await client.CreatePayout(storeId, new CreatePayoutThroughStoreRequest()
|
||||||
@@ -957,49 +959,65 @@ namespace BTCPayServer.Tests
|
|||||||
payout = await client.GetStorePayout(storeId, payout.Id);
|
payout = await client.GetStorePayout(storeId, payout.Id);
|
||||||
Assert.NotNull(payout);
|
Assert.NotNull(payout);
|
||||||
Assert.Equal(PayoutState.AwaitingPayment, payout.State);
|
Assert.Equal(PayoutState.AwaitingPayment, payout.State);
|
||||||
await AssertValidationError(new []{"PaymentProof"}, async () =>
|
await AssertValidationError(new[] { "PaymentProof" }, async () =>
|
||||||
{
|
{
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = PayoutState.Completed, PaymentProof = JObject.FromObject(new
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest()
|
||||||
|
{
|
||||||
|
State = PayoutState.Completed,
|
||||||
|
PaymentProof = JObject.FromObject(new
|
||||||
{
|
{
|
||||||
test = "zyx"
|
test = "zyx"
|
||||||
})});
|
})
|
||||||
});
|
});
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = PayoutState.InProgress, PaymentProof = JObject.FromObject(new
|
});
|
||||||
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest()
|
||||||
|
{
|
||||||
|
State = PayoutState.InProgress,
|
||||||
|
PaymentProof = JObject.FromObject(new
|
||||||
{
|
{
|
||||||
proofType = "external-proof"
|
proofType = "external-proof"
|
||||||
})});
|
})
|
||||||
|
});
|
||||||
payout = await client.GetStorePayout(storeId, payout.Id);
|
payout = await client.GetStorePayout(storeId, payout.Id);
|
||||||
Assert.NotNull(payout);
|
Assert.NotNull(payout);
|
||||||
Assert.Equal(PayoutState.InProgress, payout.State);
|
Assert.Equal(PayoutState.InProgress, payout.State);
|
||||||
Assert.True(payout.PaymentProof.TryGetValue("proofType", out var savedType));
|
Assert.True(payout.PaymentProof.TryGetValue("proofType", out var savedType));
|
||||||
Assert.Equal("external-proof",savedType);
|
Assert.Equal("external-proof", savedType);
|
||||||
|
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = PayoutState.AwaitingPayment, PaymentProof = JObject.FromObject(new
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest()
|
||||||
|
{
|
||||||
|
State = PayoutState.AwaitingPayment,
|
||||||
|
PaymentProof = JObject.FromObject(new
|
||||||
{
|
{
|
||||||
proofType = "external-proof",
|
proofType = "external-proof",
|
||||||
id="finality proof",
|
id = "finality proof",
|
||||||
link="proof.com"
|
link = "proof.com"
|
||||||
})});
|
})
|
||||||
|
});
|
||||||
payout = await client.GetStorePayout(storeId, payout.Id);
|
payout = await client.GetStorePayout(storeId, payout.Id);
|
||||||
Assert.NotNull(payout);
|
Assert.NotNull(payout);
|
||||||
Assert.Null(payout.PaymentProof);
|
Assert.Null(payout.PaymentProof);
|
||||||
Assert.Equal(PayoutState.AwaitingPayment, payout.State);
|
Assert.Equal(PayoutState.AwaitingPayment, payout.State);
|
||||||
|
|
||||||
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest() {State = PayoutState.Completed, PaymentProof = JObject.FromObject(new
|
await client.MarkPayout(storeId, payout.Id, new MarkPayoutRequest()
|
||||||
|
{
|
||||||
|
State = PayoutState.Completed,
|
||||||
|
PaymentProof = JObject.FromObject(new
|
||||||
{
|
{
|
||||||
proofType = "external-proof",
|
proofType = "external-proof",
|
||||||
id="finality proof",
|
id = "finality proof",
|
||||||
link="proof.com"
|
link = "proof.com"
|
||||||
})});
|
})
|
||||||
|
});
|
||||||
payout = await client.GetStorePayout(storeId, payout.Id);
|
payout = await client.GetStorePayout(storeId, payout.Id);
|
||||||
Assert.NotNull(payout);
|
Assert.NotNull(payout);
|
||||||
Assert.Equal(PayoutState.Completed, payout.State);
|
Assert.Equal(PayoutState.Completed, payout.State);
|
||||||
Assert.True(payout.PaymentProof.TryGetValue("proofType", out savedType));
|
Assert.True(payout.PaymentProof.TryGetValue("proofType", out savedType));
|
||||||
Assert.True(payout.PaymentProof.TryGetValue("link", out var savedLink));
|
Assert.True(payout.PaymentProof.TryGetValue("link", out var savedLink));
|
||||||
Assert.True(payout.PaymentProof.TryGetValue("id", out var savedId));
|
Assert.True(payout.PaymentProof.TryGetValue("id", out var savedId));
|
||||||
Assert.Equal("external-proof",savedType);
|
Assert.Equal("external-proof", savedType);
|
||||||
Assert.Equal("finality proof",savedId);
|
Assert.Equal("finality proof", savedId);
|
||||||
Assert.Equal("proof.com",savedLink);
|
Assert.Equal("proof.com", savedLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTimeOffset RoundSeconds(DateTimeOffset dateTimeOffset)
|
private DateTimeOffset RoundSeconds(DateTimeOffset dateTimeOffset)
|
||||||
@@ -1593,14 +1611,16 @@ namespace BTCPayServer.Tests
|
|||||||
// test validation that the invoice exists
|
// test validation that the invoice exists
|
||||||
await AssertHttpError(404, async () =>
|
await AssertHttpError(404, async () =>
|
||||||
{
|
{
|
||||||
await client.RefundInvoice(user.StoreId, "lol fake invoice id", new RefundInvoiceRequest() {
|
await client.RefundInvoice(user.StoreId, "lol fake invoice id", new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.RateThen
|
RefundVariant = RefundVariant.RateThen
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// test validation error for when invoice is not yet in the state in which it can be refunded
|
// test validation error for when invoice is not yet in the state in which it can be refunded
|
||||||
var apiError = await AssertAPIError("non-refundable", () => client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
var apiError = await AssertAPIError("non-refundable", () => client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.RateThen
|
RefundVariant = RefundVariant.RateThen
|
||||||
}));
|
}));
|
||||||
@@ -1613,14 +1633,16 @@ namespace BTCPayServer.Tests
|
|||||||
});
|
});
|
||||||
|
|
||||||
// need to set the status to the one in which we can actually refund the invoice
|
// need to set the status to the one in which we can actually refund the invoice
|
||||||
await client.MarkInvoiceStatus(user.StoreId, invoice.Id, new MarkInvoiceStatusRequest() {
|
await client.MarkInvoiceStatus(user.StoreId, invoice.Id, new MarkInvoiceStatusRequest()
|
||||||
|
{
|
||||||
Status = InvoiceStatus.Settled
|
Status = InvoiceStatus.Settled
|
||||||
});
|
});
|
||||||
|
|
||||||
// test validation for the payment method
|
// test validation for the payment method
|
||||||
var validationError = await AssertValidationError(new[] { "PaymentMethod" }, async () =>
|
var validationError = await AssertValidationError(new[] { "PaymentMethod" }, async () =>
|
||||||
{
|
{
|
||||||
await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = "fake payment method",
|
PaymentMethod = "fake payment method",
|
||||||
RefundVariant = RefundVariant.RateThen
|
RefundVariant = RefundVariant.RateThen
|
||||||
});
|
});
|
||||||
@@ -1628,7 +1650,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Contains("PaymentMethod: Please select one of the payment methods which were available for the original invoice", validationError.Message);
|
Assert.Contains("PaymentMethod: Please select one of the payment methods which were available for the original invoice", validationError.Message);
|
||||||
|
|
||||||
// test RefundVariant.RateThen
|
// test RefundVariant.RateThen
|
||||||
var pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
var pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.RateThen
|
RefundVariant = RefundVariant.RateThen
|
||||||
});
|
});
|
||||||
@@ -1638,7 +1661,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(pp.Name, $"Refund {invoice.Id}");
|
Assert.Equal(pp.Name, $"Refund {invoice.Id}");
|
||||||
|
|
||||||
// test RefundVariant.CurrentRate
|
// test RefundVariant.CurrentRate
|
||||||
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.CurrentRate
|
RefundVariant = RefundVariant.CurrentRate
|
||||||
});
|
});
|
||||||
@@ -1647,7 +1671,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(1, pp.Amount);
|
Assert.Equal(1, pp.Amount);
|
||||||
|
|
||||||
// test RefundVariant.Fiat
|
// test RefundVariant.Fiat
|
||||||
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.Fiat,
|
RefundVariant = RefundVariant.Fiat,
|
||||||
Name = "my test name"
|
Name = "my test name"
|
||||||
@@ -1660,7 +1685,8 @@ namespace BTCPayServer.Tests
|
|||||||
// test RefundVariant.Custom
|
// test RefundVariant.Custom
|
||||||
validationError = await AssertValidationError(new[] { "CustomAmount", "CustomCurrency" }, async () =>
|
validationError = await AssertValidationError(new[] { "CustomAmount", "CustomCurrency" }, async () =>
|
||||||
{
|
{
|
||||||
await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.Custom,
|
RefundVariant = RefundVariant.Custom,
|
||||||
});
|
});
|
||||||
@@ -1668,7 +1694,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Contains("CustomAmount: Amount must be greater than 0", validationError.Message);
|
Assert.Contains("CustomAmount: Amount must be greater than 0", validationError.Message);
|
||||||
Assert.Contains("CustomCurrency: Invalid currency", validationError.Message);
|
Assert.Contains("CustomCurrency: Invalid currency", validationError.Message);
|
||||||
|
|
||||||
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.Custom,
|
RefundVariant = RefundVariant.Custom,
|
||||||
CustomAmount = 69420,
|
CustomAmount = 69420,
|
||||||
@@ -1679,7 +1706,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(69420, pp.Amount);
|
Assert.Equal(69420, pp.Amount);
|
||||||
|
|
||||||
// should auto-approve if currencies match
|
// should auto-approve if currencies match
|
||||||
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest() {
|
pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
|
||||||
|
{
|
||||||
PaymentMethod = method.PaymentMethod,
|
PaymentMethod = method.PaymentMethod,
|
||||||
RefundVariant = RefundVariant.Custom,
|
RefundVariant = RefundVariant.Custom,
|
||||||
CustomAmount = 0.00069420m,
|
CustomAmount = 0.00069420m,
|
||||||
@@ -2171,7 +2199,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.NotEmpty(merchantInvoices);
|
Assert.NotEmpty(merchantInvoices);
|
||||||
Assert.Empty(merchantPendingInvoices);
|
Assert.Empty(merchantPendingInvoices);
|
||||||
// if the test ran too many times the invoice might be on a later page
|
// if the test ran too many times the invoice might be on a later page
|
||||||
if (merchantInvoices.Length < 100) Assert.Contains(merchantInvoices, i => i.Id == merchantInvoice.Id);
|
if (merchantInvoices.Length < 100)
|
||||||
|
Assert.Contains(merchantInvoices, i => i.Id == merchantInvoice.Id);
|
||||||
|
|
||||||
// Amount received might be bigger because of internal implementation shit from lightning
|
// Amount received might be bigger because of internal implementation shit from lightning
|
||||||
Assert.True(LightMoney.Satoshis(1000) <= invoice.AmountReceived);
|
Assert.True(LightMoney.Satoshis(1000) <= invoice.AmountReceived);
|
||||||
@@ -2765,7 +2794,8 @@ namespace BTCPayServer.Tests
|
|||||||
// transaction patch tests
|
// transaction patch tests
|
||||||
var patchedTransaction = await client.PatchOnChainWalletTransaction(
|
var patchedTransaction = await client.PatchOnChainWalletTransaction(
|
||||||
walletId.StoreId, walletId.CryptoCode, txdata.TransactionHash.ToString(),
|
walletId.StoreId, walletId.CryptoCode, txdata.TransactionHash.ToString(),
|
||||||
new PatchOnChainTransactionRequest() {
|
new PatchOnChainTransactionRequest()
|
||||||
|
{
|
||||||
Comment = "test comment",
|
Comment = "test comment",
|
||||||
Labels = new List<string>
|
Labels = new List<string>
|
||||||
{
|
{
|
||||||
@@ -2895,13 +2925,13 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
var users = await client.GetStoreUsers(user.StoreId);
|
var users = await client.GetStoreUsers(user.StoreId);
|
||||||
var storeuser = Assert.Single(users);
|
var storeuser = Assert.Single(users);
|
||||||
Assert.Equal(user.UserId,storeuser.UserId);
|
Assert.Equal(user.UserId, storeuser.UserId);
|
||||||
Assert.Equal(StoreRoles.Owner,storeuser.Role);
|
Assert.Equal(StoreRoles.Owner, storeuser.Role);
|
||||||
|
|
||||||
var user2= tester.NewAccount();
|
var user2 = tester.NewAccount();
|
||||||
await user2.GrantAccessAsync(false);
|
await user2.GrantAccessAsync(false);
|
||||||
|
|
||||||
var user2Client =await user2.CreateClient(Policies.CanModifyStoreSettings);
|
var user2Client = await user2.CreateClient(Policies.CanModifyStoreSettings);
|
||||||
|
|
||||||
//test no access to api when unrelated to store at all
|
//test no access to api when unrelated to store at all
|
||||||
await AssertPermissionError(Policies.CanModifyStoreSettings, async () => await user2Client.GetStoreUsers(user.StoreId));
|
await AssertPermissionError(Policies.CanModifyStoreSettings, async () => await user2Client.GetStoreUsers(user.StoreId));
|
||||||
@@ -2923,7 +2953,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
|
|
||||||
await client.AddStoreUser(user.StoreId, new StoreUserData() { Role = StoreRoles.Owner, UserId = user2.UserId });
|
await client.AddStoreUser(user.StoreId, new StoreUserData() { Role = StoreRoles.Owner, UserId = user2.UserId });
|
||||||
await AssertAPIError("duplicate-store-user-role",async ()=>
|
await AssertAPIError("duplicate-store-user-role", async () =>
|
||||||
await client.AddStoreUser(user.StoreId,
|
await client.AddStoreUser(user.StoreId,
|
||||||
new StoreUserData() { Role = StoreRoles.Owner, UserId = user2.UserId }));
|
new StoreUserData() { Role = StoreRoles.Owner, UserId = user2.UserId }));
|
||||||
await user2Client.RemoveStoreUser(user.StoreId, user.UserId);
|
await user2Client.RemoveStoreUser(user.StoreId, user.UserId);
|
||||||
@@ -2985,13 +3015,13 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
Assert.True(await adminClient.LockUser(newUser.UserId, true, CancellationToken.None));
|
Assert.True(await adminClient.LockUser(newUser.UserId, true, CancellationToken.None));
|
||||||
Assert.True((await adminClient.GetUserByIdOrEmail(newUser.UserId)).Disabled);
|
Assert.True((await adminClient.GetUserByIdOrEmail(newUser.UserId)).Disabled);
|
||||||
await AssertAPIError("unauthenticated",async () =>
|
await AssertAPIError("unauthenticated", async () =>
|
||||||
{
|
{
|
||||||
await newUserClient.GetCurrentUser();
|
await newUserClient.GetCurrentUser();
|
||||||
});
|
});
|
||||||
var newUserBasicClient = new BTCPayServerClient(newUserClient.Host, newUser.RegisterDetails.Email,
|
var newUserBasicClient = new BTCPayServerClient(newUserClient.Host, newUser.RegisterDetails.Email,
|
||||||
newUser.RegisterDetails.Password);
|
newUser.RegisterDetails.Password);
|
||||||
await AssertAPIError("unauthenticated",async () =>
|
await AssertAPIError("unauthenticated", async () =>
|
||||||
{
|
{
|
||||||
await newUserBasicClient.GetCurrentUser();
|
await newUserBasicClient.GetCurrentUser();
|
||||||
});
|
});
|
||||||
@@ -3037,17 +3067,19 @@ namespace BTCPayServer.Tests
|
|||||||
var payout = await adminClient.CreatePayout(admin.StoreId,
|
var payout = await adminClient.CreatePayout(admin.StoreId,
|
||||||
new CreatePayoutThroughStoreRequest()
|
new CreatePayoutThroughStoreRequest()
|
||||||
{
|
{
|
||||||
Approved = true, PaymentMethod = "BTC_LightningNetwork", Destination = customerInvoice.BOLT11
|
Approved = true,
|
||||||
|
PaymentMethod = "BTC_LightningNetwork",
|
||||||
|
Destination = customerInvoice.BOLT11
|
||||||
});
|
});
|
||||||
Assert.Empty(await adminClient.GetStoreLightningAutomatedPayoutProcessors(admin.StoreId, "BTC_LightningNetwork"));
|
Assert.Empty(await adminClient.GetStoreLightningAutomatedPayoutProcessors(admin.StoreId, "BTC_LightningNetwork"));
|
||||||
await adminClient.UpdateStoreLightningAutomatedPayoutProcessors(admin.StoreId, "BTC_LightningNetwork",
|
await adminClient.UpdateStoreLightningAutomatedPayoutProcessors(admin.StoreId, "BTC_LightningNetwork",
|
||||||
new LightningAutomatedPayoutSettings() {IntervalSeconds = TimeSpan.FromSeconds(2)});
|
new LightningAutomatedPayoutSettings() { IntervalSeconds = TimeSpan.FromSeconds(2) });
|
||||||
Assert.Equal(2, Assert.Single( await adminClient.GetStoreLightningAutomatedPayoutProcessors(admin.StoreId, "BTC_LightningNetwork")).IntervalSeconds.TotalSeconds);
|
Assert.Equal(2, Assert.Single(await adminClient.GetStoreLightningAutomatedPayoutProcessors(admin.StoreId, "BTC_LightningNetwork")).IntervalSeconds.TotalSeconds);
|
||||||
await TestUtils.EventuallyAsync(async () =>
|
await TestUtils.EventuallyAsync(async () =>
|
||||||
{
|
{
|
||||||
var payoutC =
|
var payoutC =
|
||||||
(await adminClient.GetStorePayouts(admin.StoreId, false)).Single(data => data.Id == payout.Id);
|
(await adminClient.GetStorePayouts(admin.StoreId, false)).Single(data => data.Id == payout.Id);
|
||||||
Assert.Equal(PayoutState.Completed , payoutC.State);
|
Assert.Equal(PayoutState.Completed, payoutC.State);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3065,7 +3097,7 @@ namespace BTCPayServer.Tests
|
|||||||
var adminClient = await admin.CreateClient(Policies.Unrestricted);
|
var adminClient = await admin.CreateClient(Policies.Unrestricted);
|
||||||
|
|
||||||
var registeredProcessors = await adminClient.GetPayoutProcessors();
|
var registeredProcessors = await adminClient.GetPayoutProcessors();
|
||||||
Assert.Equal(2,registeredProcessors.Count());
|
Assert.Equal(2, registeredProcessors.Count());
|
||||||
await adminClient.GenerateOnChainWallet(admin.StoreId, "BTC", new GenerateOnChainWalletRequest()
|
await adminClient.GenerateOnChainWallet(admin.StoreId, "BTC", new GenerateOnChainWalletRequest()
|
||||||
{
|
{
|
||||||
SavePrivateKeys = true
|
SavePrivateKeys = true
|
||||||
@@ -3092,7 +3124,7 @@ namespace BTCPayServer.Tests
|
|||||||
Amount = 100,
|
Amount = 100,
|
||||||
Currency = "USD",
|
Currency = "USD",
|
||||||
Name = "pull payment",
|
Name = "pull payment",
|
||||||
PaymentMethods = new []{ "BTC"}
|
PaymentMethods = new[] { "BTC" }
|
||||||
});
|
});
|
||||||
|
|
||||||
var notapprovedPayoutWithPullPayment = await adminClient.CreatePayout(admin.StoreId, new CreatePayoutThroughStoreRequest()
|
var notapprovedPayoutWithPullPayment = await adminClient.CreatePayout(admin.StoreId, new CreatePayoutThroughStoreRequest()
|
||||||
@@ -3120,25 +3152,25 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Empty(payouts.Where(data => data.State == PayoutState.AwaitingApproval));
|
Assert.Empty(payouts.Where(data => data.State == PayoutState.AwaitingApproval));
|
||||||
Assert.Empty(payouts.Where(data => data.PaymentMethodAmount is null));
|
Assert.Empty(payouts.Where(data => data.PaymentMethodAmount is null));
|
||||||
|
|
||||||
Assert.Empty( await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC"));
|
Assert.Empty(await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC"));
|
||||||
|
|
||||||
|
|
||||||
Assert.Empty( await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC"));
|
Assert.Empty(await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC"));
|
||||||
Assert.Empty(await adminClient.GetPayoutProcessors(admin.StoreId));
|
Assert.Empty(await adminClient.GetPayoutProcessors(admin.StoreId));
|
||||||
|
|
||||||
await adminClient.UpdateStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC",
|
await adminClient.UpdateStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC",
|
||||||
new OnChainAutomatedPayoutSettings() {IntervalSeconds = TimeSpan.FromSeconds(100000)});
|
new OnChainAutomatedPayoutSettings() { IntervalSeconds = TimeSpan.FromSeconds(100000) });
|
||||||
Assert.Equal(100000, Assert.Single( await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC")).IntervalSeconds.TotalSeconds);
|
Assert.Equal(100000, Assert.Single(await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC")).IntervalSeconds.TotalSeconds);
|
||||||
|
|
||||||
var tpGen = Assert.Single(await adminClient.GetPayoutProcessors(admin.StoreId));
|
var tpGen = Assert.Single(await adminClient.GetPayoutProcessors(admin.StoreId));
|
||||||
Assert.Equal("BTC", Assert.Single(tpGen.PaymentMethods));
|
Assert.Equal("BTC", Assert.Single(tpGen.PaymentMethods));
|
||||||
//still too poor to process any payouts
|
//still too poor to process any payouts
|
||||||
Assert.Empty( await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC"));
|
Assert.Empty(await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC"));
|
||||||
|
|
||||||
|
|
||||||
await adminClient.RemovePayoutProcessor(admin.StoreId, tpGen.Name, tpGen.PaymentMethods.First());
|
await adminClient.RemovePayoutProcessor(admin.StoreId, tpGen.Name, tpGen.PaymentMethods.First());
|
||||||
|
|
||||||
Assert.Empty( await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC"));
|
Assert.Empty(await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC"));
|
||||||
Assert.Empty(await adminClient.GetPayoutProcessors(admin.StoreId));
|
Assert.Empty(await adminClient.GetPayoutProcessors(admin.StoreId));
|
||||||
|
|
||||||
await tester.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create((await adminClient.GetOnChainWalletReceiveAddress(admin.StoreId, "BTC", true)).Address,
|
await tester.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create((await adminClient.GetOnChainWalletReceiveAddress(admin.StoreId, "BTC", true)).Address,
|
||||||
@@ -3152,8 +3184,8 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(3, payouts.Length);
|
Assert.Equal(3, payouts.Length);
|
||||||
});
|
});
|
||||||
await adminClient.UpdateStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC",
|
await adminClient.UpdateStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC",
|
||||||
new OnChainAutomatedPayoutSettings() {IntervalSeconds = TimeSpan.FromSeconds(5)});
|
new OnChainAutomatedPayoutSettings() { IntervalSeconds = TimeSpan.FromSeconds(5) });
|
||||||
Assert.Equal(5, Assert.Single( await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC")).IntervalSeconds.TotalSeconds);
|
Assert.Equal(5, Assert.Single(await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC")).IntervalSeconds.TotalSeconds);
|
||||||
await TestUtils.EventuallyAsync(async () =>
|
await TestUtils.EventuallyAsync(async () =>
|
||||||
{
|
{
|
||||||
Assert.Equal(2, (await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC")).Count());
|
Assert.Equal(2, (await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC")).Count());
|
||||||
@@ -3284,7 +3316,7 @@ namespace BTCPayServer.Tests
|
|||||||
var allObjects = await client.GetOnChainWalletObjects(admin.StoreId, "BTC");
|
var allObjects = await client.GetOnChainWalletObjects(admin.StoreId, "BTC");
|
||||||
var allTests = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test" });
|
var allTests = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test" });
|
||||||
var twoTests2 = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test", Ids = new[] { "test1", "test2", "test-unk" } });
|
var twoTests2 = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test", Ids = new[] { "test1", "test2", "test-unk" } });
|
||||||
var oneTest = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test", Ids=new[] { "test" } });
|
var oneTest = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test", Ids = new[] { "test" } });
|
||||||
var oneTestWithoutData = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test", Ids = new[] { "test" }, IncludeNeighbourData = false });
|
var oneTestWithoutData = await client.GetOnChainWalletObjects(admin.StoreId, "BTC", new GetWalletObjectsRequest() { Type = "test", Ids = new[] { "test" }, IncludeNeighbourData = false });
|
||||||
|
|
||||||
Assert.Equal(4, allObjects.Length);
|
Assert.Equal(4, allObjects.Length);
|
||||||
@@ -3338,11 +3370,11 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
Assert.Equal(0.9m,
|
Assert.Equal(0.9m,
|
||||||
Assert.Single(await clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId,
|
Assert.Single(await clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId,
|
||||||
new StoreRateConfiguration() {IsCustomScript = true, EffectiveScript = "BTC_XYZ = 1;", Spread = 10m,},
|
new StoreRateConfiguration() { IsCustomScript = true, EffectiveScript = "BTC_XYZ = 1;", Spread = 10m, },
|
||||||
new[] {"BTC_XYZ"})).Rate);
|
new[] { "BTC_XYZ" })).Rate);
|
||||||
|
|
||||||
Assert.True((await clientBasic.UpdateStoreRateConfiguration(user.StoreId,
|
Assert.True((await clientBasic.UpdateStoreRateConfiguration(user.StoreId,
|
||||||
new StoreRateConfiguration() { IsCustomScript = true, EffectiveScript = "BTC_XYZ = 1", Spread = 10m,}))
|
new StoreRateConfiguration() { IsCustomScript = true, EffectiveScript = "BTC_XYZ = 1", Spread = 10m, }))
|
||||||
.IsCustomScript);
|
.IsCustomScript);
|
||||||
|
|
||||||
config = await clientBasic.GetStoreRateConfiguration(user.StoreId);
|
config = await clientBasic.GetStoreRateConfiguration(user.StoreId);
|
||||||
@@ -3354,7 +3386,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
Assert.NotNull((await clientBasic.GetStoreRateConfiguration(user.StoreId)).EffectiveScript);
|
Assert.NotNull((await clientBasic.GetStoreRateConfiguration(user.StoreId)).EffectiveScript);
|
||||||
Assert.NotNull((await clientBasic.UpdateStoreRateConfiguration(user.StoreId,
|
Assert.NotNull((await clientBasic.UpdateStoreRateConfiguration(user.StoreId,
|
||||||
new StoreRateConfiguration() { IsCustomScript = false, PreferredSource = "coingecko"}))
|
new StoreRateConfiguration() { IsCustomScript = false, PreferredSource = "coingecko" }))
|
||||||
.PreferredSource);
|
.PreferredSource);
|
||||||
|
|
||||||
config = await clientBasic.GetStoreRateConfiguration(user.StoreId);
|
config = await clientBasic.GetStoreRateConfiguration(user.StoreId);
|
||||||
@@ -3480,10 +3512,10 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
Assert.Equal(singleAdminCustodianAccount.CustodianCode, custodian.Code);
|
Assert.Equal(singleAdminCustodianAccount.CustodianCode, custodian.Code);
|
||||||
|
|
||||||
// Wrong store ID
|
// Wrong store ID
|
||||||
await AssertApiError(403, "missing-permission",async () => await adminClient.GetCustodianAccount("WRONG-STORE-ID", accountId));
|
await AssertApiError(403, "missing-permission", async () => await adminClient.GetCustodianAccount("WRONG-STORE-ID", accountId));
|
||||||
|
|
||||||
// Wrong account ID
|
// Wrong account ID
|
||||||
await AssertApiError(404, "custodian-account-not-found",async () => await adminClient.GetCustodianAccount(storeId, "WRONG-ACCOUNT-ID"));
|
await AssertApiError(404, "custodian-account-not-found", async () => await adminClient.GetCustodianAccount(storeId, "WRONG-ACCOUNT-ID"));
|
||||||
|
|
||||||
// Manager can see, including config
|
// Manager can see, including config
|
||||||
var singleManagerCustodianAccount = await managerClient.GetCustodianAccount(storeId, accountId);
|
var singleManagerCustodianAccount = await managerClient.GetCustodianAccount(storeId, accountId);
|
||||||
@@ -3599,7 +3631,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
|
|
||||||
|
|
||||||
// Test: Get Asset Balances
|
// Test: Get Asset Balances
|
||||||
var custodianAccountWithBalances = await adminClient.GetCustodianAccount(storeId, accountId,true);
|
var custodianAccountWithBalances = await adminClient.GetCustodianAccount(storeId, accountId, true);
|
||||||
Assert.NotNull(custodianAccountWithBalances);
|
Assert.NotNull(custodianAccountWithBalances);
|
||||||
Assert.NotNull(custodianAccountWithBalances.AssetBalances);
|
Assert.NotNull(custodianAccountWithBalances.AssetBalances);
|
||||||
Assert.Equal(4, custodianAccountWithBalances.AssetBalances.Count);
|
Assert.Equal(4, custodianAccountWithBalances.AssetBalances.Count);
|
||||||
@@ -3613,7 +3645,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
Assert.Equal(MockCustodian.BalanceUSD, custodianAccountWithBalances.AssetBalances["USD"]);
|
Assert.Equal(MockCustodian.BalanceUSD, custodianAccountWithBalances.AssetBalances["USD"]);
|
||||||
|
|
||||||
// Test: Get Asset Balances omitted if we choose so
|
// Test: Get Asset Balances omitted if we choose so
|
||||||
var custodianAccountWithoutBalances = await adminClient.GetCustodianAccount(storeId, accountId,false);
|
var custodianAccountWithoutBalances = await adminClient.GetCustodianAccount(storeId, accountId, false);
|
||||||
Assert.NotNull(custodianAccountWithoutBalances);
|
Assert.NotNull(custodianAccountWithoutBalances);
|
||||||
Assert.Null(custodianAccountWithoutBalances.AssetBalances);
|
Assert.Null(custodianAccountWithoutBalances.AssetBalances);
|
||||||
|
|
||||||
@@ -3640,7 +3672,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
|
|
||||||
|
|
||||||
// Test: Trade, unauth
|
// Test: Trade, unauth
|
||||||
var tradeRequest = new TradeRequestData {FromAsset = MockCustodian.TradeFromAsset, ToAsset = MockCustodian.TradeToAsset, Qty = MockCustodian.TradeQtyBought.ToString(CultureInfo.InvariantCulture)};
|
var tradeRequest = new TradeRequestData { FromAsset = MockCustodian.TradeFromAsset, ToAsset = MockCustodian.TradeToAsset, Qty = MockCustodian.TradeQtyBought.ToString(CultureInfo.InvariantCulture) };
|
||||||
await AssertHttpError(401, async () => await unauthClient.MarketTradeCustodianAccountAsset(storeId, accountId, tradeRequest));
|
await AssertHttpError(401, async () => await unauthClient.MarketTradeCustodianAccountAsset(storeId, accountId, tradeRequest));
|
||||||
|
|
||||||
// Test: Trade, auth, but wrong permission
|
// Test: Trade, auth, but wrong permission
|
||||||
@@ -3654,30 +3686,30 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
Assert.Equal(MockCustodian.TradeId, newTradeResult.TradeId);
|
Assert.Equal(MockCustodian.TradeId, newTradeResult.TradeId);
|
||||||
Assert.Equal(tradeRequest.FromAsset, newTradeResult.FromAsset);
|
Assert.Equal(tradeRequest.FromAsset, newTradeResult.FromAsset);
|
||||||
Assert.Equal(tradeRequest.ToAsset, newTradeResult.ToAsset);
|
Assert.Equal(tradeRequest.ToAsset, newTradeResult.ToAsset);
|
||||||
Assert.NotNull( newTradeResult.LedgerEntries);
|
Assert.NotNull(newTradeResult.LedgerEntries);
|
||||||
Assert.Equal( 3, newTradeResult.LedgerEntries.Count);
|
Assert.Equal(3, newTradeResult.LedgerEntries.Count);
|
||||||
Assert.Equal( MockCustodian.TradeQtyBought, newTradeResult.LedgerEntries[0].Qty);
|
Assert.Equal(MockCustodian.TradeQtyBought, newTradeResult.LedgerEntries[0].Qty);
|
||||||
Assert.Equal( tradeRequest.ToAsset, newTradeResult.LedgerEntries[0].Asset);
|
Assert.Equal(tradeRequest.ToAsset, newTradeResult.LedgerEntries[0].Asset);
|
||||||
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade , newTradeResult.LedgerEntries[0].Type);
|
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade, newTradeResult.LedgerEntries[0].Type);
|
||||||
Assert.Equal( -1 * MockCustodian.TradeQtyBought * MockCustodian.BtcPriceInEuro, newTradeResult.LedgerEntries[1].Qty);
|
Assert.Equal(-1 * MockCustodian.TradeQtyBought * MockCustodian.BtcPriceInEuro, newTradeResult.LedgerEntries[1].Qty);
|
||||||
Assert.Equal( tradeRequest.FromAsset, newTradeResult.LedgerEntries[1].Asset);
|
Assert.Equal(tradeRequest.FromAsset, newTradeResult.LedgerEntries[1].Asset);
|
||||||
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade , newTradeResult.LedgerEntries[1].Type);
|
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade, newTradeResult.LedgerEntries[1].Type);
|
||||||
Assert.Equal( -1 * MockCustodian.TradeFeeEuro, newTradeResult.LedgerEntries[2].Qty);
|
Assert.Equal(-1 * MockCustodian.TradeFeeEuro, newTradeResult.LedgerEntries[2].Qty);
|
||||||
Assert.Equal( tradeRequest.FromAsset, newTradeResult.LedgerEntries[2].Asset);
|
Assert.Equal(tradeRequest.FromAsset, newTradeResult.LedgerEntries[2].Asset);
|
||||||
Assert.Equal(LedgerEntryData.LedgerEntryType.Fee , newTradeResult.LedgerEntries[2].Type);
|
Assert.Equal(LedgerEntryData.LedgerEntryType.Fee, newTradeResult.LedgerEntries[2].Type);
|
||||||
|
|
||||||
// Test: GetTradeQuote, SATS
|
// Test: GetTradeQuote, SATS
|
||||||
var satsTradeRequest = new TradeRequestData {FromAsset = MockCustodian.TradeFromAsset, ToAsset = "SATS", Qty = MockCustodian.TradeQtyBought.ToString(CultureInfo.InvariantCulture)};
|
var satsTradeRequest = new TradeRequestData { FromAsset = MockCustodian.TradeFromAsset, ToAsset = "SATS", Qty = MockCustodian.TradeQtyBought.ToString(CultureInfo.InvariantCulture) };
|
||||||
await AssertApiError(400, "use-asset-synonym", async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, satsTradeRequest));
|
await AssertApiError(400, "use-asset-synonym", async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, satsTradeRequest));
|
||||||
|
|
||||||
// TODO Test: Trade with percentage qty
|
// TODO Test: Trade with percentage qty
|
||||||
|
|
||||||
// Test: Trade with wrong decimal format (example: JavaScript scientific format)
|
// Test: Trade with wrong decimal format (example: JavaScript scientific format)
|
||||||
var wrongQtyTradeRequest = new TradeRequestData {FromAsset = MockCustodian.TradeFromAsset, ToAsset = MockCustodian.TradeToAsset, Qty = "6.1e-7"};
|
var wrongQtyTradeRequest = new TradeRequestData { FromAsset = MockCustodian.TradeFromAsset, ToAsset = MockCustodian.TradeToAsset, Qty = "6.1e-7" };
|
||||||
await AssertApiError(400,"bad-qty-format", async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, wrongQtyTradeRequest));
|
await AssertApiError(400, "bad-qty-format", async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, wrongQtyTradeRequest));
|
||||||
|
|
||||||
// Test: Trade, wrong assets method
|
// Test: Trade, wrong assets method
|
||||||
var wrongAssetsTradeRequest = new TradeRequestData {FromAsset = "WRONG", ToAsset = MockCustodian.TradeToAsset, Qty = MockCustodian.TradeQtyBought.ToString(CultureInfo.InvariantCulture)};
|
var wrongAssetsTradeRequest = new TradeRequestData { FromAsset = "WRONG", ToAsset = MockCustodian.TradeToAsset, Qty = MockCustodian.TradeQtyBought.ToString(CultureInfo.InvariantCulture) };
|
||||||
await AssertHttpError(WrongTradingPairException.HttpCode, async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, wrongAssetsTradeRequest));
|
await AssertHttpError(WrongTradingPairException.HttpCode, async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, wrongAssetsTradeRequest));
|
||||||
|
|
||||||
// Test: wrong account ID
|
// Test: wrong account ID
|
||||||
@@ -3687,7 +3719,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
await AssertHttpError(403, async () => await tradeClient.MarketTradeCustodianAccountAsset("WRONG-STORE-ID", accountId, tradeRequest));
|
await AssertHttpError(403, async () => await tradeClient.MarketTradeCustodianAccountAsset("WRONG-STORE-ID", accountId, tradeRequest));
|
||||||
|
|
||||||
// Test: Trade, correct assets, wrong amount
|
// Test: Trade, correct assets, wrong amount
|
||||||
var insufficientFundsTradeRequest = new TradeRequestData {FromAsset = MockCustodian.TradeFromAsset, ToAsset = MockCustodian.TradeToAsset, Qty = "0.01"};
|
var insufficientFundsTradeRequest = new TradeRequestData { FromAsset = MockCustodian.TradeFromAsset, ToAsset = MockCustodian.TradeToAsset, Qty = "0.01" };
|
||||||
await AssertApiError(400, "insufficient-funds", async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, insufficientFundsTradeRequest));
|
await AssertApiError(400, "insufficient-funds", async () => await tradeClient.MarketTradeCustodianAccountAsset(storeId, accountId, insufficientFundsTradeRequest));
|
||||||
|
|
||||||
|
|
||||||
@@ -3710,7 +3742,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
|
|
||||||
// Test: GetTradeQuote, wrong asset
|
// Test: GetTradeQuote, wrong asset
|
||||||
await AssertHttpError(404, async () => await tradeClient.GetTradeQuote(storeId, accountId, "WRONG-ASSET", MockCustodian.TradeToAsset));
|
await AssertHttpError(404, async () => await tradeClient.GetTradeQuote(storeId, accountId, "WRONG-ASSET", MockCustodian.TradeToAsset));
|
||||||
await AssertHttpError(404, async () => await tradeClient.GetTradeQuote(storeId, accountId, MockCustodian.TradeFromAsset , "WRONG-ASSET"));
|
await AssertHttpError(404, async () => await tradeClient.GetTradeQuote(storeId, accountId, MockCustodian.TradeFromAsset, "WRONG-ASSET"));
|
||||||
|
|
||||||
// Test: wrong account ID
|
// Test: wrong account ID
|
||||||
await AssertHttpError(404, async () => await tradeClient.GetTradeQuote(storeId, "WRONG-ACCOUNT-ID", MockCustodian.TradeFromAsset, MockCustodian.TradeToAsset));
|
await AssertHttpError(404, async () => await tradeClient.GetTradeQuote(storeId, "WRONG-ACCOUNT-ID", MockCustodian.TradeFromAsset, MockCustodian.TradeToAsset));
|
||||||
@@ -3736,17 +3768,17 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
Assert.Equal(MockCustodian.TradeId, tradeResult.TradeId);
|
Assert.Equal(MockCustodian.TradeId, tradeResult.TradeId);
|
||||||
Assert.Equal(tradeRequest.FromAsset, tradeResult.FromAsset);
|
Assert.Equal(tradeRequest.FromAsset, tradeResult.FromAsset);
|
||||||
Assert.Equal(tradeRequest.ToAsset, tradeResult.ToAsset);
|
Assert.Equal(tradeRequest.ToAsset, tradeResult.ToAsset);
|
||||||
Assert.NotNull( tradeResult.LedgerEntries);
|
Assert.NotNull(tradeResult.LedgerEntries);
|
||||||
Assert.Equal( 3, tradeResult.LedgerEntries.Count);
|
Assert.Equal(3, tradeResult.LedgerEntries.Count);
|
||||||
Assert.Equal( MockCustodian.TradeQtyBought, tradeResult.LedgerEntries[0].Qty);
|
Assert.Equal(MockCustodian.TradeQtyBought, tradeResult.LedgerEntries[0].Qty);
|
||||||
Assert.Equal( tradeRequest.ToAsset, tradeResult.LedgerEntries[0].Asset);
|
Assert.Equal(tradeRequest.ToAsset, tradeResult.LedgerEntries[0].Asset);
|
||||||
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade , tradeResult.LedgerEntries[0].Type);
|
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade, tradeResult.LedgerEntries[0].Type);
|
||||||
Assert.Equal( -1 * MockCustodian.TradeQtyBought * MockCustodian.BtcPriceInEuro, tradeResult.LedgerEntries[1].Qty);
|
Assert.Equal(-1 * MockCustodian.TradeQtyBought * MockCustodian.BtcPriceInEuro, tradeResult.LedgerEntries[1].Qty);
|
||||||
Assert.Equal( tradeRequest.FromAsset, tradeResult.LedgerEntries[1].Asset);
|
Assert.Equal(tradeRequest.FromAsset, tradeResult.LedgerEntries[1].Asset);
|
||||||
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade , tradeResult.LedgerEntries[1].Type);
|
Assert.Equal(LedgerEntryData.LedgerEntryType.Trade, tradeResult.LedgerEntries[1].Type);
|
||||||
Assert.Equal( -1 * MockCustodian.TradeFeeEuro, tradeResult.LedgerEntries[2].Qty);
|
Assert.Equal(-1 * MockCustodian.TradeFeeEuro, tradeResult.LedgerEntries[2].Qty);
|
||||||
Assert.Equal( tradeRequest.FromAsset, tradeResult.LedgerEntries[2].Asset);
|
Assert.Equal(tradeRequest.FromAsset, tradeResult.LedgerEntries[2].Asset);
|
||||||
Assert.Equal(LedgerEntryData.LedgerEntryType.Fee , tradeResult.LedgerEntries[2].Type);
|
Assert.Equal(LedgerEntryData.LedgerEntryType.Fee, tradeResult.LedgerEntries[2].Type);
|
||||||
|
|
||||||
// Test: GetTradeInfo, wrong trade ID
|
// Test: GetTradeInfo, wrong trade ID
|
||||||
await AssertHttpError(404, async () => await tradeClient.GetTradeInfo(storeId, accountId, "WRONG-TRADE-ID"));
|
await AssertHttpError(404, async () => await tradeClient.GetTradeInfo(storeId, accountId, "WRONG-TRADE-ID"));
|
||||||
@@ -3759,7 +3791,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
|
|
||||||
|
|
||||||
// Test: CreateWithdrawal, unauth
|
// Test: CreateWithdrawal, unauth
|
||||||
var createWithdrawalRequest = new WithdrawRequestData(MockCustodian.WithdrawalPaymentMethod, MockCustodian.WithdrawalAmount );
|
var createWithdrawalRequest = new WithdrawRequestData(MockCustodian.WithdrawalPaymentMethod, MockCustodian.WithdrawalAmount);
|
||||||
await AssertHttpError(401, async () => await unauthClient.CreateWithdrawal(storeId, accountId, createWithdrawalRequest));
|
await AssertHttpError(401, async () => await unauthClient.CreateWithdrawal(storeId, accountId, createWithdrawalRequest));
|
||||||
|
|
||||||
// Test: CreateWithdrawal, auth, but wrong permission
|
// Test: CreateWithdrawal, auth, but wrong permission
|
||||||
@@ -3771,7 +3803,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
|
|
||||||
|
|
||||||
// Test: CreateWithdrawal, wrong payment method
|
// Test: CreateWithdrawal, wrong payment method
|
||||||
var wrongPaymentMethodCreateWithdrawalRequest = new WithdrawRequestData("WRONG-PAYMENT-METHOD", MockCustodian.WithdrawalAmount );
|
var wrongPaymentMethodCreateWithdrawalRequest = new WithdrawRequestData("WRONG-PAYMENT-METHOD", MockCustodian.WithdrawalAmount);
|
||||||
await AssertHttpError(403, async () => await withdrawalClient.CreateWithdrawal(storeId, accountId, wrongPaymentMethodCreateWithdrawalRequest));
|
await AssertHttpError(403, async () => await withdrawalClient.CreateWithdrawal(storeId, accountId, wrongPaymentMethodCreateWithdrawalRequest));
|
||||||
|
|
||||||
// Test: CreateWithdrawal, wrong account ID
|
// Test: CreateWithdrawal, wrong account ID
|
||||||
@@ -3779,7 +3811,7 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
|
|||||||
|
|
||||||
// Test: CreateWithdrawal, wrong store ID
|
// Test: CreateWithdrawal, wrong store ID
|
||||||
// TODO it is wierd that 403 is considered normal, but it is like this for all calls where the store is wrong... I'd have preferred a 404 error, because the store cannot be found.
|
// TODO it is wierd that 403 is considered normal, but it is like this for all calls where the store is wrong... I'd have preferred a 404 error, because the store cannot be found.
|
||||||
await AssertHttpError(403, async () => await withdrawalClient.CreateWithdrawal( "WRONG-STORE-ID",accountId, createWithdrawalRequest));
|
await AssertHttpError(403, async () => await withdrawalClient.CreateWithdrawal("WRONG-STORE-ID", accountId, createWithdrawalRequest));
|
||||||
|
|
||||||
// Test: CreateWithdrawal, correct payment method, wrong amount
|
// Test: CreateWithdrawal, correct payment method, wrong amount
|
||||||
var wrongAmountCreateWithdrawalRequest = new WithdrawRequestData(MockCustodian.WithdrawalPaymentMethod, new decimal(0.666));
|
var wrongAmountCreateWithdrawalRequest = new WithdrawRequestData(MockCustodian.WithdrawalPaymentMethod, new decimal(0.666));
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class MockCustodian : ICustodian, ICanDeposit, ICanTrade, ICanWithdraw
|
|||||||
public List<AssetPairData> GetTradableAssetPairs()
|
public List<AssetPairData> GetTradableAssetPairs()
|
||||||
{
|
{
|
||||||
var r = new List<AssetPairData>();
|
var r = new List<AssetPairData>();
|
||||||
r.Add(new AssetPairData("BTC", "EUR", (decimal) 0.0001));
|
r.Add(new AssetPairData("BTC", "EUR", (decimal)0.0001));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -555,7 +555,7 @@ namespace BTCPayServer.Tests
|
|||||||
for (var i = 0; i < coins; i++)
|
for (var i = 0; i < coins; i++)
|
||||||
{
|
{
|
||||||
bool mined = false;
|
bool mined = false;
|
||||||
retry:
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(denomination));
|
await Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(denomination));
|
||||||
|
|||||||
@@ -1704,7 +1704,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
//lnurl-w support check
|
//lnurl-w support check
|
||||||
|
|
||||||
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();
|
||||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||||
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true);
|
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true);
|
||||||
@@ -1735,10 +1735,10 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Contains(bolt2.BOLT11, s.Driver.PageSource);
|
Assert.Contains(bolt2.BOLT11, s.Driver.PageSource);
|
||||||
|
|
||||||
Assert.Contains(PayoutState.Completed.GetStateString(), s.Driver.PageSource);
|
Assert.Contains(PayoutState.Completed.GetStateString(), s.Driver.PageSource);
|
||||||
Assert.Equal( LightningInvoiceStatus.Paid, (await s.Server.CustomerLightningD.GetInvoice(bolt2.Id)).Status );
|
Assert.Equal(LightningInvoiceStatus.Paid, (await s.Server.CustomerLightningD.GetInvoice(bolt2.Id)).Status);
|
||||||
});
|
});
|
||||||
|
|
||||||
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();
|
||||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||||
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), false);
|
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), false);
|
||||||
@@ -1867,7 +1867,8 @@ namespace BTCPayServer.Tests
|
|||||||
});
|
});
|
||||||
var greenfield = await s.AsTestAccount().CreateClient();
|
var greenfield = await s.AsTestAccount().CreateClient();
|
||||||
var paymentMethods = await greenfield.GetInvoicePaymentMethods(s.StoreId, i);
|
var paymentMethods = await greenfield.GetInvoicePaymentMethods(s.StoreId, i);
|
||||||
Assert.Single(paymentMethods, p => {
|
Assert.Single(paymentMethods, p =>
|
||||||
|
{
|
||||||
return p.AdditionalData["providedComment"].Value<string>() == "lol2";
|
return p.AdditionalData["providedComment"].Value<string>() == "lol2";
|
||||||
});
|
});
|
||||||
// Standard invoice test
|
// Standard invoice test
|
||||||
@@ -2138,13 +2139,13 @@ retry:
|
|||||||
.FindElement(By.CssSelector($"option[value='{(int)Fido2Credential.CredentialType.LNURLAuth}']")).Click();
|
.FindElement(By.CssSelector($"option[value='{(int)Fido2Credential.CredentialType.LNURLAuth}']")).Click();
|
||||||
s.Driver.FindElement(By.Id("btn-add")).Click();
|
s.Driver.FindElement(By.Id("btn-add")).Click();
|
||||||
var links = s.Driver.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href"));
|
var links = s.Driver.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href"));
|
||||||
Assert.Equal(2,links.Count());
|
Assert.Equal(2, links.Count());
|
||||||
Uri prevEndpoint = null;
|
Uri prevEndpoint = null;
|
||||||
foreach (string link in links)
|
foreach (string link in links)
|
||||||
{
|
{
|
||||||
var endpoint = LNURL.LNURL.Parse(link, out var tag);
|
var endpoint = LNURL.LNURL.Parse(link, out var tag);
|
||||||
Assert.Equal("login",tag);
|
Assert.Equal("login", tag);
|
||||||
if(endpoint.Scheme != "https")
|
if (endpoint.Scheme != "https")
|
||||||
prevEndpoint = endpoint;
|
prevEndpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2157,13 +2158,13 @@ retry:
|
|||||||
s.LogIn(user, "123456");
|
s.LogIn(user, "123456");
|
||||||
var section = s.Driver.FindElement(By.Id("lnurlauth-section"));
|
var section = s.Driver.FindElement(By.Id("lnurlauth-section"));
|
||||||
links = section.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href"));
|
links = section.FindElements(By.CssSelector(".tab-content a")).Select(element => element.GetAttribute("href"));
|
||||||
Assert.Equal(2,links.Count());
|
Assert.Equal(2, links.Count());
|
||||||
prevEndpoint = null;
|
prevEndpoint = null;
|
||||||
foreach (string link in links)
|
foreach (string link in links)
|
||||||
{
|
{
|
||||||
var endpoint = LNURL.LNURL.Parse(link, out var tag);
|
var endpoint = LNURL.LNURL.Parse(link, out var tag);
|
||||||
Assert.Equal("login",tag);
|
Assert.Equal("login", tag);
|
||||||
if(endpoint.Scheme != "https")
|
if (endpoint.Scheme != "https")
|
||||||
prevEndpoint = endpoint;
|
prevEndpoint = endpoint;
|
||||||
}
|
}
|
||||||
request = Assert.IsType<LNAuthRequest>(await LNURL.LNURL.FetchInformation(prevEndpoint, null));
|
request = Assert.IsType<LNAuthRequest>(await LNURL.LNURL.FetchInformation(prevEndpoint, null));
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace BTCPayServer.Tests
|
|||||||
public async Task CanQueryDirectProviders()
|
public async Task CanQueryDirectProviders()
|
||||||
{
|
{
|
||||||
// TODO: Check once in a while whether or not they are working again
|
// TODO: Check once in a while whether or not they are working again
|
||||||
string[] brokenShitcoinCasinos = {};
|
string[] brokenShitcoinCasinos = { };
|
||||||
var skipped = 0;
|
var skipped = 0;
|
||||||
var factory = FastTests.CreateBTCPayRateFactory();
|
var factory = FastTests.CreateBTCPayRateFactory();
|
||||||
var directlySupported = factory.GetSupportedExchanges().Where(s => s.Source == RateSource.Direct)
|
var directlySupported = factory.GetSupportedExchanges().Where(s => s.Source == RateSource.Direct)
|
||||||
@@ -225,7 +225,7 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
var uri = new Uri(url);
|
var uri = new Uri(url);
|
||||||
int retryLeft = 3;
|
int retryLeft = 3;
|
||||||
retry:
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||||
|
|||||||
@@ -199,11 +199,11 @@ namespace BTCPayServer.Tests
|
|||||||
var user = tester.NewAccount();
|
var user = tester.NewAccount();
|
||||||
await user.GrantAccessAsync();
|
await user.GrantAccessAsync();
|
||||||
var settingsRepo = tester.PayTester.ServiceProvider.GetRequiredService<IStoreRepository>();
|
var settingsRepo = tester.PayTester.ServiceProvider.GetRequiredService<IStoreRepository>();
|
||||||
var arbValue = await settingsRepo.GetSettingAsync<string>(user.StoreId,"arbitrary");
|
var arbValue = await settingsRepo.GetSettingAsync<string>(user.StoreId, "arbitrary");
|
||||||
Assert.Null(arbValue);
|
Assert.Null(arbValue);
|
||||||
await settingsRepo.UpdateSetting(user.StoreId, "arbitrary", "saved");
|
await settingsRepo.UpdateSetting(user.StoreId, "arbitrary", "saved");
|
||||||
|
|
||||||
arbValue = await settingsRepo.GetSettingAsync<string>(user.StoreId,"arbitrary");
|
arbValue = await settingsRepo.GetSettingAsync<string>(user.StoreId, "arbitrary");
|
||||||
Assert.Equal("saved", arbValue);
|
Assert.Equal("saved", arbValue);
|
||||||
|
|
||||||
await settingsRepo.UpdateSetting<TestData>(user.StoreId, "arbitrary", new TestData() { Name = "hello" });
|
await settingsRepo.UpdateSetting<TestData>(user.StoreId, "arbitrary", new TestData() { Name = "hello" });
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ public class AppSales : ViewComponent
|
|||||||
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(AppSalesViewModel vm)
|
public async Task<IViewComponentResult> InvokeAsync(AppSalesViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.App == null) throw new ArgumentNullException(nameof(vm.App));
|
if (vm.App == null)
|
||||||
if (vm.InitialRendering) return View(vm);
|
throw new ArgumentNullException(nameof(vm.App));
|
||||||
|
if (vm.InitialRendering)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
var stats = await _appService.GetSalesStats(vm.App);
|
var stats = await _appService.GetSalesStats(vm.App);
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ public class AppTopItems : ViewComponent
|
|||||||
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(AppTopItemsViewModel vm)
|
public async Task<IViewComponentResult> InvokeAsync(AppTopItemsViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.App == null) throw new ArgumentNullException(nameof(vm.App));
|
if (vm.App == null)
|
||||||
if (vm.InitialRendering) return View(vm);
|
throw new ArgumentNullException(nameof(vm.App));
|
||||||
|
if (vm.InitialRendering)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
var entries = Enum.Parse<AppType>(vm.App.AppType) == AppType.Crowdfund
|
var entries = Enum.Parse<AppType>(vm.App.AppType) == AppType.Crowdfund
|
||||||
? await _appService.GetPerkStats(vm.App)
|
? await _appService.GetPerkStats(vm.App)
|
||||||
|
|||||||
@@ -47,13 +47,16 @@ public class StoreLightningBalance : ViewComponent
|
|||||||
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(StoreLightningBalanceViewModel vm)
|
public async Task<IViewComponentResult> InvokeAsync(StoreLightningBalanceViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.Store == null) throw new ArgumentNullException(nameof(vm.Store));
|
if (vm.Store == null)
|
||||||
if (vm.CryptoCode == null) throw new ArgumentNullException(nameof(vm.CryptoCode));
|
throw new ArgumentNullException(nameof(vm.Store));
|
||||||
|
if (vm.CryptoCode == null)
|
||||||
|
throw new ArgumentNullException(nameof(vm.CryptoCode));
|
||||||
|
|
||||||
vm.DefaultCurrency = vm.Store.GetStoreBlob().DefaultCurrency;
|
vm.DefaultCurrency = vm.Store.GetStoreBlob().DefaultCurrency;
|
||||||
vm.CurrencyData = _currencies.GetCurrencyData(vm.DefaultCurrency, true);
|
vm.CurrencyData = _currencies.GetCurrencyData(vm.DefaultCurrency, true);
|
||||||
|
|
||||||
if (vm.InitialRendering) return View(vm);
|
if (vm.InitialRendering)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -61,12 +64,12 @@ public class StoreLightningBalance : ViewComponent
|
|||||||
var balance = await lightningClient.GetBalance();
|
var balance = await lightningClient.GetBalance();
|
||||||
vm.Balance = balance;
|
vm.Balance = balance;
|
||||||
vm.TotalOnchain = balance.OnchainBalance != null
|
vm.TotalOnchain = balance.OnchainBalance != null
|
||||||
? (balance.OnchainBalance.Confirmed?? 0L) + (balance.OnchainBalance.Reserved ?? 0L) +
|
? (balance.OnchainBalance.Confirmed ?? 0L) + (balance.OnchainBalance.Reserved ?? 0L) +
|
||||||
(balance.OnchainBalance.Unconfirmed ?? 0L)
|
(balance.OnchainBalance.Unconfirmed ?? 0L)
|
||||||
: null;
|
: null;
|
||||||
vm.TotalOffchain = balance.OffchainBalance != null
|
vm.TotalOffchain = balance.OffchainBalance != null
|
||||||
? (balance.OffchainBalance.Opening?? 0) + (balance.OffchainBalance.Local?? 0) +
|
? (balance.OffchainBalance.Opening ?? 0) + (balance.OffchainBalance.Local ?? 0) +
|
||||||
(balance.OffchainBalance.Closing?? 0)
|
(balance.OffchainBalance.Closing ?? 0)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
catch (NotSupportedException)
|
catch (NotSupportedException)
|
||||||
@@ -89,9 +92,10 @@ public class StoreLightningBalance : ViewComponent
|
|||||||
var existing = store.GetSupportedPaymentMethods(_networkProvider)
|
var existing = store.GetSupportedPaymentMethods(_networkProvider)
|
||||||
.OfType<LightningSupportedPaymentMethod>()
|
.OfType<LightningSupportedPaymentMethod>()
|
||||||
.FirstOrDefault(d => d.PaymentId == id);
|
.FirstOrDefault(d => d.PaymentId == id);
|
||||||
if (existing == null) return null;
|
if (existing == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (existing.GetExternalLightningUrl() is {} connectionString)
|
if (existing.GetExternalLightningUrl() is { } connectionString)
|
||||||
{
|
{
|
||||||
return _lightningClientFactory.Create(connectionString, network);
|
return _lightningClientFactory.Create(connectionString, network);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,14 @@ public class StoreLightningServices : ViewComponent
|
|||||||
|
|
||||||
public IViewComponentResult Invoke(StoreLightningServicesViewModel vm)
|
public IViewComponentResult Invoke(StoreLightningServicesViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.Store == null) throw new ArgumentNullException(nameof(vm.Store));
|
if (vm.Store == null)
|
||||||
if (vm.CryptoCode == null) throw new ArgumentNullException(nameof(vm.CryptoCode));
|
throw new ArgumentNullException(nameof(vm.Store));
|
||||||
if (vm.LightningNodeType != LightningNodeType.Internal) return View(vm);
|
if (vm.CryptoCode == null)
|
||||||
if (!User.IsInRole(Roles.ServerAdmin)) return View(vm);
|
throw new ArgumentNullException(nameof(vm.CryptoCode));
|
||||||
|
if (vm.LightningNodeType != LightningNodeType.Internal)
|
||||||
|
return View(vm);
|
||||||
|
if (!User.IsInRole(Roles.ServerAdmin))
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
var services = _externalServiceOptions.Value.ExternalServices.ToList()
|
var services = _externalServiceOptions.Value.ExternalServices.ToList()
|
||||||
.Where(service => ExternalServices.LightningServiceTypes.Contains(service.Type))
|
.Where(service => ExternalServices.LightningServiceTypes.Contains(service.Type))
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using Dapper;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -9,6 +8,7 @@ using BTCPayServer.Data;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
|
using Dapper;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -41,12 +41,15 @@ public class StoreNumbers : ViewComponent
|
|||||||
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(StoreNumbersViewModel vm)
|
public async Task<IViewComponentResult> InvokeAsync(StoreNumbersViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.Store == null) throw new ArgumentNullException(nameof(vm.Store));
|
if (vm.Store == null)
|
||||||
if (vm.CryptoCode == null) throw new ArgumentNullException(nameof(vm.CryptoCode));
|
throw new ArgumentNullException(nameof(vm.Store));
|
||||||
|
if (vm.CryptoCode == null)
|
||||||
|
throw new ArgumentNullException(nameof(vm.CryptoCode));
|
||||||
|
|
||||||
vm.WalletId = new WalletId(vm.Store.Id, vm.CryptoCode);
|
vm.WalletId = new WalletId(vm.Store.Id, vm.CryptoCode);
|
||||||
|
|
||||||
if (vm.InitialRendering) return View(vm);
|
if (vm.InitialRendering)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
await using var ctx = _dbContextFactory.CreateContext();
|
await using var ctx = _dbContextFactory.CreateContext();
|
||||||
var payoutsCount = await ctx.Payouts
|
var payoutsCount = await ctx.Payouts
|
||||||
|
|||||||
@@ -35,15 +35,18 @@ public class StoreRecentInvoices : ViewComponent
|
|||||||
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(StoreRecentInvoicesViewModel vm)
|
public async Task<IViewComponentResult> InvokeAsync(StoreRecentInvoicesViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.Store == null) throw new ArgumentNullException(nameof(vm.Store));
|
if (vm.Store == null)
|
||||||
if (vm.CryptoCode == null) throw new ArgumentNullException(nameof(vm.CryptoCode));
|
throw new ArgumentNullException(nameof(vm.Store));
|
||||||
if (vm.InitialRendering) return View(vm);
|
if (vm.CryptoCode == null)
|
||||||
|
throw new ArgumentNullException(nameof(vm.CryptoCode));
|
||||||
|
if (vm.InitialRendering)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
var userId = _userManager.GetUserId(UserClaimsPrincipal);
|
var userId = _userManager.GetUserId(UserClaimsPrincipal);
|
||||||
var invoiceEntities = await _invoiceRepo.GetInvoices(new InvoiceQuery
|
var invoiceEntities = await _invoiceRepo.GetInvoices(new InvoiceQuery
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
StoreId = new [] { vm.Store.Id },
|
StoreId = new[] { vm.Store.Id },
|
||||||
IncludeArchived = false,
|
IncludeArchived = false,
|
||||||
IncludeRefunds = true,
|
IncludeRefunds = true,
|
||||||
Take = 5
|
Take = 5
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Services;
|
|
||||||
using BTCPayServer.Models.StoreViewModels;
|
using BTCPayServer.Models.StoreViewModels;
|
||||||
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Dapper;
|
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
|
using Dapper;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NBXplorer.Client;
|
|
||||||
using static BTCPayServer.Components.StoreRecentTransactions.StoreRecentTransactionsViewModel;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
using NBXplorer.Client;
|
||||||
|
using static BTCPayServer.Components.StoreRecentTransactions.StoreRecentTransactionsViewModel;
|
||||||
|
|
||||||
namespace BTCPayServer.Components.StoreRecentTransactions;
|
namespace BTCPayServer.Components.StoreRecentTransactions;
|
||||||
|
|
||||||
@@ -35,12 +35,15 @@ public class StoreRecentTransactions : ViewComponent
|
|||||||
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(StoreRecentTransactionsViewModel vm)
|
public async Task<IViewComponentResult> InvokeAsync(StoreRecentTransactionsViewModel vm)
|
||||||
{
|
{
|
||||||
if (vm.Store == null) throw new ArgumentNullException(nameof(vm.Store));
|
if (vm.Store == null)
|
||||||
if (vm.CryptoCode == null) throw new ArgumentNullException(nameof(vm.CryptoCode));
|
throw new ArgumentNullException(nameof(vm.Store));
|
||||||
|
if (vm.CryptoCode == null)
|
||||||
|
throw new ArgumentNullException(nameof(vm.CryptoCode));
|
||||||
|
|
||||||
vm.WalletId = new WalletId(vm.Store.Id, vm.CryptoCode);
|
vm.WalletId = new WalletId(vm.Store.Id, vm.CryptoCode);
|
||||||
|
|
||||||
if (vm.InitialRendering) return View(vm);
|
if (vm.InitialRendering)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
var derivationSettings = vm.Store.GetDerivationSchemeSettings(NetworkProvider, vm.CryptoCode);
|
var derivationSettings = vm.Store.GetDerivationSchemeSettings(NetworkProvider, vm.CryptoCode);
|
||||||
var transactions = new List<StoreRecentTransactionViewModel>();
|
var transactions = new List<StoreRecentTransactionViewModel>();
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class StoreWalletBalance : ViewComponent
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using CancellationTokenSource cts = new (TimeSpan.FromSeconds(3));
|
using CancellationTokenSource cts = new(TimeSpan.FromSeconds(3));
|
||||||
var wallet = _walletProvider.GetWallet(_networkProvider.DefaultNetwork);
|
var wallet = _walletProvider.GetWallet(_networkProvider.DefaultNetwork);
|
||||||
var derivation = store.GetDerivationSchemeSettings(_networkProvider, walletId.CryptoCode);
|
var derivation = store.GetDerivationSchemeSettings(_networkProvider, walletId.CryptoCode);
|
||||||
if (derivation is not null)
|
if (derivation is not null)
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ using BTCPayServer.Client.Models;
|
|||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Rating;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Rating;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
@@ -439,7 +439,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RefundVariant.Custom:
|
case RefundVariant.Custom:
|
||||||
if (request.CustomAmount is null || (request.CustomAmount is decimal v && v <= 0)) {
|
if (request.CustomAmount is null || (request.CustomAmount is decimal v && v <= 0))
|
||||||
|
{
|
||||||
this.ModelState.AddModelError(nameof(request.CustomAmount), "Amount must be greater than 0");
|
this.ModelState.AddModelError(nameof(request.CustomAmount), "Amount must be greater than 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +600,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
Amount = entity.Price,
|
Amount = entity.Price,
|
||||||
Type = entity.Type,
|
Type = entity.Type,
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
CheckoutLink = request is null? null: linkGenerator.CheckoutLink(entity.Id, request.Scheme, request.Host, request.PathBase),
|
CheckoutLink = request is null ? null : linkGenerator.CheckoutLink(entity.Id, request.Scheme, request.Host, request.PathBase),
|
||||||
Status = entity.Status.ToModernStatus(),
|
Status = entity.Status.ToModernStatus(),
|
||||||
AdditionalStatus = entity.ExceptionStatus,
|
AdditionalStatus = entity.ExceptionStatus,
|
||||||
Currency = entity.Currency,
|
Currency = entity.Currency,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
{
|
{
|
||||||
private readonly IEnumerable<IPayoutProcessorFactory> _factories;
|
private readonly IEnumerable<IPayoutProcessorFactory> _factories;
|
||||||
|
|
||||||
public GreenfieldPayoutProcessorsController(IEnumerable<IPayoutProcessorFactory>factories)
|
public GreenfieldPayoutProcessorsController(IEnumerable<IPayoutProcessorFactory> factories)
|
||||||
{
|
{
|
||||||
_factories = factories;
|
_factories = factories;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
if (pp is null)
|
if (pp is null)
|
||||||
return PullPaymentNotFound();
|
return PullPaymentNotFound();
|
||||||
|
|
||||||
var payouts =await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
var payouts = await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
||||||
{
|
{
|
||||||
PullPayments = new[] {pullPaymentId},
|
PullPayments = new[] { pullPaymentId },
|
||||||
States = GetStateFilter(includeCancelled)
|
States = GetStateFilter(includeCancelled)
|
||||||
});
|
});
|
||||||
return base.Ok(payouts
|
return base.Ok(payouts
|
||||||
@@ -219,7 +219,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
var payout = (await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
var payout = (await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
||||||
{
|
{
|
||||||
PullPayments = new[] {pullPaymentId}, PayoutIds = new[] {payoutId}
|
PullPayments = new[] { pullPaymentId },
|
||||||
|
PayoutIds = new[] { payoutId }
|
||||||
})).FirstOrDefault();
|
})).FirstOrDefault();
|
||||||
|
|
||||||
|
|
||||||
@@ -413,7 +414,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
{
|
{
|
||||||
var payouts = await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
var payouts = await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {storeId},
|
Stores = new[] { storeId },
|
||||||
States = GetStateFilter(includeCancelled)
|
States = GetStateFilter(includeCancelled)
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -426,7 +427,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
[Authorize(Policy = Policies.CanManagePullPayments, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
[Authorize(Policy = Policies.CanManagePullPayments, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
public async Task<IActionResult> CancelPayout(string storeId, string payoutId)
|
public async Task<IActionResult> CancelPayout(string storeId, string payoutId)
|
||||||
{
|
{
|
||||||
var res= await _pullPaymentService.Cancel(new PullPaymentHostedService.CancelRequest(new[] { payoutId }, new []{storeId}));
|
var res = await _pullPaymentService.Cancel(new PullPaymentHostedService.CancelRequest(new[] { payoutId }, new[] { storeId }));
|
||||||
return MapResult(res.First().Value);
|
return MapResult(res.First().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +531,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
var payout = (await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
var payout = (await _pullPaymentService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {storeId}, PayoutIds = new[] {payoutId}
|
Stores = new[] { storeId },
|
||||||
|
PayoutIds = new[] { payoutId }
|
||||||
})).FirstOrDefault();
|
})).FirstOrDefault();
|
||||||
|
|
||||||
if (payout is null)
|
if (payout is null)
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
await _payoutProcessorService.GetProcessors(
|
await _payoutProcessorService.GetProcessors(
|
||||||
new PayoutProcessorService.PayoutProcessorQuery()
|
new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {storeId},
|
Stores = new[] { storeId },
|
||||||
Processors = new[] {LightningAutomatedPayoutSenderFactory.ProcessorName},
|
Processors = new[] { LightningAutomatedPayoutSenderFactory.ProcessorName },
|
||||||
PaymentMethods = paymentMethod is null ? null : new[] {paymentMethod}
|
PaymentMethods = paymentMethod is null ? null : new[] { paymentMethod }
|
||||||
});
|
});
|
||||||
|
|
||||||
return Ok(configured.Select(ToModel).ToArray());
|
return Ok(configured.Select(ToModel).ToArray());
|
||||||
@@ -61,7 +61,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
private static AutomatedPayoutBlob FromModel(LightningAutomatedPayoutSettings data)
|
private static AutomatedPayoutBlob FromModel(LightningAutomatedPayoutSettings data)
|
||||||
{
|
{
|
||||||
return new AutomatedPayoutBlob() {Interval = data.IntervalSeconds};
|
return new AutomatedPayoutBlob() { Interval = data.IntervalSeconds };
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
@@ -75,9 +75,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
(await _payoutProcessorService.GetProcessors(
|
(await _payoutProcessorService.GetProcessors(
|
||||||
new PayoutProcessorService.PayoutProcessorQuery()
|
new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {storeId},
|
Stores = new[] { storeId },
|
||||||
Processors = new[] {LightningAutomatedPayoutSenderFactory.ProcessorName},
|
Processors = new[] { LightningAutomatedPayoutSenderFactory.ProcessorName },
|
||||||
PaymentMethods = new[] {paymentMethod}
|
PaymentMethods = new[] { paymentMethod }
|
||||||
}))
|
}))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
activeProcessor ??= new PayoutProcessorData();
|
activeProcessor ??= new PayoutProcessorData();
|
||||||
@@ -88,7 +88,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
var tcs = new TaskCompletionSource();
|
var tcs = new TaskCompletionSource();
|
||||||
_eventAggregator.Publish(new PayoutProcessorUpdated()
|
_eventAggregator.Publish(new PayoutProcessorUpdated()
|
||||||
{
|
{
|
||||||
Data = activeProcessor, Id = activeProcessor.Id, Processed = tcs
|
Data = activeProcessor,
|
||||||
|
Id = activeProcessor.Id,
|
||||||
|
Processed = tcs
|
||||||
});
|
});
|
||||||
await tcs.Task;
|
await tcs.Task;
|
||||||
return Ok(ToModel(activeProcessor));
|
return Ok(ToModel(activeProcessor));
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
await _payoutProcessorService.GetProcessors(
|
await _payoutProcessorService.GetProcessors(
|
||||||
new PayoutProcessorService.PayoutProcessorQuery()
|
new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {storeId},
|
Stores = new[] { storeId },
|
||||||
Processors = new[] {OnChainAutomatedPayoutSenderFactory.ProcessorName},
|
Processors = new[] { OnChainAutomatedPayoutSenderFactory.ProcessorName },
|
||||||
PaymentMethods = paymentMethod is null ? null : new[] {paymentMethod}
|
PaymentMethods = paymentMethod is null ? null : new[] { paymentMethod }
|
||||||
});
|
});
|
||||||
|
|
||||||
return Ok(configured.Select(ToModel).ToArray());
|
return Ok(configured.Select(ToModel).ToArray());
|
||||||
@@ -81,9 +81,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
(await _payoutProcessorService.GetProcessors(
|
(await _payoutProcessorService.GetProcessors(
|
||||||
new PayoutProcessorService.PayoutProcessorQuery()
|
new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {storeId},
|
Stores = new[] { storeId },
|
||||||
Processors = new[] {OnChainAutomatedPayoutSenderFactory.ProcessorName},
|
Processors = new[] { OnChainAutomatedPayoutSenderFactory.ProcessorName },
|
||||||
PaymentMethods = new[] {paymentMethod}
|
PaymentMethods = new[] { paymentMethod }
|
||||||
}))
|
}))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
activeProcessor ??= new PayoutProcessorData();
|
activeProcessor ??= new PayoutProcessorData();
|
||||||
@@ -94,7 +94,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
var tcs = new TaskCompletionSource();
|
var tcs = new TaskCompletionSource();
|
||||||
_eventAggregator.Publish(new PayoutProcessorUpdated()
|
_eventAggregator.Publish(new PayoutProcessorUpdated()
|
||||||
{
|
{
|
||||||
Data = activeProcessor, Id = activeProcessor.Id, Processed = tcs
|
Data = activeProcessor,
|
||||||
|
Id = activeProcessor.Id,
|
||||||
|
Processed = tcs
|
||||||
});
|
});
|
||||||
await tcs.Task;
|
await tcs.Task;
|
||||||
return Ok(ToModel(activeProcessor));
|
return Ok(ToModel(activeProcessor));
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace BTCPayServer.Controllers.GreenField
|
|||||||
var emailSender = await _emailSenderFactory.GetEmailSender(storeId);
|
var emailSender = await _emailSenderFactory.GetEmailSender(storeId);
|
||||||
if (emailSender is null)
|
if (emailSender is null)
|
||||||
{
|
{
|
||||||
return this.CreateAPIError(404,"smtp-not-configured", "Store does not have an SMTP server configured.");
|
return this.CreateAPIError(404, "smtp-not-configured", "Store does not have an SMTP server configured.");
|
||||||
}
|
}
|
||||||
emailSender.SendEmail(to, request.Subject, request.Body);
|
emailSender.SendEmail(to, request.Subject, request.Body);
|
||||||
return Ok();
|
return Ok();
|
||||||
@@ -89,7 +89,7 @@ namespace BTCPayServer.Controllers.GreenField
|
|||||||
}
|
}
|
||||||
private EmailSettings FromModel(Data.StoreData data)
|
private EmailSettings FromModel(Data.StoreData data)
|
||||||
{
|
{
|
||||||
return data.GetStoreBlob().EmailSettings??new();
|
return data.GetStoreBlob().EmailSettings ?? new();
|
||||||
}
|
}
|
||||||
private IActionResult StoreNotFound()
|
private IActionResult StoreNotFound()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ using BTCPayServer.Models.WalletViewModels;
|
|||||||
using BTCPayServer.Payments.PayJoin;
|
using BTCPayServer.Payments.PayJoin;
|
||||||
using BTCPayServer.Payments.PayJoin.Sender;
|
using BTCPayServer.Payments.PayJoin.Sender;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Wallets;
|
|
||||||
using BTCPayServer.Services.Labels;
|
using BTCPayServer.Services.Labels;
|
||||||
|
using BTCPayServer.Services.Wallets;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.Payment;
|
using NBitcoin.Payment;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
using NBXplorer.Models;
|
using NBXplorer.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StoreData = BTCPayServer.Data.StoreData;
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers.Greenfield
|
namespace BTCPayServer.Controllers.Greenfield
|
||||||
{
|
{
|
||||||
@@ -145,12 +145,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
{
|
{
|
||||||
bip21.QueryParams.Add(PayjoinClient.BIP21EndpointKey,
|
bip21.QueryParams.Add(PayjoinClient.BIP21EndpointKey,
|
||||||
Request.GetAbsoluteUri(Url.Action(nameof(PayJoinEndpointController.Submit), "PayJoinEndpoint",
|
Request.GetAbsoluteUri(Url.Action(nameof(PayJoinEndpointController.Submit), "PayJoinEndpoint",
|
||||||
new {cryptoCode})));
|
new { cryptoCode })));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(new OnChainWalletAddressData()
|
return Ok(new OnChainWalletAddressData()
|
||||||
{
|
{
|
||||||
Address = kpi.Address?.ToString(), PaymentLink = bip21.ToString(), KeyPath = kpi.KeyPath
|
Address = kpi.Address?.ToString(),
|
||||||
|
PaymentLink = bip21.ToString(),
|
||||||
|
KeyPath = kpi.KeyPath
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +191,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
var wallet = _btcPayWalletProvider.GetWallet(network);
|
var wallet = _btcPayWalletProvider.GetWallet(network);
|
||||||
var walletId = new WalletId(storeId, cryptoCode);
|
var walletId = new WalletId(storeId, cryptoCode);
|
||||||
var walletTransactionsInfoAsync = await _walletRepository.GetWalletTransactionsInfo(walletId, (string[] ) null);
|
var walletTransactionsInfoAsync = await _walletRepository.GetWalletTransactionsInfo(walletId, (string[])null);
|
||||||
|
|
||||||
var preFiltering = true;
|
var preFiltering = true;
|
||||||
if (statusFilter?.Any() is true || !string.IsNullOrWhiteSpace(labelFilter))
|
if (statusFilter?.Any() is true || !string.IsNullOrWhiteSpace(labelFilter))
|
||||||
@@ -246,7 +248,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));
|
||||||
@@ -288,7 +290,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}
|
}
|
||||||
|
|
||||||
var walletTransactionsInfo =
|
var walletTransactionsInfo =
|
||||||
(await _walletRepository.GetWalletTransactionsInfo(walletId, new[] {transactionId}))
|
(await _walletRepository.GetWalletTransactionsInfo(walletId, new[] { transactionId }))
|
||||||
.Values
|
.Values
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
@@ -588,7 +590,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
new PayjoinWallet(derivationScheme),
|
new PayjoinWallet(derivationScheme),
|
||||||
psbt.PSBT, CancellationToken.None);
|
psbt.PSBT, CancellationToken.None);
|
||||||
psbt.PSBT.Settings.SigningOptions =
|
psbt.PSBT.Settings.SigningOptions =
|
||||||
new SigningOptions() {EnforceLowR = !(signingContext?.EnforceLowR is false)};
|
new SigningOptions() { EnforceLowR = !(signingContext?.EnforceLowR is false) };
|
||||||
payjoinPSBT = psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, rootedKeyPath);
|
payjoinPSBT = psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, rootedKeyPath);
|
||||||
payjoinPSBT.Finalize();
|
payjoinPSBT.Finalize();
|
||||||
var payjoinTransaction = payjoinPSBT.ExtractTransaction();
|
var payjoinTransaction = payjoinPSBT.ExtractTransaction();
|
||||||
|
|||||||
@@ -43,15 +43,15 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpDelete("~/api/v1/stores/{storeId}/payout-processors/{processor}/{paymentMethod}")]
|
[HttpDelete("~/api/v1/stores/{storeId}/payout-processors/{processor}/{paymentMethod}")]
|
||||||
public async Task<IActionResult> RemoveStorePayoutProcessor(
|
public async Task<IActionResult> RemoveStorePayoutProcessor(
|
||||||
string storeId,string processor,string paymentMethod)
|
string storeId, string processor, string paymentMethod)
|
||||||
{
|
{
|
||||||
var matched =
|
var matched =
|
||||||
(await _payoutProcessorService.GetProcessors(
|
(await _payoutProcessorService.GetProcessors(
|
||||||
new PayoutProcessorService.PayoutProcessorQuery()
|
new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] { storeId },
|
Stores = new[] { storeId },
|
||||||
Processors = new []{ processor},
|
Processors = new[] { processor },
|
||||||
PaymentMethods = new []{paymentMethod}
|
PaymentMethods = new[] { paymentMethod }
|
||||||
})).FirstOrDefault();
|
})).FirstOrDefault();
|
||||||
if (matched is null)
|
if (matched is null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace BTCPayServer.Controllers.GreenField
|
|||||||
public ActionResult<List<RateSource>> GetRateSources()
|
public ActionResult<List<RateSource>> GetRateSources()
|
||||||
{
|
{
|
||||||
return Ok(_rateProviderFactory.RateProviderFactory.GetSupportedExchanges().Select(provider =>
|
return Ok(_rateProviderFactory.RateProviderFactory.GetSupportedExchanges().Select(provider =>
|
||||||
new RateSource() {Id = provider.Id, Name = provider.DisplayName}));
|
new RateSource() { Id = provider.Id, Name = provider.DisplayName }));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("")]
|
[HttpPut("")]
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
private IEnumerable<StoreUserData> FromModel(Data.StoreData data)
|
private IEnumerable<StoreUserData> FromModel(Data.StoreData data)
|
||||||
{
|
{
|
||||||
return data.UserStores.Select(store => new StoreUserData() { UserId = store.ApplicationUserId, Role = store.Role});
|
return data.UserStores.Select(store => new StoreUserData() { UserId = store.ApplicationUserId, Role = store.Role });
|
||||||
}
|
}
|
||||||
private IActionResult StoreNotFound()
|
private IActionResult StoreNotFound()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
[HttpGet("~/api/v1/users/{idOrEmail}")]
|
[HttpGet("~/api/v1/users/{idOrEmail}")]
|
||||||
public async Task<IActionResult> GetUser(string idOrEmail)
|
public async Task<IActionResult> GetUser(string idOrEmail)
|
||||||
{
|
{
|
||||||
var user = (await _userManager.FindByIdAsync(idOrEmail) ) ?? await _userManager.FindByEmailAsync(idOrEmail);
|
var user = (await _userManager.FindByIdAsync(idOrEmail)) ?? await _userManager.FindByEmailAsync(idOrEmail);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
return Ok(await FromModel(user));
|
return Ok(await FromModel(user));
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ActivatorUtilities.CreateInstance<LocalBTCPayServerClient>(_serviceProvider,
|
return ActivatorUtilities.CreateInstance<LocalBTCPayServerClient>(_serviceProvider,
|
||||||
new LocalHttpContextAccessor() {HttpContext = context});
|
new LocalHttpContextAccessor() { HttpContext = context });
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -686,7 +686,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
{
|
{
|
||||||
return GetFromActionResult<NotificationData>(
|
return GetFromActionResult<NotificationData>(
|
||||||
await GetController<GreenfieldNotificationsController>().UpdateNotification(notificationId,
|
await GetController<GreenfieldNotificationsController>().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)
|
||||||
@@ -1056,7 +1056,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
public override async Task<OnChainWalletTransactionData> PatchOnChainWalletTransaction(string storeId,
|
public override async Task<OnChainWalletTransactionData> PatchOnChainWalletTransaction(string storeId,
|
||||||
string cryptoCode, string transactionId,
|
string cryptoCode, string transactionId,
|
||||||
PatchOnChainTransactionRequest request, bool force = false,CancellationToken token = default)
|
PatchOnChainTransactionRequest request, bool force = false, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
return GetFromActionResult<OnChainWalletTransactionData>(
|
return GetFromActionResult<OnChainWalletTransactionData>(
|
||||||
await GetController<GreenfieldStoreOnChainWalletsController>().PatchOnChainWalletTransaction(storeId, cryptoCode, transactionId,
|
await GetController<GreenfieldStoreOnChainWalletsController>().PatchOnChainWalletTransaction(storeId, cryptoCode, transactionId,
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class LightningAddressService
|
|||||||
{
|
{
|
||||||
return await _memoryCache.GetOrCreateAsync(GetKey(username), async entry =>
|
return await _memoryCache.GetOrCreateAsync(GetKey(username), async entry =>
|
||||||
{
|
{
|
||||||
var result = await Get(new LightningAddressQuery() {Usernames = new[] {username}});
|
var result = await Get(new LightningAddressQuery() { Usernames = new[] { username } });
|
||||||
return result.FirstOrDefault();
|
return result.FirstOrDefault();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ public class LightningAddressService
|
|||||||
public async Task<bool> Set(LightningAddressData data)
|
public async Task<bool> Set(LightningAddressData data)
|
||||||
{
|
{
|
||||||
await using var context = _applicationDbContextFactory.CreateContext();
|
await using var context = _applicationDbContextFactory.CreateContext();
|
||||||
var result = (await GetCore(context, new LightningAddressQuery() {Usernames = new[] {data.Username}}))
|
var result = (await GetCore(context, new LightningAddressQuery() { Usernames = new[] { data.Username } }))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
if (result is not null)
|
if (result is not null)
|
||||||
{
|
{
|
||||||
@@ -83,8 +83,9 @@ public class LightningAddressService
|
|||||||
public async Task<bool> Remove(string username, string? storeId = null)
|
public async Task<bool> Remove(string username, string? storeId = null)
|
||||||
{
|
{
|
||||||
await using var context = _applicationDbContextFactory.CreateContext();
|
await using var context = _applicationDbContextFactory.CreateContext();
|
||||||
var x = (await GetCore(context, new LightningAddressQuery() {Usernames = new[] {username}})).FirstOrDefault();
|
var x = (await GetCore(context, new LightningAddressQuery() { Usernames = new[] { username } })).FirstOrDefault();
|
||||||
if (x is null) return true;
|
if (x is null)
|
||||||
|
return true;
|
||||||
if (storeId is not null && x.StoreDataId != storeId)
|
if (storeId is not null && x.StoreDataId != storeId)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -98,7 +99,7 @@ public class LightningAddressService
|
|||||||
|
|
||||||
public async Task Set(LightningAddressData data, ApplicationDbContext context)
|
public async Task Set(LightningAddressData data, ApplicationDbContext context)
|
||||||
{
|
{
|
||||||
var result = (await GetCore(context, new LightningAddressQuery() {Usernames = new[] {data.Username}}))
|
var result = (await GetCore(context, new LightningAddressQuery() { Usernames = new[] { data.Username } }))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
if (result is not null)
|
if (result is not null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,8 +68,7 @@ namespace BTCPayServer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newCredential = new Fido2Credential {Name = name, ApplicationUserId = userId, Type = Fido2Credential.CredentialType.LNURLAuth, Blob = pubkeyBytes};
|
var newCredential = new Fido2Credential() { Name = name, ApplicationUserId = userId, Type = Fido2Credential.CredentialType.LNURLAuth, Blob = pubkeyBytes };
|
||||||
|
|
||||||
await dbContext.Fido2Credentials.AddAsync(newCredential);
|
await dbContext.Fido2Credentials.AddAsync(newCredential);
|
||||||
await dbContext.SaveChangesAsync();
|
await dbContext.SaveChangesAsync();
|
||||||
CreationStore.Remove(userId, out _);
|
CreationStore.Remove(userId, out _);
|
||||||
@@ -84,7 +83,7 @@ namespace BTCPayServer
|
|||||||
public async Task Remove(string id, string userId)
|
public async Task Remove(string id, string userId)
|
||||||
{
|
{
|
||||||
await using var context = _contextFactory.CreateContext();
|
await using var context = _contextFactory.CreateContext();
|
||||||
var device = await context.Fido2Credentials.FindAsync( id);
|
var device = await context.Fido2Credentials.FindAsync(id);
|
||||||
if (device == null || !device.ApplicationUserId.Equals(userId, StringComparison.InvariantCulture))
|
if (device == null || !device.ApplicationUserId.Equals(userId, StringComparison.InvariantCulture))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -112,7 +111,8 @@ namespace BTCPayServer
|
|||||||
return k1;
|
return k1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> CompleteLogin(string userId, ECDSASignature sig, PubKey pubKey){
|
public async Task<bool> CompleteLogin(string userId, ECDSASignature sig, PubKey pubKey)
|
||||||
|
{
|
||||||
await using var dbContext = _contextFactory.CreateContext();
|
await using var dbContext = _contextFactory.CreateContext();
|
||||||
userId = userId.ToLowerInvariant();
|
userId = userId.ToLowerInvariant();
|
||||||
var user = await dbContext.Users.Include(applicationUser => applicationUser.Fido2Credentials)
|
var user = await dbContext.Users.Include(applicationUser => applicationUser.Fido2Credentials)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
@@ -179,8 +179,8 @@ 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,
|
||||||
LoginWithLNURLAuthViewModel = lnurlAuthCredentials? await BuildLNURLAuthViewModel(model.RememberMe, user): null,
|
LoginWithLNURLAuthViewModel = lnurlAuthCredentials ? await BuildLNURLAuthViewModel(model.RememberMe, user) : null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -212,7 +212,7 @@ namespace BTCPayServer.Controllers
|
|||||||
if (result.IsLockedOut)
|
if (result.IsLockedOut)
|
||||||
{
|
{
|
||||||
_logger.LogWarning($"User '{user.Id}' account locked out.");
|
_logger.LogWarning($"User '{user.Id}' account locked out.");
|
||||||
return RedirectToAction(nameof(Lockout), new { user.LockoutEnd});
|
return RedirectToAction(nameof(Lockout), new { user.LockoutEnd });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -262,7 +262,7 @@ namespace BTCPayServer.Controllers
|
|||||||
LNURLEndpoint = new Uri(_linkGenerator.GetUriByAction(
|
LNURLEndpoint = new Uri(_linkGenerator.GetUriByAction(
|
||||||
action: nameof(UILNURLAuthController.LoginResponse),
|
action: nameof(UILNURLAuthController.LoginResponse),
|
||||||
controller: "UILNURLAuth",
|
controller: "UILNURLAuth",
|
||||||
values: new { userId = user.Id, action="login", tag="login", k1= Encoders.Hex.EncodeData(r) }, Request.Scheme, Request.Host, Request.PathBase))
|
values: new { userId = user.Id, action = "login", tag = "login", k1 = Encoders.Hex.EncodeData(r) }, Request.Scheme, Request.Host, Request.PathBase))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -431,7 +431,7 @@ namespace BTCPayServer.Controllers
|
|||||||
else if (result.IsLockedOut)
|
else if (result.IsLockedOut)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
|
_logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
|
||||||
return RedirectToAction(nameof(Lockout), new { user.LockoutEnd});
|
return RedirectToAction(nameof(Lockout), new { user.LockoutEnd });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -501,7 +501,7 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
_logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
|
_logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
|
||||||
|
|
||||||
return RedirectToAction(nameof(Lockout), new { user.LockoutEnd});
|
return RedirectToAction(nameof(Lockout), new { user.LockoutEnd });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -306,7 +306,9 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
var custodianAccountData = new CustodianAccountData
|
var custodianAccountData = new CustodianAccountData
|
||||||
{
|
{
|
||||||
CustodianCode = vm.SelectedCustodian, StoreId = vm.StoreId, Name = custodian.Name
|
CustodianCode = vm.SelectedCustodian,
|
||||||
|
StoreId = vm.StoreId,
|
||||||
|
Name = custodian.Name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace BTCPayServer.Controllers
|
|||||||
var cryptoCode = isSats ? "BTC" : request.CryptoCode;
|
var cryptoCode = isSats ? "BTC" : request.CryptoCode;
|
||||||
var amount = new Money(request.Amount, isSats ? MoneyUnit.Satoshi : MoneyUnit.BTC);
|
var amount = new Money(request.Amount, isSats ? MoneyUnit.Satoshi : MoneyUnit.BTC);
|
||||||
var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode).NBitcoinNetwork;
|
var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode).NBitcoinNetwork;
|
||||||
var paymentMethodId = new [] {store.GetDefaultPaymentId()}
|
var paymentMethodId = new[] { store.GetDefaultPaymentId() }
|
||||||
.Concat(store.GetEnabledPaymentIds(_NetworkProvider))
|
.Concat(store.GetEnabledPaymentIds(_NetworkProvider))
|
||||||
.FirstOrDefault(p => p?.ToString() == request.PaymentMethodId);
|
.FirstOrDefault(p => p?.ToString() == request.PaymentMethodId);
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
var receipt = InvoiceDataBase.ReceiptOptions.Merge(store.GetStoreBlob().ReceiptOptions, i.ReceiptOptions);
|
var receipt = InvoiceDataBase.ReceiptOptions.Merge(store.GetStoreBlob().ReceiptOptions, i.ReceiptOptions);
|
||||||
|
|
||||||
if (receipt.Enabled is not true) return NotFound();
|
if (receipt.Enabled is not true)
|
||||||
|
return NotFound();
|
||||||
if (i.Status.ToModernStatus() != InvoiceStatus.Settled)
|
if (i.Status.ToModernStatus() != InvoiceStatus.Settled)
|
||||||
{
|
{
|
||||||
return View(new InvoiceReceiptViewModel
|
return View(new InvoiceReceiptViewModel
|
||||||
@@ -738,10 +739,10 @@ namespace BTCPayServer.Controllers
|
|||||||
lang ??= storeBlob.DefaultLang;
|
lang ??= storeBlob.DefaultLang;
|
||||||
|
|
||||||
var receiptEnabled = InvoiceDataBase.ReceiptOptions.Merge(storeBlob.ReceiptOptions, invoice.ReceiptOptions).Enabled is true;
|
var receiptEnabled = InvoiceDataBase.ReceiptOptions.Merge(storeBlob.ReceiptOptions, invoice.ReceiptOptions).Enabled is true;
|
||||||
var receiptUrl = receiptEnabled? _linkGenerator.GetUriByAction(
|
var receiptUrl = receiptEnabled ? _linkGenerator.GetUriByAction(
|
||||||
nameof(InvoiceReceipt),
|
nameof(InvoiceReceipt),
|
||||||
"UIInvoice",
|
"UIInvoice",
|
||||||
new {invoiceId},
|
new { invoiceId },
|
||||||
Request.Scheme,
|
Request.Scheme,
|
||||||
Request.Host,
|
Request.Host,
|
||||||
Request.PathBase) : null;
|
Request.PathBase) : null;
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||||
{
|
{
|
||||||
Severity = StatusMessageModel.StatusSeverity.Success, Html = "LNURL Auth was removed successfully."
|
Severity = StatusMessageModel.StatusSeverity.Success,
|
||||||
|
Html = "LNURL Auth was removed successfully."
|
||||||
});
|
});
|
||||||
|
|
||||||
return RedirectToList();
|
return RedirectToList();
|
||||||
@@ -108,7 +109,8 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
return BadRequest(new LNUrlStatusResponse
|
return BadRequest(new LNUrlStatusResponse
|
||||||
{
|
{
|
||||||
Reason = "The challenge could not be verified", Status = "ERROR"
|
Reason = "The challenge could not be verified",
|
||||||
|
Status = "ERROR"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +134,8 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
return BadRequest(new LNUrlStatusResponse
|
return BadRequest(new LNUrlStatusResponse
|
||||||
{
|
{
|
||||||
Reason = "The challenge could not be verified", Status = "ERROR"
|
Reason = "The challenge could not be verified",
|
||||||
|
Status = "ERROR"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,11 +127,11 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
if (!BOLT11PaymentRequest.TryParse(pr, out var result, network.NBitcoinNetwork) || result is null)
|
if (!BOLT11PaymentRequest.TryParse(pr, out var result, network.NBitcoinNetwork) || result is null)
|
||||||
{
|
{
|
||||||
return BadRequest(new LNUrlStatusResponse {Status = "ERROR", Reason = "Pr was not a valid BOLT11"});
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr was not a valid BOLT11" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.MinimumAmount < request.MinWithdrawable || result.MinimumAmount > request.MaxWithdrawable)
|
if (result.MinimumAmount < request.MinWithdrawable || result.MinimumAmount > request.MaxWithdrawable)
|
||||||
return BadRequest(new LNUrlStatusResponse {Status = "ERROR", Reason = "Pr was not within bounds"});
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr was not within bounds" });
|
||||||
var store = await _storeRepository.FindStore(pp.StoreId);
|
var store = await _storeRepository.FindStore(pp.StoreId);
|
||||||
var pm = store!.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
var pm = store!.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||||
.OfType<LightningSupportedPaymentMethod>()
|
.OfType<LightningSupportedPaymentMethod>()
|
||||||
@@ -151,7 +151,7 @@ namespace BTCPayServer
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (claimResponse.Result != ClaimRequest.ClaimResult.Ok)
|
if (claimResponse.Result != ClaimRequest.ClaimResult.Ok)
|
||||||
return BadRequest(new LNUrlStatusResponse {Status = "ERROR", Reason = "Pr could not be paid"});
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr could not be paid" });
|
||||||
switch (claimResponse.PayoutData.State)
|
switch (claimResponse.PayoutData.State)
|
||||||
{
|
{
|
||||||
case PayoutState.AwaitingPayment:
|
case PayoutState.AwaitingPayment:
|
||||||
@@ -203,9 +203,9 @@ namespace BTCPayServer
|
|||||||
});
|
});
|
||||||
case PayoutState.InProgress:
|
case PayoutState.InProgress:
|
||||||
case PayoutState.Completed:
|
case PayoutState.Completed:
|
||||||
return Ok(new LNUrlStatusResponse {Status = "OK"});
|
return Ok(new LNUrlStatusResponse { Status = "OK" });
|
||||||
case PayoutState.Cancelled:
|
case PayoutState.Cancelled:
|
||||||
return BadRequest(new LNUrlStatusResponse {Status = "ERROR", Reason = "Pr could not be paid"});
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr could not be paid" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(request);
|
return Ok(request);
|
||||||
@@ -274,7 +274,7 @@ namespace BTCPayServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await GetLNURL(cryptoCode, app.StoreDataId, currencyCode, null, null,
|
return await GetLNURL(cryptoCode, app.StoreDataId, currencyCode, null, null,
|
||||||
() => (null, app, item, new List<string> {AppService.GetAppInternalTag(appId)}, item.Price.Value, true));
|
() => (null, app, item, new List<string> { AppService.GetAppInternalTag(appId) }, item.Price.Value, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EditLightningAddressVM
|
public class EditLightningAddressVM
|
||||||
@@ -433,10 +433,10 @@ namespace BTCPayServer
|
|||||||
.Replace("{ItemDescription}", i.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
.Replace("{ItemDescription}", i.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
||||||
.Replace("{OrderId}", i.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
.Replace("{OrderId}", i.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
lnurlMetadata.Add(new[] {"text/plain", description});
|
lnurlMetadata.Add(new[] { "text/plain", description });
|
||||||
if (!string.IsNullOrEmpty(username))
|
if (!string.IsNullOrEmpty(username))
|
||||||
{
|
{
|
||||||
lnurlMetadata.Add(new[] {"text/identifier", lnAddress});
|
lnurlMetadata.Add(new[] { "text/identifier", lnAddress });
|
||||||
}
|
}
|
||||||
return Ok(new LNURLPayRequest
|
return Ok(new LNURLPayRequest
|
||||||
{
|
{
|
||||||
@@ -451,7 +451,7 @@ namespace BTCPayServer
|
|||||||
Callback = new Uri(_linkGenerator.GetUriByAction(
|
Callback = new Uri(_linkGenerator.GetUriByAction(
|
||||||
action: nameof(GetLNURLForInvoice),
|
action: nameof(GetLNURLForInvoice),
|
||||||
controller: "UILNURL",
|
controller: "UILNURL",
|
||||||
values: new {cryptoCode, invoiceId = i.Id}, Request.Scheme, Request.Host, Request.PathBase))
|
values: new { cryptoCode, invoiceId = i.Id }, Request.Scheme, Request.Host, Request.PathBase))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,28 +508,28 @@ namespace BTCPayServer
|
|||||||
.Replace("{ItemDescription}", i.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
.Replace("{ItemDescription}", i.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
||||||
.Replace("{OrderId}", i.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
.Replace("{OrderId}", i.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
lnurlMetadata.Add(new[] {"text/plain", description});
|
lnurlMetadata.Add(new[] { "text/plain", description });
|
||||||
if (!string.IsNullOrEmpty(paymentMethodDetails.ConsumedLightningAddress))
|
if (!string.IsNullOrEmpty(paymentMethodDetails.ConsumedLightningAddress))
|
||||||
{
|
{
|
||||||
lnurlMetadata.Add(new[] {"text/identifier", paymentMethodDetails.ConsumedLightningAddress});
|
lnurlMetadata.Add(new[] { "text/identifier", paymentMethodDetails.ConsumedLightningAddress });
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadata = JsonConvert.SerializeObject(lnurlMetadata);
|
var metadata = JsonConvert.SerializeObject(lnurlMetadata);
|
||||||
if (amount.HasValue && (amount < min || amount > max))
|
if (amount.HasValue && (amount < min || amount > max))
|
||||||
{
|
{
|
||||||
return BadRequest(new LNUrlStatusResponse {Status = "ERROR", Reason = "Amount is out of bounds."});
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Amount is out of bounds." });
|
||||||
}
|
}
|
||||||
|
|
||||||
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction successAction = null;
|
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction successAction = null;
|
||||||
|
|
||||||
if ((i.ReceiptOptions?.Enabled ??blob.ReceiptOptions.Enabled ) is true)
|
if ((i.ReceiptOptions?.Enabled ?? blob.ReceiptOptions.Enabled) is true)
|
||||||
{
|
{
|
||||||
successAction =
|
successAction =
|
||||||
new LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionUrl
|
new LNURLPayRequest.LNURLPayRequestCallbackResponse.LNURLPayRequestSuccessActionUrl
|
||||||
{
|
{
|
||||||
Tag = "url",
|
Tag = "url",
|
||||||
Description = "Thank you for your purchase. Here is your receipt",
|
Description = "Thank you for your purchase. Here is your receipt",
|
||||||
Url = _linkGenerator.GetUriByAction(HttpContext, "InvoiceReceipt", "UIInvoice", new { invoiceId})
|
Url = _linkGenerator.GetUriByAction(HttpContext, "InvoiceReceipt", "UIInvoice", new { invoiceId })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +609,9 @@ namespace BTCPayServer
|
|||||||
paymentMethodDetails, pmi));
|
paymentMethodDetails, pmi));
|
||||||
return Ok(new LNURLPayRequest.LNURLPayRequestCallbackResponse
|
return Ok(new LNURLPayRequest.LNURLPayRequestCallbackResponse
|
||||||
{
|
{
|
||||||
Disposable = true, Routes = Array.Empty<string>(), Pr = paymentMethodDetails.BOLT11,
|
Disposable = true,
|
||||||
|
Routes = Array.Empty<string>(),
|
||||||
|
Pr = paymentMethodDetails.BOLT11,
|
||||||
SuccessAction = successAction
|
SuccessAction = successAction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -625,7 +627,9 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
return Ok(new LNURLPayRequest.LNURLPayRequestCallbackResponse
|
return Ok(new LNURLPayRequest.LNURLPayRequestCallbackResponse
|
||||||
{
|
{
|
||||||
Disposable = true, Routes = Array.Empty<string>(), Pr = paymentMethodDetails.BOLT11,
|
Disposable = true,
|
||||||
|
Routes = Array.Empty<string>(),
|
||||||
|
Pr = paymentMethodDetails.BOLT11,
|
||||||
SuccessAction = successAction
|
SuccessAction = successAction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -633,7 +637,8 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
return BadRequest(new LNUrlStatusResponse
|
return BadRequest(new LNUrlStatusResponse
|
||||||
{
|
{
|
||||||
Status = "ERROR", Reason = "Invoice not in a valid payable state"
|
Status = "ERROR",
|
||||||
|
Reason = "Invoice not in a valid payable state"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,11 +655,11 @@ namespace BTCPayServer
|
|||||||
Message = "LNURL is required for lightning addresses but has not yet been enabled.",
|
Message = "LNURL is required for lightning addresses but has not yet been enabled.",
|
||||||
Severity = StatusMessageModel.StatusSeverity.Error
|
Severity = StatusMessageModel.StatusSeverity.Error
|
||||||
});
|
});
|
||||||
return RedirectToAction(nameof(UIStoresController.GeneralSettings), "UIStores", new {storeId});
|
return RedirectToAction(nameof(UIStoresController.GeneralSettings), "UIStores", new { storeId });
|
||||||
}
|
}
|
||||||
|
|
||||||
var addresses =
|
var addresses =
|
||||||
await _lightningAddressService.Get(new LightningAddressQuery() {StoreIds = new[] {storeId}});
|
await _lightningAddressService.Get(new LightningAddressQuery() { StoreIds = new[] { storeId } });
|
||||||
|
|
||||||
return View(new EditLightningAddressVM
|
return View(new EditLightningAddressVM
|
||||||
{
|
{
|
||||||
@@ -701,7 +706,9 @@ namespace BTCPayServer
|
|||||||
Username = vm.Add.Username,
|
Username = vm.Add.Username,
|
||||||
Blob = new LightningAddressDataBlob()
|
Blob = new LightningAddressDataBlob()
|
||||||
{
|
{
|
||||||
Max = vm.Add.Max, Min = vm.Add.Min, CurrencyCode = vm.Add.CurrencyCode
|
Max = vm.Add.Max,
|
||||||
|
Min = vm.Add.Min,
|
||||||
|
CurrencyCode = vm.Add.CurrencyCode
|
||||||
}.SerializeBlob()
|
}.SerializeBlob()
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ namespace BTCPayServer.Controllers
|
|||||||
if (Policies.IsStorePolicy(requested.Key))
|
if (Policies.IsStorePolicy(requested.Key))
|
||||||
{
|
{
|
||||||
if ((vm.SelectiveStores && !existing.Any(p => p.Scope == vm.StoreId)) ||
|
if ((vm.SelectiveStores && !existing.Any(p => p.Scope == vm.StoreId)) ||
|
||||||
(!vm.SelectiveStores && existing.Any(p => !string.IsNullOrEmpty(p.Scope))) )
|
(!vm.SelectiveStores && existing.Any(p => !string.IsNullOrEmpty(p.Scope))))
|
||||||
{
|
{
|
||||||
fail = true;
|
fail = true;
|
||||||
break;
|
break;
|
||||||
@@ -566,7 +566,7 @@ namespace BTCPayServer.Controllers
|
|||||||
public bool Forbidden { get; set; }
|
public bool Forbidden { get; set; }
|
||||||
|
|
||||||
public ApiKeyStoreMode StoreMode { get; set; } = ApiKeyStoreMode.AllStores;
|
public ApiKeyStoreMode StoreMode { get; set; } = ApiKeyStoreMode.AllStores;
|
||||||
public List<string> SpecificStores { get; set; } = new ();
|
public List<string> SpecificStores { get; set; } = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace BTCPayServer.Controllers
|
|||||||
var totalPaid = payouts.Where(p => p.Entity.State != PayoutState.Cancelled).Select(p => p.Blob.Amount).Sum();
|
var totalPaid = payouts.Where(p => p.Entity.State != PayoutState.Cancelled).Select(p => p.Blob.Amount).Sum();
|
||||||
var amountDue = blob.Limit - totalPaid;
|
var amountDue = blob.Limit - totalPaid;
|
||||||
|
|
||||||
ViewPullPaymentModel vm = new (pp, DateTimeOffset.UtcNow)
|
ViewPullPaymentModel vm = new(pp, DateTimeOffset.UtcNow)
|
||||||
{
|
{
|
||||||
AmountFormatted = _currencyNameTable.FormatCurrency(blob.Limit, blob.Currency),
|
AmountFormatted = _currencyNameTable.FormatCurrency(blob.Limit, blob.Currency),
|
||||||
AmountCollected = totalPaid,
|
AmountCollected = totalPaid,
|
||||||
@@ -224,7 +224,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||||
{
|
{
|
||||||
Message = $"Your claim request of {_currencyNameTable.DisplayFormatCurrency(vm.ClaimedAmount, ppBlob.Currency)} to {vm.Destination} has been submitted and is awaiting {(result.PayoutData.State == PayoutState.AwaitingApproval? "approval": "payment")}.",
|
Message = $"Your claim request of {_currencyNameTable.DisplayFormatCurrency(vm.ClaimedAmount, ppBlob.Currency)} to {vm.Destination} has been submitted and is awaiting {(result.PayoutData.State == PayoutState.AwaitingApproval ? "approval" : "payment")}.",
|
||||||
Severity = StatusMessageModel.StatusSeverity.Success
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Files uploaded, restart server to load plugins" ,
|
Message = "Files uploaded, restart server to load plugins",
|
||||||
Severity = StatusMessageModel.StatusSeverity.Success
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
return RedirectToAction("ListPlugins");
|
return RedirectToAction("ListPlugins");
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ using BTCPayServer.Models.ServerViewModels;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers
|
namespace BTCPayServer.Controllers
|
||||||
@@ -261,7 +261,7 @@ namespace BTCPayServer.Controllers
|
|||||||
return View("Confirm", new ConfirmModel("Disable admin",
|
return View("Confirm", new ConfirmModel("Disable admin",
|
||||||
$"Unable to proceed: As the user <strong>{user.Email}</strong> is the last enabled admin, it cannot be disabled."));
|
$"Unable to proceed: As the user <strong>{user.Email}</strong> is the last enabled admin, it cannot be disabled."));
|
||||||
}
|
}
|
||||||
return View("Confirm", new ConfirmModel($"{(enable? "Enable" : "Disable")} user", $"The user <strong>{user.Email}</strong> will be {(enable? "enabled" : "disabled")}. Are you sure?", (enable? "Enable" : "Disable")));
|
return View("Confirm", new ConfirmModel($"{(enable ? "Enable" : "Disable")} user", $"The user <strong>{user.Email}</strong> will be {(enable ? "enabled" : "disabled")}. Are you sure?", (enable ? "Enable" : "Disable")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("server/users/{userId}/toggle")]
|
[HttpPost("server/users/{userId}/toggle")]
|
||||||
@@ -275,9 +275,9 @@ namespace BTCPayServer.Controllers
|
|||||||
TempData[WellKnownTempData.SuccessMessage] = $"User was the last enabled admin and could not be disabled.";
|
TempData[WellKnownTempData.SuccessMessage] = $"User was the last enabled admin and could not be disabled.";
|
||||||
return RedirectToAction(nameof(ListUsers));
|
return RedirectToAction(nameof(ListUsers));
|
||||||
}
|
}
|
||||||
await _userService.ToggleUser(userId, enable? null: DateTimeOffset.MaxValue);
|
await _userService.ToggleUser(userId, enable ? null : DateTimeOffset.MaxValue);
|
||||||
|
|
||||||
TempData[WellKnownTempData.SuccessMessage] = $"User {(enable? "enabled": "disabled")}";
|
TempData[WellKnownTempData.SuccessMessage] = $"User {(enable ? "enabled" : "disabled")}";
|
||||||
return RedirectToAction(nameof(ListUsers));
|
return RedirectToAction(nameof(ListUsers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ namespace BTCPayServer.Controllers
|
|||||||
});
|
});
|
||||||
this.TempData.SetStatusMessageModel(new StatusMessageModel()
|
this.TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Pull payment request created", Severity = StatusMessageModel.StatusSeverity.Success
|
Message = "Pull payment request created",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
return RedirectToAction(nameof(PullPayments), new { storeId = storeId });
|
return RedirectToAction(nameof(PullPayments), new { storeId = storeId });
|
||||||
}
|
}
|
||||||
@@ -194,7 +195,9 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
var vm = this.ParseListQuery(new PullPaymentsModel
|
var vm = this.ParseListQuery(new PullPaymentsModel
|
||||||
{
|
{
|
||||||
Skip = skip, Count = count, ActiveState = pullPaymentState
|
Skip = skip,
|
||||||
|
Count = count,
|
||||||
|
ActiveState = pullPaymentState
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (pullPaymentState)
|
switch (pullPaymentState)
|
||||||
@@ -257,7 +260,8 @@ namespace BTCPayServer.Controllers
|
|||||||
await _pullPaymentService.Cancel(new HostedServices.PullPaymentHostedService.CancelRequest(pullPaymentId));
|
await _pullPaymentService.Cancel(new HostedServices.PullPaymentHostedService.CancelRequest(pullPaymentId));
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Pull payment archived", Severity = StatusMessageModel.StatusSeverity.Success
|
Message = "Pull payment archived",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
return RedirectToAction(nameof(PullPayments), new { storeId });
|
return RedirectToAction(nameof(PullPayments), new { storeId });
|
||||||
}
|
}
|
||||||
@@ -282,7 +286,8 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "No payout selected", Severity = StatusMessageModel.StatusSeverity.Error
|
Message = "No payout selected",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Error
|
||||||
});
|
});
|
||||||
return RedirectToAction(nameof(Payouts),
|
return RedirectToAction(nameof(Payouts),
|
||||||
new
|
new
|
||||||
@@ -362,7 +367,8 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Payouts approved", Severity = StatusMessageModel.StatusSeverity.Success
|
Message = "Payouts approved",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -412,17 +418,19 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Payouts marked as paid", Severity = StatusMessageModel.StatusSeverity.Success
|
Message = "Payouts marked as paid",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "cancel":
|
case "cancel":
|
||||||
await _pullPaymentService.Cancel(
|
await _pullPaymentService.Cancel(
|
||||||
new PullPaymentHostedService.CancelRequest(payoutIds, new[] {storeId}));
|
new PullPaymentHostedService.CancelRequest(payoutIds, new[] { storeId }));
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Payouts archived", Severity = StatusMessageModel.StatusSeverity.Success
|
Message = "Payouts archived",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -494,7 +502,7 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
vm.PaymentMethodCount = (await payoutRequest.GroupBy(data => data.PaymentMethodId)
|
vm.PaymentMethodCount = (await payoutRequest.GroupBy(data => data.PaymentMethodId)
|
||||||
.Select(datas => new {datas.Key, Count = datas.Count()}).ToListAsync())
|
.Select(datas => new { datas.Key, Count = datas.Count() }).ToListAsync())
|
||||||
.ToDictionary(datas => datas.Key, arg => arg.Count);
|
.ToDictionary(datas => datas.Key, arg => arg.Count);
|
||||||
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() })
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ namespace BTCPayServer.Controllers
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Widget data
|
// Widget data
|
||||||
if (!vm.WalletEnabled && !vm.LightningEnabled) return View(vm);
|
if (!vm.WalletEnabled && !vm.LightningEnabled)
|
||||||
|
return View(vm);
|
||||||
|
|
||||||
var userId = GetUserId();
|
var userId = GetUserId();
|
||||||
var apps = await _appService.GetAllApps(userId, false, store.Id);
|
var apps = await _appService.GetAllApps(userId, false, store.Id);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace BTCPayServer.Controllers
|
|||||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||||
{
|
{
|
||||||
Severity = StatusMessageModel.StatusSeverity.Warning,
|
Severity = StatusMessageModel.StatusSeverity.Warning,
|
||||||
Html = $"You need to configure email settings before this feature works. <a class='alert-link' href='{Url.Action("StoreEmailSettings", new {storeId})}'>Configure now</a>."
|
Html = $"You need to configure email settings before this feature works. <a class='alert-link' href='{Url.Action("StoreEmailSettings", new { storeId })}'>Configure now</a>."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,8 @@ namespace BTCPayServer.Controllers
|
|||||||
var item = command[(command.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) + 1)..];
|
var item = command[(command.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) + 1)..];
|
||||||
var index = int.Parse(item, CultureInfo.InvariantCulture);
|
var index = int.Parse(item, CultureInfo.InvariantCulture);
|
||||||
vm.Rules.RemoveAt(index);
|
vm.Rules.RemoveAt(index);
|
||||||
} else if (command == "add")
|
}
|
||||||
|
else if (command == "add")
|
||||||
{
|
{
|
||||||
vm.Rules.Add(new StoreEmailRule());
|
vm.Rules.Add(new StoreEmailRule());
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ namespace BTCPayServer.Controllers
|
|||||||
Severity = StatusMessageModel.StatusSeverity.Success,
|
Severity = StatusMessageModel.StatusSeverity.Success,
|
||||||
Message = "Store email rules saved"
|
Message = "Store email rules saved"
|
||||||
});
|
});
|
||||||
return RedirectToAction("StoreEmails", new {storeId});
|
return RedirectToAction("StoreEmails", new { storeId });
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StoreEmailRuleViewModel
|
public class StoreEmailRuleViewModel
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ namespace BTCPayServer.Controllers
|
|||||||
[HttpPost("{storeId}/users/{userId}/delete")]
|
[HttpPost("{storeId}/users/{userId}/delete")]
|
||||||
public async Task<IActionResult> DeleteStoreUserPost(string storeId, string userId)
|
public async Task<IActionResult> DeleteStoreUserPost(string storeId, string userId)
|
||||||
{
|
{
|
||||||
if(await _Repo.RemoveStoreUser(storeId, userId))
|
if (await _Repo.RemoveStoreUser(storeId, userId))
|
||||||
TempData[WellKnownTempData.SuccessMessage] = "User removed successfully.";
|
TempData[WellKnownTempData.SuccessMessage] = "User removed successfully.";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,7 +95,8 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
private string GetUserId() => _userManager.GetUserId(User);
|
private string GetUserId() => _userManager.GetUserId(User);
|
||||||
|
|
||||||
private SelectList GetExchangesSelectList(string selected) {
|
private SelectList GetExchangesSelectList(string selected)
|
||||||
|
{
|
||||||
var exchanges = _rateFactory.RateProviderFactory
|
var exchanges = _rateFactory.RateProviderFactory
|
||||||
.GetSupportedExchanges()
|
.GetSupportedExchanges()
|
||||||
.Where(r => !string.IsNullOrWhiteSpace(r.Name))
|
.Where(r => !string.IsNullOrWhiteSpace(r.Name))
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ namespace BTCPayServer.Controllers
|
|||||||
builder.SendFees(bumpFee);
|
builder.SendFees(bumpFee);
|
||||||
builder.SendAll(returnAddress);
|
builder.SendAll(returnAddress);
|
||||||
|
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
var psbt = builder.BuildPSBT(false);
|
var psbt = builder.BuildPSBT(false);
|
||||||
psbt = (await explorer.UpdatePSBTAsync(new UpdatePSBTRequest()
|
psbt = (await explorer.UpdatePSBTAsync(new UpdatePSBTRequest()
|
||||||
{
|
{
|
||||||
@@ -143,7 +144,9 @@ namespace BTCPayServer.Controllers
|
|||||||
{ "returnUrl", returnUrl }
|
{ "returnUrl", returnUrl }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception ex) {
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
TempData[WellKnownTempData.ErrorMessage] = ex.Message;
|
TempData[WellKnownTempData.ErrorMessage] = ex.Message;
|
||||||
|
|
||||||
return LocalRedirect(returnUrl);
|
return LocalRedirect(returnUrl);
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ using BTCPayServer.Abstractions.Extensions;
|
|||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.BIP78.Sender;
|
using BTCPayServer.BIP78.Sender;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.ModelBinders;
|
using BTCPayServer.ModelBinders;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
using BTCPayServer.Models.WalletViewModels;
|
using BTCPayServer.Models.WalletViewModels;
|
||||||
@@ -23,24 +25,22 @@ using BTCPayServer.Services.Labels;
|
|||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
|
using BTCPayServer.Services.Wallets.Export;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using BTCPayServer.Client.Models;
|
|
||||||
using BTCPayServer.Logging;
|
|
||||||
using BTCPayServer.Services.Wallets.Export;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
using NBXplorer.Client;
|
using NBXplorer.Client;
|
||||||
using NBXplorer.DerivationStrategy;
|
using NBXplorer.DerivationStrategy;
|
||||||
using NBXplorer.Models;
|
using NBXplorer.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using StoreData = BTCPayServer.Data.StoreData;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers
|
namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
@@ -476,7 +476,8 @@ namespace BTCPayServer.Controllers
|
|||||||
(int)network.NBitcoinNetwork.Consensus.GetExpectedBlocksFor(time));
|
(int)network.NBitcoinNetwork.Consensus.GetExpectedBlocksFor(time));
|
||||||
return new WalletSendModel.FeeRateOption()
|
return new WalletSendModel.FeeRateOption()
|
||||||
{
|
{
|
||||||
Target = time, FeeRate = result.SatoshiPerByte
|
Target = time,
|
||||||
|
FeeRate = result.SatoshiPerByte
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -781,13 +782,13 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
message += $"<br/><br/>{errorMessage}";
|
message += $"<br/><br/>{errorMessage}";
|
||||||
}
|
}
|
||||||
else if(message is null && errorMessage is not null)
|
else if (message is null && errorMessage is not null)
|
||||||
{
|
{
|
||||||
message = errorMessage;
|
message = errorMessage;
|
||||||
}
|
}
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Severity =someFailed? StatusMessageModel.StatusSeverity.Warning:
|
Severity = someFailed ? StatusMessageModel.StatusSeverity.Warning :
|
||||||
StatusMessageModel.StatusSeverity.Success,
|
StatusMessageModel.StatusSeverity.Success,
|
||||||
Html = message
|
Html = message
|
||||||
});
|
});
|
||||||
@@ -846,7 +847,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
private void LoadFromBIP21(WalletSendModel vm, string bip21, BTCPayNetwork network)
|
private void LoadFromBIP21(WalletSendModel vm, string bip21, BTCPayNetwork network)
|
||||||
{
|
{
|
||||||
vm.Outputs ??= new ();
|
vm.Outputs ??= new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var uriBuilder = new NBitcoin.Payment.BitcoinUrlBuilder(bip21, network.NBitcoinNetwork);
|
var uriBuilder = new NBitcoin.Payment.BitcoinUrlBuilder(bip21, network.NBitcoinNetwork);
|
||||||
@@ -1294,7 +1295,7 @@ namespace BTCPayServer.Controllers
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
var wallet = _walletProvider.GetWallet(paymentMethod.Network);
|
var wallet = _walletProvider.GetWallet(paymentMethod.Network);
|
||||||
var walletTransactionsInfoAsync = WalletRepository.GetWalletTransactionsInfo(walletId, (string[] ) null);
|
var walletTransactionsInfoAsync = WalletRepository.GetWalletTransactionsInfo(walletId, (string[])null);
|
||||||
var input = await wallet.FetchTransactionHistory(paymentMethod.AccountDerivation, null, null);
|
var input = await wallet.FetchTransactionHistory(paymentMethod.AccountDerivation, null, null);
|
||||||
var walletTransactionsInfo = await walletTransactionsInfoAsync;
|
var walletTransactionsInfo = await walletTransactionsInfoAsync;
|
||||||
var export = new TransactionsExport(wallet, walletTransactionsInfo);
|
var export = new TransactionsExport(wallet, walletTransactionsInfo);
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
|||||||
&& data.State == PayoutState.AwaitingPayment)
|
&& data.State == PayoutState.AwaitingPayment)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var pullPaymentIds = payouts.Select(data => data.PullPaymentDataId).Distinct().Where(s => s!= null).ToArray();
|
var pullPaymentIds = payouts.Select(data => data.PullPaymentDataId).Distinct().Where(s => s != null).ToArray();
|
||||||
var storeId = payouts.First().StoreDataId;
|
var storeId = payouts.First().StoreDataId;
|
||||||
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
|
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
|
||||||
List<string> bip21 = new List<string>();
|
List<string> bip21 = new List<string>();
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
|||||||
|
|
||||||
public bool CanHandle(PaymentMethodId paymentMethod)
|
public bool CanHandle(PaymentMethodId paymentMethod)
|
||||||
{
|
{
|
||||||
return (paymentMethod.PaymentType == LightningPaymentType.Instance || paymentMethod.PaymentType == LNURLPayPaymentType.Instance ) &&
|
return (paymentMethod.PaymentType == LightningPaymentType.Instance || paymentMethod.PaymentType == LNURLPayPaymentType.Instance) &&
|
||||||
_btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethod.CryptoCode)?.SupportLightning is true;
|
_btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethod.CryptoCode)?.SupportLightning is true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
|||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(result.Result == PayResult.Unknown)
|
else if (result.Result == PayResult.Unknown)
|
||||||
{
|
{
|
||||||
payoutData.State = PayoutState.InProgress;
|
payoutData.State = PayoutState.InProgress;
|
||||||
message = "The payment has been initiated but is still in-flight.";
|
message = "The payment has been initiated but is still in-flight.";
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ namespace BTCPayServer.Data
|
|||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JObject RecommendedExchanges = new ()
|
public static JObject RecommendedExchanges = new()
|
||||||
{
|
{
|
||||||
{ "EUR", "kraken" },
|
{ "EUR", "kraken" },
|
||||||
{ "USD", "kraken" },
|
{ "USD", "kraken" },
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||||||
scheme, host, pathbase);
|
scheme, host, pathbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string PayoutLink(this LinkGenerator urlHelper, string walletIdOrStoreId, string pullPaymentId, PayoutState payoutState,string scheme, HostString host, string pathbase)
|
public static string PayoutLink(this LinkGenerator urlHelper, string walletIdOrStoreId, string pullPaymentId, PayoutState payoutState, string scheme, HostString host, string pathbase)
|
||||||
{
|
{
|
||||||
WalletId.TryParse(walletIdOrStoreId, out var wallet);
|
WalletId.TryParse(walletIdOrStoreId, out var wallet);
|
||||||
return urlHelper.GetUriByAction(
|
return urlHelper.GetUriByAction(
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class FormDataService
|
|||||||
|
|
||||||
public static readonly Form StaticFormEmail = new()
|
public static readonly Form StaticFormEmail = new()
|
||||||
{
|
{
|
||||||
Fields = new List<Field>() {Field.Create("Enter your email", "buyerEmail", null, true, null, "email")}
|
Fields = new List<Field>() { Field.Create("Enter your email", "buyerEmail", null, true, null, "email") }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly Form StaticFormAddress = new()
|
public static readonly Form StaticFormAddress = new()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using BTCPayServer.Abstractions.Form;
|
|||||||
|
|
||||||
namespace BTCPayServer.Forms;
|
namespace BTCPayServer.Forms;
|
||||||
|
|
||||||
public class HtmlFieldsetFormProvider: IFormComponentProvider
|
public class HtmlFieldsetFormProvider : IFormComponentProvider
|
||||||
{
|
{
|
||||||
public string View => "Forms/FieldSetElement";
|
public string View => "Forms/FieldSetElement";
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using BTCPayServer.Validation;
|
|||||||
|
|
||||||
namespace BTCPayServer.Forms;
|
namespace BTCPayServer.Forms;
|
||||||
|
|
||||||
public class HtmlInputFormProvider: FormComponentProviderBase
|
public class HtmlInputFormProvider : FormComponentProviderBase
|
||||||
{
|
{
|
||||||
public override void Register(Dictionary<string, IFormComponentProvider> typeToComponentProvider)
|
public override void Register(Dictionary<string, IFormComponentProvider> typeToComponentProvider)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
|
|
||||||
protected BaseAsyncService(ILogger logger)
|
protected BaseAsyncService(ILogger logger)
|
||||||
{
|
{
|
||||||
Logs = new Logs() { PayServer = logger, Events = logger, Configuration = logger};
|
Logs = new Logs() { PayServer = logger, Events = logger, Configuration = logger };
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task StartAsync(CancellationToken cancellationToken)
|
public virtual Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
public EventHostedServiceBase(EventAggregator eventAggregator, ILogger logger)
|
public EventHostedServiceBase(EventAggregator eventAggregator, ILogger logger)
|
||||||
{
|
{
|
||||||
_EventAggregator = eventAggregator;
|
_EventAggregator = eventAggregator;
|
||||||
Logs = new Logs() { PayServer = logger, Events = logger, Configuration = logger};
|
Logs = new Logs() { PayServer = logger, Events = logger, Configuration = logger };
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Channel<object> _Events = Channel.CreateUnbounded<object>();
|
readonly Channel<object> _Events = Channel.CreateUnbounded<object>();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
Invoice = invoice;
|
Invoice = invoice;
|
||||||
}
|
}
|
||||||
public InvoiceEntity Invoice { get; set; }
|
public InvoiceEntity Invoice { get; set; }
|
||||||
public List<object> Events { get; set; } = new ();
|
public List<object> Events { get; set; } = new();
|
||||||
|
|
||||||
bool _dirty;
|
bool _dirty;
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
Logs = logs;
|
Logs = logs;
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly CompositeDisposable _leases = new ();
|
readonly CompositeDisposable _leases = new();
|
||||||
|
|
||||||
|
|
||||||
private void UpdateInvoice(UpdateInvoiceContext context)
|
private void UpdateInvoice(UpdateInvoiceContext context)
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
payoutHandler.StartBackgroundCheck(Subscribe);
|
payoutHandler.StartBackgroundCheck(Subscribe);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new[] {Loop()};
|
return new[] { Loop() };
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Subscribe(params Type[] events)
|
private void Subscribe(params Type[] events)
|
||||||
@@ -428,7 +428,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
switch (req.Request.State)
|
switch (req.Request.State)
|
||||||
{
|
{
|
||||||
case PayoutState.Completed or PayoutState.InProgress
|
case PayoutState.Completed or PayoutState.InProgress
|
||||||
when payout.State is not PayoutState.AwaitingPayment and not PayoutState.Completed and not PayoutState.InProgress :
|
when payout.State is not PayoutState.AwaitingPayment and not PayoutState.Completed and not PayoutState.InProgress:
|
||||||
case PayoutState.AwaitingPayment when payout.State is not PayoutState.InProgress:
|
case PayoutState.AwaitingPayment when payout.State is not PayoutState.InProgress:
|
||||||
req.Completion.SetResult(MarkPayoutRequest.PayoutPaidResult.InvalidState);
|
req.Completion.SetResult(MarkPayoutRequest.PayoutPaidResult.InvalidState);
|
||||||
return;
|
return;
|
||||||
@@ -526,7 +526,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
: await ctx.Payouts.GetPayoutInPeriod(pp, now)
|
: await ctx.Payouts.GetPayoutInPeriod(pp, now)
|
||||||
.Where(p => p.State != PayoutState.Cancelled).ToListAsync();
|
.Where(p => p.State != PayoutState.Cancelled).ToListAsync();
|
||||||
|
|
||||||
var payouts = payoutsRaw?.Select(o => new {Entity = o, Blob = o.GetBlob(_jsonSerializerSettings)});
|
var payouts = payoutsRaw?.Select(o => new { Entity = o, Blob = o.GetBlob(_jsonSerializerSettings) });
|
||||||
var limit = ppBlob?.Limit ?? 0;
|
var limit = ppBlob?.Limit ?? 0;
|
||||||
var totalPayout = payouts?.Select(p => p.Blob.Amount)?.Sum();
|
var totalPayout = payouts?.Select(p => p.Blob.Amount)?.Sum();
|
||||||
var claimed = req.ClaimRequest.Value is decimal v ? v : limit - (totalPayout ?? 0);
|
var claimed = req.ClaimRequest.Value is decimal v ? v : limit - (totalPayout ?? 0);
|
||||||
@@ -554,7 +554,8 @@ namespace BTCPayServer.HostedServices
|
|||||||
};
|
};
|
||||||
var payoutBlob = new PayoutBlob()
|
var payoutBlob = new PayoutBlob()
|
||||||
{
|
{
|
||||||
Amount = claimed, Destination = req.ClaimRequest.Destination.ToString()
|
Amount = claimed,
|
||||||
|
Destination = req.ClaimRequest.Destination.ToString()
|
||||||
};
|
};
|
||||||
payout.SetBlob(payoutBlob, _jsonSerializerSettings);
|
payout.SetBlob(payoutBlob, _jsonSerializerSettings);
|
||||||
await ctx.Payouts.AddAsync(payout);
|
await ctx.Payouts.AddAsync(payout);
|
||||||
@@ -616,7 +617,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
List<PayoutData> payouts = null;
|
List<PayoutData> payouts = null;
|
||||||
if (cancel.PullPaymentId != null)
|
if (cancel.PullPaymentId != null)
|
||||||
{
|
{
|
||||||
ctx.PullPayments.Attach(new Data.PullPaymentData() {Id = cancel.PullPaymentId, Archived = true})
|
ctx.PullPayments.Attach(new Data.PullPaymentData() { Id = cancel.PullPaymentId, Archived = true })
|
||||||
.Property(o => o.Archived).IsModified = true;
|
.Property(o => o.Archived).IsModified = true;
|
||||||
payouts = await ctx.Payouts
|
payouts = await ctx.Payouts
|
||||||
.Where(p => p.PullPaymentDataId == cancel.PullPaymentId)
|
.Where(p => p.PullPaymentDataId == cancel.PullPaymentId)
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Controllers;
|
using BTCPayServer.Controllers;
|
||||||
using BTCPayServer.Data;
|
|
||||||
using BTCPayServer.Controllers.Greenfield;
|
using BTCPayServer.Controllers.Greenfield;
|
||||||
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Services.Mails;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using BTCPayServer.Services.Invoices;
|
|
||||||
using InvoiceData = BTCPayServer.Client.Models.InvoiceData;
|
using InvoiceData = BTCPayServer.Client.Models.InvoiceData;
|
||||||
|
|
||||||
namespace BTCPayServer.HostedServices;
|
namespace BTCPayServer.HostedServices;
|
||||||
@@ -63,7 +63,7 @@ public class StoreEmailRuleProcessorSender : EventHostedServiceBase
|
|||||||
var sender = await _emailSenderFactory.GetEmailSender(invoiceEvent.Invoice.StoreId);
|
var sender = await _emailSenderFactory.GetEmailSender(invoiceEvent.Invoice.StoreId);
|
||||||
foreach (UIStoresController.StoreEmailRule actionableRule in actionableRules)
|
foreach (UIStoresController.StoreEmailRule actionableRule in actionableRules)
|
||||||
{
|
{
|
||||||
var recipients = (actionableRule.To?.Split(",", StringSplitOptions.RemoveEmptyEntries)??Array.Empty<string>())
|
var recipients = (actionableRule.To?.Split(",", StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>())
|
||||||
.Select(o =>
|
.Select(o =>
|
||||||
{
|
{
|
||||||
MailboxAddressValidator.TryParse(o, out var mb);
|
MailboxAddressValidator.TryParse(o, out var mb);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case InvoiceEvent {Name: InvoiceEvent.ReceivedPayment} invoiceEvent when
|
case InvoiceEvent { Name: InvoiceEvent.ReceivedPayment } invoiceEvent when
|
||||||
invoiceEvent.Payment.GetPaymentMethodId()?.PaymentType == BitcoinPaymentType.Instance &&
|
invoiceEvent.Payment.GetPaymentMethodId()?.PaymentType == BitcoinPaymentType.Instance &&
|
||||||
invoiceEvent.Payment.GetCryptoPaymentData() is BitcoinLikePaymentData bitcoinLikePaymentData:
|
invoiceEvent.Payment.GetCryptoPaymentData() is BitcoinLikePaymentData bitcoinLikePaymentData:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -343,11 +343,12 @@ namespace BTCPayServer.Hosting
|
|||||||
}
|
}
|
||||||
|
|
||||||
var storeids = lightningAddressSettings.StoreToItemMap.Keys.ToArray();
|
var storeids = lightningAddressSettings.StoreToItemMap.Keys.ToArray();
|
||||||
var existingStores = (await ctx.Stores.Where(data => storeids.Contains(data.Id)).Select(data => data.Id ).ToArrayAsync()).ToHashSet();
|
var existingStores = (await ctx.Stores.Where(data => storeids.Contains(data.Id)).Select(data => data.Id).ToArrayAsync()).ToHashSet();
|
||||||
|
|
||||||
foreach (var storeMap in lightningAddressSettings.StoreToItemMap)
|
foreach (var storeMap in lightningAddressSettings.StoreToItemMap)
|
||||||
{
|
{
|
||||||
if (!existingStores.Contains(storeMap.Key)) continue;
|
if (!existingStores.Contains(storeMap.Key))
|
||||||
|
continue;
|
||||||
foreach (var storeitem in storeMap.Value)
|
foreach (var storeitem in storeMap.Value)
|
||||||
{
|
{
|
||||||
if (lightningAddressSettings.Items.TryGetValue(storeitem, out var val))
|
if (lightningAddressSettings.Items.TryGetValue(storeitem, out var val))
|
||||||
@@ -404,14 +405,14 @@ WHERE cte.""Id""=p.""Id""
|
|||||||
var queryable = ctx.Payouts.Where(data => data.StoreDataId == null);
|
var queryable = ctx.Payouts.Where(data => data.StoreDataId == null);
|
||||||
var count = await queryable.CountAsync();
|
var count = await queryable.CountAsync();
|
||||||
_logger.LogInformation($"Migrating {count} payouts to have a store id explicitly");
|
_logger.LogInformation($"Migrating {count} payouts to have a store id explicitly");
|
||||||
for (int i = 0; i < count; i+=1000)
|
for (int i = 0; i < count; i += 1000)
|
||||||
{
|
{
|
||||||
await queryable.Include(data => data.PullPaymentData).Skip(i).Take(1000)
|
await queryable.Include(data => data.PullPaymentData).Skip(i).Take(1000)
|
||||||
.ForEachAsync(data => data.StoreDataId = data.PullPaymentData.StoreId);
|
.ForEachAsync(data => data.StoreDataId = data.PullPaymentData.StoreId);
|
||||||
|
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
|
||||||
_logger.LogInformation($"Migrated {i+1000}/{count} payouts to have a store id explicitly");
|
_logger.LogInformation($"Migrated {i + 1000}/{count} payouts to have a store id explicitly");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace BTCPayServer.Models.CustodianAccountViewModels
|
|||||||
{
|
{
|
||||||
public class ViewCustodianAccountBalancesViewModel
|
public class ViewCustodianAccountBalancesViewModel
|
||||||
{
|
{
|
||||||
public Dictionary<string,AssetBalanceInfo> AssetBalances { get; set; }
|
public Dictionary<string, AssetBalanceInfo> AssetBalances { get; set; }
|
||||||
public string AssetBalanceExceptionMessage { get; set; }
|
public string AssetBalanceExceptionMessage { get; set; }
|
||||||
|
|
||||||
public string StoreId { get; set; }
|
public string StoreId { get; set; }
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user