mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
wip
This commit is contained in:
@@ -49,7 +49,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly WalletRepository _walletRepository;
|
private readonly WalletRepository _walletRepository;
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly BitcoinLikePayoutHandler _bitcoinLikePayoutHandler;
|
private readonly IPayoutHandler _bitcoinLikePayoutHandler;
|
||||||
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
|
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
|
||||||
private readonly Services.Wallets.BTCPayWallet _btcPayWallet;
|
private readonly Services.Wallets.BTCPayWallet _btcPayWallet;
|
||||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||||
@@ -63,7 +63,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
WalletRepository walletRepository,
|
WalletRepository walletRepository,
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
BitcoinLikePayoutHandler bitcoinLikePayoutHandler,
|
IPayoutHandler bitcoinLikePayoutHandler,
|
||||||
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
||||||
Services.Wallets.BTCPayWallet btcPayWallet,
|
Services.Wallets.BTCPayWallet btcPayWallet,
|
||||||
PullPaymentHostedService pullPaymentHostedService,
|
PullPaymentHostedService pullPaymentHostedService,
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Services;
|
using BTCPayServer.Abstractions.Services;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
using BTCPayServer.Plugins.Wabisabi.Coordinator;
|
using BTCPayServer.Plugins.Wabisabi.Coordinator;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using Microsoft.AspNetCore.JsonPatch;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.ObjectPool;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using NBitcoin;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using WalletWasabi.WabiSabi.Backend;
|
using WalletWasabi.WabiSabi.Backend;
|
||||||
using WalletWasabi.WabiSabi.Models.Serialization;
|
using WalletWasabi.WabiSabi.Models.Serialization;
|
||||||
|
|
||||||
@@ -13,7 +25,6 @@ public static class CoordinatorExtensions
|
|||||||
{
|
{
|
||||||
public static void AddWabisabiCoordinator(this IServiceCollection services)
|
public static void AddWabisabiCoordinator(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
services.AddSingleton<WabisabiCoordinatorService>();
|
services.AddSingleton<WabisabiCoordinatorService>();
|
||||||
services.AddSingleton<WabiSabiConfig.CoordinatorScriptResolver, WabisabiScriptResolver>();
|
services.AddSingleton<WabiSabiConfig.CoordinatorScriptResolver, WabisabiScriptResolver>();
|
||||||
services.AddTransient(provider =>
|
services.AddTransient(provider =>
|
||||||
@@ -23,6 +34,7 @@ public static class CoordinatorExtensions
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WabiSabiController(s.IdempotencyRequestCache, s.WabiSabiCoordinator.Arena,
|
return new WabiSabiController(s.IdempotencyRequestCache, s.WabiSabiCoordinator.Arena,
|
||||||
s.WabiSabiCoordinator.CoinJoinFeeRateStatStore);
|
s.WabiSabiCoordinator.CoinJoinFeeRateStatStore);
|
||||||
});
|
});
|
||||||
@@ -34,7 +46,6 @@ public static class CoordinatorExtensions
|
|||||||
services.AddHttpClient("wabisabi-coordinator-scripts-no-redirect.onion")
|
services.AddHttpClient("wabisabi-coordinator-scripts-no-redirect.onion")
|
||||||
.ConfigurePrimaryHttpMessageHandler(provider =>
|
.ConfigurePrimaryHttpMessageHandler(provider =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var handler = new Socks5HttpClientHandler(provider.GetRequiredService<BTCPayServerOptions>());
|
var handler = new Socks5HttpClientHandler(provider.GetRequiredService<BTCPayServerOptions>());
|
||||||
handler.AllowAutoRedirect = false;
|
handler.AllowAutoRedirect = false;
|
||||||
return handler;
|
return handler;
|
||||||
@@ -47,15 +58,83 @@ public static class CoordinatorExtensions
|
|||||||
return handler;
|
return handler;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.ConfigureOptions<WasabiInputFormatterJsonMvcOptionsSetup>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//inside Startup.ConfigureServices
|
public class WasabiInputFormatter : NewtonsoftJsonInputFormatter
|
||||||
services.AddControllerBasedJsonInputFormatter(formatter => {
|
|
||||||
formatter.ForControllersWithAttribute<UseWasabiJsonInputFormatterAttribute>()
|
|
||||||
.ForActionsWithAttribute<UseWasabiJsonInputFormatterAttribute>()
|
|
||||||
.WithSerializerSettingsConfigurer(settings =>
|
|
||||||
{
|
{
|
||||||
settings.Converters = JsonSerializationOptions.Default.Settings.Converters;
|
public WasabiInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool,
|
||||||
});
|
ObjectPoolProvider objectPoolProvider, MvcOptions options, MvcNewtonsoftJsonOptions jsonOptions) : base(logger,
|
||||||
});
|
serializerSettings, charPool, objectPoolProvider, options, jsonOptions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead(InputFormatterContext context)
|
||||||
|
{
|
||||||
|
var controllerName = context.HttpContext.Request.RouteValues["controller"]?.ToString();
|
||||||
|
return controllerName == "WabiSabi";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WasabiOutputFormatter : NewtonsoftJsonOutputFormatter
|
||||||
|
{
|
||||||
|
public WasabiOutputFormatter(JsonSerializerSettings serializerSettings, ArrayPool<char> charPool,
|
||||||
|
MvcOptions options, MvcNewtonsoftJsonOptions jsonOptions) : base(serializerSettings, charPool, options,
|
||||||
|
jsonOptions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||||
|
{
|
||||||
|
var controllerName = context.HttpContext.Request.RouteValues["controller"]?.ToString();
|
||||||
|
return controllerName == "WabiSabi";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class WasabiInputFormatterJsonMvcOptionsSetup : IConfigureOptions<MvcOptions>
|
||||||
|
{
|
||||||
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
|
private readonly MvcNewtonsoftJsonOptions _jsonOptions;
|
||||||
|
private readonly ArrayPool<char> _charPool;
|
||||||
|
private readonly ObjectPoolProvider _objectPoolProvider;
|
||||||
|
private readonly JsonSerializerSettings _settings;
|
||||||
|
|
||||||
|
public WasabiInputFormatterJsonMvcOptionsSetup(
|
||||||
|
ILoggerFactory loggerFactory,
|
||||||
|
IOptions<MvcNewtonsoftJsonOptions> jsonOptions,
|
||||||
|
ArrayPool<char> charPool,
|
||||||
|
ObjectPoolProvider objectPoolProvider)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(loggerFactory);
|
||||||
|
ArgumentNullException.ThrowIfNull(jsonOptions);
|
||||||
|
ArgumentNullException.ThrowIfNull(charPool);
|
||||||
|
ArgumentNullException.ThrowIfNull(objectPoolProvider);
|
||||||
|
|
||||||
|
_loggerFactory = loggerFactory;
|
||||||
|
_jsonOptions = jsonOptions.Value;
|
||||||
|
_charPool = charPool;
|
||||||
|
_objectPoolProvider = objectPoolProvider;
|
||||||
|
|
||||||
|
_settings = JsonSerializationOptions.Default.Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(MvcOptions options)
|
||||||
|
{
|
||||||
|
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(BitcoinAddress)));
|
||||||
|
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Script)));
|
||||||
|
|
||||||
|
options.InputFormatters.Insert(0, new WasabiInputFormatter(
|
||||||
|
_loggerFactory.CreateLogger<WasabiInputFormatter>(),
|
||||||
|
_settings,
|
||||||
|
_charPool,
|
||||||
|
_objectPoolProvider,
|
||||||
|
options,
|
||||||
|
_jsonOptions));
|
||||||
|
options.OutputFormatters.Insert(0, new WasabiOutputFormatter(
|
||||||
|
_settings,
|
||||||
|
_charPool,
|
||||||
|
options,
|
||||||
|
_jsonOptions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
using System.Buffers;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
public abstract class ContextAwareMultiPooledSerializerJsonInputFormatter : ContextAwareSerializerJsonInputFormatter
|
|
||||||
{
|
|
||||||
public ContextAwareMultiPooledSerializerJsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, MvcOptions options, MvcNewtonsoftJsonOptions jsonOptions)
|
|
||||||
: base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
readonly IDictionary<object, ObjectPool<JsonSerializer>> _serializerPools = new ConcurrentDictionary<object, ObjectPool<JsonSerializer>>();
|
|
||||||
readonly AsyncLocal<object> _currentPoolKeyAsyncLocal = new AsyncLocal<object>();
|
|
||||||
protected object CurrentPoolKey => _currentPoolKeyAsyncLocal.Value;
|
|
||||||
protected abstract object GetSerializerPoolKey(InputFormatterContext context);
|
|
||||||
protected override JsonSerializer CreateJsonSerializer(InputFormatterContext context)
|
|
||||||
{
|
|
||||||
object poolKey = GetSerializerPoolKey(context) ?? "";
|
|
||||||
if(!_serializerPools.TryGetValue(poolKey, out var pool))
|
|
||||||
{
|
|
||||||
//clone the settings
|
|
||||||
var serializerSettings = new JsonSerializerSettings();
|
|
||||||
foreach(var prop in typeof(JsonSerializerSettings).GetProperties().Where(e => e.CanWrite))
|
|
||||||
{
|
|
||||||
prop.SetValue(serializerSettings, prop.GetValue(SerializerSettings));
|
|
||||||
}
|
|
||||||
ConfigureSerializerSettings(serializerSettings, poolKey, context);
|
|
||||||
pool = PoolProvider.Create(new JsonSerializerPooledPolicy(serializerSettings));
|
|
||||||
_serializerPools[poolKey] = pool;
|
|
||||||
}
|
|
||||||
_currentPoolKeyAsyncLocal.Value = poolKey;
|
|
||||||
return pool.Get();
|
|
||||||
}
|
|
||||||
protected override void ReleaseJsonSerializer(JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
if(_serializerPools.TryGetValue(CurrentPoolKey ?? "", out var pool))
|
|
||||||
{
|
|
||||||
pool.Return(serializer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected virtual void ConfigureSerializerSettings(JsonSerializerSettings serializerSettings, object poolKey, InputFormatterContext context) { }
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
using System.Buffers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
public abstract class ContextAwareSerializerJsonInputFormatter : NewtonsoftJsonInputFormatter
|
|
||||||
{
|
|
||||||
public ContextAwareSerializerJsonInputFormatter(ILogger logger,
|
|
||||||
JsonSerializerSettings serializerSettings,
|
|
||||||
ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, MvcOptions options, MvcNewtonsoftJsonOptions jsonOptions) : base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions)
|
|
||||||
{
|
|
||||||
PoolProvider = objectPoolProvider;
|
|
||||||
}
|
|
||||||
readonly AsyncLocal<InputFormatterContext> _currentContextAsyncLocal = new AsyncLocal<InputFormatterContext>();
|
|
||||||
readonly AsyncLocal<ActionContext> _currentActionAsyncLocal = new AsyncLocal<ActionContext>();
|
|
||||||
protected InputFormatterContext CurrentContext => _currentContextAsyncLocal.Value;
|
|
||||||
protected ActionContext CurrentAction => _currentActionAsyncLocal.Value;
|
|
||||||
protected ObjectPoolProvider PoolProvider { get; }
|
|
||||||
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
|
|
||||||
{
|
|
||||||
_currentContextAsyncLocal.Value = context;
|
|
||||||
_currentActionAsyncLocal.Value = context.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>().ActionContext;
|
|
||||||
return base.ReadRequestBodyAsync(context, encoding);
|
|
||||||
}
|
|
||||||
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
|
|
||||||
{
|
|
||||||
_currentContextAsyncLocal.Value = context;
|
|
||||||
_currentActionAsyncLocal.Value = context.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>().ActionContext;
|
|
||||||
return base.ReadRequestBodyAsync(context);
|
|
||||||
}
|
|
||||||
protected virtual JsonSerializer CreateJsonSerializer(InputFormatterContext context) => null;
|
|
||||||
protected override JsonSerializer CreateJsonSerializer()
|
|
||||||
{
|
|
||||||
var context = CurrentContext;
|
|
||||||
return (context == null ? null : CreateJsonSerializer(context)) ?? base.CreateJsonSerializer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
public class ControllerBasedJsonInputFormatter : ContextAwareMultiPooledSerializerJsonInputFormatter,
|
|
||||||
IControllerBasedJsonSerializerSettingsBuilder
|
|
||||||
{
|
|
||||||
public ControllerBasedJsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, MvcOptions options, MvcNewtonsoftJsonOptions jsonOptions) : base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
readonly IDictionary<object, Action<JsonSerializerSettings>> _configureSerializerSettings
|
|
||||||
= new Dictionary<object, Action<JsonSerializerSettings>>();
|
|
||||||
readonly HashSet<object> _beingAppliedConfigurationKeys = new HashSet<object>();
|
|
||||||
protected override object GetSerializerPoolKey(InputFormatterContext context)
|
|
||||||
{
|
|
||||||
var routeValues = context.HttpContext.GetRouteData()?.Values;
|
|
||||||
var controllerName = routeValues == null ? null : routeValues["controller"]?.ToString();
|
|
||||||
if(controllerName != null && _configureSerializerSettings.ContainsKey(controllerName))
|
|
||||||
{
|
|
||||||
return controllerName;
|
|
||||||
}
|
|
||||||
var actionContext = CurrentAction;
|
|
||||||
if (actionContext != null && actionContext.ActionDescriptor is ControllerActionDescriptor actionDesc)
|
|
||||||
{
|
|
||||||
foreach (var attr in actionDesc.MethodInfo.GetCustomAttributes(true)
|
|
||||||
.Concat(actionDesc.ControllerTypeInfo.GetCustomAttributes(true)))
|
|
||||||
{
|
|
||||||
var key = attr.GetType();
|
|
||||||
if (_configureSerializerSettings.ContainsKey(key))
|
|
||||||
{
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public IControllerBasedJsonSerializerSettingsBuilder ForControllers(params string[] controllerNames)
|
|
||||||
{
|
|
||||||
foreach(var controllerName in controllerNames ?? Enumerable.Empty<string>())
|
|
||||||
{
|
|
||||||
_beingAppliedConfigurationKeys.Add((controllerName ?? "").ToLowerInvariant());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public IControllerBasedJsonSerializerSettingsBuilder ForControllersWithAttribute<T>()
|
|
||||||
{
|
|
||||||
_beingAppliedConfigurationKeys.Add(typeof(T));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public IControllerBasedJsonSerializerSettingsBuilder ForActionsWithAttribute<T>()
|
|
||||||
{
|
|
||||||
_beingAppliedConfigurationKeys.Add(typeof(T));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
ControllerBasedJsonInputFormatter IControllerBasedJsonSerializerSettingsBuilder.WithSerializerSettingsConfigurer(Action<JsonSerializerSettings> configurer)
|
|
||||||
{
|
|
||||||
if (configurer == null) throw new ArgumentNullException(nameof(configurer));
|
|
||||||
foreach(var key in _beingAppliedConfigurationKeys)
|
|
||||||
{
|
|
||||||
_configureSerializerSettings[key] = configurer;
|
|
||||||
}
|
|
||||||
_beingAppliedConfigurationKeys.Clear();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
protected override void ConfigureSerializerSettings(JsonSerializerSettings serializerSettings, object poolKey, InputFormatterContext context)
|
|
||||||
{
|
|
||||||
if (_configureSerializerSettings.TryGetValue(poolKey, out var configurer))
|
|
||||||
{
|
|
||||||
configurer.Invoke(serializerSettings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
public class ControllerBasedJsonInputFormatterMvcOptionsSetup : IConfigureOptions<MvcOptions>
|
|
||||||
{
|
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
|
||||||
private readonly MvcNewtonsoftJsonOptions _jsonOptions;
|
|
||||||
private readonly ArrayPool<char> _charPool;
|
|
||||||
private readonly ObjectPoolProvider _objectPoolProvider;
|
|
||||||
public ControllerBasedJsonInputFormatterMvcOptionsSetup(
|
|
||||||
ILoggerFactory loggerFactory,
|
|
||||||
IOptions<MvcNewtonsoftJsonOptions> jsonOptions,
|
|
||||||
ArrayPool<char> charPool,
|
|
||||||
ObjectPoolProvider objectPoolProvider)
|
|
||||||
{
|
|
||||||
if (loggerFactory == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(loggerFactory));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jsonOptions == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(jsonOptions));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (charPool == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(charPool));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (objectPoolProvider == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(objectPoolProvider));
|
|
||||||
}
|
|
||||||
|
|
||||||
_loggerFactory = loggerFactory;
|
|
||||||
_jsonOptions = jsonOptions.Value;
|
|
||||||
_charPool = charPool;
|
|
||||||
_objectPoolProvider = objectPoolProvider;
|
|
||||||
}
|
|
||||||
public void Configure(MvcOptions options)
|
|
||||||
{
|
|
||||||
//remove the default
|
|
||||||
options.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
|
|
||||||
//add our own
|
|
||||||
var jsonInputLogger = _loggerFactory.CreateLogger<ControllerBasedJsonInputFormatter>();
|
|
||||||
|
|
||||||
options.InputFormatters.Add(new ControllerBasedJsonInputFormatter(
|
|
||||||
jsonInputLogger,
|
|
||||||
_jsonOptions.SerializerSettings,
|
|
||||||
_charPool,
|
|
||||||
_objectPoolProvider,
|
|
||||||
options,
|
|
||||||
_jsonOptions));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//there is a similar class like this implemented by the framework
|
|
||||||
//but it's a pity that it's internal
|
|
||||||
//So we define our own class here (which is exactly the same from the source code)
|
|
||||||
//It's quite simple like this
|
|
||||||
|
|
||||||
//This attribute is used as a marker to decorate any controllers
|
|
||||||
//or actions that you want to apply your custom input formatter
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
||||||
|
|
||||||
public static class ControllerBasedJsonInputFormatterServiceCollectionExtensions
|
|
||||||
{
|
|
||||||
public static IServiceCollection AddControllerBasedJsonInputFormatter(this IServiceCollection services,
|
|
||||||
Action<ControllerBasedJsonInputFormatter> configureFormatter)
|
|
||||||
{
|
|
||||||
if(configureFormatter == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(configureFormatter));
|
|
||||||
}
|
|
||||||
services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();
|
|
||||||
return services.ConfigureOptions<ControllerBasedJsonInputFormatterMvcOptionsSetup>()
|
|
||||||
.PostConfigure<MvcOptions>(o => {
|
|
||||||
var jsonInputFormatter = o.InputFormatters.OfType<ControllerBasedJsonInputFormatter>().FirstOrDefault();
|
|
||||||
if(jsonInputFormatter != null)
|
|
||||||
{
|
|
||||||
configureFormatter(jsonInputFormatter);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
public interface IControllerBasedJsonSerializerSettingsBuilder
|
|
||||||
{
|
|
||||||
ControllerBasedJsonInputFormatter WithSerializerSettingsConfigurer(Action<JsonSerializerSettings> configurer);
|
|
||||||
IControllerBasedJsonSerializerSettingsBuilder ForControllers(params string[] controllerNames);
|
|
||||||
IControllerBasedJsonSerializerSettingsBuilder ForControllersWithAttribute<T>();
|
|
||||||
IControllerBasedJsonSerializerSettingsBuilder ForActionsWithAttribute<T>();
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
public class JsonSerializerPooledPolicy : IPooledObjectPolicy<JsonSerializer>
|
|
||||||
{
|
|
||||||
private readonly JsonSerializerSettings _serializerSettings;
|
|
||||||
|
|
||||||
public JsonSerializerPooledPolicy(JsonSerializerSettings serializerSettings)
|
|
||||||
{
|
|
||||||
_serializerSettings = serializerSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonSerializer Create() => JsonSerializer.Create(_serializerSettings);
|
|
||||||
|
|
||||||
public bool Return(JsonSerializer serializer) => true;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
|
||||||
public class UseWasabiJsonInputFormatterAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Serialization;
|
|
||||||
using WalletWasabi.WabiSabi.Models.Serialization;
|
|
||||||
|
|
||||||
namespace WalletWasabi.Backend.Filters;
|
|
||||||
|
|
||||||
public class WasabiSpecificJsonSerializerFilter: Attribute, IResultFilter{
|
|
||||||
|
|
||||||
public void OnResultExecuted(ResultExecutedContext context)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnResultExecuting(ResultExecutingContext context)
|
|
||||||
{
|
|
||||||
if (context.Result is ObjectResult objectResult)
|
|
||||||
{
|
|
||||||
var serializerSettings = new JsonSerializerSettings()
|
|
||||||
{
|
|
||||||
Converters = JsonSerializationOptions.Default.Settings.Converters
|
|
||||||
};
|
|
||||||
|
|
||||||
var mvoptions = new MvcOptions();
|
|
||||||
|
|
||||||
var jsonFormatter = new NewtonsoftJsonOutputFormatter(
|
|
||||||
serializerSettings,
|
|
||||||
ArrayPool<char>.Shared, mvoptions, new MvcNewtonsoftJsonOptions());
|
|
||||||
|
|
||||||
objectResult.Formatters.Add(jsonFormatter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -16,9 +16,7 @@ namespace WalletWasabi.Backend.Controllers;
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
[ExceptionTranslate]
|
[ExceptionTranslate]
|
||||||
[LateResponseLoggerFilter]
|
[LateResponseLoggerFilter]
|
||||||
[WasabiSpecificJsonSerializerFilter]
|
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[UseWasabiJsonInputFormatter ]
|
|
||||||
[Route("plugins/wabisabi-coordinator/wabisabi")]
|
[Route("plugins/wabisabi-coordinator/wabisabi")]
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
public class WabiSabiController : ControllerBase, IWabiSabiApiRequestHandler
|
public class WabiSabiController : ControllerBase, IWabiSabiApiRequestHandler
|
||||||
@@ -35,13 +33,14 @@ public class WabiSabiController : ControllerBase, IWabiSabiApiRequestHandler
|
|||||||
private Arena Arena { get; }
|
private Arena Arena { get; }
|
||||||
private CoinJoinFeeRateStatStore CoinJoinFeeRateStatStore { get; }
|
private CoinJoinFeeRateStatStore CoinJoinFeeRateStatStore { get; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpPost("status")]
|
[HttpPost("status")]
|
||||||
public async Task<RoundStateResponse> GetStatusAsync(RoundStateRequest request, CancellationToken cancellationToken)
|
public async Task<RoundStateResponse> GetStatusAsync(RoundStateRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var response = await Arena.GetStatusAsync(request, cancellationToken);
|
var response = await Arena.GetStatusAsync(request, cancellationToken);
|
||||||
var medians = CoinJoinFeeRateStatStore.GetDefaultMedians();
|
var medians = CoinJoinFeeRateStatStore.GetDefaultMedians();
|
||||||
var ret = new RoundStateResponse(response.RoundStates, medians);
|
var ret = new RoundStateResponse(response.RoundStates, medians);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ Reputation risks: as the coordinator, the user may be associated with illegal ac
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vm.UriToAdvertise = Request.GetAbsoluteRootUri();
|
vm.UriToAdvertise = new Uri( Request.GetAbsoluteRootUri() + "plugins/wabisabi-coordinator");
|
||||||
TempData["SuccessMessage"] = $"Will create nostr events that point to { vm.UriToAdvertise }";
|
TempData["SuccessMessage"] = $"Will create nostr events that point to { vm.UriToAdvertise }";
|
||||||
await _wabisabiCoordinatorService.UpdateSettings( vm);
|
await _wabisabiCoordinatorService.UpdateSettings( vm);
|
||||||
return RedirectToAction(nameof(UpdateWabisabiSettings));
|
return RedirectToAction(nameof(UpdateWabisabiSettings));
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@using BTCPayServer.Abstractions.Contracts
|
@using BTCPayServer.Abstractions.Contracts
|
||||||
@using NBitcoin
|
@using NBitcoin
|
||||||
@using System.Security.Claims
|
@using System.Security.Claims
|
||||||
|
@using System.Web.NBitcoin
|
||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.TagHelpers
|
@using BTCPayServer.Abstractions.TagHelpers
|
||||||
@using BTCPayServer.Client
|
@using BTCPayServer.Client
|
||||||
@@ -344,13 +345,15 @@
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var safeName = HttpUtility.UrlEncode(s.Coordinator);
|
||||||
|
|
||||||
<div class="card mt-3">
|
<div class="card mt-3">
|
||||||
<div class="card-header d-flex justify-content-between">
|
<div class="card-header d-flex justify-content-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
|
|
||||||
<h3>@coordinator.CoordinatorDisplayName</h3>
|
<h3>@coordinator.CoordinatorDisplayName</h3>
|
||||||
@if (coordinator.CoordinatorName != "local" && coordinator.CoordinatorName != "zksnacks")
|
@if (coordinator.CoordinatorName != "local")
|
||||||
{
|
{
|
||||||
<button name="command" type="submit" value="remove-coordinator:@(coordinator.CoordinatorName)" class="btn btn-link txt-danger" permission="@Policies.CanModifyServerSettings">Remove</button>
|
<button name="command" type="submit" value="remove-coordinator:@(coordinator.CoordinatorName)" class="btn btn-link txt-danger" permission="@Policies.CanModifyServerSettings">Remove</button>
|
||||||
}
|
}
|
||||||
@@ -369,7 +372,7 @@
|
|||||||
var round = coordinator.RoundStateUpdater.RoundStates.Last(pair => pair.Value.BlameOf == uint256.Zero).Value;
|
var round = coordinator.RoundStateUpdater.RoundStates.Last(pair => pair.Value.BlameOf == uint256.Zero).Value;
|
||||||
var roundParameters = round.CoinjoinState.Parameters;
|
var roundParameters = round.CoinjoinState.Parameters;
|
||||||
|
|
||||||
<div class="modal modal-lg fade" id="config-@s.Coordinator">
|
<div class="modal modal-lg fade" id="config-@safeName">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@@ -426,7 +429,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="px-2 cursor-pointer"
|
<a class="px-2 cursor-pointer"
|
||||||
data-bs-toggle="modal" data-bs-target="#config-@s.Coordinator">
|
data-bs-toggle="modal" data-bs-target="#config-@safeName">
|
||||||
Coordinator Config
|
Coordinator Config
|
||||||
</a>
|
</a>
|
||||||
@if (Model.Settings[index].RoundWhenEnabled is not null && !BTCPayWallet.IsRoundOk(roundParameters, Model.Settings[index]))
|
@if (Model.Settings[index].RoundWhenEnabled is not null && !BTCPayWallet.IsRoundOk(roundParameters, Model.Settings[index]))
|
||||||
@@ -436,7 +439,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<a class="px-2 w-100 cursor-pointer"
|
<a class="px-2 w-100 cursor-pointer"
|
||||||
data-bs-toggle="modal" data-bs-target="#terms-@s.Coordinator"
|
data-bs-toggle="modal" data-bs-target="#terms-@safeName"
|
||||||
style="
|
style="
|
||||||
right: 0;
|
right: 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
@@ -465,7 +468,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal modal-lg fade" id="terms-@s.Coordinator">
|
<div class="modal modal-lg fade" id="terms-@safeName">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ public class WabisabiPlugin : BaseBTCPayServerPlugin
|
|||||||
utxoLocker,
|
utxoLocker,
|
||||||
provider.GetRequiredService<EventAggregator>(),
|
provider.GetRequiredService<EventAggregator>(),
|
||||||
provider.GetRequiredService<ILogger<WalletProvider>>(),
|
provider.GetRequiredService<ILogger<WalletProvider>>(),
|
||||||
provider.GetRequiredService<BTCPayNetworkProvider>(),
|
|
||||||
provider.GetRequiredService<PaymentMethodHandlerDictionary>(),
|
provider.GetRequiredService<PaymentMethodHandlerDictionary>(),
|
||||||
provider.GetRequiredService<IMemoryCache>()
|
provider.GetRequiredService<IMemoryCache>()
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Common;
|
using BTCPayServer.Common;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
@@ -38,7 +36,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
private readonly EventAggregator _eventAggregator;
|
private readonly EventAggregator _eventAggregator;
|
||||||
private readonly ILogger<WalletProvider> _logger;
|
private readonly ILogger<WalletProvider> _logger;
|
||||||
private readonly BTCPayNetworkProvider _networkProvider;
|
|
||||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly IMemoryCache _memoryCache;
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
|
||||||
@@ -55,7 +52,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
IUTXOLocker utxoLocker,
|
IUTXOLocker utxoLocker,
|
||||||
EventAggregator eventAggregator,
|
EventAggregator eventAggregator,
|
||||||
ILogger<WalletProvider> logger,
|
ILogger<WalletProvider> logger,
|
||||||
BTCPayNetworkProvider networkProvider,
|
|
||||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
IMemoryCache memoryCache) : base(TimeSpan.FromMinutes(5))
|
IMemoryCache memoryCache) : base(TimeSpan.FromMinutes(5))
|
||||||
{
|
{
|
||||||
@@ -66,7 +62,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_networkProvider = networkProvider;
|
|
||||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_memoryCache = memoryCache;
|
_memoryCache = memoryCache;
|
||||||
}
|
}
|
||||||
@@ -102,40 +97,44 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
var accountKeyPath2 = await explorerClient.GetMetadataAsync<RootedKeyPath>(derivationStrategy,
|
var accountKeyPath2 = await explorerClient.GetMetadataAsync<RootedKeyPath>(derivationStrategy,
|
||||||
WellknownMetadataKeys.AccountKeyPath);
|
WellknownMetadataKeys.AccountKeyPath);
|
||||||
accountKeyPath = accountKeyPath2 ?? accountKeyPath;
|
accountKeyPath = accountKeyPath2 ?? accountKeyPath;
|
||||||
var smartifier = new Smartifier(_memoryCache,_logger,_serviceProvider.GetRequiredService<WalletRepository>(),
|
var smartifier = new Smartifier(_memoryCache, _logger,
|
||||||
|
_serviceProvider.GetRequiredService<WalletRepository>(),
|
||||||
explorerClient, derivationStrategy, name, UtxoLocker, accountKeyPath);
|
explorerClient, derivationStrategy, name, UtxoLocker, accountKeyPath);
|
||||||
if (masterKey is null || accountKey is null || accountKeyPath is null)
|
if (masterKey is null || accountKey is null || accountKeyPath is null)
|
||||||
{
|
{
|
||||||
keychain = new BTCPayKeyChain(explorerClient, derivationStrategy, null, null, smartifier);
|
keychain = new BTCPayKeyChain(explorerClient, derivationStrategy, null, null, smartifier);
|
||||||
}else
|
}
|
||||||
keychain = new BTCPayKeyChain(explorerClient, derivationStrategy, masterKey, accountKey, smartifier);
|
else
|
||||||
|
keychain = new BTCPayKeyChain(explorerClient, derivationStrategy, masterKey, accountKey,
|
||||||
|
smartifier);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var smartifier = new Smartifier(_memoryCache, _logger,_serviceProvider.GetRequiredService<WalletRepository>(), explorerClient,
|
var smartifier = new Smartifier(_memoryCache, _logger,
|
||||||
|
_serviceProvider.GetRequiredService<WalletRepository>(), explorerClient,
|
||||||
derivationStrategy, name, UtxoLocker, accountKeyPath);
|
derivationStrategy, name, UtxoLocker, accountKeyPath);
|
||||||
keychain = new BTCPayKeyChain(explorerClient, derivationStrategy, null, null, smartifier);
|
keychain = new BTCPayKeyChain(explorerClient, derivationStrategy, null, null, smartifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var payoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||||
|
|
||||||
return new BTCPayWallet(
|
return new BTCPayWallet(
|
||||||
_serviceProvider.GetRequiredService<PaymentMethodHandlerDictionary>(),
|
_serviceProvider.GetRequiredService<PaymentMethodHandlerDictionary>(),
|
||||||
_serviceProvider.GetRequiredService<WalletRepository>(),
|
_serviceProvider.GetRequiredService<WalletRepository>(),
|
||||||
_serviceProvider.GetRequiredService<BTCPayNetworkProvider>(),
|
_serviceProvider.GetRequiredService<BTCPayNetworkProvider>(),
|
||||||
_serviceProvider.GetRequiredService<BitcoinLikePayoutHandler>(),
|
_serviceProvider.GetRequiredService<PayoutMethodHandlerDictionary>()[payoutMethodId],
|
||||||
_serviceProvider.GetRequiredService<BTCPayNetworkJsonSerializerSettings>(),
|
_serviceProvider.GetRequiredService<BTCPayNetworkJsonSerializerSettings>(),
|
||||||
_serviceProvider.GetRequiredService<Services.Wallets.BTCPayWalletProvider>().GetWallet("BTC"),
|
_serviceProvider.GetRequiredService<Services.Wallets.BTCPayWalletProvider>().GetWallet("BTC"),
|
||||||
_serviceProvider.GetRequiredService<PullPaymentHostedService>(),derivationStrategy, explorerClient, keychain,
|
_serviceProvider.GetRequiredService<PullPaymentHostedService>(), derivationStrategy, explorerClient,
|
||||||
|
keychain,
|
||||||
name, wabisabiStoreSettings, UtxoLocker,
|
name, wabisabiStoreSettings, UtxoLocker,
|
||||||
_loggerFactory,
|
_loggerFactory,
|
||||||
_serviceProvider.GetRequiredService<StoreRepository>(),
|
_serviceProvider.GetRequiredService<StoreRepository>(),
|
||||||
_serviceProvider.GetRequiredService<IMemoryCache>()
|
_serviceProvider.GetRequiredService<IMemoryCache>()
|
||||||
);
|
);
|
||||||
|
|
||||||
}, _logger);
|
}, _logger);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<IWallet>> GetWalletsAsync()
|
public async Task<IEnumerable<IWallet>> GetWalletsAsync()
|
||||||
{
|
{
|
||||||
var explorerClient = _explorerClientProvider.GetExplorerClient("BTC");
|
var explorerClient = _explorerClientProvider.GetExplorerClient("BTC");
|
||||||
@@ -152,10 +151,8 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task ResetWabisabiStuckPayouts(string[] storeIds)
|
public async Task ResetWabisabiStuckPayouts(string[] storeIds)
|
||||||
{
|
{
|
||||||
|
|
||||||
await _initialLoad.Task;
|
await _initialLoad.Task;
|
||||||
|
|
||||||
|
|
||||||
@@ -164,6 +161,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pullPaymentHostedService = _serviceProvider.GetRequiredService<PullPaymentHostedService>();
|
var pullPaymentHostedService = _serviceProvider.GetRequiredService<PullPaymentHostedService>();
|
||||||
var payouts = await pullPaymentHostedService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
var payouts = await pullPaymentHostedService.GetPayouts(new PullPaymentHostedService.PayoutQuery()
|
||||||
{
|
{
|
||||||
@@ -197,7 +195,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
|
|
||||||
protected override async Task ActionAsync(CancellationToken cancel)
|
protected override async Task ActionAsync(CancellationToken cancel)
|
||||||
{
|
{
|
||||||
|
|
||||||
// var toCheck = LoadedWallets.Keys.ToList();
|
// var toCheck = LoadedWallets.Keys.ToList();
|
||||||
// while (toCheck.Any())
|
// while (toCheck.Any())
|
||||||
// {
|
// {
|
||||||
@@ -214,7 +211,8 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
if (LoadedWallets.TryGetValue(storeId, out var currentWallet))
|
if (LoadedWallets.TryGetValue(storeId, out var currentWallet))
|
||||||
{
|
{
|
||||||
await UnloadWallet(storeId);
|
await UnloadWallet(storeId);
|
||||||
if(_cachedSettings.TryGetValue(storeId , out var settings) && settings.Settings.Any(coordinatorSettings => coordinatorSettings.Enabled))
|
if (_cachedSettings.TryGetValue(storeId, out var settings) &&
|
||||||
|
settings.Settings.Any(coordinatorSettings => coordinatorSettings.Enabled))
|
||||||
await GetWalletAsync(storeId);
|
await GetWalletAsync(storeId);
|
||||||
await GetWalletAsync(storeId);
|
await GetWalletAsync(storeId);
|
||||||
}
|
}
|
||||||
@@ -232,13 +230,13 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
|
|
||||||
public async Task SettingsUpdated(string storeId, WabisabiStoreSettings wabisabiSettings)
|
public async Task SettingsUpdated(string storeId, WabisabiStoreSettings wabisabiSettings)
|
||||||
{
|
{
|
||||||
|
|
||||||
_cachedSettings.AddOrReplace(storeId, wabisabiSettings);
|
_cachedSettings.AddOrReplace(storeId, wabisabiSettings);
|
||||||
|
|
||||||
if (!wabisabiSettings.Active || wabisabiSettings.Settings.All(settings => !settings.Enabled))
|
if (!wabisabiSettings.Active || wabisabiSettings.Settings.All(settings => !settings.Enabled))
|
||||||
{
|
{
|
||||||
await UnloadWallet(storeId);
|
await UnloadWallet(storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoadedWallets.TryGetValue(storeId, out var existingWallet))
|
if (LoadedWallets.TryGetValue(storeId, out var existingWallet))
|
||||||
{
|
{
|
||||||
var btcpayWallet = await existingWallet.Value;
|
var btcpayWallet = await existingWallet.Value;
|
||||||
@@ -258,6 +256,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
await UnloadWallet(storeId);
|
await UnloadWallet(storeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StartAsync(CancellationToken cancellationToken)
|
public override Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
@@ -270,7 +269,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
{
|
{
|
||||||
await _initialLoad.Task;
|
await _initialLoad.Task;
|
||||||
await UnloadWallet(@event.StoreId);
|
await UnloadWallet(@event.StoreId);
|
||||||
|
|
||||||
}));
|
}));
|
||||||
_disposables.Add(_eventAggregator.SubscribeAsync<WalletChangedEvent>(async @event =>
|
_disposables.Add(_eventAggregator.SubscribeAsync<WalletChangedEvent>(async @event =>
|
||||||
{
|
{
|
||||||
@@ -279,7 +277,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
await _initialLoad.Task;
|
await _initialLoad.Task;
|
||||||
await Check(@event.WalletId.StoreId, cancellationToken);
|
await Check(@event.WalletId.StoreId, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return base.StartAsync(cancellationToken);
|
return base.StartAsync(cancellationToken);
|
||||||
|
|||||||
Reference in New Issue
Block a user