mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-18 16:14:25 +01:00
better send tools
This commit is contained in:
@@ -336,6 +336,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
{
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
var txHash = result.UnsignedCoinJoin.GetHash();
|
||||
var kp = await ExplorerClient.GetMetadataAsync<RootedKeyPath>(DerivationScheme,
|
||||
WellknownMetadataKeys.AccountKeyPath);
|
||||
|
||||
@@ -409,7 +410,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
{
|
||||
Round = result.RoundId.ToString(),
|
||||
CoordinatorName = coordinatorName,
|
||||
Transaction = result.UnsignedCoinJoin.GetHash().ToString(),
|
||||
Transaction = txHash.ToString(),
|
||||
CoinsIn = smartTx.WalletInputs.Select(coin => new CoinjoinData.CoinjoinDataCoin()
|
||||
{
|
||||
AnonymitySet = coin.AnonymitySet,
|
||||
@@ -455,12 +456,12 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
{
|
||||
await _walletRepository.AddWalletTransactionAttachment(
|
||||
new WalletId(storeIdForutxo, "BTC"),
|
||||
result.UnsignedCoinJoin.GetHash(),
|
||||
txHash,
|
||||
new List<Attachment>()
|
||||
{
|
||||
new Attachment("coinjoin", result.RoundId.ToString(), JObject.FromObject(new CoinjoinData()
|
||||
{
|
||||
Transaction = result.UnsignedCoinJoin.GetHash().ToString(),
|
||||
Transaction = txHash.ToString(),
|
||||
Round = result.RoundId.ToString(),
|
||||
CoinsOut = mixedCoins.Select(coin => new CoinjoinData.CoinjoinDataCoin()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
@using BTCPayServer.Security
|
||||
@using NBitcoin
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Plugins.Wabisabi
|
||||
@using WalletWasabi.Blockchain.Analysis
|
||||
@model BTCPayServer.Models.WalletViewModels.WalletSendModel
|
||||
|
||||
@inject ContentSecurityPolicies contentSecurityPolicies
|
||||
@inject WalletProvider _walletProvider
|
||||
@inject IScopeProvider ScopeProvider
|
||||
@{
|
||||
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
||||
contentSecurityPolicies.Add("script-src", $"'nonce-{nonce}'");
|
||||
contentSecurityPolicies.AllowUnsafeHashes();
|
||||
var storeId = ScopeProvider.GetCurrentStoreId();
|
||||
var w = await _walletProvider.GetWalletAsync(storeId);
|
||||
}
|
||||
|
||||
@if (w is not null)
|
||||
{
|
||||
|
||||
<div style="display: none">
|
||||
<div id="wabisabitemplate">
|
||||
<button type="button"
|
||||
id="privatesend"
|
||||
class="btn btn-primary"
|
||||
title="Optimzie coin selection for privacy">
|
||||
Private coin selection
|
||||
<i class="fa fa-user-secret"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<datalist id="wabisabidenominations">
|
||||
@foreach (var stdDenom in BlockchainAnalyzer.StdDenoms)
|
||||
{
|
||||
var num = new Money(stdDenom).ToDecimal(MoneyUnit.BTC);
|
||||
<option value="@num">Privacy suggestion (used in coinjoins)</option>
|
||||
}
|
||||
</datalist>
|
||||
|
||||
|
||||
<script type="text/javascript" nonce="@nonce">
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
const amountElements = document.querySelectorAll("[name^='Outputs'][name$='Amount']");
|
||||
amountElements.forEach(value => {
|
||||
value.setAttribute("list","wabisabidenominations" );
|
||||
});
|
||||
document.querySelector("#SignTransaction").insertAdjacentElement("beforeBegin", document.getElementById("wabisabitemplate"))
|
||||
|
||||
document.getElementById("privatesend").addEventListener("click", async ev => {
|
||||
document.getElementById("InputSelection").value = "True";
|
||||
const amountElements = document.querySelectorAll("[name^='Outputs'][name$='Amount']");
|
||||
let amount = 0;
|
||||
amountElements.forEach(value => {
|
||||
try {
|
||||
|
||||
amount+= parseFloat(value.value);
|
||||
}catch{}
|
||||
});
|
||||
if (!amount){
|
||||
return;
|
||||
}
|
||||
const url =@Safe.Json(@Url.Action("ComputeCoinSelection", "WabisabiStore", new { storeId }));
|
||||
const response = await fetch(`${url}?amount=${amount}`);
|
||||
const coins = await response.json();
|
||||
let selectedInputsElement = document.getElementById("SelectedInputs");
|
||||
if (!selectedInputsElement){
|
||||
selectedInputsElement = document.createElement("select");
|
||||
selectedInputsElement.setAttribute("name", "SelectedInputs")
|
||||
selectedInputsElement.setAttribute("id", "SelectedInputs")
|
||||
selectedInputsElement.setAttribute("multiple", "multiple")
|
||||
selectedInputsElement.style.display = "none";
|
||||
ev.target.insertAdjacentElement("beforeBegin",selectedInputsElement);
|
||||
}else{
|
||||
while (selectedInputsElement.options.length > 0) {
|
||||
selectedInputsElement.remove(0);
|
||||
}
|
||||
}
|
||||
for (const coin of coins) {
|
||||
selectedInputsElement.add(new Option(coin, coin, true, true),undefined);
|
||||
}
|
||||
document.getElementsByTagName("form")[0].submit();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
}
|
||||
@@ -94,6 +94,8 @@ public class WabisabiPlugin : BaseBTCPayServerPlugin
|
||||
"store-integrations-nav"));
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("Wabisabi/WabisabiDashboard",
|
||||
"dashboard"));
|
||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("Wabisabi/WabisabiWalletSend",
|
||||
"onchain-wallet-send"));
|
||||
|
||||
applicationBuilder.AddSingleton<IPayoutProcessorFactory, WabisabiPayoutProcessor>();
|
||||
Logger.SetMinimumLevel(LogLevel.Info);
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
_walletRepository = walletRepository;
|
||||
_payoutProcessorService = payoutProcessorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_eventAggregator.Subscribe()
|
||||
}
|
||||
|
||||
public async Task<WabisabiStoreSettings> GetWabisabiForStore(string storeId)
|
||||
|
||||
@@ -11,6 +11,8 @@ using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Common;
|
||||
using BTCPayServer.Filters;
|
||||
using BTCPayServer.Models.WalletViewModels;
|
||||
using BTCPayServer.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -90,7 +92,7 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
|
||||
if (Uri.TryCreate(relay, UriKind.Absolute, out var relayUri))
|
||||
{
|
||||
ViewBag.DiscoveredCoordinators =await Nostr.Discover(relayUri,
|
||||
ViewBag.DiscoveredCoordinators = await Nostr.Discover(relayUri,
|
||||
_explorerClientProvider.GetExplorerClient("BTC").Network.NBitcoinNetwork,
|
||||
coordSettings.Key?.CreateXOnlyPubKey().ToHex(), CancellationToken.None);
|
||||
}
|
||||
@@ -177,10 +179,12 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
return View(vm);
|
||||
}
|
||||
}
|
||||
|
||||
[Route("coinjoins")]
|
||||
public async Task<IActionResult> ListCoinjoins(string storeId, CoinjoinsViewModel viewModel, [FromServices] WalletRepository walletRepository)
|
||||
public async Task<IActionResult> ListCoinjoins(string storeId, CoinjoinsViewModel viewModel,
|
||||
[FromServices] WalletRepository walletRepository)
|
||||
{
|
||||
var objects =await _WabisabiService.GetCoinjoinHistory(storeId);
|
||||
var objects = await _WabisabiService.GetCoinjoinHistory(storeId);
|
||||
|
||||
viewModel ??= new CoinjoinsViewModel();
|
||||
viewModel.Coinjoins = objects
|
||||
@@ -189,7 +193,8 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
viewModel.Total = objects.Count();
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
|
||||
[XFrameOptions(XFrameOptionsAttribute.XFrameOptions.SameOrigin)]
|
||||
[HttpGet("spend")]
|
||||
public async Task<IActionResult> Spend(string storeId)
|
||||
{
|
||||
@@ -201,6 +206,7 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
return View(new SpendViewModel() { });
|
||||
}
|
||||
|
||||
[XFrameOptions(XFrameOptionsAttribute.XFrameOptions.SameOrigin)]
|
||||
[HttpPost("spend")]
|
||||
public async Task<IActionResult> Spend(string storeId, SpendViewModel spendViewModel, string command)
|
||||
{
|
||||
@@ -274,7 +280,7 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
{
|
||||
if (spendViewModel.SelectedCoins?.Any() is true)
|
||||
{
|
||||
coins = (CoinsView)coins.FilterBy(coin =>
|
||||
coins = (CoinsView) coins.FilterBy(coin =>
|
||||
spendViewModel.SelectedCoins.Contains(coin.Outpoint.ToString()));
|
||||
}
|
||||
}
|
||||
@@ -290,11 +296,11 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
var defaultCoinSelector = new DefaultCoinSelector();
|
||||
var defaultSelection =
|
||||
(defaultCoinSelector.Select(coins.Select(coin => coin.Coin).ToArray(),
|
||||
new Money((decimal)spendViewModel.Amount, MoneyUnit.BTC)) ?? Array.Empty<ICoin>())
|
||||
.ToArray();
|
||||
new Money((decimal) spendViewModel.Amount, MoneyUnit.BTC)) ?? Array.Empty<ICoin>())
|
||||
.ToArray();
|
||||
var selector = new SmartCoinSelector(coins.ToList());
|
||||
var smartSelection = selector.Select(defaultSelection,
|
||||
new Money((decimal)spendViewModel.Amount, MoneyUnit.BTC));
|
||||
new Money((decimal) spendViewModel.Amount, MoneyUnit.BTC));
|
||||
spendViewModel.SelectedCoins = smartSelection.Select(coin => coin.Outpoint.ToString()).ToArray();
|
||||
return View(spendViewModel);
|
||||
}
|
||||
@@ -326,7 +332,27 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
return View(spendViewModel);
|
||||
}
|
||||
|
||||
[HttpGet("select-coins")]
|
||||
public async Task<IActionResult> ComputeCoinSelection(string storeId, decimal amount)
|
||||
{
|
||||
if ((await _walletProvider.GetWalletAsync(storeId)) is not BTCPayWallet wallet)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
|
||||
var coins = await wallet.GetAllCoins();
|
||||
var defaultCoinSelector = new DefaultCoinSelector();
|
||||
var defaultSelection =
|
||||
(defaultCoinSelector.Select(coins.Select(coin => coin.Coin).ToArray(),
|
||||
new Money(amount, MoneyUnit.BTC)) ?? Array.Empty<ICoin>())
|
||||
.ToArray();
|
||||
var selector = new SmartCoinSelector(coins.ToList());
|
||||
var smartSelection = selector.Select(defaultSelection,
|
||||
new Money((decimal) amount, MoneyUnit.BTC));
|
||||
return Ok(smartSelection.Select(coin => coin.Outpoint.ToString()).ToArray());
|
||||
}
|
||||
|
||||
public class SpendViewModel
|
||||
{
|
||||
public string Destination { get; set; }
|
||||
@@ -334,4 +360,4 @@ namespace BTCPayServer.Plugins.Wabisabi
|
||||
public string[] SelectedCoins { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user