mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
remove aopp and bump w
This commit is contained in:
@@ -1,222 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web;
|
|
||||||
using BTCPayServer.Abstractions.Constants;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Client;
|
|
||||||
using BTCPayServer.Client.Models;
|
|
||||||
using BTCPayServer.Common;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using NBitcoin;
|
|
||||||
using NBitcoin.Crypto;
|
|
||||||
using NBitcoin.Protocol;
|
|
||||||
using NBXplorer;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.AOPP
|
|
||||||
{
|
|
||||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
|
||||||
[Route("plugins/{storeId}/AOPP")]
|
|
||||||
public class AOPPController : Controller
|
|
||||||
{
|
|
||||||
private readonly BTCPayServerClient _btcPayServerClient;
|
|
||||||
private readonly AOPPService _AOPPService;
|
|
||||||
|
|
||||||
public AOPPController(BTCPayServerClient btcPayServerClient, AOPPService AOPPService)
|
|
||||||
{
|
|
||||||
_btcPayServerClient = btcPayServerClient;
|
|
||||||
_AOPPService = AOPPService;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("")]
|
|
||||||
public async Task<IActionResult> UpdateAOPPSettings(string storeId)
|
|
||||||
{
|
|
||||||
var store = await _btcPayServerClient.GetStore(storeId);
|
|
||||||
|
|
||||||
UpdateAOPPSettingsViewModel vm = new UpdateAOPPSettingsViewModel();
|
|
||||||
vm.StoreName = store.Name;
|
|
||||||
AOPPSettings AOPP = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AOPP = await _AOPPService.GetAOPPForStore(storeId);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
SetExistingValues(AOPP, vm);
|
|
||||||
return View(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetExistingValues(AOPPSettings existing, UpdateAOPPSettingsViewModel vm)
|
|
||||||
{
|
|
||||||
if (existing == null)
|
|
||||||
return;
|
|
||||||
vm.Enabled = existing.Enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("")]
|
|
||||||
public async Task<IActionResult> UpdateAOPPSettings(string storeId, UpdateAOPPSettingsViewModel vm,
|
|
||||||
string command)
|
|
||||||
{
|
|
||||||
if (vm.Enabled)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return View(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var AOPPSettings = new AOPPSettings()
|
|
||||||
{
|
|
||||||
Enabled = vm.Enabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (command)
|
|
||||||
{
|
|
||||||
case "save":
|
|
||||||
await _AOPPService.SetAOPPForStore(storeId, AOPPSettings);
|
|
||||||
TempData["SuccessMessage"] = "AOPP settings modified";
|
|
||||||
return RedirectToAction(nameof(UpdateAOPPSettings), new {storeId});
|
|
||||||
|
|
||||||
default:
|
|
||||||
return View(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal static String BITCOIN_SIGNED_MESSAGE_HEADER = "Bitcoin Signed Message:\n";
|
|
||||||
internal static byte[] BITCOIN_SIGNED_MESSAGE_HEADER_BYTES = Encoding.UTF8.GetBytes(BITCOIN_SIGNED_MESSAGE_HEADER);
|
|
||||||
|
|
||||||
//http://bitcoinj.googlecode.com/git-history/keychain/core/src/main/java/com/google/bitcoin/core/Utils.java
|
|
||||||
private static byte[] FormatMessageForSigning(byte[] messageBytes)
|
|
||||||
{
|
|
||||||
MemoryStream ms = new MemoryStream();
|
|
||||||
|
|
||||||
ms.WriteByte((byte)BITCOIN_SIGNED_MESSAGE_HEADER_BYTES.Length);
|
|
||||||
ms.Write(BITCOIN_SIGNED_MESSAGE_HEADER_BYTES, 0, BITCOIN_SIGNED_MESSAGE_HEADER_BYTES.Length);
|
|
||||||
|
|
||||||
VarInt size = new VarInt((ulong)messageBytes.Length);
|
|
||||||
ms.Write(size.ToBytes(), 0, size.ToBytes().Length);
|
|
||||||
ms.Write(messageBytes, 0, messageBytes.Length);
|
|
||||||
return ms.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AoppRequest
|
|
||||||
{
|
|
||||||
public Uri aopp { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
[Route("{invoiceId}")]
|
|
||||||
[AllowAnonymous]
|
|
||||||
public async Task<IActionResult> AOPPExecute(string storeId, string invoiceId,
|
|
||||||
[FromBody] AoppRequest request ,
|
|
||||||
[FromServices] IHttpClientFactory httpClientFactory,
|
|
||||||
[FromServices] BTCPayNetworkProvider btcPayNetworkProvider,
|
|
||||||
[FromServices] IExplorerClientProvider explorerClientProvider,
|
|
||||||
[FromServices] BTCPayServerClient btcPayServerClient,
|
|
||||||
[FromServices] IBTCPayServerClientFactory btcPayServerClientFactory)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var client = await btcPayServerClientFactory.Create(null, new[] {storeId});
|
|
||||||
|
|
||||||
var invoice = await client.GetInvoice(storeId, invoiceId);
|
|
||||||
if (invoice.Status is not InvoiceStatus.New)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var qs = HttpUtility.ParseQueryString(request.aopp.Query);
|
|
||||||
var asset = qs.Get("asset");
|
|
||||||
var network = btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(asset);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var invoicePaymentMethods = await client.GetInvoicePaymentMethods(storeId, invoiceId);
|
|
||||||
|
|
||||||
var pm = invoicePaymentMethods.FirstOrDefault(model =>
|
|
||||||
model.PaymentMethod.Equals(asset, StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
if (pm is null)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
var supported = (await client.GetStoreOnChainPaymentMethods(storeId))
|
|
||||||
.FirstOrDefault(settings => settings.CryptoCode.Equals(asset, StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
;
|
|
||||||
var msg = qs.Get("msg");
|
|
||||||
var format = qs.Get("format");
|
|
||||||
var callback = new Uri(qs.Get("callback")!, UriKind.Absolute);
|
|
||||||
ScriptType? expectedType = null;
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case "p2pkh":
|
|
||||||
expectedType = ScriptType.P2PKH;
|
|
||||||
break;
|
|
||||||
case "p2wpkh":
|
|
||||||
expectedType = ScriptType.P2WPKH;
|
|
||||||
break;
|
|
||||||
case "p2sh":
|
|
||||||
expectedType = ScriptType.P2SH;
|
|
||||||
break;
|
|
||||||
case "p2tr":
|
|
||||||
expectedType = ScriptType.Taproot;
|
|
||||||
break;
|
|
||||||
case "any":
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var address = BitcoinAddress.Create(pm.Destination, network.NBitcoinNetwork);
|
|
||||||
if (expectedType is not null && !address.ScriptPubKey
|
|
||||||
.IsScriptType(expectedType.Value))
|
|
||||||
{
|
|
||||||
return BadRequest();
|
|
||||||
}
|
|
||||||
var derivatonScheme =
|
|
||||||
network.NBXplorerNetwork.DerivationStrategyFactory.Parse(supported.DerivationScheme);
|
|
||||||
var explorerClient = explorerClientProvider.GetExplorerClient(network);
|
|
||||||
var extKeyStr = await explorerClient.GetMetadataAsync<string>(
|
|
||||||
derivatonScheme,
|
|
||||||
WellknownMetadataKeys.AccountHDKey);
|
|
||||||
if (extKeyStr == null)
|
|
||||||
{
|
|
||||||
return BadRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
var accountKey = ExtKey.Parse(extKeyStr, network.NBitcoinNetwork);
|
|
||||||
|
|
||||||
var keyInfo = await explorerClient.GetKeyInformationAsync(derivatonScheme, address.ScriptPubKey);
|
|
||||||
var privateKey = accountKey.Derive(keyInfo.KeyPath).PrivateKey;
|
|
||||||
|
|
||||||
var messageBytes = Encoding.UTF8.GetBytes(msg);
|
|
||||||
byte[] data = FormatMessageForSigning(messageBytes);
|
|
||||||
var hash = Hashes.DoubleSHA256(data);
|
|
||||||
var sig = Convert.ToBase64String(privateKey.SignCompact(hash, true).Signature);
|
|
||||||
|
|
||||||
var response = new
|
|
||||||
{
|
|
||||||
version = 0,
|
|
||||||
address = pm.Destination,
|
|
||||||
signature = sig
|
|
||||||
};
|
|
||||||
using var httpClient = httpClientFactory.CreateClient();
|
|
||||||
await httpClient.PostAsync(callback,
|
|
||||||
new StringContent(JsonConvert.SerializeObject(response), Encoding.UTF8, "application/json"));
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return BadRequest(new {ErrorMessage = e.Message});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
|
||||||
using BTCPayServer.Abstractions.Services;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.AOPP
|
|
||||||
{
|
|
||||||
public class AOPPPlugin : BaseBTCPayServerPlugin
|
|
||||||
{
|
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
|
||||||
{
|
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.7.4" }
|
|
||||||
};
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
|
||||||
{
|
|
||||||
applicationBuilder.AddSingleton<AOPPService>();
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/StoreIntegrationAOPPOption",
|
|
||||||
"store-integrations-list"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/CheckoutContentExtension",
|
|
||||||
"checkout-bitcoin-post-content"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/CheckoutContentExtension",
|
|
||||||
"checkout-lightning-post-content"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/CheckoutTabExtension",
|
|
||||||
"checkout-bitcoin-post-tabs"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/CheckoutTabExtension",
|
|
||||||
"checkout-lightning-post-tabs"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/CheckoutEnd",
|
|
||||||
"checkout-end"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("AOPP/AOPPNav",
|
|
||||||
"store-integrations-nav"));
|
|
||||||
base.Execute(applicationBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.AOPP
|
|
||||||
{
|
|
||||||
public class AOPPService
|
|
||||||
{
|
|
||||||
private readonly ISettingsRepository _settingsRepository;
|
|
||||||
private readonly IMemoryCache _memoryCache;
|
|
||||||
private readonly IStoreRepository _storeRepository;
|
|
||||||
|
|
||||||
public AOPPService(ISettingsRepository settingsRepository, IMemoryCache memoryCache,
|
|
||||||
IStoreRepository storeRepository)
|
|
||||||
{
|
|
||||||
_settingsRepository = settingsRepository;
|
|
||||||
_memoryCache = memoryCache;
|
|
||||||
_storeRepository = storeRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<AOPPSettings> GetAOPPForStore(string storeId)
|
|
||||||
{
|
|
||||||
var k = $"{nameof(AOPPSettings)}_{storeId}";
|
|
||||||
return await _memoryCache.GetOrCreateAsync(k, async _ =>
|
|
||||||
{
|
|
||||||
var res = await _storeRepository.GetSettingAsync<AOPPSettings>(storeId,
|
|
||||||
nameof(AOPPSettings));
|
|
||||||
if (res is not null) return res;
|
|
||||||
res = await _settingsRepository.GetSettingAsync<AOPPSettings>(k);
|
|
||||||
|
|
||||||
if (res is not null)
|
|
||||||
{
|
|
||||||
await SetAOPPForStore(storeId, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
await _settingsRepository.UpdateSetting<AOPPSettings>(null, k);
|
|
||||||
return res;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetAOPPForStore(string storeId, AOPPSettings AOPPSettings)
|
|
||||||
{
|
|
||||||
var k = $"{nameof(AOPPSettings)}_{storeId}";
|
|
||||||
await _storeRepository.UpdateSetting(storeId, nameof(AOPPSettings), AOPPSettings);
|
|
||||||
_memoryCache.Set(k, AOPPSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace BTCPayServer.Plugins.AOPP
|
|
||||||
{
|
|
||||||
public class AOPPSettings
|
|
||||||
{
|
|
||||||
public bool Enabled { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
<!-- Plugin specific properties -->
|
<!-- Plugin specific properties -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>LN Prism</Product>
|
<Product>Prism</Product>
|
||||||
<Description>Automated value splits for lightning.</Description>
|
<Description>Automated value splits for Bitcoin.</Description>
|
||||||
<Version>1.2.0</Version>
|
<Version>1.2.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Wabisabi Coinjoin</Product>
|
<Product>Wabisabi Coinjoin</Product>
|
||||||
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
|
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
|
||||||
<Version>1.0.60</Version>
|
<Version>1.0.61</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NLog;
|
||||||
using WabiSabi.Crypto;
|
using WabiSabi.Crypto;
|
||||||
using WalletWasabi.Affiliation;
|
using WalletWasabi.Affiliation;
|
||||||
using WalletWasabi.WabiSabi;
|
using WalletWasabi.WabiSabi;
|
||||||
@@ -13,8 +16,9 @@ public class ExceptionTranslateAttribute : ExceptionFilterAttribute
|
|||||||
{
|
{
|
||||||
public override void OnException(ExceptionContext context)
|
public override void OnException(ExceptionContext context)
|
||||||
{
|
{
|
||||||
|
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<WabiSabiCoordinator>>();
|
||||||
var exception = context.Exception.InnerException ?? context.Exception;
|
var exception = context.Exception.InnerException ?? context.Exception;
|
||||||
|
logger.LogError(exception, "Exception occured in WabiSabiCoordinator API, ");
|
||||||
context.Result = exception switch
|
context.Result = exception switch
|
||||||
{
|
{
|
||||||
WabiSabiProtocolException e => new JsonResult(new Error(
|
WabiSabiProtocolException e => new JsonResult(new Error(
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WalletWasabi.Logging;
|
using WalletWasabi.Logging;
|
||||||
|
using WalletWasabi.WabiSabi;
|
||||||
using WalletWasabi.WabiSabi.Backend.Models;
|
using WalletWasabi.WabiSabi.Backend.Models;
|
||||||
|
|
||||||
namespace WalletWasabi.Backend.Filters;
|
namespace WalletWasabi.Backend.Filters;
|
||||||
@@ -8,6 +11,7 @@ public class LateResponseLoggerFilter : ExceptionFilterAttribute
|
|||||||
{
|
{
|
||||||
public override void OnException(ExceptionContext context)
|
public override void OnException(ExceptionContext context)
|
||||||
{
|
{
|
||||||
|
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<WabiSabiCoordinator>>();
|
||||||
if (context.Exception is not WrongPhaseException ex)
|
if (context.Exception is not WrongPhaseException ex)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -15,6 +19,6 @@ public class LateResponseLoggerFilter : ExceptionFilterAttribute
|
|||||||
|
|
||||||
var actionName = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ActionName;
|
var actionName = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ActionName;
|
||||||
|
|
||||||
Logger.LogInfo($"Request '{actionName}' missing the phase '{string.Join(",", ex.ExpectedPhases)}' ('{ex.PhaseTimeout}' timeout) by '{ex.Late}'. Round id '{ex.RoundId}'.");
|
logger.LogInformation($"Request '{actionName}' missing the phase '{string.Join(",", ex.ExpectedPhases)}' ('{ex.PhaseTimeout}' timeout) by '{ex.Late}'. Round id '{ex.RoundId}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using WalletWasabi.Logging;
|
using NLog;
|
||||||
using WalletWasabi.WabiSabi.Client.Banning;
|
using WalletWasabi.WabiSabi.Client.Banning;
|
||||||
|
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||||
|
using Logger = WalletWasabi.Logging.Logger;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Wabisabi;
|
namespace BTCPayServer.Plugins.Wabisabi;
|
||||||
|
|
||||||
@@ -27,7 +30,7 @@ public class SettingsCoinPrison : CoinPrison
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<SettingsCoinPrison> CreateFromCoordinatorName(SettingsRepository settingsRepository,
|
public static async Task<SettingsCoinPrison> CreateFromCoordinatorName(SettingsRepository settingsRepository,
|
||||||
string coordinatorName)
|
string coordinatorName, ILogger logger)
|
||||||
{
|
{
|
||||||
HashSet<PrisonedCoinRecord> prisonedCoinRecords = new();
|
HashSet<PrisonedCoinRecord> prisonedCoinRecords = new();
|
||||||
try
|
try
|
||||||
@@ -35,7 +38,7 @@ public class SettingsCoinPrison : CoinPrison
|
|||||||
var data = await settingsRepository.GetSettingAsync<string>("wabisabi_" + coordinatorName + "_bannedcoins");
|
var data = await settingsRepository.GetSettingAsync<string>("wabisabi_" + coordinatorName + "_bannedcoins");
|
||||||
if (string.IsNullOrWhiteSpace(data))
|
if (string.IsNullOrWhiteSpace(data))
|
||||||
{
|
{
|
||||||
Logger.LogDebug("Prisoned coins file is empty.");
|
logger.LogDebug("Prisoned coins file is empty.");
|
||||||
return new(settingsRepository, coordinatorName);
|
return new(settingsRepository, coordinatorName);
|
||||||
}
|
}
|
||||||
prisonedCoinRecords = JsonConvert.DeserializeObject<HashSet<PrisonedCoinRecord>>(data)
|
prisonedCoinRecords = JsonConvert.DeserializeObject<HashSet<PrisonedCoinRecord>>(data)
|
||||||
@@ -43,7 +46,7 @@ public class SettingsCoinPrison : CoinPrison
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
Logger.LogError($"There was an error during loading {nameof(SettingsCoinPrison)}. Ignoring corrupt data.", exc);
|
logger.LogError($"There was an error during loading {nameof(SettingsCoinPrison)}. Ignoring corrupt data.", exc);
|
||||||
}
|
}
|
||||||
return new(settingsRepository, coordinatorName){ BannedCoins = prisonedCoinRecords };
|
return new(settingsRepository, coordinatorName){ BannedCoins = prisonedCoinRecords };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,14 +49,15 @@ public class Smartifier
|
|||||||
public readonly ConcurrentDictionary<OutPoint, Task<SmartCoin>> Coins = new();
|
public readonly ConcurrentDictionary<OutPoint, Task<SmartCoin>> Coins = new();
|
||||||
|
|
||||||
public static async Task<T?> GetOrCreate<T, Y>(ConcurrentDictionary<Y, Lazy<Task<T?>>> collection, Y key, Func<Task<T?>> create, ILogger logger = null)
|
public static async Task<T?> GetOrCreate<T, Y>(ConcurrentDictionary<Y, Lazy<Task<T?>>> collection, Y key, Func<Task<T?>> create, ILogger logger = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var lazyTask = new Lazy<Task<T?>>(() => FetchFromServer(create, logger, key));
|
var lazyTask = new Lazy<Task<T?>>(() => FetchFromServer(create, logger, key));
|
||||||
|
|
||||||
// Even if multiple threads provide their own new Lazy instances, only one will be stored.
|
// Even if multiple threads provide their own new Lazy instances, only one will be stored.
|
||||||
var task = collection.GetOrAdd(key, lazyTask).Value;
|
var task = collection.GetOrAdd(key, lazyTask).Value;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await task;
|
return await task;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
|||||||
@@ -203,6 +203,10 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@coin.AnonymitySet.ToString("0.##")
|
@coin.AnonymitySet.ToString("0.##")
|
||||||
|
@if (!coin.IsSufficientlyDistancedFromExternalKeys)
|
||||||
|
{
|
||||||
|
<span>(too close to entry)</span>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@coin.Amount.ToDecimal(MoneyUnit.BTC) BTC
|
@coin.Amount.ToDecimal(MoneyUnit.BTC) BTC
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ public class WabisabiCoordinatorClientInstance:IHostedService
|
|||||||
|
|
||||||
CoinPrison = SettingsCoinPrison.CreateFromCoordinatorName(
|
CoinPrison = SettingsCoinPrison.CreateFromCoordinatorName(
|
||||||
serviceProvider.GetRequiredService<SettingsRepository>(),
|
serviceProvider.GetRequiredService<SettingsRepository>(),
|
||||||
CoordinatorName).GetAwaiter().GetResult();
|
CoordinatorName, _logger).GetAwaiter().GetResult();
|
||||||
|
|
||||||
CoinJoinManager = new CoinJoinManager(coordinatorName, WalletProvider, RoundStateUpdater,
|
CoinJoinManager = new CoinJoinManager(coordinatorName, WalletProvider, RoundStateUpdater,
|
||||||
WasabiHttpClientFactory,
|
WasabiHttpClientFactory,
|
||||||
|
|||||||
Reference in New Issue
Block a user