mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
wabiupdate
This commit is contained in:
@@ -27,8 +27,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.FixedF
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.LiquidPlus", "Plugins\BTCPayServer.Plugins.LiquidPlus\BTCPayServer.Plugins.LiquidPlus.csproj", "{B4E2ED08-4AD3-4648-8BDB-3107200460B9}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.LiquidPlus", "Plugins\BTCPayServer.Plugins.LiquidPlus\BTCPayServer.Plugins.LiquidPlus.csproj", "{B4E2ED08-4AD3-4648-8BDB-3107200460B9}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.NFC", "Plugins\BTCPayServer.Plugins.NFC\BTCPayServer.Plugins.NFC.csproj", "{71885A5E-1B00-4676-9566-D81AAE37406C}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.SideShift", "Plugins\BTCPayServer.Plugins.SideShift\BTCPayServer.Plugins.SideShift.csproj", "{5E1BAA06-7828-47BC-89D6-19C2A78EA427}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.SideShift", "Plugins\BTCPayServer.Plugins.SideShift\BTCPayServer.Plugins.SideShift.csproj", "{5E1BAA06-7828-47BC-89D6-19C2A78EA427}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.TicketTailor", "Plugins\BTCPayServer.Plugins.TicketTailor\BTCPayServer.Plugins.TicketTailor.csproj", "{7AFC20EB-1696-47D7-8E57-822B05DD18F2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTCPayServer.Plugins.TicketTailor", "Plugins\BTCPayServer.Plugins.TicketTailor\BTCPayServer.Plugins.TicketTailor.csproj", "{7AFC20EB-1696-47D7-8E57-822B05DD18F2}"
|
||||||
@@ -151,14 +149,6 @@ Global
|
|||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Altcoins-Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Altcoins-Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Altcoins-Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{71885A5E-1B00-4676-9566-D81AAE37406C}.Altcoins-Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>10</LangVersion>
|
<LangVersion>11</LangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -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.55</Version>
|
<Version>1.0.56</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NNostr.Client" Version="0.0.34" />
|
<PackageReference Include="NNostr.Client" Version="0.0.37" />
|
||||||
<PackageReference Include="WabiSabi" Version="1.0.1.2" />
|
<PackageReference Include="WabiSabi" Version="1.0.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Target Name="DeleteExampleFile" AfterTargets="Publish">
|
<Target Name="DeleteExampleFile" AfterTargets="Publish">
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using BTCPayServer.Payments.PayJoin;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
@@ -53,7 +54,8 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
public readonly ILogger Logger;
|
public readonly ILogger Logger;
|
||||||
public static readonly BlockchainAnalyzer BlockchainAnalyzer = new();
|
public static readonly BlockchainAnalyzer BlockchainAnalyzer = new();
|
||||||
|
|
||||||
public BTCPayWallet(WalletRepository walletRepository,
|
public BTCPayWallet(
|
||||||
|
WalletRepository walletRepository,
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
BitcoinLikePayoutHandler bitcoinLikePayoutHandler,
|
BitcoinLikePayoutHandler bitcoinLikePayoutHandler,
|
||||||
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
||||||
@@ -66,7 +68,8 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
WabisabiStoreSettings wabisabiStoreSettings,
|
WabisabiStoreSettings wabisabiStoreSettings,
|
||||||
IUTXOLocker utxoLocker,
|
IUTXOLocker utxoLocker,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
StoreRepository storeRepository)
|
StoreRepository storeRepository,
|
||||||
|
IMemoryCache memoryCache)
|
||||||
{
|
{
|
||||||
KeyChain = keyChain;
|
KeyChain = keyChain;
|
||||||
_walletRepository = walletRepository;
|
_walletRepository = walletRepository;
|
||||||
@@ -81,6 +84,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
WabisabiStoreSettings = wabisabiStoreSettings;
|
WabisabiStoreSettings = wabisabiStoreSettings;
|
||||||
UtxoLocker = utxoLocker;
|
UtxoLocker = utxoLocker;
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
|
_memoryCache = memoryCache;
|
||||||
Logger = loggerFactory.CreateLogger($"BTCPayWallet_{storeId}");
|
Logger = loggerFactory.CreateLogger($"BTCPayWallet_{storeId}");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -147,6 +151,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
private IRoundCoinSelector _coinSelector;
|
private IRoundCoinSelector _coinSelector;
|
||||||
public Smartifier _smartifier => (KeyChain as BTCPayKeyChain)?.Smartifier;
|
public Smartifier _smartifier => (KeyChain as BTCPayKeyChain)?.Smartifier;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
|
||||||
public IRoundCoinSelector GetCoinSelector()
|
public IRoundCoinSelector GetCoinSelector()
|
||||||
{
|
{
|
||||||
@@ -492,7 +497,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
}))}, "utxo");
|
}))}, "utxo");
|
||||||
|
|
||||||
}
|
}
|
||||||
_smartifier.Transactions.AddOrReplace(txHash, Task.FromResult(smartTx));
|
_smartifier.SmartTransactions.AddOrReplace(txHash, Task.FromResult(smartTx));
|
||||||
//
|
//
|
||||||
// var kp = await ExplorerClient.GetMetadataAsync<RootedKeyPath>(DerivationScheme,
|
// var kp = await ExplorerClient.GetMetadataAsync<RootedKeyPath>(DerivationScheme,
|
||||||
// WellknownMetadataKeys.AccountKeyPath);
|
// WellknownMetadataKeys.AccountKeyPath);
|
||||||
@@ -552,6 +557,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
|
||||||
Logger.LogInformation($"Registered coinjoin result for {StoreId} in {stopwatch.Elapsed}");
|
Logger.LogInformation($"Registered coinjoin result for {StoreId} in {stopwatch.Elapsed}");
|
||||||
|
_memoryCache.Remove(WabisabiService.GetCacheKey(StoreId) + "cjhistory");
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ Reputation risks: as the coordinator, the user may be associated with illegal ac
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
vm.UriToAdvertise = Request.GetAbsoluteRootUri();
|
vm.UriToAdvertise = Request.GetAbsoluteRootUri();
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,9 +195,7 @@ public class WabisabiCoordinatorService : PeriodicRunner
|
|||||||
var coordinatorParameters =
|
var coordinatorParameters =
|
||||||
new CoordinatorParameters(Path.Combine(_dataDirectories.Value.DataDir, "Plugins", "Coinjoin"));
|
new CoordinatorParameters(Path.Combine(_dataDirectories.Value.DataDir, "Plugins", "Coinjoin"));
|
||||||
var coinJoinIdStore =
|
var coinJoinIdStore =
|
||||||
CoinJoinIdStore.Create(
|
CoinJoinIdStore.Create( coordinatorParameters.CoinJoinIdStoreFilePath);
|
||||||
Path.Combine(coordinatorParameters.ApplicationDataDir, "CcjCoordinator",
|
|
||||||
$"CoinJoins{explorerClient.Network}.txt"), coordinatorParameters.CoinJoinIdStoreFilePath);
|
|
||||||
var coinJoinScriptStore = CoinJoinScriptStore.LoadFromFile(coordinatorParameters.CoinJoinScriptStoreFilePath);
|
var coinJoinScriptStore = CoinJoinScriptStore.LoadFromFile(coordinatorParameters.CoinJoinScriptStoreFilePath);
|
||||||
var rpc = new BtcPayRpcClient(explorerClient.RPCClient, _memoryCache, explorerClient);
|
var rpc = new BtcPayRpcClient(explorerClient.RPCClient, _memoryCache, explorerClient);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Wabisabi;
|
namespace BTCPayServer.Plugins.Wabisabi;
|
||||||
|
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
|
public static string ToSentenceCase(this string str)
|
||||||
|
{
|
||||||
|
return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns an existing task from the concurrent dictionary, or adds a new task
|
/// Returns an existing task from the concurrent dictionary, or adds a new task
|
||||||
/// using the specified asynchronous factory method. Concurrent invocations for
|
/// using the specified asynchronous factory method. Concurrent invocations for
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using BTCPayServer.Abstractions.Contracts;
|
|||||||
using BTCPayServer.Payments.PayJoin;
|
using BTCPayServer.Payments.PayJoin;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
using NBXplorer.DerivationStrategy;
|
using NBXplorer.DerivationStrategy;
|
||||||
@@ -22,6 +23,7 @@ namespace BTCPayServer.Plugins.Wabisabi;
|
|||||||
|
|
||||||
public class Smartifier
|
public class Smartifier
|
||||||
{
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
private readonly WalletRepository _walletRepository;
|
private readonly WalletRepository _walletRepository;
|
||||||
private readonly ExplorerClient _explorerClient;
|
private readonly ExplorerClient _explorerClient;
|
||||||
public DerivationStrategyBase DerivationScheme { get; }
|
public DerivationStrategyBase DerivationScheme { get; }
|
||||||
@@ -29,10 +31,12 @@ public class Smartifier
|
|||||||
private readonly IUTXOLocker _utxoLocker;
|
private readonly IUTXOLocker _utxoLocker;
|
||||||
|
|
||||||
public Smartifier(
|
public Smartifier(
|
||||||
|
ILogger logger,
|
||||||
WalletRepository walletRepository,
|
WalletRepository walletRepository,
|
||||||
ExplorerClient explorerClient, DerivationStrategyBase derivationStrategyBase, string storeId,
|
ExplorerClient explorerClient, DerivationStrategyBase derivationStrategyBase, string storeId,
|
||||||
IUTXOLocker utxoLocker, RootedKeyPath accountKeyPath)
|
IUTXOLocker utxoLocker, RootedKeyPath accountKeyPath)
|
||||||
{
|
{
|
||||||
|
_logger = logger;
|
||||||
_walletRepository = walletRepository;
|
_walletRepository = walletRepository;
|
||||||
_explorerClient = explorerClient;
|
_explorerClient = explorerClient;
|
||||||
DerivationScheme = derivationStrategyBase;
|
DerivationScheme = derivationStrategyBase;
|
||||||
@@ -40,10 +44,49 @@ public class Smartifier
|
|||||||
_utxoLocker = utxoLocker;
|
_utxoLocker = utxoLocker;
|
||||||
_accountKeyPath = accountKeyPath;
|
_accountKeyPath = accountKeyPath;
|
||||||
}
|
}
|
||||||
|
public readonly ConcurrentDictionary<uint256, Lazy<Task<TransactionInformation>>> TransactionInformations = new();
|
||||||
public readonly ConcurrentDictionary<uint256, Task<TransactionInformation>> CachedTransactions = new();
|
public readonly ConcurrentDictionary<uint256, Task<SmartTransaction>> SmartTransactions = new();
|
||||||
public readonly ConcurrentDictionary<uint256, Task<SmartTransaction>> Transactions = new();
|
|
||||||
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)
|
||||||
|
{
|
||||||
|
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.
|
||||||
|
var task = collection.GetOrAdd(key, lazyTask).Value;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await task;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// If there's an error, remove the lazy task from the dictionary.
|
||||||
|
collection.TryRemove(key, out _);
|
||||||
|
// The error has already been logged inside FetchFromServer.
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<T?> FetchFromServer<T, Y>(Func<Task<T?>> create, ILogger logger, Y key)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await create();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger?.LogError(e, "Error while loading(and caching) {key}", key);
|
||||||
|
throw; // Re-throw the exception so the outer catch can handle it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<TransactionInformation?> GetTransactionInfo(uint256 hash)
|
||||||
|
{
|
||||||
|
return await GetOrCreate(TransactionInformations , hash, () => _explorerClient.GetTransactionAsync(DerivationScheme, hash), _logger);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly RootedKeyPath _accountKeyPath;
|
private readonly RootedKeyPath _accountKeyPath;
|
||||||
|
|
||||||
public async Task LoadCoins(List<ReceivedCoin> coins, int current ,
|
public async Task LoadCoins(List<ReceivedCoin> coins, int current ,
|
||||||
@@ -57,15 +100,14 @@ public class Smartifier
|
|||||||
var txs = coins.Select(data => data.OutPoint.Hash).Distinct();
|
var txs = coins.Select(data => data.OutPoint.Hash).Distinct();
|
||||||
foreach (uint256 tx in txs)
|
foreach (uint256 tx in txs)
|
||||||
{
|
{
|
||||||
if(!CachedTransactions.ContainsKey(tx))
|
_ =GetTransactionInfo(tx);
|
||||||
CachedTransactions.TryAdd(tx, _explorerClient.GetTransactionAsync(DerivationScheme, tx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var coin in coins)
|
foreach (var coin in coins)
|
||||||
{
|
{
|
||||||
var tx = await Transactions.GetOrAdd(coin.OutPoint.Hash, async uint256 =>
|
var tx = await SmartTransactions.GetOrAdd(coin.OutPoint.Hash, async uint256 =>
|
||||||
{
|
{
|
||||||
var unsmartTx = await CachedTransactions[coin.OutPoint.Hash];
|
var unsmartTx = await GetTransactionInfo(coin.OutPoint.Hash);
|
||||||
if (unsmartTx?.Transaction is null)
|
if (unsmartTx?.Transaction is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -85,17 +127,7 @@ public class Smartifier
|
|||||||
potentialMatches.TryAdd(matchedInput, potentialMatchesForInput.ToArray());
|
potentialMatches.TryAdd(matchedInput, potentialMatchesForInput.ToArray());
|
||||||
foreach (IndexedTxIn potentialMatchForInput in potentialMatchesForInput)
|
foreach (IndexedTxIn potentialMatchForInput in potentialMatchesForInput)
|
||||||
{
|
{
|
||||||
TransactionInformation ti = null;
|
var ti = await GetTransactionInfo(potentialMatchForInput.PrevOut.Hash);
|
||||||
try
|
|
||||||
{
|
|
||||||
ti = await CachedTransactions.GetOrAdd(potentialMatchForInput.PrevOut.Hash,
|
|
||||||
_explorerClient.GetTransactionAsync(DerivationScheme,
|
|
||||||
potentialMatchForInput.PrevOut.Hash));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
CachedTransactions.Remove(potentialMatchForInput.PrevOut.Hash, out _);
|
|
||||||
}
|
|
||||||
if (ti is not null)
|
if (ti is not null)
|
||||||
{
|
{
|
||||||
MatchedOutput found = ti.Outputs.Find(output =>
|
MatchedOutput found = ti.Outputs.Find(output =>
|
||||||
@@ -157,7 +189,6 @@ public class Smartifier
|
|||||||
var smartCoin = await Coins.GetOrAdd(coin.OutPoint, async point =>
|
var smartCoin = await Coins.GetOrAdd(coin.OutPoint, async point =>
|
||||||
{
|
{
|
||||||
utxoLabels.TryGetValue(coin.OutPoint, out var labels);
|
utxoLabels.TryGetValue(coin.OutPoint, out var labels);
|
||||||
var unsmartTx = await CachedTransactions[coin.OutPoint.Hash];
|
|
||||||
var pubKey = DerivationScheme.GetChild(coin.KeyPath).GetExtPubKeys().First().PubKey;
|
var pubKey = DerivationScheme.GetChild(coin.KeyPath).GetExtPubKeys().First().PubKey;
|
||||||
//if there is no account key path, it most likely means this is a watch only wallet. Fake the key path
|
//if there is no account key path, it most likely means this is a watch only wallet. Fake the key path
|
||||||
var kp = _accountKeyPath?.Derive(coin.KeyPath).KeyPath ?? new KeyPath(0,0,0,0,0);
|
var kp = _accountKeyPath?.Derive(coin.KeyPath).KeyPath ?? new KeyPath(0,0,0,0,0);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
@using BTCPayServer.Abstractions.Contracts
|
@using BTCPayServer.Abstractions.Contracts
|
||||||
@model WalletWasabi.Backend.Controllers.DiscoveredCoordinator
|
@model WalletWasabi.Backend.Controllers.DiscoveredCoordinator
|
||||||
@inject IScopeProvider ScopeProvider
|
@inject IScopeProvider ScopeProvider
|
||||||
<form asp-action="AddCoordinator" method="post" class="card mt-3" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()" permission="@Policies.CanModifyServerSettings">
|
<form asp-action="AddCoordinator" asp-controller="WabisabiStore" method="post" class="card mt-3" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()" permission="@Policies.CanModifyServerSettings">
|
||||||
<input type="hidden" asp-for="Description"/>
|
<input type="hidden" asp-for="Description"/>
|
||||||
<input type="hidden" asp-for="Name"/>
|
<input type="hidden" asp-for="Name"/>
|
||||||
<input type="hidden" asp-for="Uri"/>
|
<input type="hidden" asp-for="Uri"/>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<p>@Model.Description</p>
|
<p>@Model.Description</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group form-check">
|
<div class="form-group form-check">
|
||||||
<button name="command" type="submit" class="btn btn-primary btn-lg">Add</button>
|
<button name="command" type="submit" class="btn btn-primary btn-lg">Add</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-secondary mt-2" permission="@Policies.CanModifyServerSettings"
|
@* <button type="button" class="btn btn-secondary mt-2" permission="@Policies.CanModifyServerSettings" *@
|
||||||
data-bs-toggle="modal" data-bs-target="#discover-prompt">
|
@* data-bs-toggle="modal" data-bs-target="#discover-prompt"> *@
|
||||||
Add Coordinator
|
@* Add Coordinator *@
|
||||||
</button>
|
@* </button> *@
|
||||||
<div class="modal fade" id="discover-prompt" permission="@Policies.CanModifyServerSettings">
|
<div class="modal fade" id="discover-prompt" permission="@Policies.CanModifyServerSettings">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content ">
|
<div class="tab-content ">
|
||||||
<form asp-action="AddCoordinator" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()"
|
<form asp-action="AddCoordinator" asp-controller="WabisabiStore" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()"
|
||||||
class="tab-pane fade show active " id="nostr-tab-pane" role="tabpanel" aria-labelledby="home-tab" tabindex="0">
|
class="tab-pane fade show active " id="nostr-tab-pane" role="tabpanel" aria-labelledby="home-tab" tabindex="0">
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<form asp-action="AddCoordinator" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()"
|
<form asp-action="AddCoordinator" asp-controller="WabisabiStore" asp-route-storeId="@ScopeProvider.GetCurrentStoreId()"
|
||||||
class="tab-pane fade" id="manual-tab-pane" role="tabpanel" tabindex="0">
|
class="tab-pane fade" id="manual-tab-pane" role="tabpanel" tabindex="0">
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
@using BTCPayServer.Abstractions.Contracts
|
@using BTCPayServer.Abstractions.Contracts
|
||||||
@using BTCPayServer.Client
|
|
||||||
@using BTCPayServer.Client.Models
|
|
||||||
@using BTCPayServer.Common
|
@using BTCPayServer.Common
|
||||||
@using BTCPayServer.Plugins.Wabisabi
|
@using BTCPayServer.Plugins.Wabisabi
|
||||||
@using BTCPayServer.Security
|
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
||||||
@using NBitcoin
|
@using NBitcoin
|
||||||
@using WalletWasabi.Blockchain.Analysis
|
@using WalletWasabi.Extensions
|
||||||
|
@using WalletWasabi.WabiSabi.Backend.Rounds
|
||||||
|
@using WalletWasabi.WabiSabi.Client
|
||||||
|
@using WalletWasabi.WabiSabi.Models
|
||||||
@model object
|
@model object
|
||||||
@inject IScopeProvider ScopeProvider
|
@inject IScopeProvider ScopeProvider
|
||||||
@inject BTCPayServerClient Client
|
|
||||||
@inject WabisabiService WabisabiService;
|
@inject WabisabiService WabisabiService;
|
||||||
@inject WalletProvider WalletProvider;
|
@inject WalletProvider WalletProvider;
|
||||||
@inject WabisabiCoordinatorClientInstanceManager WabisabiCoordinatorClientInstanceManager
|
@inject WabisabiCoordinatorClientInstanceManager WabisabiCoordinatorClientInstanceManager
|
||||||
@@ -22,12 +20,6 @@
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (!(await ExplorerClientProvider.GetExplorerClient("BTC").GetStatusAsync()).IsFullySynched)
|
|
||||||
{
|
|
||||||
available = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var storeId = ScopeProvider.GetCurrentStoreId();
|
var storeId = ScopeProvider.GetCurrentStoreId();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -57,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<div class="widget store-wallet-balance" >
|
<div class="widget store-wallet-balance">
|
||||||
<header>
|
<header>
|
||||||
<h3>Recent Coinjoins</h3>
|
<h3>Recent Coinjoins</h3>
|
||||||
@if (cjHistory.Any())
|
@if (cjHistory.Any())
|
||||||
@@ -89,7 +81,7 @@
|
|||||||
|
|
||||||
var privacyPercentage = Math.Round(privacy * 100);
|
var privacyPercentage = Math.Round(privacy * 100);
|
||||||
var colorCoins = coins.GroupBy(coin => coin.CoinColor(wallet.AnonScoreTarget)).ToDictionary(grouping => grouping.Key, grouping => grouping);
|
var colorCoins = coins.GroupBy(coin => coin.CoinColor(wallet.AnonScoreTarget)).ToDictionary(grouping => grouping.Key, grouping => grouping);
|
||||||
<div class="widget store-numbers" >
|
<div class="widget store-numbers">
|
||||||
|
|
||||||
@if (wallet is { })
|
@if (wallet is { })
|
||||||
{
|
{
|
||||||
@@ -151,35 +143,35 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@{
|
@* @{ *@
|
||||||
var coinjoined = @coins.CoinJoinInProcess();
|
@* var coinjoined = @coins.CoinJoinInProcess(); *@
|
||||||
}
|
@* } *@
|
||||||
@if (coinjoined.Any())
|
@* @if (coinjoined.Any()) *@
|
||||||
{
|
@* { *@
|
||||||
var count = @coins.CoinJoinInProcess().Count();
|
@* var count = @coins.CoinJoinInProcess().Count(); *@
|
||||||
var totalCount = @coins.Count();
|
@* var totalCount = @coins.Count(); *@
|
||||||
var sum = @coinjoined.TotalAmount().ToDecimal(MoneyUnit.BTC);
|
@* var sum = @coinjoined.TotalAmount().ToDecimal(MoneyUnit.BTC); *@
|
||||||
var totalSum = @coins.TotalAmount().ToDecimal(MoneyUnit.BTC);
|
@* var totalSum = @coins.TotalAmount().ToDecimal(MoneyUnit.BTC); *@
|
||||||
var sumPercentage = decimal.Divide(sum, totalSum) * 100;
|
@* var sumPercentage = decimal.Divide(sum, totalSum) * 100; *@
|
||||||
var countPercentage = decimal.Divide(count, totalCount) * 100;
|
@* var countPercentage = decimal.Divide(count, totalCount) * 100; *@
|
||||||
|
@* *@
|
||||||
<div>
|
@* <div> *@
|
||||||
<h6 class="mb-2">Coins currently joining</h6>
|
@* <h6 class="mb-2">Coins currently joining</h6> *@
|
||||||
<div class="progress mb-2 position-relative" style="height: 2rem;">
|
@* <div class="progress mb-2 position-relative" style="height: 2rem;"> *@
|
||||||
<div class="w-100 text-center position-absolute bg-transparent progress-bar h-100">@count </div>
|
@* <div class="w-100 text-center position-absolute bg-transparent progress-bar h-100">@count </div> *@
|
||||||
<div class="progress-bar bg-info progress-bar-striped progress-bar-animated w-100" role="progressbar"></div>
|
@* <div class="progress-bar bg-info progress-bar-striped progress-bar-animated w-100" role="progressbar"></div> *@
|
||||||
</div>
|
@* </div> *@
|
||||||
</div>
|
@* </div> *@
|
||||||
<div>
|
@* <div> *@
|
||||||
<h6 class="mb-2">Value currently joining</h6>
|
@* <h6 class="mb-2">Value currently joining</h6> *@
|
||||||
<div class="progress mb-2 position-relative" style="height: 2rem;">
|
@* <div class="progress mb-2 position-relative" style="height: 2rem;"> *@
|
||||||
<div class="w-100 text-center position-absolute bg-transparent progress-bar h-100">@sum BTC</div>
|
@* <div class="w-100 text-center position-absolute bg-transparent progress-bar h-100">@sum BTC</div> *@
|
||||||
<div class="progress-bar bg-info progress-bar-striped progress-bar-animated w-100" role="progressbar"></div>
|
@* <div class="progress-bar bg-info progress-bar-striped progress-bar-animated w-100" role="progressbar"></div> *@
|
||||||
|
@* *@
|
||||||
|
@* *@
|
||||||
</div>
|
@* </div> *@
|
||||||
</div>
|
@* </div> *@
|
||||||
}
|
@* } *@
|
||||||
|
|
||||||
|
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
@@ -272,7 +264,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group list-group-flush mb-2">
|
<div class="list-group list-group-flush mt-4 mb-3">
|
||||||
<h5 class="list-group-item-heading text-muted">Enabled coordinators</h5>
|
<h5 class="list-group-item-heading text-muted">Enabled coordinators</h5>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
@@ -282,42 +274,172 @@
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
<div class="list-group-item">
|
|
||||||
<h6>@coordinator.CoordinatorDisplayName</h6>
|
|
||||||
<div class="row ">
|
|
||||||
<span class="text-muted col-sm-12 col-xxl-9 p-0 text-break">
|
|
||||||
@coordinator.Coordinator
|
|
||||||
</span>
|
|
||||||
|
|
||||||
@if (!coordinator.WasabiCoordinatorStatusFetcher.Connected)
|
RoundState currentRound = null;
|
||||||
|
CoinJoinTracker tracker = null;
|
||||||
|
if (coordinator.CoinJoinManager.TrackedCoinJoins?.TryGetValue(wallet.WalletName, out tracker) is true &&
|
||||||
|
tracker?.CoinJoinClient?.CurrentRoundId is { } &&
|
||||||
|
tracker?.CoinJoinClient?.RoundStatusUpdater?.RoundStates?.TryGetValue(tracker?.CoinJoinClient?.CurrentRoundId, out currentRound) is true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
var statusMsg = coordinator.WasabiCoordinatorStatusFetcher.Connected ? $"Connected to {(coordinator.Coordinator?.ToString() ?? "local")}" : $"Not connected to {(coordinator.Coordinator?.ToString() ?? "local")}";
|
||||||
|
<div class="list-group-item">
|
||||||
|
<div class="d-flex flex-wrap align-items-center justify-content-between gap-3">
|
||||||
|
<div class="d-flex flex-wrap align-items-center justify-content-between gap-3" data-bs-toggle="tooltip" title="@statusMsg">
|
||||||
|
<span class="btcpay-status btcpay-status--@(coordinator.WasabiCoordinatorStatusFetcher.Connected ? "enabled" : "disabled")"></span>
|
||||||
|
<h6>@coordinator.CoordinatorDisplayName</h6>
|
||||||
|
</div>
|
||||||
|
@if(currentRound is not null)
|
||||||
{
|
{
|
||||||
<p class="text-danger mb-0 col-sm-12 col-xxl-3 p-0 text-break">Not connected</p>
|
<div class="timer cursor-pointer" data-bs-toggle="collapse" data-bs-target="#cj-@currentRound.Id">
|
||||||
}
|
<span class="spinner-border spinner-border-sm" role="status">
|
||||||
else
|
<span class="visually-hidden"></span>
|
||||||
|
</span>
|
||||||
|
<span class="h6">Mixing</span>
|
||||||
|
<vc:icon symbol="caret-down" />
|
||||||
|
</div>
|
||||||
|
}else if( coordinator.WasabiCoordinatorStatusFetcher.Connected)
|
||||||
{
|
{
|
||||||
<p class="text-success mb-0 col-sm-12 col-xxl-3 p-0 text-break">Connected</p>
|
|
||||||
|
<span class="h6">Idle</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@{
|
@{
|
||||||
|
|
||||||
if (coordinator.CoinPrison is not null)
|
if (coordinator.CoinPrison is not null)
|
||||||
{
|
{
|
||||||
|
var bannedCoins = coins.Where(coin => coordinator.CoinPrison.TryGetOrRemoveBannedCoin(coin.Outpoint, out _));
|
||||||
var bannedCoins = coins.Where(coin => coordinator.CoinPrison.TryGetOrRemoveBannedCoin(coin.Outpoint, out _));
|
|
||||||
@if (bannedCoins.Any())
|
@if (bannedCoins.Any())
|
||||||
{
|
{
|
||||||
<div>
|
<div class="text-muted">@bannedCoins.Count() banned coins(for disrupting rounds)</div>
|
||||||
<h6 class="mb-2">Coins currently banned (for disrupting rounds)</h6>
|
|
||||||
<div class="progress mb-2 position-relative" style="height: 2rem;">
|
|
||||||
<div class="w-100 text-center position-absolute bg-transparent progress-bar h-100">@bannedCoins.Count() </div>
|
|
||||||
<div class="progress-bar bg-danger w-100" role="progressbar"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (currentRound is not null)
|
||||||
|
{
|
||||||
|
<div class="collapse table-responsive @(enabledSettings.Count() ==1? "show": "")" id="cj-@currentRound.Id">
|
||||||
|
<table class="table ">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Status</th>
|
||||||
|
<td class="text-truncate">@currentRound.Phase.ToString().ToSentenceCase()</td>
|
||||||
|
</tr><tr>
|
||||||
|
<th scope="row">Round id</th>
|
||||||
|
<td class="text-truncate" style="max-width: 200px" title="@currentRound.Id.ToString()">@currentRound.Id.ToString()</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Mining feerate</th>
|
||||||
|
<td >@currentRound.CoinjoinState.Parameters.MiningFeeRate.ToString()</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Coinjoin total inputs</th>
|
||||||
|
<td >@currentRound.CoinjoinState.Inputs.Count() inputs (@currentRound.CoinjoinState.Inputs.Sum(coin => coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC)</td>
|
||||||
|
</tr>
|
||||||
|
@if (!tracker.CoinJoinClient.CoinsToRegister.IsEmpty)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Your inputs</th>
|
||||||
|
<td class="row" >
|
||||||
|
<span class="w-100">Registered @tracker.CoinJoinClient.CoinsInCriticalPhase.Count() inputs (@tracker.CoinJoinClient.CoinsInCriticalPhase.Sum(coin => coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) / @tracker.CoinJoinClient.CoinsToRegister.Count() inputs (@tracker.CoinJoinClient.CoinsToRegister.Sum(coin => coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) </span>
|
||||||
|
@if (tracker.BannedCoins.Any())
|
||||||
|
{
|
||||||
|
<span class="w-100 text-danger">but got @tracker.BannedCoins.Count() inputs (@tracker.BannedCoins.Sum(coin => coin.Coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) banned</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (currentRound.Phase >= Phase.OutputRegistration)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Coinjoin total outputs</th>
|
||||||
|
<td >@currentRound.CoinjoinState.Outputs.Count() outputs (@currentRound.CoinjoinState.Outputs.Sum(coin => coin.Value.ToDecimal(MoneyUnit.BTC)) BTC)</td>
|
||||||
|
</tr>
|
||||||
|
if (tracker.CoinJoinClient.OutputTxOuts is { } outputs)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Your outputs</th>
|
||||||
|
<td >@outputs.outputTxOuts.Count() outputs (@outputs.outputTxOuts.Sum(coin => coin.Value.ToDecimal(MoneyUnit.BTC)) BTC, @outputs.batchedPayments.Count() batched payments)</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@* <div class="collapse table-responsive" id="cj-@currentRound.Id"> *@
|
||||||
|
@* *@
|
||||||
|
@* <dl> *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px"> *@
|
||||||
|
@* Status *@
|
||||||
|
@* </dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* @currentRound.Phase.ToString().ToSentenceCase() *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px"> *@
|
||||||
|
@* Round ID *@
|
||||||
|
@* </dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* @currentRound.Id.ToString() *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px"> *@
|
||||||
|
@* Mining feerate *@
|
||||||
|
@* </dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* @currentRound.CoinjoinState.Parameters.MiningFeeRate.ToString() *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px"> *@
|
||||||
|
@* Coinjoin total inputs *@
|
||||||
|
@* </dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* @currentRound.CoinjoinState.Inputs.Count() inputs (@currentRound.CoinjoinState.Inputs.Sum(coin => coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* *@
|
||||||
|
@* *@
|
||||||
|
@* @if (!tracker.CoinJoinClient.CoinsToRegister.IsEmpty) *@
|
||||||
|
@* { *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px">Your inputs</dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* <span class="w-100">Registered @tracker.CoinJoinClient.CoinsInCriticalPhase.Count() inputs (@tracker.CoinJoinClient.CoinsInCriticalPhase.Sum(coin => coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) / @tracker.CoinJoinClient.CoinsToRegister.Count() inputs (@tracker.CoinJoinClient.CoinsToRegister.Sum(coin => coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) </span> *@
|
||||||
|
@* @if (tracker.BannedCoins.Any()) *@
|
||||||
|
@* { *@
|
||||||
|
@* <span class="w-100 text-danger">but got @tracker.BannedCoins.Count() inputs (@tracker.BannedCoins.Sum(coin => coin.Coin.Amount.ToDecimal(MoneyUnit.BTC)) BTC) banned</span> *@
|
||||||
|
@* } *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* } *@
|
||||||
|
@* *@
|
||||||
|
@* @if (currentRound.Phase >= Phase.OutputRegistration) *@
|
||||||
|
@* { *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px">Coinjoin total outputs</dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* @currentRound.CoinjoinState.Outputs.Count() outputs (@currentRound.CoinjoinState.Outputs.Sum(coin => coin.Value.ToDecimal(MoneyUnit.BTC)) BTC) *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* if (tracker.CoinJoinClient.OutputTxOuts is { } outputs) *@
|
||||||
|
@* { *@
|
||||||
|
@* <div class="d-flex flex-wrap align-items-center gap-2"> *@
|
||||||
|
@* <dt class="w-100px">>Your outputs</dt> *@
|
||||||
|
@* <dd> *@
|
||||||
|
@* @outputs.outputTxOuts.Count() outputs (@outputs.outputTxOuts.Sum(coin => coin.Value.ToDecimal(MoneyUnit.BTC)) BTC, @outputs.batchedPayments.Count() batched payments) *@
|
||||||
|
@* </dd> *@
|
||||||
|
@* </div> *@
|
||||||
|
@* } *@
|
||||||
|
@* } *@
|
||||||
|
@* </dl> *@
|
||||||
|
@* *@
|
||||||
|
@* </div> *@
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,8 +448,6 @@
|
|||||||
<button type="button" class="btn btn-text p-1" data-bs-toggle="modal" data-bs-target="#coins">
|
<button type="button" class="btn btn-text p-1" data-bs-toggle="modal" data-bs-target="#coins">
|
||||||
View coins
|
View coins
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
@using WalletWasabi.Backend.Controllers
|
|
||||||
@using BTCPayServer.Plugins.Wabisabi
|
@using BTCPayServer.Plugins.Wabisabi
|
||||||
@model WalletWasabi.Backend.Controllers.WabisabiCoordinatorSettings
|
@model WalletWasabi.Backend.Controllers.WabisabiCoordinatorSettings
|
||||||
|
|
||||||
@@ -8,9 +7,19 @@
|
|||||||
ViewData["NavPartialName"] = "../UIServer/_Nav";
|
ViewData["NavPartialName"] = "../UIServer/_Nav";
|
||||||
}
|
}
|
||||||
|
|
||||||
<h2 class="mb-4">Coinjoin coordinator configuration</h2>
|
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||||
|
<h3 class="mb-0">
|
||||||
|
<span>Coinjoin coordinator</span>
|
||||||
|
<a href="https://docs.btcpayserver.org/Wabisabi" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||||
|
<vc:icon symbol="info"/>
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<button name="command" type="submit" value="save" class="btn btn-primary mt-3 mt-sm-0">Save</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xxl-constrain col-xl-8">
|
<div class="col-xxl-constrain col-xl-8">
|
||||||
<div class="form-group form-check">
|
<div class="form-group form-check">
|
||||||
@@ -36,9 +45,8 @@
|
|||||||
</textarea>
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row ">
|
<div class="col-xxl-constrain col-xl-4">
|
||||||
<div class="col-xxl-constrain col-xl-8">
|
|
||||||
<h3 class="mb-3">Publish to Nostr </h3>
|
<h3 class="mb-3">Publish to Nostr </h3>
|
||||||
<div class="form-group ">
|
<div class="form-group ">
|
||||||
<label asp-for="NostrRelay" class="form-label">Nostr Relay</label>
|
<label asp-for="NostrRelay" class="form-label">Nostr Relay</label>
|
||||||
@@ -68,7 +76,6 @@
|
|||||||
<p class=" alert alert-warning" style="white-space: pre-line">
|
<p class=" alert alert-warning" style="white-space: pre-line">
|
||||||
@WabisabiCoordinatorConfigController.OurDisclaimer
|
@WabisabiCoordinatorConfigController.OurDisclaimer
|
||||||
</p>
|
</p>
|
||||||
<button name="command" type="submit" value="save" class="btn btn-primary mt-2">Save</button>
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,15 +1,25 @@
|
|||||||
|
@using BTCPayServer.Components
|
||||||
@using BTCPayServer.Components
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
|
||||||
@using BTCPayServer.Views.Stores
|
|
||||||
@model BTCPayServer.Plugins.Wabisabi.CoinjoinsViewModel
|
@model BTCPayServer.Plugins.Wabisabi.CoinjoinsViewModel
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage(StoreNavPages.Plugins);
|
var storeId = Context.GetCurrentStoreId();
|
||||||
|
ViewData.SetActivePage("CoinjoinHistory", "Coinjoin", "Coinjoin History", storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||||
<h3 class="mb-0">Coinjoin History</h3>
|
<h3 class="mb-0">
|
||||||
|
<span>@ViewData["Title"]</span>
|
||||||
|
<a href="https://docs.btcpayserver.org/Wabisabi" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||||
|
<vc:icon symbol="info"/>
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<a asp-action="UpdateWabisabiStoreSettings" asp-route-storeId="@storeId" class="btn btn-primary mt-3 mt-sm-0" role="button">
|
||||||
|
<span class="fa fa-settings"></span>
|
||||||
|
Settings
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<partial name="Wabisabi/CoinjoinHistoryTable" model="Model.Coinjoins.ToList()" />
|
|
||||||
|
<partial name="Wabisabi/CoinjoinHistoryTable" model="Model.Coinjoins.ToList()"/>
|
||||||
<vc:pager view-model="Model"></vc:pager>
|
<vc:pager view-model="Model"></vc:pager>
|
||||||
@@ -17,9 +17,7 @@
|
|||||||
@inject BTCPayServerOptions BtcPayServerOptions
|
@inject BTCPayServerOptions BtcPayServerOptions
|
||||||
@{
|
@{
|
||||||
var storeId = _scopeProvider.GetCurrentStoreId();
|
var storeId = _scopeProvider.GetCurrentStoreId();
|
||||||
Layout = "../Shared/_NavLayout.cshtml";
|
ViewData.SetActivePage("CoinjoinSettings", "Coinjoin", "Coinjoin settings", storeId);
|
||||||
ViewData["NavPartialName"] = "../UIStores/_Nav";
|
|
||||||
ViewData.SetActivePage("Plugins", "BTCPayServer.Views.Stores.StoreNavPages", "Wabisabi coinjoin support", storeId);
|
|
||||||
var userid = Context.User.Claims.Single(claim => claim.Type == ClaimTypes.NameIdentifier).Value;
|
var userid = Context.User.Claims.Single(claim => claim.Type == ClaimTypes.NameIdentifier).Value;
|
||||||
var anyEnabled = Model.Settings.Any(settings => settings.Enabled);
|
var anyEnabled = Model.Settings.Any(settings => settings.Enabled);
|
||||||
ScriptPubKeyType? scriptType;
|
ScriptPubKeyType? scriptType;
|
||||||
@@ -34,28 +32,45 @@
|
|||||||
.Select(pair => new SelectListItem(pair.Value.s.StoreName, pair.Key, Model.MixToOtherWallet == pair.Key)).Prepend(new SelectListItem("None", ""));
|
.Select(pair => new SelectListItem(pair.Value.s.StoreName, pair.Key, Model.MixToOtherWallet == pair.Key)).Prepend(new SelectListItem("None", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="d-flex">
|
<form method="post">
|
||||||
<h2 class="">Coinjoin configuration</h2>
|
|
||||||
<a href="https://github.com/Kukks/BTCPayServerPlugins/blob/master/Plugins/BTCPayServer.Plugins.Wabisabi/readme.md" class="ms-1" target="_blank" rel="noreferrer noopener">
|
|
||||||
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
<partial name="_StatusMessage"/>
|
||||||
|
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||||
|
<h3 class="mb-0">
|
||||||
|
<span>@ViewData["Title"]</span>
|
||||||
|
<a href="https://docs.btcpayserver.org/Wabisabi" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||||
|
<vc:icon symbol="info"/>
|
||||||
</a>
|
</a>
|
||||||
|
</h3>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<button name="command" type="submit" value="save" class="btn btn-primary mt-3 mt-sm-0">Save</button>
|
||||||
|
<a asp-action="ListCoinjoins" asp-route-storeId="@storeId" class="btn btn-secondary mt-3 mt-sm-0" role="button">
|
||||||
|
Coinjoin History
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-secondary mt-3 mt-sm-0" permission="@Policies.CanModifyServerSettings"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#discover-prompt">
|
||||||
|
Add Coordinator
|
||||||
|
</button>
|
||||||
|
<a asp-controller="WabisabiCoordinatorConfig" asp-action="UpdateWabisabiSettings" class="btn btn-secondary mt-3 mt-sm-0" permission="@Policies.CanModifyServerSettings">Coordinator</a>
|
||||||
|
@* <a class="btn btn-secondary mt-3 mt-sm-0" href="https://gist.github.com/nopara73/bb17e89d7dc9af536ca41f50f705d329" rel="noreferrer noopener" target="_blank">Enable Discreet payments - Coming soon</a> *@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form method="post">
|
|
||||||
@{
|
@{
|
||||||
if (BtcPayServerOptions.SocksEndpoint is null)
|
if (BtcPayServerOptions.SocksEndpoint is null)
|
||||||
{
|
{
|
||||||
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
||||||
<vc:icon symbol="warning"/>
|
<vc:icon symbol="warning"/>
|
||||||
<span class="ms-3">TOR is not configured on this BTCPay Server instance. All communication will be over clearnet and therefore not private!</span>
|
<span class="ms-3">TOR is not configured on this BTCPay Server instance. All communication will be over clearnet and therefore not private!</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
var wallet = await WalletProvider.GetWalletAsync(storeId);
|
var wallet = await WalletProvider.GetWalletAsync(storeId);
|
||||||
if (wallet is BTCPayWallet)
|
if (wallet is BTCPayWallet)
|
||||||
{
|
{
|
||||||
|
|
||||||
@if (!((BTCPayKeyChain) wallet.KeyChain).KeysAvailable)
|
@if (!((BTCPayKeyChain) wallet.KeyChain).KeysAvailable)
|
||||||
{
|
{
|
||||||
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
||||||
@@ -217,7 +232,7 @@
|
|||||||
|
|
||||||
<span class="text-muted">@coordinator.Coordinator</span>
|
<span class="text-muted">@coordinator.Coordinator</span>
|
||||||
<div>
|
<div>
|
||||||
<div>@(!coordinator.WasabiCoordinatorStatusFetcher.Connected? "Coordinator Status: Not connected": "Coordinator Status: Connected")</div>
|
<div>@(!coordinator.WasabiCoordinatorStatusFetcher.Connected ? "Coordinator Status: Not connected" : "Coordinator Status: Connected")</div>
|
||||||
|
|
||||||
@if (!string.IsNullOrEmpty(coordinator.Description))
|
@if (!string.IsNullOrEmpty(coordinator.Description))
|
||||||
{
|
{
|
||||||
@@ -346,15 +361,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<button name="command" type="submit" value="save" class="btn btn-primary mt-2">Save</button>
|
|
||||||
<a asp-controller="WabisabiStore" asp-action="ListCoinjoins" class="btn btn-secondary mt-2" asp-route-storeId="@storeId">Coinjoins</a>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
<a asp-controller="WabisabiCoordinatorConfig" asp-action="UpdateWabisabiSettings" class="btn btn-secondary mt-2" permission="@Policies.CanModifyServerSettings">Coordinator runner</a>
|
|
||||||
|
|
||||||
<partial name="Wabisabi/AddCoordinatorPrompt" model="@(new DiscoveredCoordinator())"/>
|
<partial name="Wabisabi/AddCoordinatorPrompt" model="@(new DiscoveredCoordinator())"/>
|
||||||
<a class="btn btn-secondary mt-2" href="https://gist.github.com/nopara73/bb17e89d7dc9af536ca41f50f705d329" rel="noreferrer noopener" target="_blank">Enable Discreet payments - Coming soon</a>
|
|
||||||
|
|
||||||
|
|
||||||
@section PageFootContent {
|
@section PageFootContent {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ using WalletWasabi.WabiSabi.Client.RoundStateAwaiters;
|
|||||||
using WalletWasabi.WabiSabi.Client.StatusChangedEvents;
|
using WalletWasabi.WabiSabi.Client.StatusChangedEvents;
|
||||||
using WalletWasabi.Wallets;
|
using WalletWasabi.Wallets;
|
||||||
using WalletWasabi.WebClients.Wasabi;
|
using WalletWasabi.WebClients.Wasabi;
|
||||||
using HttpClientFactory = WalletWasabi.WebClients.Wasabi.HttpClientFactory;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Wabisabi;
|
namespace BTCPayServer.Plugins.Wabisabi;
|
||||||
|
|
||||||
@@ -137,7 +136,7 @@ public class WabisabiCoordinatorClientInstance
|
|||||||
public Uri Coordinator { get; set; }
|
public Uri Coordinator { get; set; }
|
||||||
public WalletProvider WalletProvider { get; }
|
public WalletProvider WalletProvider { get; }
|
||||||
public string TermsConditions { get; set; }
|
public string TermsConditions { get; set; }
|
||||||
public HttpClientFactory WasabiHttpClientFactory { get; set; }
|
public WasabiHttpClientFactory WasabiHttpClientFactory { get; set; }
|
||||||
public RoundStateUpdater RoundStateUpdater { get; set; }
|
public RoundStateUpdater RoundStateUpdater { get; set; }
|
||||||
public CoinPrison CoinPrison { get; private set; }
|
public CoinPrison CoinPrison { get; private set; }
|
||||||
public WasabiCoordinatorStatusFetcher WasabiCoordinatorStatusFetcher { get; set; }
|
public WasabiCoordinatorStatusFetcher WasabiCoordinatorStatusFetcher { get; set; }
|
||||||
@@ -176,7 +175,7 @@ public class WabisabiCoordinatorClientInstance
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WasabiHttpClientFactory = new HttpClientFactory(torEndpoint, () => Coordinator);
|
WasabiHttpClientFactory = new WasabiHttpClientFactory(torEndpoint, () => Coordinator);
|
||||||
var roundStateUpdaterCircuit = new PersonCircuit();
|
var roundStateUpdaterCircuit = new PersonCircuit();
|
||||||
var roundStateUpdaterHttpClient =
|
var roundStateUpdaterHttpClient =
|
||||||
WasabiHttpClientFactory.NewHttpClient(Mode.SingleCircuitPerLifetime, roundStateUpdaterCircuit);
|
WasabiHttpClientFactory.NewHttpClient(Mode.SingleCircuitPerLifetime, roundStateUpdaterCircuit);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
@@ -20,7 +21,7 @@ public class WabisabiPlugin : BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.11.0" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.11.5" }
|
||||||
};
|
};
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
@@ -140,3 +141,4 @@ public class WabisabiPlugin : BaseBTCPayServerPlugin
|
|||||||
base.Execute(applicationBuilder, applicationBuilderApplicationServices);
|
base.Execute(applicationBuilder, applicationBuilderApplicationServices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -33,7 +34,7 @@ namespace BTCPayServer.Plugins.Wabisabi
|
|||||||
_memoryCache = memoryCache;
|
_memoryCache = memoryCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetCacheKey(string storeId)
|
public static string GetCacheKey(string storeId)
|
||||||
{
|
{
|
||||||
return $"{nameof(WabisabiStoreSettings)}-{storeId}";
|
return $"{nameof(WabisabiStoreSettings)}-{storeId}";
|
||||||
}
|
}
|
||||||
@@ -76,7 +77,7 @@ namespace BTCPayServer.Plugins.Wabisabi
|
|||||||
_walletProvider.LoadedWallets.TryGetValue(storeId, out var walletTask);
|
_walletProvider.LoadedWallets.TryGetValue(storeId, out var walletTask);
|
||||||
if (walletTask != null)
|
if (walletTask != null)
|
||||||
{
|
{
|
||||||
var wallet = await walletTask;
|
var wallet = await walletTask.Value;
|
||||||
await _coordinatorClientInstanceManager.StopWallet(wallet, setting.Coordinator);
|
await _coordinatorClientInstanceManager.StopWallet(wallet, setting.Coordinator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,15 +137,29 @@ namespace BTCPayServer.Plugins.Wabisabi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<List<BTCPayWallet.CoinjoinData>> GetCoinjoinHistory(string storeId)
|
public async Task<List<BTCPayWallet.CoinjoinData>> GetCoinjoinHistory(string storeId, bool force = false)
|
||||||
{
|
{
|
||||||
return (await _walletRepository.GetWalletObjects(
|
var k = GetCacheKey(storeId) + "cjhistory";
|
||||||
new GetWalletObjectsQuery(new WalletId(storeId, "BTC"))
|
if (force)
|
||||||
{
|
{
|
||||||
Type = "coinjoin"
|
_memoryCache.Remove(k);
|
||||||
})).Values.Where(data => !string.IsNullOrEmpty(data.Data))
|
}
|
||||||
.Select(data => JObject.Parse(data.Data).ToObject<BTCPayWallet.CoinjoinData>())
|
|
||||||
.OrderByDescending(tuple => tuple.Timestamp).ToList();
|
return await _memoryCache.GetOrCreateAsync(k, async entry =>
|
||||||
|
{
|
||||||
|
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1);
|
||||||
|
var result = (await _walletRepository.GetWalletObjects(
|
||||||
|
new GetWalletObjectsQuery(new WalletId(storeId, "BTC"))
|
||||||
|
{
|
||||||
|
Type = "coinjoin"
|
||||||
|
})).Values.Where(data => !string.IsNullOrEmpty(data.Data))
|
||||||
|
.Select(data => JObject.Parse(data.Data).ToObject<BTCPayWallet.CoinjoinData>())
|
||||||
|
.OrderByDescending(tuple => tuple.Timestamp).ToList();
|
||||||
|
entry.Value = result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using BTCPayServer.HostedServices;
|
|||||||
using BTCPayServer.Payments.PayJoin;
|
using BTCPayServer.Payments.PayJoin;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -57,7 +58,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
_networkProvider = networkProvider;
|
_networkProvider = networkProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly ConcurrentDictionary<string, Task<IWallet?>> LoadedWallets = new();
|
public readonly ConcurrentDictionary<string, Lazy<Task<IWallet>>> LoadedWallets = new();
|
||||||
|
|
||||||
public class WalletUnloadEventArgs : EventArgs
|
public class WalletUnloadEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
@@ -73,7 +74,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
public async Task<IWallet?> GetWalletAsync(string name)
|
public async Task<IWallet?> GetWalletAsync(string name)
|
||||||
{
|
{
|
||||||
await initialLoad.Task;
|
await initialLoad.Task;
|
||||||
return await LoadedWallets.GetOrAddAsync(name, async s =>
|
return await Smartifier.GetOrCreate(LoadedWallets, name, async () =>
|
||||||
{
|
{
|
||||||
if (!_cachedSettings.TryGetValue(name, out var wabisabiStoreSettings))
|
if (!_cachedSettings.TryGetValue(name, out var wabisabiStoreSettings))
|
||||||
{
|
{
|
||||||
@@ -101,7 +102,7 @@ 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(_serviceProvider.GetRequiredService<WalletRepository>(),
|
var smartifier = new Smartifier(_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)
|
||||||
{
|
{
|
||||||
@@ -112,7 +113,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var smartifier = new Smartifier(_serviceProvider.GetRequiredService<WalletRepository>(), explorerClient,
|
var smartifier = new Smartifier(_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);
|
||||||
}
|
}
|
||||||
@@ -127,9 +128,11 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
_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>()
|
||||||
|
);
|
||||||
|
|
||||||
});
|
}, _logger);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +234,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
LoadedWallets.TryRemove(name, out var walletTask);
|
LoadedWallets.TryRemove(name, out var walletTask);
|
||||||
if (walletTask != null)
|
if (walletTask != null)
|
||||||
{
|
{
|
||||||
var wallet = await walletTask;
|
var wallet = await walletTask.Value;
|
||||||
WalletUnloaded?.Invoke(this, new WalletUnloadEventArgs(wallet));
|
WalletUnloaded?.Invoke(this, new WalletUnloadEventArgs(wallet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +250,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
|||||||
{
|
{
|
||||||
|
|
||||||
_cachedSettings.AddOrReplace(storeId, wabisabiSettings);
|
_cachedSettings.AddOrReplace(storeId, wabisabiSettings);
|
||||||
var btcpayWalet = (BTCPayWallet) await existingWallet;
|
var btcpayWalet = (BTCPayWallet) await existingWallet.Value;
|
||||||
if (btcpayWalet is null)
|
if (btcpayWalet is null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
Submodule submodules/btcpayserver updated: cdffe9b355...25af9c4227
Submodule submodules/walletwasabi updated: 17e053ce5f...84f310060d
Reference in New Issue
Block a user