Compare commits

..

1 Commits

Author SHA1 Message Date
b9896037ba fix sln csproj ref
fixes 
2021-02-15 07:38:32 +01:00
1234 changed files with 74858 additions and 91313 deletions
.circleci
.editorconfig.gitignore
.vscode
BTCPayServer.Abstractions
BTCPayServer.Client
BTCPayServer.Client.csprojBTCPayServerClient.Invoices.csBTCPayServerClient.LNURLPayPaymentMethods.csBTCPayServerClient.Lightning.Internal.csBTCPayServerClient.Lightning.Store.csBTCPayServerClient.LightningNetworkPaymentMethods.csBTCPayServerClient.Misc.csBTCPayServerClient.Notifications.csBTCPayServerClient.OnChainPaymentMethods.csBTCPayServerClient.OnChainWallet.csBTCPayServerClient.PaymentRequests.csBTCPayServerClient.PullPayments.csBTCPayServerClient.StoreEmail.csBTCPayServerClient.StorePaymentMethods.csBTCPayServerClient.StoreUsers.csBTCPayServerClient.Users.csBTCPayServerClient.Webhooks.csBTCPayServerClient.csGreenFieldAPIException.csGreenFieldValidationException.cs
JsonConverters
Models
Permissions.cs
BTCPayServer.Common
BTCPayServer.Data
BTCPayServer.PluginPacker
BTCPayServer.Plugins.Test
BTCPayServer.Rating
BTCPayServer.Tests
BTCPayServer
BTCPayServer.csproj
Components
Configuration
Controllers
AccessTokenController.csAccountController.csAppsController.Crowdfund.csAppsController.PointOfSale.csAppsController.csAppsPublicController.csErrorController.cs
GreenField
HomeController.csInvoiceController.API.csInvoiceController.UI.csInvoiceController.csLnurlAuthService.csMacaroons.csManageController.2FA.csManageController.APIKeys.csManageController.Notifications.csManageController.U2F.csManageController.csNotificationsController.csPaymentRequestController.csPublicController.csPublicLightningNodeInfoController.csPullPaymentController.csRateController.csServerController.Plugins.csServerController.Storage.csServerController.Users.csServerController.csStorageController.csStoresController.BTCLike.csStoresController.CoinSwitch.csStoresController.Email.csStoresController.Integrations.csStoresController.LightningLike.csStoresController.Onchain.csStoresController.csUIAppsController.csUIHomeController.csUIInvoiceController.Testing.csUILNURLAuthController.csUILNURLController.csUIManageController.LoginCodes.csUIStorePullPaymentsController.PullPayments.csUIStoresController.Integrations.csUIStoresController.LightningLike.csUIStoresController.Onchain.csUIUserStoresController.csUserStoresController.csVaultController.csWalletsController.PSBT.csWalletsController.PullPayments.csWalletsController.cs
CurrencyValue.cs
Data
DerivationSchemeParser.csDerivationSchemeSettings.csEventAggregator.cs
Events
ExplorerClientProvider.csExtensions.cs
Extensions
Fido2
Filters
HostedServices
Hosting
JsonHttpException.cs
Logging
ModelBinders
Models
PaymentRequest
Payments
Plugins
Program.cs
Properties
SSH
SearchString.cs
Security
Services
Altcoins
Apps
BTCPayNetworkJsonSerializerSettings.csBTCPayServerEnvironment.csCheater.csDefaultSwaggerProvider.csDelayedTransactionBroadcaster.cs
Fees
Invoices
Labels
LanguageService.csLightningClientFactoryService.cs
Mails
MigrationSettings.csNBXSyncSummaryProvider.cs
Notifications
PayjoinClient.cs
PaymentRequests
PoliciesSettings.csSettingsRepository.cs
Shopify
Socks5HttpClientHandler.cs
Stores
ThemesSettings.csTorServices.csUserService.csWalletRepository.cs
Wallets
Storage
TagHelpers
U2F
Views
Account
Apps
AppsPublic
Error
EthereumLikeStore
Home
Invoice
Manage
MoneroLikeStore
Notifications
PaymentRequest
Public
PublicLightningNodeInfo
PullPayment
Server
Shared
Stores
UIAccount
UIApps
UIAppsPublic
UIError
UIFido2
UIHome
UIInvoice
UILNURL
UILNURLAuth
UILightning
UILightningLikePayout
UIManage
UINotifications
UIPaymentRequest
UIPublic
UIPublicLightningNodeInfo
UIServer
UIShopify
UIStorePullPayments
UIStores
UIUserStores
UIWallets
UIZcashLikeStore
UserStores
ViewsRazor.cs
Wallets
WalletId.csWebSocketHelper.csWebsocketExtensions.csWellKnownTempData.csZoneLimits.cs_ViewImports.cshtmlbundleconfig.json
wwwroot
_bootstrap_kitchensink.html
cart
checkout
crowdfund-admin
crowdfund
img
imlegacy
js
light-pos
locales
main
paybutton
payment-request-admin
payment-request
pos-admin
swagger/v1
vendor
Build
Changelog.mdLICENSEREADME.mdamd64.Dockerfilearm32v7.Dockerfilearm64v8.Dockerfilebtcpayserver.slndocker-entrypoint.shpublish-docker.ps1

@ -2,15 +2,15 @@ version: 2
jobs:
fast_tests:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- run:
command: |
cd .circleci && ./run-tests.sh "Fast=Fast|ThirdParty=ThirdParty" && ./can-build.sh
cd .circleci && ./run-tests.sh "Fast=Fast" && ./can-build.sh
selenium_tests:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- run:
@ -18,26 +18,32 @@ jobs:
cd .circleci && ./run-tests.sh "Selenium=Selenium"
integration_tests:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- run:
command: |
cd .circleci && ./run-tests.sh "Integration=Integration"
trigger_docs_build:
external_tests:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- run:
command: |
curl -X POST -H "Authorization: token $GH_PAT" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/btcpayserver/btcpayserver-doc/dispatches --data '{"event_type": "build_docs"}'
if [ "$CIRCLE_PROJECT_USERNAME" == "btcpayserver" ] && [ "$CIRCLE_PROJECT_REPONAME" == "btcpayserver" ]; then
cd .circleci && ./run-tests.sh "ExternalIntegration=ExternalIntegration"
else
echo "Skipping running ExternalIntegration tests outside of context of main user and repository that have access to secrets"
fi
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
amd64:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- checkout
- run:
command: |
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
@ -50,9 +56,9 @@ jobs:
arm32v7:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- checkout
- run:
command: |
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
@ -66,9 +72,9 @@ jobs:
arm64v8:
machine:
image: ubuntu-2004:202111-02
enabled: true
steps:
- checkout
- checkout
- run:
command: |
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
@ -82,10 +88,15 @@ jobs:
multiarch:
machine:
image: ubuntu-2004:202201-02
enabled: true
image: circleci/classic:201808-01
steps:
- run:
command: |
# Turn on Experimental features
sudo mkdir $HOME/.docker
sudo sh -c 'echo "{ \"experimental\": \"enabled\" }" >> $HOME/.docker/config.json'
#
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
#
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
@ -94,7 +105,8 @@ jobs:
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 --os linux --arch arm --variant v7
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-arm64v8 --os linux --arch arm64 --variant v8
sudo docker manifest push $DOCKERHUB_REPO:$LATEST_TAG -p
sudo docker manifest create --amend $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm64v8
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 --os linux --arch amd64
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 --os linux --arch arm --variant v7
@ -108,15 +120,12 @@ workflows:
- fast_tests
- selenium_tests
- integration_tests
publish:
jobs:
- trigger_docs_build:
- external_tests:
filters:
branches:
ignore: /.*/
# only act on version tags
tags:
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
only: master
publish:
jobs:
- amd64:
filters:
# ignore any commit on any branch by default
@ -126,6 +135,7 @@ workflows:
# OR feature tags like vlndseedbackup
# OR features on specific versions like v1.0.0.88-lndseedbackup-1
tags:
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
- arm32v7:
filters:

@ -121,11 +121,8 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_style_prefer_null_check_over_type_check = true:warning
csharp_prefer_simple_using_statement = true:warning
# C++ Files
[*.{cpp,h,in}]
curly_bracket_next_line = true
indent_brace_style = Allman

1
.gitignore vendored

@ -299,4 +299,3 @@ BTCPayServer/wwwroot/bundles/*
BTCPayServer/testpwd
.DS_Store
Packed Plugins
Plugins/packed

4
.vscode/launch.json vendored

@ -10,14 +10,14 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/BTCPayServer/bin/Debug/net6.0/BTCPayServer.dll",
"program": "${workspaceFolder}/BTCPayServer/bin/Debug/netcoreapp3.1/BTCPayServer.dll",
"args": [],
"cwd": "${workspaceFolder}/BTCPayServer",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
"pattern": "\\bListening on\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"

@ -31,12 +31,9 @@
<None Include="icon.png" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BTCPayServer.Client\BTCPayServer.Client.csproj" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
</ItemGroup>
</Project>

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

@ -1,7 +0,0 @@
namespace BTCPayServer.Abstractions.Constants;
public class WellKnownTempData
{
public const string SuccessMessage = nameof(SuccessMessage);
public const string ErrorMessage = nameof(ErrorMessage);
}

@ -9,7 +9,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
namespace BTCPayServer.Abstractions.Contracts
{
public abstract class BaseDbContextFactory<T> where T : DbContext
public abstract class BaseDbContextFactory<T> where T: DbContext
{
private readonly IOptions<DatabaseOptions> _options;
private readonly string _schemaPrefix;
@ -24,9 +24,7 @@ namespace BTCPayServer.Abstractions.Contracts
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
{
#pragma warning disable EF1001 // Internal EF Core API usage.
public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions opts) : base(dependencies, opts)
#pragma warning restore EF1001 // Internal EF Core API usage.
public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IMigrationsAnnotationProvider annotations, Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions opts) : base(dependencies, annotations, opts)
{
}
@ -92,10 +90,10 @@ namespace BTCPayServer.Abstractions.Contracts
.ReplaceService<IMigrationsSqlGenerator, CustomNpgsqlMigrationsSqlGenerator>();
break;
case DatabaseType.MySQL:
builder.UseMySql(_options.Value.ConnectionString, ServerVersion.AutoDetect(_options.Value.ConnectionString), o =>
builder.UseMySql(_options.Value.ConnectionString, o =>
{
o.EnableRetryOnFailure(10);
if (!string.IsNullOrEmpty(_schemaPrefix))
{
o.MigrationsHistoryTable(_schemaPrefix);
@ -106,6 +104,6 @@ namespace BTCPayServer.Abstractions.Contracts
throw new ArgumentOutOfRangeException();
}
}
}
}

@ -1,12 +0,0 @@
using System.Threading.Tasks;
using BTCPayServer.Client;
using Microsoft.AspNetCore.Http;
namespace BTCPayServer.Abstractions.Contracts
{
public interface IBTCPayServerClientFactory
{
Task<BTCPayServerClient> Create(string userId, params string[] storeIds);
Task<BTCPayServerClient> Create(string userId, string[] storeIds, HttpContext httpRequest);
}
}

@ -28,5 +28,5 @@ namespace BTCPayServer.Abstractions.Contracts
}
}
}
}

@ -1,17 +0,0 @@
#nullable enable
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace BTCPayServer.Abstractions.Contracts;
public interface IFileService
{
Task<bool> IsAvailable();
Task<IStoredFile> AddFile(IFormFile file, string userId);
Task<IStoredFile> AddFile(Uri file, string userId);
Task<string?> GetFileUrl(Uri baseUri, string fileId);
Task<string?> GetTemporaryFileUrl(Uri baseUri, string fileId, DateTimeOffset expiry,
bool isDownload);
Task RemoveFile(string fileId, string userId);
}

@ -7,7 +7,7 @@ namespace BTCPayServer.Abstractions.Contracts
public abstract string Identifier { get; }
public abstract string NotificationType { get; }
}
public interface INotificationHandler
{
string NotificationType { get; }
@ -15,7 +15,7 @@ namespace BTCPayServer.Abstractions.Contracts
public (string identifier, string name)[] Meta { get; }
void FillViewModel(object notification, NotificationViewModel vm);
}
public class NotificationViewModel
{
public string Id { get; set; }

@ -5,7 +5,7 @@ namespace BTCPayServer.Abstractions.Contracts
public interface IPluginHookFilter
{
public string Hook { get; }
Task<object> Execute(object args);
}
}

@ -1,4 +1,3 @@
#nullable enable
using System.Threading;
using System.Threading.Tasks;
@ -6,8 +5,8 @@ namespace BTCPayServer.Abstractions.Contracts
{
public interface ISettingsRepository
{
Task<T?> GetSettingAsync<T>(string? name = null) where T : class;
Task UpdateSetting<T>(T obj, string? name = null) where T : class;
Task<T> WaitSettingsChanged<T>(CancellationToken cancellationToken = default) where T : class;
Task<T> GetSettingAsync<T>(string name = null);
Task UpdateSetting<T>(T obj, string name = null);
Task<T> WaitSettingsChanged<T>(CancellationToken cancellationToken = default);
}
}

@ -1,12 +0,0 @@
using System;
namespace BTCPayServer.Abstractions.Contracts;
public interface IStoredFile
{
string Id { get; set; }
string FileName { get; set; }
string StorageFileName { get; set; }
DateTime Timestamp { get; set; }
string ApplicationUserId { get; set; }
}

@ -1,9 +0,0 @@
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Abstractions.Contracts;
public interface ISwaggerProvider
{
Task<JObject> Fetch();
}

@ -1,5 +1,3 @@
using System.Collections.Generic;
namespace BTCPayServer.Abstractions.Contracts
{
public interface ISyncSummaryProvider
@ -7,12 +5,5 @@ namespace BTCPayServer.Abstractions.Contracts
bool AllAvailable();
string Partial { get; }
IEnumerable<ISyncStatus> GetStatuses();
}
public interface ISyncStatus
{
public string CryptoCode { get; set; }
public bool Available { get; }
}
}

@ -3,7 +3,7 @@ namespace BTCPayServer.Abstractions.Contracts
public interface IUIExtension
{
string Partial { get; }
string Location { get; }
}
}

@ -0,0 +1,20 @@
using System.Text.Json;
using BTCPayServer.Abstractions.Models;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace BTCPayServer.Abstractions.Extensions
{
public static class SetStatusMessageModelExtensions
{
public static void SetStatusMessageModel(this ITempDataDictionary tempData, StatusMessageModel statusMessage)
{
if (statusMessage == null)
{
tempData.Remove("StatusMessageModel");
return;
}
tempData["StatusMessageModel"] = JsonSerializer.Serialize(statusMessage, new JsonSerializerOptions());
}
}
}

@ -1,43 +0,0 @@
using System.Collections.Generic;
using BTCPayServer.Client.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace BTCPayServer.Abstractions.Extensions;
public static class GreenfieldExtensions
{
public static IActionResult CreateValidationError(this ControllerBase controller, ModelStateDictionary modelState)
{
return controller.UnprocessableEntity(modelState.ToGreenfieldValidationError());
}
public static List<GreenfieldValidationError> ToGreenfieldValidationError(this ModelStateDictionary modelState)
{
List<GreenfieldValidationError> errors = new List<GreenfieldValidationError>();
foreach (var error in modelState)
{
foreach (var errorMessage in error.Value.Errors)
{
errors.Add(new GreenfieldValidationError(error.Key, errorMessage.ErrorMessage));
}
}
return errors;
}
public static IActionResult CreateAPIError(this ControllerBase controller, string errorCode, string errorMessage)
{
return controller.BadRequest(new GreenfieldAPIError(errorCode, errorMessage));
}
public static IActionResult CreateAPIError(this ControllerBase controller, int httpCode, string errorCode, string errorMessage)
{
return controller.StatusCode(httpCode, new GreenfieldAPIError(errorCode, errorMessage));
}
public static IActionResult CreateAPIPermissionError(this ControllerBase controller, string missingPermission, string message = null)
{
return controller.StatusCode(403, new GreenfieldPermissionAPIError(missingPermission, message));
}
}

@ -1,120 +0,0 @@
using System;
using Microsoft.AspNetCore.Http;
namespace BTCPayServer.Abstractions.Extensions;
public static class HttpRequestExtensions
{
public static bool IsOnion(this HttpRequest request)
{
if (request?.Host.Host == null)
return false;
return request.Host.Host.EndsWith(".onion", StringComparison.OrdinalIgnoreCase);
}
public static string GetAbsoluteRoot(this HttpRequest request)
{
return string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent(),
request.PathBase.ToUriComponent());
}
public static Uri GetAbsoluteRootUri(this HttpRequest request)
{
return new Uri(request.GetAbsoluteRoot());
}
public static string GetCurrentUrl(this HttpRequest request)
{
return string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent(),
request.PathBase.ToUriComponent(),
request.Path.ToUriComponent());
}
public static string GetCurrentPath(this HttpRequest request)
{
return string.Concat(
request.PathBase.ToUriComponent(),
request.Path.ToUriComponent());
}
public static string GetCurrentPathWithQueryString(this HttpRequest request)
{
return request.PathBase + request.Path + request.QueryString;
}
/// <summary>
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
/// If 'toto' and RootPath is empty returns '/toto'
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <returns></returns>
public static string GetRelativePath(this HttpRequest request, string path)
{
if (path.Length > 0 && path[0] != '/')
path = $"/{path}";
return string.Concat(
request.PathBase.ToUriComponent(),
path);
}
/// <summary>
/// If 'https://example.com/toto' returns 'https://example.com/toto'
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
/// If 'toto' and RootPath is empty returns '/toto'
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <returns></returns>
public static string GetRelativePathOrAbsolute(this HttpRequest request, string path)
{
if (!Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uri) ||
uri.IsAbsoluteUri)
return path;
if (path.Length > 0 && path[0] != '/')
path = $"/{path}";
return string.Concat(
request.PathBase.ToUriComponent(),
path);
}
public static string GetAbsoluteUri(this HttpRequest request, string redirectUrl)
{
bool isRelative =
(redirectUrl.Length > 0 && redirectUrl[0] == '/')
|| !new Uri(redirectUrl, UriKind.RelativeOrAbsolute).IsAbsoluteUri;
return isRelative ? request.GetAbsoluteRoot() + redirectUrl : redirectUrl;
}
/// <summary>
/// Will return an absolute URL.
/// If `relativeOrAsbolute` is absolute, returns it.
/// If `relativeOrAsbolute` is relative, send absolute url based on the HOST of this request (without PathBase)
/// </summary>
/// <param name="request"></param>
/// <param name="relativeOrAbsolte"></param>
/// <returns></returns>
public static Uri GetAbsoluteUriNoPathBase(this HttpRequest request, Uri relativeOrAbsolute = null)
{
if (relativeOrAbsolute == null)
{
return new Uri(string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent()), UriKind.Absolute);
}
if (relativeOrAbsolute.IsAbsoluteUri)
return relativeOrAbsolute;
return new Uri(string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent()) + relativeOrAbsolute.ToString().WithStartingSlash(), UriKind.Absolute);
}
}

@ -1,59 +0,0 @@
using System.Text.Json;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Models;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Abstractions.Extensions;
public static class SetStatusMessageModelExtensions
{
public static void SetStatusMessageModel(this ITempDataDictionary tempData, StatusMessageModel statusMessage)
{
if (statusMessage == null)
{
tempData.Remove("StatusMessageModel");
return;
}
tempData["StatusMessageModel"] = JsonSerializer.Serialize(statusMessage, new JsonSerializerOptions());
}
public static StatusMessageModel GetStatusMessageModel(this ITempDataDictionary tempData)
{
tempData.TryGetValue(WellKnownTempData.SuccessMessage, out var successMessage);
tempData.TryGetValue(WellKnownTempData.ErrorMessage, out var errorMessage);
tempData.TryGetValue("StatusMessageModel", out var model);
if (successMessage != null || errorMessage != null)
{
var parsedModel = new StatusMessageModel();
parsedModel.Message = (string)successMessage ?? (string)errorMessage;
if (successMessage != null)
{
parsedModel.Severity = StatusMessageModel.StatusSeverity.Success;
}
else
{
parsedModel.Severity = StatusMessageModel.StatusSeverity.Error;
}
return parsedModel;
}
else if (model != null && model is string str)
{
return JObject.Parse(str).ToObject<StatusMessageModel>();
}
return null;
}
public static bool HasStatusMessage(this ITempDataDictionary tempData)
{
return (tempData.Peek(WellKnownTempData.SuccessMessage) ??
tempData.Peek(WellKnownTempData.ErrorMessage) ??
tempData.Peek("StatusMessageModel")) != null;
}
public static bool HasErrorMessage(this ITempDataDictionary tempData)
{
return GetStatusMessageModel(tempData)?.Severity == StatusMessageModel.StatusSeverity.Error;
}
}

@ -1,45 +0,0 @@
using System;
using System.IO;
using System.Linq;
namespace BTCPayServer.Abstractions.Extensions;
public static class StringExtensions
{
public static bool IsValidFileName(this string fileName)
{
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
|| c == Path.AltDirectorySeparatorChar
|| c == Path.DirectorySeparatorChar
|| c == Path.PathSeparator
|| c == '\\');
}
public static string Truncate(this string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
return value;
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
public static string WithTrailingSlash(this string str)
{
if (str.EndsWith("/", StringComparison.InvariantCulture))
return str;
return str + "/";
}
public static string WithStartingSlash(this string str)
{
if (str.StartsWith("/", StringComparison.InvariantCulture))
return str;
return $"/{str}";
}
public static string WithoutEndingSlash(this string str)
{
if (str.EndsWith("/", StringComparison.InvariantCulture))
return str.Substring(0, str.Length - 1);
return str;
}
}

@ -1,121 +0,0 @@
using System;
using System.Globalization;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace BTCPayServer.Abstractions.Extensions
{
public static class ViewsRazor
{
private const string ACTIVE_CATEGORY_KEY = "ActiveCategory";
private const string ACTIVE_PAGE_KEY = "ActivePage";
private const string ACTIVE_ID_KEY = "ActiveId";
public static void SetActivePage<T>(this ViewDataDictionary viewData, T activePage, string title = null, string activeId = null)
where T : IConvertible
{
SetActivePage(viewData, activePage.ToString(), activePage.GetType().ToString(), title, activeId);
}
public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null)
{
// Page Title
viewData["Title"] = title ?? activePage;
// Navigation
viewData[ACTIVE_PAGE_KEY] = activePage;
viewData[ACTIVE_ID_KEY] = activeId;
SetActiveCategory(viewData, category);
}
public static void SetActiveCategory<T>(this ViewDataDictionary viewData, T activeCategory)
{
SetActiveCategory(viewData, activeCategory.ToString());
}
public static void SetActiveCategory(this ViewDataDictionary viewData, string activeCategory)
{
viewData[ACTIVE_CATEGORY_KEY] = activeCategory;
}
public static string IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
{
return IsActiveCategory(viewData, category.ToString(), id);
}
public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
{
return null;
}
var activeId = viewData[ACTIVE_ID_KEY];
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryMatch = category.Equals(activeCategory, StringComparison.InvariantCultureIgnoreCase);
var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryMatch && idMatch ? "active" : null;
}
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
where T : IConvertible
{
return IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id);
}
public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
{
return null;
}
var activeId = viewData[ACTIVE_ID_KEY];
var activePage = viewData[ACTIVE_PAGE_KEY]?.ToString();
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryAndPageMatch = (category == null || activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase)) && page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase);
var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryAndPageMatch && idMatch ? "active" : null;
}
public static HtmlString ToBrowserDate(this DateTimeOffset date)
{
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
}
public static HtmlString ToBrowserDate(this DateTime date)
{
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
}
public static string ToTimeAgo(this DateTimeOffset date)
{
var diff = DateTimeOffset.UtcNow - date;
var formatted = diff.Seconds > 0
? $"{diff.TimeString()} ago"
: $"in {diff.Negate().TimeString()}";
return formatted;
}
public static string TimeString(this TimeSpan timeSpan)
{
if (timeSpan.TotalMinutes < 1)
{
return $"{(int)timeSpan.TotalSeconds} second{Plural((int)timeSpan.TotalSeconds)}";
}
if (timeSpan.TotalHours < 1)
{
return $"{(int)timeSpan.TotalMinutes} minute{Plural((int)timeSpan.TotalMinutes)}";
}
if (timeSpan.Days < 1)
{
return $"{(int)timeSpan.TotalHours} hour{Plural((int)timeSpan.TotalHours)}";
}
return $"{(int)timeSpan.TotalDays} day{Plural((int)timeSpan.TotalDays)}";
}
private static string Plural(int totalDays)
{
return totalDays > 1 ? "s" : string.Empty;
}
}
}

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

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

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

@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>10.0</LangVersion>
<Company>BTCPay Server</Company>
<Copyright>Copyright © BTCPay Server 2020</Copyright>
<Description>A client library for BTCPay Server Greenfield API</Description>
@ -14,7 +13,7 @@
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<PropertyGroup>
<Version Condition=" '$(Version)' == '' ">1.6.0</Version>
<Version Condition=" '$(Version)' == '' ">1.2.0</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PublishRepositoryUrl>true</PublishRepositoryUrl>
@ -28,9 +27,9 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NBitcoin" Version="7.0.1" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NBitcoin" Version="5.0.73" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>
<None Include="icon.png" Pack="true" PackagePath="\" />

@ -1,56 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using NBitcoin;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<InvoiceData>> GetInvoices(string storeId, string[] orderId = null,
InvoiceStatus[] status = null,
DateTimeOffset? startDate = null,
DateTimeOffset? endDate = null,
string textSearch = null,
bool includeArchived = false,
int? skip = null,
int? take = null,
public virtual async Task<IEnumerable<InvoiceData>> GetInvoices(string storeId, bool includeArchived = false,
CancellationToken token = default)
{
Dictionary<string, object> queryPayload = new Dictionary<string, object>();
queryPayload.Add(nameof(includeArchived), includeArchived);
if (startDate is DateTimeOffset s)
queryPayload.Add(nameof(startDate), Utils.DateTimeToUnixTime(s));
if (endDate is DateTimeOffset e)
queryPayload.Add(nameof(endDate), Utils.DateTimeToUnixTime(e));
if (orderId != null)
queryPayload.Add(nameof(orderId), orderId);
if (textSearch != null)
queryPayload.Add(nameof(textSearch), textSearch);
if (status != null)
queryPayload.Add(nameof(status), status.Select(s => s.ToString().ToLower()).ToArray());
if (skip != null)
{
queryPayload.Add(nameof(skip), skip);
}
if (take != null)
{
queryPayload.Add(nameof(take), take);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices",
queryPayload), token);
new Dictionary<string, object>() {{nameof(includeArchived), includeArchived}}), token);
return await HandleResponse<IEnumerable<InvoiceData>>(response);
}
@ -105,7 +70,7 @@ namespace BTCPayServer.Client
{
if (request == null)
throw new ArgumentNullException(nameof(request));
if (request.Status != InvoiceStatus.Settled && request.Status != InvoiceStatus.Invalid)
if (request.Status!= InvoiceStatus.Settled && request.Status!= InvoiceStatus.Invalid)
throw new ArgumentOutOfRangeException(nameof(request.Status), "Status can only be Invalid or Complete");
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/status", bodyPayload: request,
@ -116,17 +81,9 @@ namespace BTCPayServer.Client
public virtual async Task<InvoiceData> UnarchiveInvoice(string storeId, string invoiceId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive",
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive",
method: HttpMethod.Post), token);
return await HandleResponse<InvoiceData>(response);
}
public virtual async Task ActivateInvoicePaymentMethod(string storeId, string invoiceId, string paymentMethod, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate",
method: HttpMethod.Post), token);
await HandleResponse(response);
}
}
}

@ -1,59 +0,0 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<LNURLPayPaymentMethodData>>
GetStoreLNURLPayPaymentMethods(string storeId, bool? enabled = null,
CancellationToken token = default)
{
var query = new Dictionary<string, object>();
if (enabled != null)
{
query.Add(nameof(enabled), enabled);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay",
query), token);
return await HandleResponse<IEnumerable<LNURLPayPaymentMethodData>>(response);
}
public virtual async Task<LNURLPayPaymentMethodData> GetStoreLNURLPayPaymentMethod(
string storeId,
string cryptoCode, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay/{cryptoCode}"), token);
return await HandleResponse<LNURLPayPaymentMethodData>(response);
}
public virtual async Task RemoveStoreLNURLPayPaymentMethod(string storeId,
string cryptoCode, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay/{cryptoCode}",
method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<LNURLPayPaymentMethodData> UpdateStoreLNURLPayPaymentMethod(
string storeId,
string cryptoCode, LNURLPayPaymentMethodData paymentMethod,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay/{cryptoCode}",
bodyPayload: paymentMethod, method: HttpMethod.Put), token);
return await HandleResponse<LNURLPayPaymentMethodData>(response);
}
}
}

@ -9,7 +9,7 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<LightningNodeInformationData> GetLightningNodeInfo(string cryptoCode,
public async Task<LightningNodeInformationData> GetLightningNodeInfo(string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
@ -18,7 +18,7 @@ namespace BTCPayServer.Client
return await HandleResponse<LightningNodeInformationData>(response);
}
public virtual async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
public async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
CancellationToken token = default)
{
if (request == null)
@ -29,7 +29,7 @@ namespace BTCPayServer.Client
await HandleResponse(response);
}
public virtual async Task<IEnumerable<LightningChannelData>> GetLightningNodeChannels(string cryptoCode,
public async Task<IEnumerable<LightningChannelData>> GetLightningNodeChannels(string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
@ -38,23 +38,24 @@ namespace BTCPayServer.Client
return await HandleResponse<IEnumerable<LightningChannelData>>(response);
}
public virtual async Task OpenLightningChannel(string cryptoCode, OpenLightningChannelRequest request,
public async Task<string> OpenLightningChannel(string cryptoCode, OpenLightningChannelRequest request,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/channels", bodyPayload: request,
method: HttpMethod.Post), token);
await HandleResponse(response);
return await HandleResponse<string>(response);
}
public virtual async Task<string> GetLightningDepositAddress(string cryptoCode, CancellationToken token = default)
public async Task<string> GetLightningDepositAddress(string cryptoCode, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/address", method: HttpMethod.Post), token);
return await HandleResponse<string>(response);
}
public virtual async Task<LightningPaymentData> PayLightningInvoice(string cryptoCode, PayLightningInvoiceRequest request,
public async Task PayLightningInvoice(string cryptoCode, PayLightningInvoiceRequest request,
CancellationToken token = default)
{
if (request == null)
@ -62,10 +63,10 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/invoices/pay", bodyPayload: request,
method: HttpMethod.Post), token);
return await HandleResponse<LightningPaymentData>(response);
await HandleResponse(response);
}
public virtual async Task<LightningInvoiceData> GetLightningInvoice(string cryptoCode,
public async Task<LightningInvoiceData> GetLightningInvoice(string cryptoCode,
string invoiceId, CancellationToken token = default)
{
if (invoiceId == null)
@ -76,7 +77,7 @@ namespace BTCPayServer.Client
return await HandleResponse<LightningInvoiceData>(response);
}
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string cryptoCode, CreateLightningInvoiceRequest request,
public async Task<LightningInvoiceData> CreateLightningInvoice(string cryptoCode, CreateLightningInvoiceRequest request,
CancellationToken token = default)
{
if (request == null)

@ -9,7 +9,7 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<LightningNodeInformationData> GetLightningNodeInfo(string storeId, string cryptoCode,
public async Task<LightningNodeInformationData> GetLightningNodeInfo(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
@ -18,7 +18,7 @@ namespace BTCPayServer.Client
return await HandleResponse<LightningNodeInformationData>(response);
}
public virtual async Task ConnectToLightningNode(string storeId, string cryptoCode, ConnectToNodeRequest request,
public async Task ConnectToLightningNode(string storeId, string cryptoCode, ConnectToNodeRequest request,
CancellationToken token = default)
{
if (request == null)
@ -29,7 +29,7 @@ namespace BTCPayServer.Client
await HandleResponse(response);
}
public virtual async Task<IEnumerable<LightningChannelData>> GetLightningNodeChannels(string storeId, string cryptoCode,
public async Task<IEnumerable<LightningChannelData>> GetLightningNodeChannels(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
@ -38,16 +38,16 @@ namespace BTCPayServer.Client
return await HandleResponse<IEnumerable<LightningChannelData>>(response);
}
public virtual async Task OpenLightningChannel(string storeId, string cryptoCode, OpenLightningChannelRequest request,
public async Task<string> OpenLightningChannel(string storeId, string cryptoCode, OpenLightningChannelRequest request,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/channels", bodyPayload: request,
method: HttpMethod.Post), token);
await HandleResponse(response);
return await HandleResponse<string>(response);
}
public virtual async Task<string> GetLightningDepositAddress(string storeId, string cryptoCode,
public async Task<string> GetLightningDepositAddress(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
@ -56,7 +56,7 @@ namespace BTCPayServer.Client
return await HandleResponse<string>(response);
}
public virtual async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request,
public async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request,
CancellationToken token = default)
{
if (request == null)
@ -67,7 +67,7 @@ namespace BTCPayServer.Client
await HandleResponse(response);
}
public virtual async Task<LightningInvoiceData> GetLightningInvoice(string storeId, string cryptoCode,
public async Task<LightningInvoiceData> GetLightningInvoice(string storeId, string cryptoCode,
string invoiceId, CancellationToken token = default)
{
if (invoiceId == null)
@ -78,7 +78,7 @@ namespace BTCPayServer.Client
return await HandleResponse<LightningInvoiceData>(response);
}
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string storeId, string cryptoCode,
public async Task<LightningInvoiceData> CreateLightningInvoice(string storeId, string cryptoCode,
CreateLightningInvoiceRequest request, CancellationToken token = default)
{
if (request == null)

@ -1,59 +0,0 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<LightningNetworkPaymentMethodData>>
GetStoreLightningNetworkPaymentMethods(string storeId, bool? enabled = null,
CancellationToken token = default)
{
var query = new Dictionary<string, object>();
if (enabled != null)
{
query.Add(nameof(enabled), enabled);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork",
query), token);
return await HandleResponse<IEnumerable<LightningNetworkPaymentMethodData>>(response);
}
public virtual async Task<LightningNetworkPaymentMethodData> GetStoreLightningNetworkPaymentMethod(
string storeId,
string cryptoCode, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork/{cryptoCode}"), token);
return await HandleResponse<LightningNetworkPaymentMethodData>(response);
}
public virtual async Task RemoveStoreLightningNetworkPaymentMethod(string storeId,
string cryptoCode, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork/{cryptoCode}",
method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<LightningNetworkPaymentMethodData> UpdateStoreLightningNetworkPaymentMethod(
string storeId,
string cryptoCode, UpdateLightningNetworkPaymentMethodRequest paymentMethod,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork/{cryptoCode}",
bodyPayload: paymentMethod, method: HttpMethod.Put), token);
return await HandleResponse<LightningNetworkPaymentMethodData>(response);
}
}
}

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<PermissionMetadata[]> GetPermissionMetadata(CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest("misc/permissions"), token);
return await HandleResponse<PermissionMetadata[]>(response);
}
public virtual async Task<Language[]> GetAvailableLanguages(CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest("misc/lang"), token);
return await HandleResponse<Language[]>(response);
}
}
}

@ -9,22 +9,13 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null, int? skip = null,
int? take = null, CancellationToken token = default)
public virtual async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null,
CancellationToken token = default)
{
Dictionary<string, object> queryPayload = new Dictionary<string, object>();
if (seen != null)
queryPayload.Add(nameof(seen), seen);
if (skip != null)
queryPayload.Add(nameof(skip), skip);
if (take != null)
queryPayload.Add(nameof(take), take);
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications",
queryPayload), token);
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications",
seen != null ? new Dictionary<string, object>() {{nameof(seen), seen}} : null), token);
return await HandleResponse<IEnumerable<NotificationData>>(response);
}
@ -41,7 +32,7 @@ namespace BTCPayServer.Client
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}",
method: HttpMethod.Put, bodyPayload: new UpdateNotification() { Seen = seen }), token);
method: HttpMethod.Put, bodyPayload: new UpdateNotification() {Seen = seen}), token);
return await HandleResponse<NotificationData>(response);
}

@ -9,19 +9,11 @@ namespace BTCPayServer.Client
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<OnChainPaymentMethodData>> GetStoreOnChainPaymentMethods(string storeId,
bool? enabled = null,
CancellationToken token = default)
{
var query = new Dictionary<string, object>();
if (enabled != null)
{
query.Add(nameof(enabled), enabled);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain",
query), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain"), token);
return await HandleResponse<IEnumerable<OnChainPaymentMethodData>>(response);
}
@ -45,7 +37,7 @@ namespace BTCPayServer.Client
}
public virtual async Task<OnChainPaymentMethodData> UpdateStoreOnChainPaymentMethod(string storeId,
string cryptoCode, UpdateOnChainPaymentMethodRequest paymentMethod,
string cryptoCode, OnChainPaymentMethodData paymentMethod,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
@ -56,14 +48,14 @@ namespace BTCPayServer.Client
public virtual async Task<OnChainPaymentMethodPreviewResultData>
PreviewProposedStoreOnChainPaymentMethodAddresses(
string storeId, string cryptoCode, UpdateOnChainPaymentMethodRequest paymentMethod, int offset = 0,
string storeId, string cryptoCode, OnChainPaymentMethodData paymentMethod, int offset = 0,
int amount = 10,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview",
bodyPayload: paymentMethod,
queryPayload: new Dictionary<string, object>() { { "offset", offset }, { "amount", amount } },
queryPayload: new Dictionary<string, object>() {{"offset", offset}, {"amount", amount}},
method: HttpMethod.Post), token);
return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response);
}
@ -74,21 +66,9 @@ namespace BTCPayServer.Client
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview",
queryPayload: new Dictionary<string, object>() { { "offset", offset }, { "amount", amount } },
queryPayload: new Dictionary<string, object>() {{"offset", offset}, {"amount", amount}},
method: HttpMethod.Get), token);
return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response);
}
public virtual async Task<OnChainPaymentMethodDataWithSensitiveData> GenerateOnChainWallet(string storeId,
string cryptoCode, GenerateOnChainWalletRequest request,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/generate",
bodyPayload: request,
method: HttpMethod.Post), token);
return await HandleResponse<OnChainPaymentMethodDataWithSensitiveData>(response);
}
}
}

@ -1,122 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using NBitcoin;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<OnChainWalletOverviewData> ShowOnChainWalletOverview(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet"), token);
return await HandleResponse<OnChainWalletOverviewData>(response);
}
public virtual async Task<OnChainWalletFeeRateData> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null,
CancellationToken token = default)
{
Dictionary<string, object> queryParams = new Dictionary<string, object>();
if (blockTarget != null)
{
queryParams.Add("blockTarget", blockTarget);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/feeRate", queryParams), token);
return await HandleResponse<OnChainWalletFeeRateData>(response);
}
public virtual async Task<OnChainWalletAddressData> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address", new Dictionary<string, object>()
{
{"forceGenerate", forceGenerate}
}), token);
return await HandleResponse<OnChainWalletAddressData>(response);
}
public virtual async Task UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address", method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<IEnumerable<OnChainWalletTransactionData>> ShowOnChainWalletTransactions(
string storeId, string cryptoCode, TransactionStatus[] statusFilter = null,
CancellationToken token = default)
{
var query = new Dictionary<string, object>();
if (statusFilter?.Any() is true)
{
query.Add(nameof(statusFilter), statusFilter);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", query), token);
return await HandleResponse<IEnumerable<OnChainWalletTransactionData>>(response);
}
public virtual async Task<OnChainWalletTransactionData> GetOnChainWalletTransaction(
string storeId, string cryptoCode, string transactionId,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions/{transactionId}"), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
public virtual async Task<IEnumerable<OnChainWalletUTXOData>> GetOnChainWalletUTXOs(string storeId,
string cryptoCode,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/utxos"), token);
return await HandleResponse<IEnumerable<OnChainWalletUTXOData>>(response);
}
public virtual async Task<OnChainWalletTransactionData> CreateOnChainTransaction(string storeId,
string cryptoCode, CreateOnChainTransactionRequest request,
CancellationToken token = default)
{
if (!request.ProceedWithBroadcast)
{
throw new ArgumentOutOfRangeException(nameof(request.ProceedWithBroadcast),
"Please use CreateOnChainTransactionButDoNotBroadcast when wanting to only create the transaction");
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
public virtual async Task<Transaction> CreateOnChainTransactionButDoNotBroadcast(string storeId,
string cryptoCode, CreateOnChainTransactionRequest request, Network network,
CancellationToken token = default)
{
if (request.ProceedWithBroadcast)
{
throw new ArgumentOutOfRangeException(nameof(request.ProceedWithBroadcast),
"Please use CreateOnChainTransaction when wanting to also broadcast the transaction");
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
return Transaction.Parse(await HandleResponse<string>(response), network);
}
}
}

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

@ -9,18 +9,18 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<PullPaymentData> CreatePullPayment(string storeId, CreatePullPaymentRequest request, CancellationToken cancellationToken = default)
public async Task<PullPaymentData> CreatePullPayment(string storeId, CreatePullPaymentRequest request, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/pull-payments", bodyPayload: request, method: HttpMethod.Post), cancellationToken);
return await HandleResponse<PullPaymentData>(response);
}
public virtual async Task<PullPaymentData> GetPullPayment(string pullPaymentId, CancellationToken cancellationToken = default)
public async Task<PullPaymentData> GetPullPayment(string pullPaymentId, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}", method: HttpMethod.Get), cancellationToken);
return await HandleResponse<PullPaymentData>(response);
}
public virtual async Task<PullPaymentData[]> GetPullPayments(string storeId, bool includeArchived = false, CancellationToken cancellationToken = default)
public async Task<PullPaymentData[]> GetPullPayments(string storeId, bool includeArchived = false, CancellationToken cancellationToken = default)
{
Dictionary<string, object> query = new Dictionary<string, object>();
query.Add("includeArchived", includeArchived);
@ -28,44 +28,34 @@ namespace BTCPayServer.Client
return await HandleResponse<PullPaymentData[]>(response);
}
public virtual async Task ArchivePullPayment(string storeId, string pullPaymentId, CancellationToken cancellationToken = default)
public async Task ArchivePullPayment(string storeId, string pullPaymentId, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}", method: HttpMethod.Delete), cancellationToken);
await HandleResponse(response);
}
public virtual async Task<PayoutData[]> GetPayouts(string pullPaymentId, bool includeCancelled = false, CancellationToken cancellationToken = default)
public async Task<PayoutData[]> GetPayouts(string pullPaymentId, bool includeCancelled = false, CancellationToken cancellationToken = default)
{
Dictionary<string, object> query = new Dictionary<string, object>();
query.Add("includeCancelled", includeCancelled);
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}/payouts", queryPayload: query, method: HttpMethod.Get), cancellationToken);
return await HandleResponse<PayoutData[]>(response);
}
public virtual async Task<PayoutData> CreatePayout(string pullPaymentId, CreatePayoutRequest payoutRequest, CancellationToken cancellationToken = default)
public async Task<PayoutData> CreatePayout(string pullPaymentId, CreatePayoutRequest payoutRequest, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}/payouts", bodyPayload: payoutRequest, method: HttpMethod.Post), cancellationToken);
return await HandleResponse<PayoutData>(response);
}
public virtual async Task CancelPayout(string storeId, string payoutId, CancellationToken cancellationToken = default)
public async Task CancelPayout(string storeId, string payoutId, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/payouts/{HttpUtility.UrlEncode(payoutId)}", method: HttpMethod.Delete), cancellationToken);
await HandleResponse(response);
}
public virtual async Task<PayoutData> ApprovePayout(string storeId, string payoutId, ApprovePayoutRequest request, CancellationToken cancellationToken = default)
public async Task<PayoutData> ApprovePayout(string storeId, string payoutId, ApprovePayoutRequest request, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/payouts/{HttpUtility.UrlEncode(payoutId)}", bodyPayload: request, method: HttpMethod.Post), cancellationToken);
return await HandleResponse<PayoutData>(response);
}
public async Task MarkPayoutPaid(string storeId, string payoutId,
CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest(
$"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/payouts/{HttpUtility.UrlEncode(payoutId)}/mark-paid",
method: HttpMethod.Post), cancellationToken);
await HandleResponse(response);
}
}
}

@ -1,37 +0,0 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<EmailSettingsData> GetStoreEmailSettings(string storeId,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/email", method: HttpMethod.Get),
token);
return await HandleResponse<EmailSettingsData>(response);
}
public virtual async Task<EmailSettingsData> UpdateStoreEmailSettings(string storeId, EmailSettingsData request,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/email", bodyPayload: request, method: HttpMethod.Put),
token);
return await HandleResponse<EmailSettingsData>(response);
}
public virtual async Task SendEmail(string storeId, SendEmailRequest request,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/email/send", bodyPayload: request, method: HttpMethod.Post),
token);
await HandleResponse(response);
}
}
}

@ -1,27 +0,0 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<Dictionary<string, GenericPaymentMethodData>> GetStorePaymentMethods(string storeId,
bool? enabled = null,
CancellationToken token = default)
{
var query = new Dictionary<string, object>();
if (enabled != null)
{
query.Add(nameof(enabled), enabled);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods",
query), token);
return await HandleResponse<Dictionary<string, GenericPaymentMethodData>>(response);
}
}
}

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<StoreUserData>> GetStoreUsers(string storeId,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/users"), token);
return await HandleResponse<IEnumerable<StoreUserData>>(response);
}
public virtual async Task RemoveStoreUser(string storeId, string userId, CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/users/{userId}", method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task AddStoreUser(string storeId, StoreUserData request,
CancellationToken token = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/users", bodyPayload: request, method: HttpMethod.Post),
token);
await HandleResponse(response);
}
}
}

@ -1,4 +1,3 @@
#nullable enable
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@ -20,28 +19,5 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/users", null, request, HttpMethod.Post), token);
return await HandleResponse<ApplicationUserData>(response);
}
public virtual async Task DeleteUser(string userId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}", null, HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<ApplicationUserData> GetUserByIdOrEmail(string idOrEmail, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}", null, HttpMethod.Get), token);
return await HandleResponse<ApplicationUserData>(response);
}
public virtual async Task<ApplicationUserData[]> GetUsers( CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/", null, HttpMethod.Get), token);
return await HandleResponse<ApplicationUserData[]>(response);
}
public virtual async Task DeleteCurrentUser(CancellationToken token = default)
{
await DeleteUser("me", token);
}
}
}

@ -1,58 +1,60 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<StoreWebhookData> CreateWebhook(string storeId, Client.Models.CreateStoreWebhookRequest create, CancellationToken token = default)
public async Task<StoreWebhookData> CreateWebhook(string storeId, Client.Models.CreateStoreWebhookRequest create, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks", bodyPayload: create, method: HttpMethod.Post), token);
return await HandleResponse<StoreWebhookData>(response);
}
public virtual async Task<StoreWebhookData> GetWebhook(string storeId, string webhookId, CancellationToken token = default)
public async Task<StoreWebhookData> GetWebhook(string storeId, string webhookId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}"), token);
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
return null;
return await HandleResponse<StoreWebhookData>(response);
}
public virtual async Task<StoreWebhookData> UpdateWebhook(string storeId, string webhookId, Models.UpdateStoreWebhookRequest update, CancellationToken token = default)
public async Task<StoreWebhookData> UpdateWebhook(string storeId, string webhookId, Models.UpdateStoreWebhookRequest update, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}", bodyPayload: update, method: HttpMethod.Put), token);
return await HandleResponse<StoreWebhookData>(response);
}
public virtual async Task<bool> DeleteWebhook(string storeId, string webhookId, CancellationToken token = default)
public async Task<bool> DeleteWebhook(string storeId, string webhookId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}", method: HttpMethod.Delete), token);
return response.IsSuccessStatusCode;
}
public virtual async Task<StoreWebhookData[]> GetWebhooks(string storeId, CancellationToken token = default)
public async Task<StoreWebhookData[]> GetWebhooks(string storeId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks"), token);
return await HandleResponse<StoreWebhookData[]>(response);
}
public virtual async Task<WebhookDeliveryData[]> GetWebhookDeliveries(string storeId, string webhookId, CancellationToken token = default)
public async Task<WebhookDeliveryData[]> GetWebhookDeliveries(string storeId, string webhookId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}/deliveries"), token);
return await HandleResponse<WebhookDeliveryData[]>(response);
}
public virtual async Task<WebhookDeliveryData> GetWebhookDelivery(string storeId, string webhookId, string deliveryId, CancellationToken token = default)
public async Task<WebhookDeliveryData> GetWebhookDelivery(string storeId, string webhookId, string deliveryId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}/deliveries/{deliveryId}"), token);
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
return null;
return await HandleResponse<WebhookDeliveryData>(response);
}
public virtual async Task<string> RedeliverWebhook(string storeId, string webhookId, string deliveryId, CancellationToken token = default)
public async Task<string> RedeliverWebhook(string storeId, string webhookId, string deliveryId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}/deliveries/{deliveryId}/redeliver", null, HttpMethod.Post), token);
return await HandleResponse<string>(response);
}
public virtual async Task<WebhookEvent> GetWebhookDeliveryRequest(string storeId, string webhookId, string deliveryId, CancellationToken token = default)
public async Task<WebhookEvent> GetWebhookDeliveryRequest(string storeId, string webhookId, string deliveryId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/webhooks/{webhookId}/deliveries/{deliveryId}/request"), token);
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)

@ -5,7 +5,6 @@ using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
@ -18,6 +17,7 @@ namespace BTCPayServer.Client
private readonly string _username;
private readonly string _password;
private readonly HttpClient _httpClient;
public Uri Host => _btcpayHost;
public string APIKey => _apiKey;
@ -47,25 +47,18 @@ namespace BTCPayServer.Client
protected async Task HandleResponse(HttpResponseMessage message)
{
if (!message.IsSuccessStatusCode && message.Content?.Headers?.ContentType?.MediaType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) is true)
if (message.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity)
{
if (message.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(await message.Content.ReadAsStringAsync());
throw new GreenfieldValidationException(err);
}
if (message.StatusCode == System.Net.HttpStatusCode.Forbidden)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldPermissionAPIError>(await message.Content.ReadAsStringAsync());
throw new GreenfieldAPIException((int)message.StatusCode, err);
}
else
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldAPIError>(await message.Content.ReadAsStringAsync());
if (err.Code != null)
throw new GreenfieldAPIException((int)message.StatusCode, err);
}
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(await message.Content.ReadAsStringAsync());
;
throw new GreenFieldValidationException(err);
}
else if (message.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldAPIError>(await message.Content.ReadAsStringAsync());
throw new GreenFieldAPIException(err);
}
message.EnsureSuccessStatusCode();
}
@ -76,20 +69,6 @@ namespace BTCPayServer.Client
return JsonConvert.DeserializeObject<T>(str);
}
public async Task<T> SendHttpRequest<T>(string path,
Dictionary<string, object> queryPayload = null,
HttpMethod method = null, CancellationToken cancellationToken = default)
{
using var resp = await _httpClient.SendAsync(CreateHttpRequest(path, queryPayload, method), cancellationToken);
return await HandleResponse<T>(resp);
}
public async Task<T> SendHttpRequest<T>(string path,
object bodyPayload = null,
HttpMethod method = null, CancellationToken cancellationToken = default)
{
using var resp = await _httpClient.SendAsync(CreateHttpRequest(path: path, bodyPayload: bodyPayload, method: method), cancellationToken);
return await HandleResponse<T>(resp);
}
protected virtual HttpRequestMessage CreateHttpRequest(string path,
Dictionary<string, object> queryPayload = null,
HttpMethod method = null)

@ -2,16 +2,14 @@ using System;
namespace BTCPayServer.Client
{
public class GreenfieldAPIException : Exception
public class GreenFieldAPIException : Exception
{
public GreenfieldAPIException(int httpCode, Models.GreenfieldAPIError error) : base(error.Message)
public GreenFieldAPIException(Models.GreenfieldAPIError error) : base(error.Message)
{
if (error == null)
throw new ArgumentNullException(nameof(error));
HttpCode = httpCode;
APIError = error;
}
public Models.GreenfieldAPIError APIError { get; }
public int HttpCode { get; set; }
}
}

@ -4,9 +4,9 @@ using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public class GreenfieldValidationException : Exception
public class GreenFieldValidationException : Exception
{
public GreenfieldValidationException(Models.GreenfieldValidationError[] errors) : base(BuildMessage(errors))
public GreenFieldValidationException(Models.GreenfieldValidationError[] errors) : base(BuildMessage(errors))
{
ValidationErrors = errors;
}

@ -1,31 +0,0 @@
using System;
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.JsonConverters
{
public class MnemonicJsonConverter : JsonConverter<Mnemonic>
{
public override Mnemonic ReadJson(JsonReader reader, Type objectType, Mnemonic existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
return reader.TokenType switch
{
JsonToken.String => new Mnemonic((string)reader.Value),
JsonToken.Null => null,
_ => throw new JsonObjectException(reader.Path, "Mnemonic must be a json string")
};
}
public override void WriteJson(JsonWriter writer, Mnemonic value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(value.ToString());
else
{
writer.WriteNull();
}
}
}
}

@ -19,7 +19,7 @@ namespace BTCPayServer.Client.JsonConverters
public override void WriteJson(JsonWriter writer, [AllowNull] NodeInfo value, JsonSerializer serializer)
{
if (value is not null)
if (value is NodeInfo)
writer.WriteValue(value.ToString());
}
}

@ -22,17 +22,13 @@ namespace BTCPayServer.JsonConverters
switch (token.Type)
{
case JTokenType.Float:
if (objectType == typeof(decimal) || objectType == typeof(decimal?))
return token.Value<decimal>();
if (objectType == typeof(double) || objectType == typeof(double?))
return token.Value<double>();
throw new JsonSerializationException("Unexpected object type: " + objectType);
case JTokenType.Integer:
case JTokenType.String:
if (objectType == typeof(decimal) || objectType == typeof(decimal?))
if (objectType == typeof(decimal) || objectType == typeof(decimal?) )
return decimal.Parse(token.ToString(), CultureInfo.InvariantCulture);
if (objectType == typeof(double) || objectType == typeof(double?))
return double.Parse(token.ToString(), CultureInfo.InvariantCulture);
throw new JsonSerializationException("Unexpected object type: " + objectType);
case JTokenType.Null when objectType == typeof(decimal?) || objectType == typeof(double?):
return null;

@ -29,17 +29,6 @@ namespace BTCPayServer.Client.JsonConverters
return TimeSpan.FromMinutes(value);
}
}
public class Days : TimeSpanJsonConverter
{
protected override long ToLong(TimeSpan value)
{
return (long)value.TotalDays;
}
protected override TimeSpan ToTimespan(long value)
{
return TimeSpan.FromDays(value);
}
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TimeSpan) || objectType == typeof(TimeSpan?);

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NBitcoin;
using Newtonsoft.Json;
public class WordcountJsonConverter : JsonConverter
{
static WordcountJsonConverter()
{
_Wordcount = new Dictionary<long, WordCount>()
{
{18, WordCount.Eighteen},
{15, WordCount.Fifteen},
{12, WordCount.Twelve},
{24, WordCount.TwentyFour},
{21, WordCount.TwentyOne}
};
_WordcountReverse = _Wordcount.ToDictionary(kv => kv.Value, kv => kv.Key);
}
public override bool CanConvert(Type objectType)
{
return typeof(NBitcoin.WordCount).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()) ||
typeof(NBitcoin.WordCount?).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return default;
if (reader.TokenType != JsonToken.Integer)
throw new NBitcoin.JsonConverters.JsonObjectException(
$"Unexpected json token type, expected Integer, actual {reader.TokenType}", reader);
if (!_Wordcount.TryGetValue((long)reader.Value, out var result))
throw new NBitcoin.JsonConverters.JsonObjectException(
$"Invalid WordCount, possible values {string.Join(", ", _Wordcount.Keys.ToArray())} (default: 12)",
reader);
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is WordCount wc)
writer.WriteValue(_WordcountReverse[wc]);
}
readonly static Dictionary<long, WordCount> _Wordcount = new Dictionary<long, WordCount>()
{
{18, WordCount.Eighteen},
{15, WordCount.Fifteen},
{12, WordCount.Twelve},
{24, WordCount.TwentyFour},
{21, WordCount.TwentyOne}
};
readonly static Dictionary<WordCount, long> _WordcountReverse;
}

@ -1,55 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NBitcoin;
using Newtonsoft.Json;
public class WordlistJsonConverter : JsonConverter
{
static WordlistJsonConverter()
{
_Wordlists = new Dictionary<string, Wordlist>(StringComparer.OrdinalIgnoreCase)
{
{"English", Wordlist.English},
{"Japanese", Wordlist.Japanese},
{"Spanish", Wordlist.Spanish},
{"ChineseSimplified", Wordlist.ChineseSimplified},
{"ChineseTraditional", Wordlist.ChineseTraditional},
{"French", Wordlist.French},
{"PortugueseBrazil", Wordlist.PortugueseBrazil},
{"Czech", Wordlist.Czech}
};
_WordlistsReverse = _Wordlists.ToDictionary(kv => kv.Value, kv => kv.Key);
}
public override bool CanConvert(Type objectType)
{
return typeof(Wordlist).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
if (reader.TokenType != JsonToken.String)
throw new NBitcoin.JsonConverters.JsonObjectException(
$"Unexpected json token type, expected String, actual {reader.TokenType}", reader);
if (!_Wordlists.TryGetValue((string)reader.Value, out var result))
throw new NBitcoin.JsonConverters.JsonObjectException(
$"Invalid wordlist, possible values {string.Join(", ", _Wordlists.Keys.ToArray())} (default: English)",
reader);
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is Wordlist wl)
writer.WriteValue(_WordlistsReverse[wl]);
}
readonly static Dictionary<string, Wordlist> _Wordlists;
readonly static Dictionary<Wordlist, string> _WordlistsReverse;
}

@ -4,4 +4,4 @@ namespace BTCPayServer.Client.Models
{
public string Email { get; set; }
}
}
}

@ -1,12 +1,39 @@
using System;
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models
{
public class CreateInvoiceRequest : InvoiceDataBase
public class CreateInvoiceRequest
{
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? Amount { get; set; }
public string[] AdditionalSearchTerms { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
public JObject Metadata { get; set; }
public CheckoutOptions Checkout { get; set; } = new CheckoutOptions();
public class CheckoutOptions
{
[JsonConverter(typeof(StringEnumConverter))]
public SpeedPolicy? SpeedPolicy { get; set; }
public string[] PaymentMethods { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Minutes))]
[JsonProperty("expirationMinutes")]
public TimeSpan? Expiration { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Minutes))]
[JsonProperty("monitoringMinutes")]
public TimeSpan? Monitoring { get; set; }
public double? PaymentTolerance { get; set; }
[JsonProperty("redirectURL")]
public string RedirectURL { get; set; }
public string DefaultLanguage { get; set; }
}
}
}

@ -1,6 +1,6 @@
using System;
using BTCPayServer.Lightning;
using NBitcoin;
using BTCPayServer.Lightning.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
@ -11,19 +11,15 @@ namespace BTCPayServer.Client.Models
{
}
public CreateLightningInvoiceRequest(LightMoney amount, string description, TimeSpan expiry)
{
Amount = amount;
Description = description;
Expiry = expiry;
}
[JsonConverter(typeof(JsonConverters.LightMoneyJsonConverter))]
[JsonConverter(typeof(BTCPayServer.Client.JsonConverters.LightMoneyJsonConverter))]
public LightMoney Amount { get; set; }
public string Description { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
public uint256 DescriptionHash { get; set; }
[JsonConverter(typeof(JsonConverters.TimeSpanJsonConverter.Seconds))]
public TimeSpan Expiry { get; set; }
public bool PrivateRouteHints { get; set; }

@ -1,30 +0,0 @@
using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class CreateOnChainTransactionRequest
{
public class CreateOnChainTransactionRequestDestination
{
public string Destination { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? Amount { get; set; }
public bool SubtractFromAmount { get; set; }
}
[JsonConverter(typeof(FeeRateJsonConverter))]
public FeeRate FeeRate { get; set; }
public bool ProceedWithPayjoin { get; set; } = true;
public bool ProceedWithBroadcast { get; set; } = true;
public bool NoChange { get; set; } = false;
[JsonProperty(ItemConverterType = typeof(OutpointJsonConverter))]
public List<OutPoint> SelectedInputs { get; set; } = null;
public List<CreateOnChainTransactionRequestDestination> Destinations { get; set; }
[JsonProperty("rbf")]
public bool? RBF { get; set; } = null;
}
}

@ -8,15 +8,11 @@ namespace BTCPayServer.Client.Models
public class CreatePullPaymentRequest
{
public string Name { get; set; }
public string Description { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan? Period { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Days))]
[JsonProperty("BOLT11Expiration")]
public TimeSpan? BOLT11Expiration { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? ExpiresAt { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]

@ -1,33 +0,0 @@
namespace BTCPayServer.Client.Models;
public class EmailSettingsData
{
public string Server
{
get; set;
}
public int? Port
{
get; set;
}
public string Login
{
get; set;
}
public string Password
{
get; set;
}
public string FromDisplay
{
get; set;
}
public string From
{
get; set;
}
}

@ -1,25 +0,0 @@
using BTCPayServer.Client.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace BTCPayServer.Client
{
public class GenerateOnChainWalletRequest
{
public int AccountNumber { get; set; } = 0;
[JsonConverter(typeof(MnemonicJsonConverter))]
public Mnemonic ExistingMnemonic { get; set; }
[JsonConverter(typeof(WordlistJsonConverter))]
public NBitcoin.Wordlist WordList { get; set; }
[JsonConverter(typeof(WordcountJsonConverter))]
public NBitcoin.WordCount? WordCount { get; set; } = NBitcoin.WordCount.Twelve;
[JsonConverter(typeof(StringEnumConverter))]
public NBitcoin.ScriptPubKeyType ScriptPubKeyType { get; set; } = ScriptPubKeyType.Segwit;
public string Passphrase { get; set; }
public bool ImportKeysToRPC { get; set; }
public bool SavePrivateKeys { get; set; }
}
}

@ -1,9 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class GenericPaymentMethodData
{
public bool Enabled { get; set; }
public object Data { get; set; }
public string CryptoCode { get; set; }
}
}

@ -1,17 +0,0 @@
using System;
namespace BTCPayServer.Client.Models
{
public class GreenfieldPermissionAPIError : GreenfieldAPIError
{
public GreenfieldPermissionAPIError(string missingPermission, string message = null) : base()
{
MissingPermission = missingPermission;
Code = "missing-permission";
Message = message ?? $"Insufficient API Permissions. Please use an API key with permission \"{MissingPermission}\". You can create an API key in your account's settings / Api Keys.";
}
public string MissingPermission { get; }
}
}

@ -1,55 +1,12 @@
using System;
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models
{
public enum InvoiceType
{
Standard,
TopUp
}
public class InvoiceDataBase
{
[JsonConverter(typeof(StringEnumConverter))]
public InvoiceType Type { get; set; }
public string Currency { get; set; }
public JObject Metadata { get; set; }
public CheckoutOptions Checkout { get; set; } = new CheckoutOptions();
public class CheckoutOptions
{
[JsonConverter(typeof(StringEnumConverter))]
public SpeedPolicy? SpeedPolicy { get; set; }
public string[] PaymentMethods { get; set; }
public string DefaultPaymentMethod { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Minutes))]
[JsonProperty("expirationMinutes")]
public TimeSpan? Expiration { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Minutes))]
[JsonProperty("monitoringMinutes")]
public TimeSpan? Monitoring { get; set; }
public double? PaymentTolerance { get; set; }
[JsonProperty("redirectURL")]
public string RedirectURL { get; set; }
public bool? RedirectAutomatically { get; set; }
public bool? RequiresRefundEmail { get; set; } = null;
public string DefaultLanguage { get; set; }
}
}
public class InvoiceData : InvoiceDataBase
public class InvoiceData : CreateInvoiceRequest
{
public string Id { get; set; }
public string StoreId { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string CheckoutLink { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public InvoiceStatus Status { get; set; }
@ -61,9 +18,6 @@ namespace BTCPayServer.Client.Models
public DateTimeOffset ExpirationTime { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset CreatedTime { get; set; }
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public InvoiceStatus[] AvailableStatusesForManualMarking { get; set; }
public bool Archived { get; set; }
}
public enum InvoiceStatus
{

@ -9,4 +9,4 @@ namespace BTCPayServer.Client.Models
Invalid,
PaidOver
}
}
}

@ -3,13 +3,11 @@ using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models
{
public class InvoicePaymentMethodDataModel
{
public bool Activated { get; set; }
public string Destination { get; set; }
public string PaymentLink { get; set; }
@ -34,9 +32,6 @@ namespace BTCPayServer.Client.Models
public List<Payment> Payments { get; set; }
public string PaymentMethod { get; set; }
public string CryptoCode { get; set; }
public JObject AdditionalData { get; set; }
public class Payment
{
public string Id { get; set; }
@ -54,7 +49,7 @@ namespace BTCPayServer.Client.Models
public PaymentStatus Status { get; set; }
public string Destination { get; set; }
public enum PaymentStatus
{
Invalid,

@ -1,14 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class LNURLPayPaymentMethodBaseData
{
public bool UseBech32Scheme { get; set; }
public bool EnableForStandardInvoices { get; set; }
public bool LUD12Enabled { get; set; }
public LNURLPayPaymentMethodBaseData()
{
}
}
}

@ -1,27 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class LNURLPayPaymentMethodData : LNURLPayPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Crypto code of the payment method
/// </summary>
public string CryptoCode { get; set; }
public LNURLPayPaymentMethodData()
{
}
public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme, bool enableForStandardInvoices)
{
Enabled = enabled;
CryptoCode = cryptoCode;
UseBech32Scheme = useBech32Scheme;
EnableForStandardInvoices = enableForStandardInvoices;
}
}
}

@ -1,14 +0,0 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models
{
public class LabelData
{
public string Type { get; set; }
public string Text { get; set; }
[JsonExtensionData] public Dictionary<string, JToken> AdditionalData { get; set; }
}
}

@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class Language
{
public Language(string code, string displayName)
{
DisplayName = displayName;
Code = code;
}
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("currentLanguage")]
public string DisplayName { get; set; }
}
}

@ -1,13 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class LightningNetworkPaymentMethodBaseData
{
public string ConnectionString { get; set; }
public bool DisableBOLT11PaymentOption { get; set; }
public LightningNetworkPaymentMethodBaseData()
{
}
}
}

@ -1,30 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class LightningNetworkPaymentMethodData : LightningNetworkPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Crypto code of the payment method
/// </summary>
public string CryptoCode { get; set; }
public LightningNetworkPaymentMethodData()
{
}
public LightningNetworkPaymentMethodData(string cryptoCode, string connectionString, bool enabled, string paymentMethod, bool disableBOLT11PaymentOption)
{
Enabled = enabled;
CryptoCode = cryptoCode;
ConnectionString = connectionString;
PaymentMethod = paymentMethod;
DisableBOLT11PaymentOption = disableBOLT11PaymentOption;
}
public string PaymentMethod { get; set; }
}
}

@ -1,15 +0,0 @@
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.Lightning;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class LightningPaymentData
{
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney TotalAmount { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney FeeAmount { get; set; }
}
}

@ -1,24 +0,0 @@
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainPaymentMethodBaseData
{
/// <summary>
/// The derivation scheme
/// </summary>
public string DerivationScheme { get; set; }
public string Label { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
public RootedKeyPath AccountKeyPath { get; set; }
public OnChainPaymentMethodBaseData()
{
}
}
}

@ -1,47 +1,39 @@
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainPaymentMethodDataPreview : OnChainPaymentMethodBaseData
{
/// <summary>
/// Crypto code of the payment method
/// </summary>
public string CryptoCode { get; set; }
public OnChainPaymentMethodDataPreview()
{
}
public OnChainPaymentMethodDataPreview(string cryptoCode, string derivationScheme, string label, RootedKeyPath accountKeyPath)
{
Label = label;
AccountKeyPath = accountKeyPath;
CryptoCode = cryptoCode;
DerivationScheme = derivationScheme;
}
}
public class OnChainPaymentMethodData : OnChainPaymentMethodDataPreview
public class OnChainPaymentMethodData
{
/// <summary>
/// Whether the payment method is enabled
/// </summary>
public bool Enabled { get; set; }
public string PaymentMethod { get; set; }
/// <summary>
/// Crypto code of the payment method
/// </summary>
public string CryptoCode { get; set; }
/// <summary>
/// The derivation scheme
/// </summary>
public string DerivationScheme { get; set; }
public string Label { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
public RootedKeyPath AccountKeyPath { get; set; }
public OnChainPaymentMethodData()
{
}
public OnChainPaymentMethodData(string cryptoCode, string derivationScheme, bool enabled, string label, RootedKeyPath accountKeyPath, string paymentMethod) :
base(cryptoCode, derivationScheme, label, accountKeyPath)
public OnChainPaymentMethodData(string cryptoCode, string derivationScheme, bool enabled)
{
Enabled = enabled;
PaymentMethod = paymentMethod;
CryptoCode = cryptoCode;
DerivationScheme = derivationScheme;
}
}
}

@ -1,23 +0,0 @@
using BTCPayServer.Client.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainPaymentMethodDataWithSensitiveData : OnChainPaymentMethodData
{
public OnChainPaymentMethodDataWithSensitiveData()
{
}
public OnChainPaymentMethodDataWithSensitiveData(string cryptoCode, string derivationScheme, bool enabled,
string label, RootedKeyPath accountKeyPath, Mnemonic mnemonic, string paymentMethod) : base(cryptoCode, derivationScheme, enabled,
label, accountKeyPath, paymentMethod)
{
Mnemonic = mnemonic;
}
[JsonConverter(typeof(MnemonicJsonConverter))]
public Mnemonic Mnemonic { get; set; }
}
}

@ -1,15 +0,0 @@
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainWalletAddressData
{
public string Address { get; set; }
[JsonConverter(typeof(KeyPathJsonConverter))]
public KeyPath KeyPath { get; set; }
public string PaymentLink { get; set; }
}
}

@ -1,12 +0,0 @@
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainWalletFeeRateData
{
[JsonConverter(typeof(FeeRateJsonConverter))]
public FeeRate FeeRate { get; set; }
}
}

@ -1,17 +0,0 @@
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainWalletOverviewData
{
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Balance { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal UnconfirmedBalance { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal ConfirmedBalance { get; set; }
public string Label { get; set; }
}
}

@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainWalletTransactionData
{
[JsonConverter(typeof(UInt256JsonConverter))]
public uint256 TransactionHash { get; set; }
public string Comment { get; set; }
public Dictionary<string, LabelData> Labels { get; set; } = new Dictionary<string, LabelData>();
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(UInt256JsonConverter))]
public uint256 BlockHash { get; set; }
public int? BlockHeight { get; set; }
public int Confirmations { get; set; }
[JsonConverter(typeof(DateTimeToUnixTimeConverter))]
public DateTimeOffset Timestamp { get; set; }
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public TransactionStatus Status { get; set; }
}
}

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainWalletUTXOData
{
public string Comment { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(OutpointJsonConverter))]
public OutPoint Outpoint { get; set; }
public string Link { get; set; }
public Dictionary<string, LabelData> Labels { get; set; }
[JsonConverter(typeof(DateTimeToUnixTimeConverter))]
public DateTimeOffset Timestamp { get; set; }
[JsonConverter(typeof(KeyPathJsonConverter))]
public KeyPath KeyPath { get; set; }
public string Address { get; set; }
public int Confirmations { get; set; }
}
}

@ -1,20 +1,8 @@
#nullable enable
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class PayLightningInvoiceRequest
{
[JsonProperty("BOLT11")]
[Newtonsoft.Json.JsonProperty("BOLT11")]
public string BOLT11 { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public float? MaxFeePercent { get; set; }
[JsonConverter(typeof(MoneyJsonConverter))]
public Money? MaxFeeFlat { get; set; }
}
}

@ -8,12 +8,10 @@ namespace BTCPayServer.Client.Models
{
public class PaymentRequestBaseData
{
public string StoreId { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? ExpiryDate { get; set; }
public DateTime? ExpiryDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Email { get; set; }

@ -8,8 +8,7 @@ namespace BTCPayServer.Client.Models
{
[JsonConverter(typeof(StringEnumConverter))]
public PaymentRequestData.PaymentRequestStatus Status { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset CreatedTime { get; set; }
public DateTimeOffset Created { get; set; }
public string Id { get; set; }
public bool Archived { get; set; }

@ -21,7 +21,6 @@ namespace BTCPayServer.Client.Models
public string PullPaymentId { get; set; }
public string Destination { get; set; }
public string PaymentMethod { get; set; }
public string CryptoCode { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]

@ -1,40 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class PermissionMetadata
{
static PermissionMetadata()
{
Dictionary<string, PermissionMetadata> nodes = new Dictionary<string, PermissionMetadata>();
foreach (var policy in Client.Policies.AllPolicies)
{
nodes.Add(policy, new PermissionMetadata() { PermissionName = policy });
}
foreach (var n in nodes)
{
foreach (var policy in Client.Policies.AllPolicies)
{
if (policy.Equals(n.Key, StringComparison.OrdinalIgnoreCase))
continue;
if (Client.Permission.Create(n.Key).Contains(Client.Permission.Create(policy)))
n.Value.SubPermissions.Add(policy);
}
}
foreach (var n in nodes)
{
n.Value.SubPermissions.Sort();
}
PermissionNodes = nodes.Values.OrderBy(v => v.PermissionName).ToArray();
}
public readonly static PermissionMetadata[] PermissionNodes;
[JsonProperty("name")]
public string PermissionName { get; set; }
[JsonProperty("included")]
public List<string> SubPermissions { get; set; } = new List<string>();
}
}

@ -5,13 +5,6 @@ using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public enum PullPaymentState
{
Active,
Expired,
Archived,
Future
}
public class PullPaymentData
{
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
@ -20,15 +13,11 @@ namespace BTCPayServer.Client.Models
public DateTimeOffset? ExpiresAt { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan? Period { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Days))]
[JsonProperty("BOLT11Expiration")]
public TimeSpan BOLT11Expiration { get; set; }
public bool Archived { get; set; }
public string ViewLink { get; set; }
}

@ -1,10 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class SendEmailRequest
{
public string Email;
public string Subject;
public string Body;
}
}

@ -27,17 +27,12 @@ namespace BTCPayServer.Client.Models
/// <summary>
/// detailed sync information per chain
/// </summary>
public IEnumerable<SyncStatus> SyncStatus { get; set; }
public IEnumerable<ServerInfoSyncStatusData> SyncStatus { get; set; }
}
public class SyncStatus
public class ServerInfoSyncStatusData
{
public string CryptoCode { get; set; }
public virtual bool Available { get; set; }
}
public class ServerInfoSyncStatusData : SyncStatus
{
public int ChainHeight { get; set; }
public int? SyncHeight { get; set; }
public ServerInfoNodeData NodeInformation { get; set; }

@ -29,21 +29,21 @@ namespace BTCPayServer.Client.Models
public string LightningDescriptionTemplate { get; set; }
public double PaymentTolerance { get; set; } = 0;
public bool AnyoneCanCreateInvoice { get; set; }
public string DefaultCurrency { get; set; }
public bool RequiresRefundEmail { get; set; }
public bool LightningAmountInSatoshi { get; set; }
public bool LightningPrivateRouteHints { get; set; }
public bool OnChainWithLnInvoiceFallback { get; set; }
public bool LazyPaymentMethods { get; set; }
public bool RedirectAutomatically { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public bool ShowRecommendedFee { get; set; } = true;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int RecommendedFeeBlockTarget { get; set; } = 1;
public string DefaultPaymentMethod { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string DefaultLang { get; set; } = "en";
@ -53,6 +53,8 @@ namespace BTCPayServer.Client.Models
public string HtmlTitle { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public NetworkFeeMode NetworkFeeMode { get; set; } = NetworkFeeMode.Never;

@ -7,14 +7,4 @@ namespace BTCPayServer.Client.Models
/// </summary>
public string Id { get; set; }
}
public class StoreUserData
{
/// <summary>
/// the id of the user
/// </summary>
public string UserId { get; set; }
public string Role { get; set; }
}
}

@ -1,9 +0,0 @@
namespace BTCPayServer.Client.Models
{
public enum TransactionStatus
{
Unconfirmed,
Confirmed,
Replaced
}
}

@ -1,20 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class UpdateLightningNetworkPaymentMethodRequest : LightningNetworkPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled
/// </summary>
public bool Enabled { get; set; }
public UpdateLightningNetworkPaymentMethodRequest()
{
}
public UpdateLightningNetworkPaymentMethodRequest(string connectionString, bool enabled)
{
Enabled = enabled;
ConnectionString = connectionString;
}
}
}

@ -1,25 +0,0 @@
using NBitcoin;
namespace BTCPayServer.Client.Models
{
public class UpdateOnChainPaymentMethodRequest : OnChainPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled
/// </summary>
public bool Enabled { get; set; }
public UpdateOnChainPaymentMethodRequest()
{
}
public UpdateOnChainPaymentMethodRequest(bool enabled, string derivationScheme, string label, RootedKeyPath accountKeyPath)
{
Enabled = enabled;
Label = label;
AccountKeyPath = accountKeyPath;
DerivationScheme = derivationScheme;
}
}
}

@ -19,31 +19,7 @@ namespace BTCPayServer.Client.Models
}
public string DeliveryId { get; set; }
public string WebhookId { get; set; }
string _OriginalDeliveryId;
public string OriginalDeliveryId
{
get
{
if (_OriginalDeliveryId is null)
{
// Due to a typo in old version, we serialized `orignalDeliveryId` rather than `orignalDeliveryId`
// We silently fix that here.
// Note we can remove this code later on, as old webhook event are unlikely to be useful to anyone,
// and having a null orignalDeliveryId is not end of the world
if (AdditionalData != null &&
AdditionalData.TryGetValue("orignalDeliveryId", out var tok))
{
_OriginalDeliveryId = tok.Value<string>();
AdditionalData.Remove("orignalDeliveryId");
}
}
return _OriginalDeliveryId;
}
set
{
_OriginalDeliveryId = value;
}
}
public string OrignalDeliveryId { get; set; }
public bool IsRedelivery { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public WebhookEventType Type { get; set; }

@ -11,7 +11,6 @@ namespace BTCPayServer.Client.Models
InvoiceProcessing,
InvoiceExpired,
InvoiceSettled,
InvoiceInvalid,
InvoicePaymentSettled,
InvoiceInvalid
}
}

@ -10,89 +10,72 @@ namespace BTCPayServer.Client.Models
{
public WebhookInvoiceEvent()
{
}
}
public WebhookInvoiceEvent(WebhookEventType evtType)
{
this.Type = evtType;
}
[JsonProperty(Order = 1)] public string StoreId { get; set; }
[JsonProperty(Order = 2)] public string InvoiceId { get; set; }
[JsonProperty(Order = 1)]
public string StoreId { get; set; }
[JsonProperty(Order = 2)]
public string InvoiceId { get; set; }
}
public class WebhookInvoiceSettledEvent : WebhookInvoiceEvent
{
public WebhookInvoiceSettledEvent()
{
}
}
public WebhookInvoiceSettledEvent(WebhookEventType evtType) : base(evtType)
{
}
public bool ManuallyMarked { get; set; }
}
public class WebhookInvoiceInvalidEvent : WebhookInvoiceEvent
{
public WebhookInvoiceInvalidEvent()
{
}
}
public WebhookInvoiceInvalidEvent(WebhookEventType evtType) : base(evtType)
{
}
public bool ManuallyMarked { get; set; }
}
public class WebhookInvoiceProcessingEvent : WebhookInvoiceEvent
{
public WebhookInvoiceProcessingEvent()
{
}
}
public WebhookInvoiceProcessingEvent(WebhookEventType evtType) : base(evtType)
{
}
public bool OverPaid { get; set; }
}
public class WebhookInvoiceReceivedPaymentEvent : WebhookInvoiceEvent
{
public WebhookInvoiceReceivedPaymentEvent()
{
}
}
public WebhookInvoiceReceivedPaymentEvent(WebhookEventType evtType) : base(evtType)
{
}
public bool AfterExpiration { get; set; }
public string PaymentMethod { get; set; }
public InvoicePaymentMethodDataModel.Payment Payment { get; set; }
public bool OverPaid { get; set; }
}
public class WebhookInvoicePaymentSettledEvent : WebhookInvoiceReceivedPaymentEvent
{
public WebhookInvoicePaymentSettledEvent()
{
}
public WebhookInvoicePaymentSettledEvent(WebhookEventType evtType) : base(evtType)
{
}
}
public class WebhookInvoiceExpiredEvent : WebhookInvoiceEvent
{
public WebhookInvoiceExpiredEvent()
{
}
}
public WebhookInvoiceExpiredEvent(WebhookEventType evtType) : base(evtType)
{
}

@ -17,16 +17,13 @@ namespace BTCPayServer.Client
public const string CanViewStoreSettings = "btcpay.store.canviewstoresettings";
public const string CanViewInvoices = "btcpay.store.canviewinvoices";
public const string CanCreateInvoice = "btcpay.store.cancreateinvoice";
public const string CanModifyInvoices = "btcpay.store.canmodifyinvoices";
public const string CanViewPaymentRequests = "btcpay.store.canviewpaymentrequests";
public const string CanModifyPaymentRequests = "btcpay.store.canmodifypaymentrequests";
public const string CanModifyProfile = "btcpay.user.canmodifyprofile";
public const string CanViewProfile = "btcpay.user.canviewprofile";
public const string CanManageNotificationsForUser = "btcpay.user.canmanagenotificationsforuser";
public const string CanViewNotificationsForUser = "btcpay.user.canviewnotificationsforuser";
public const string CanViewUsers = "btcpay.server.canviewusers";
public const string CanCreateUser = "btcpay.server.cancreateuser";
public const string CanDeleteUser = "btcpay.user.candeleteuser";
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
public const string Unrestricted = "unrestricted";
public static IEnumerable<string> AllPolicies
@ -35,7 +32,6 @@ namespace BTCPayServer.Client
{
yield return CanViewInvoices;
yield return CanCreateInvoice;
yield return CanModifyInvoices;
yield return CanModifyStoreWebhooks;
yield return CanModifyServerSettings;
yield return CanModifyStoreSettings;
@ -44,9 +40,7 @@ namespace BTCPayServer.Client
yield return CanModifyPaymentRequests;
yield return CanModifyProfile;
yield return CanViewProfile;
yield return CanViewUsers;
yield return CanCreateUser;
yield return CanDeleteUser;
yield return CanManageNotificationsForUser;
yield return CanViewNotificationsForUser;
yield return Unrestricted;
@ -168,22 +162,17 @@ namespace BTCPayServer.Client
switch (subpolicy)
{
case Policies.CanViewInvoices when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewInvoices when this.Policy == Policies.CanModifyInvoices:
case Policies.CanModifyStoreWebhooks when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewInvoices when this.Policy == Policies.CanViewStoreSettings:
case Policies.CanViewStoreSettings when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanCreateInvoice when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanModifyInvoices when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewProfile when this.Policy == Policies.CanModifyProfile:
case Policies.CanModifyPaymentRequests when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanManagePullPayments when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanViewStoreSettings:
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanModifyPaymentRequests:
case Policies.CanCreateLightningInvoiceInternalNode when this.Policy == Policies.CanUseInternalLightningNode:
case Policies.CanCreateLightningInvoiceInStore when this.Policy == Policies.CanUseLightningNodeInStore:
case Policies.CanViewNotificationsForUser when this.Policy == Policies.CanManageNotificationsForUser:
case Policies.CanUseInternalLightningNode when this.Policy == Policies.CanModifyServerSettings:
return true;
default:
return false;

@ -1,28 +0,0 @@
using NBitcoin;
using NBXplorer;
namespace BTCPayServer
{
public partial class BTCPayNetworkProvider
{
public void InitAlthash()
{
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("HTML");
Add(new BTCPayNetwork()
{
CryptoCode = nbxplorerNetwork.CryptoCode,
DisplayName = "Althash",
BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://explorer.htmlcoin.com/api/tx/{0}" : "https://explorer.htmlcoin.com/api/tx/{0}",
NBXplorerNetwork = nbxplorerNetwork,
DefaultRateRules = new[]
{
"HTML_X = HTML_USD",
"HTML_USD = hitbtc(HTML_USD)"
},
CryptoImagePath = "imlegacy/althash.png",
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("88'") : new KeyPath("1'")
});
}
}
}

@ -15,6 +15,7 @@ namespace BTCPayServer
? "https://chainz.cryptoid.info/agm/tx.dws?{0}"
: "https://chainz.cryptoid.info/agm-test/tx.dws?{0}",
NBXplorerNetwork = nbxplorerNetwork,
UriScheme = "argoneum",
DefaultRateRules = new[]
{
"AGM_X = AGM_BTC * BTC_X",

@ -13,6 +13,7 @@ namespace BTCPayServer
DisplayName = "BGold",
BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://btgexplorer.com/tx/{0}" : "https://testnet.btgexplorer.com/tx/{0}",
NBXplorerNetwork = nbxplorerNetwork,
UriScheme = "bitcoingold",
DefaultRateRules = new[]
{
"BTG_X = BTG_BTC * BTC_X",

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