mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-03 17:36:59 +01:00
Wallet prep work for BPU (#1331)
* Wallet prep work for BPU This PR prepares the wallet for #1321. It makes transfers from the vault and ledger to go to their own post actions for processing (not particularly useful in this PR but is needed in BPU to propose a new tx) It also makes the Sign with seed consistent with redirect to /psbt/ready after signing which it did not do (it stayed on the seed route) * fix test * add assert
This commit is contained in:
parent
07f0d95f56
commit
db6a4687d2
8 changed files with 157 additions and 95 deletions
|
@ -71,7 +71,7 @@ namespace BTCPayServer.Tests
|
|||
BitcoinAddress.Create(vmLedger.HintChange, user.SupportedNetwork.NBitcoinNetwork);
|
||||
Assert.NotNull(vmLedger.WebsocketPath);
|
||||
|
||||
string redirectedPSBT = AssertRedirectedPSBT(await walletController.WalletSend(walletId, sendModel, command: "analyze-psbt"));
|
||||
string redirectedPSBT = AssertRedirectedPSBT(await walletController.WalletSend(walletId, sendModel, command: "analyze-psbt"), nameof(walletController.WalletPSBT));
|
||||
var vmPSBT = await walletController.WalletPSBT(walletId, new WalletPSBTViewModel() { PSBT = redirectedPSBT }).AssertViewModelAsync<WalletPSBTViewModel>();
|
||||
var unsignedPSBT = PSBT.Parse(vmPSBT.PSBT, user.SupportedNetwork.NBitcoinNetwork);
|
||||
Assert.NotNull(vmPSBT.Decoded);
|
||||
|
@ -80,14 +80,20 @@ namespace BTCPayServer.Tests
|
|||
PSBT.Load(filePSBT.FileContents, user.SupportedNetwork.NBitcoinNetwork);
|
||||
|
||||
await walletController.WalletPSBT(walletId, vmPSBT, "ledger").AssertViewModelAsync<WalletSendLedgerModel>();
|
||||
var vmPSBT2 = await walletController.WalletPSBT(walletId, vmPSBT, "broadcast").AssertViewModelAsync<WalletPSBTReadyViewModel>();
|
||||
var vmPSBT2 = await walletController.WalletPSBTReady(walletId, new WalletPSBTReadyViewModel()
|
||||
{
|
||||
PSBT = AssertRedirectedPSBT( await walletController.WalletPSBT(walletId, vmPSBT, "broadcast"), nameof(walletController.WalletPSBTReady))
|
||||
} ).AssertViewModelAsync<WalletPSBTReadyViewModel>();
|
||||
Assert.NotEmpty(vmPSBT2.Inputs.Where(i => i.Error != null));
|
||||
Assert.Equal(vmPSBT.PSBT, vmPSBT2.PSBT);
|
||||
|
||||
var signedPSBT = unsignedPSBT.Clone();
|
||||
signedPSBT.SignAll(user.DerivationScheme, user.ExtKey);
|
||||
vmPSBT.PSBT = signedPSBT.ToBase64();
|
||||
var psbtReady = await walletController.WalletPSBT(walletId, vmPSBT, "broadcast").AssertViewModelAsync<WalletPSBTReadyViewModel>();
|
||||
var psbtReady = await walletController.WalletPSBTReady(walletId, new WalletPSBTReadyViewModel()
|
||||
{
|
||||
PSBT = AssertRedirectedPSBT( await walletController.WalletPSBT(walletId, vmPSBT, "broadcast"), nameof(walletController.WalletPSBTReady))
|
||||
} ).AssertViewModelAsync<WalletPSBTReadyViewModel>();
|
||||
Assert.Equal(2 + 1, psbtReady.Destinations.Count); // The fee is a destination
|
||||
Assert.Contains(psbtReady.Destinations, d => d.Destination == sendDestination && !d.Positive);
|
||||
Assert.Contains(psbtReady.Destinations, d => d.Positive);
|
||||
|
@ -98,7 +104,7 @@ namespace BTCPayServer.Tests
|
|||
var combineVM = await walletController.WalletPSBT(walletId, vmPSBT, "combine").AssertViewModelAsync<WalletPSBTCombineViewModel>();
|
||||
Assert.Equal(vmPSBT.PSBT, combineVM.OtherPSBT);
|
||||
combineVM.PSBT = signedPSBT.ToBase64();
|
||||
var psbt = AssertRedirectedPSBT(await walletController.WalletPSBTCombine(walletId, combineVM));
|
||||
var psbt = AssertRedirectedPSBT(await walletController.WalletPSBTCombine(walletId, combineVM), nameof(walletController.WalletPSBT));
|
||||
|
||||
var signedPSBT2 = PSBT.Parse(psbt, user.SupportedNetwork.NBitcoinNetwork);
|
||||
Assert.True(signedPSBT.TryFinalize(out _));
|
||||
|
@ -108,7 +114,7 @@ namespace BTCPayServer.Tests
|
|||
// Can use uploaded file?
|
||||
combineVM.PSBT = null;
|
||||
combineVM.UploadedPSBTFile = TestUtils.GetFormFile("signedPSBT", signedPSBT.ToBytes());
|
||||
psbt = AssertRedirectedPSBT(await walletController.WalletPSBTCombine(walletId, combineVM));
|
||||
psbt = AssertRedirectedPSBT(await walletController.WalletPSBTCombine(walletId, combineVM), nameof(walletController.WalletPSBT));
|
||||
signedPSBT2 = PSBT.Parse(psbt, user.SupportedNetwork.NBitcoinNetwork);
|
||||
Assert.True(signedPSBT.TryFinalize(out _));
|
||||
Assert.True(signedPSBT2.TryFinalize(out _));
|
||||
|
@ -116,17 +122,18 @@ namespace BTCPayServer.Tests
|
|||
|
||||
var ready = (await walletController.WalletPSBTReady(walletId, signedPSBT.ToBase64())).AssertViewModel<WalletPSBTReadyViewModel>();
|
||||
Assert.Equal(signedPSBT.ToBase64(), ready.PSBT);
|
||||
psbt = AssertRedirectedPSBT(await walletController.WalletPSBTReady(walletId, ready, command: "analyze-psbt"));
|
||||
psbt = AssertRedirectedPSBT(await walletController.WalletPSBTReady(walletId, ready, command: "analyze-psbt"), nameof(walletController.WalletPSBT));
|
||||
Assert.Equal(signedPSBT.ToBase64(), psbt);
|
||||
redirect = Assert.IsType<RedirectToActionResult>(await walletController.WalletPSBTReady(walletId, ready, command: "broadcast"));
|
||||
Assert.Equal(nameof(walletController.WalletTransactions), redirect.ActionName);
|
||||
}
|
||||
}
|
||||
|
||||
private static string AssertRedirectedPSBT(IActionResult view)
|
||||
private static string AssertRedirectedPSBT(IActionResult view, string actionName)
|
||||
{
|
||||
var postRedirectView = Assert.IsType<ViewResult>(view);
|
||||
var postRedirectViewModel = Assert.IsType<PostRedirectViewModel>(postRedirectView.Model);
|
||||
Assert.Equal(actionName, postRedirectViewModel.AspAction);
|
||||
var redirectedPSBT = postRedirectViewModel.Parameters.Single(p => p.Key == "psbt").Value;
|
||||
return redirectedPSBT;
|
||||
}
|
||||
|
|
|
@ -566,9 +566,10 @@ namespace BTCPayServer.Tests
|
|||
Assert.Contains(jack.ToString(), s.Driver.PageSource);
|
||||
Assert.Contains("0.01000000", s.Driver.PageSource);
|
||||
s.Driver.FindElement(By.CssSelector("button[value=analyze-psbt]")).ForceClick();
|
||||
Assert.EndsWith("psbt", s.Driver.Url);
|
||||
s.Driver.FindElement(By.CssSelector("#OtherActions")).ForceClick();
|
||||
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
|
||||
Assert.EndsWith("psbt", s.Driver.Url);
|
||||
Assert.EndsWith("psbt/ready", s.Driver.Url);
|
||||
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
|
||||
Assert.Equal(walletTransactionLink, s.Driver.Url);
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
var nbx = ExplorerClientProvider.GetExplorerClient(network);
|
||||
CreatePSBTRequest psbtRequest = new CreatePSBTRequest();
|
||||
|
||||
foreach (var transactionOutput in sendModel.Outputs)
|
||||
{
|
||||
var psbtDestination = new CreatePSBTDestination();
|
||||
|
@ -65,7 +64,7 @@ namespace BTCPayServer.Controllers
|
|||
vm.Decoded = psbt.ToString();
|
||||
vm.PSBT = psbt.ToBase64();
|
||||
}
|
||||
return View(vm ?? new WalletPSBTViewModel() { CryptoCode = walletId.CryptoCode });
|
||||
return View(nameof(WalletPSBT), vm ?? new WalletPSBTViewModel() { CryptoCode = walletId.CryptoCode });
|
||||
}
|
||||
[HttpPost]
|
||||
[Route("{walletId}/psbt")]
|
||||
|
@ -107,7 +106,7 @@ namespace BTCPayServer.Controllers
|
|||
return View(vm);
|
||||
}
|
||||
TempData[WellKnownTempData.SuccessMessage] = "PSBT updated!";
|
||||
return RedirectToWalletPSBT(walletId, psbt, vm.FileName);
|
||||
return RedirectToWalletPSBT(psbt, vm.FileName);
|
||||
case "seed":
|
||||
return SignWithSeed(walletId, psbt.ToBase64());
|
||||
case "nbx-seed":
|
||||
|
@ -125,7 +124,7 @@ namespace BTCPayServer.Controllers
|
|||
return View(vm);
|
||||
case "broadcast":
|
||||
{
|
||||
return await WalletPSBTReady(walletId, psbt.ToBase64());
|
||||
return RedirectToWalletPSBTReady(psbt.ToBase64());
|
||||
}
|
||||
case "combine":
|
||||
ModelState.Remove(nameof(vm.PSBT));
|
||||
|
@ -162,7 +161,6 @@ namespace BTCPayServer.Controllers
|
|||
var vm = new WalletPSBTReadyViewModel() { PSBT = psbt };
|
||||
vm.SigningKey = signingKey;
|
||||
vm.SigningKeyPath = signingKeyPath;
|
||||
|
||||
var derivationSchemeSettings = GetDerivationSchemeSettings(walletId);
|
||||
if (derivationSchemeSettings == null)
|
||||
return NotFound();
|
||||
|
@ -224,7 +222,7 @@ namespace BTCPayServer.Controllers
|
|||
vm.CanCalculateBalance = true;
|
||||
vm.Positive = balanceChange >= Money.Zero;
|
||||
}
|
||||
|
||||
vm.Inputs = new List<WalletPSBTReadyViewModel.InputViewModel>();
|
||||
foreach (var input in psbtObject.Inputs)
|
||||
{
|
||||
var inputVm = new WalletPSBTReadyViewModel.InputViewModel();
|
||||
|
@ -237,7 +235,7 @@ namespace BTCPayServer.Controllers
|
|||
inputVm.Positive = balanceChange2 >= Money.Zero;
|
||||
inputVm.Index = (int)input.Index;
|
||||
}
|
||||
|
||||
vm.Destinations = new List<WalletPSBTReadyViewModel.DestinationViewModel>();
|
||||
foreach (var output in psbtObject.Outputs)
|
||||
{
|
||||
var dest = new WalletPSBTReadyViewModel.DestinationViewModel();
|
||||
|
@ -297,14 +295,14 @@ namespace BTCPayServer.Controllers
|
|||
catch
|
||||
{
|
||||
vm.GlobalError = "Invalid PSBT";
|
||||
return View(vm);
|
||||
return View(nameof(WalletPSBTReady),vm);
|
||||
}
|
||||
if (command == "broadcast")
|
||||
{
|
||||
if (!psbt.IsAllFinalized() && !psbt.TryFinalize(out var errors))
|
||||
{
|
||||
vm.SetErrors(errors);
|
||||
return View(vm);
|
||||
return View(nameof(WalletPSBTReady),vm);
|
||||
}
|
||||
var transaction = psbt.ExtractTransaction();
|
||||
try
|
||||
|
@ -313,24 +311,24 @@ namespace BTCPayServer.Controllers
|
|||
if (!broadcastResult.Success)
|
||||
{
|
||||
vm.GlobalError = $"RPC Error while broadcasting: {broadcastResult.RPCCode} {broadcastResult.RPCCodeMessage} {broadcastResult.RPCMessage}";
|
||||
return View(vm);
|
||||
return View(nameof(WalletPSBTReady),vm);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
vm.GlobalError = "Error while broadcasting: " + ex.Message;
|
||||
return View(vm);
|
||||
return View(nameof(WalletPSBTReady),vm);
|
||||
}
|
||||
return RedirectToWalletTransaction(walletId, transaction);
|
||||
}
|
||||
else if (command == "analyze-psbt")
|
||||
{
|
||||
return RedirectToWalletPSBT(walletId, psbt);
|
||||
return RedirectToWalletPSBT(psbt);
|
||||
}
|
||||
else
|
||||
{
|
||||
vm.GlobalError = "Unknown command";
|
||||
return View(vm);
|
||||
return View(nameof(WalletPSBTReady),vm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +357,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
sourcePSBT = sourcePSBT.Combine(psbt);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "PSBT Successfully combined!";
|
||||
return RedirectToWalletPSBT(walletId, sourcePSBT);
|
||||
return RedirectToWalletPSBT(sourcePSBT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
|
@ -8,7 +7,6 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.ModelBinders;
|
||||
using BTCPayServer.Models;
|
||||
|
@ -19,21 +17,15 @@ using BTCPayServer.Services;
|
|||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using LedgerWallet;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NBitcoin;
|
||||
using NBitcoin.DataEncoders;
|
||||
using NBXplorer;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json;
|
||||
using static BTCPayServer.Controllers.StoresController;
|
||||
|
||||
namespace BTCPayServer.Controllers
|
||||
{
|
||||
|
@ -420,7 +412,7 @@ namespace BTCPayServer.Controllers
|
|||
var balance = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation);
|
||||
model.NBXSeedAvailable = await CanUseHotWallet() && !string.IsNullOrEmpty(await ExplorerClientProvider.GetExplorerClient(network)
|
||||
.GetMetadataAsync<string>(GetDerivationSchemeSettings(walletId).AccountDerivation,
|
||||
WellknownMetadataKeys.Mnemonic));
|
||||
WellknownMetadataKeys.MasterHDKey));
|
||||
model.CurrentBalance = await balance;
|
||||
model.RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi;
|
||||
model.FeeSatoshiPerByte = model.RecommendedSatoshiPerByte;
|
||||
|
@ -593,7 +585,7 @@ namespace BTCPayServer.Controllers
|
|||
case "analyze-psbt":
|
||||
var name =
|
||||
$"Send-{string.Join('_', vm.Outputs.Select(output => $"{output.Amount}->{output.DestinationAddress}{(output.SubtractFeesFromOutput ? "-Fees" : string.Empty)}"))}.psbt";
|
||||
return RedirectToWalletPSBT(walletId, psbt.PSBT, name);
|
||||
return RedirectToWalletPSBT(psbt.PSBT, name);
|
||||
default:
|
||||
return View(vm);
|
||||
}
|
||||
|
@ -651,7 +643,31 @@ namespace BTCPayServer.Controllers
|
|||
});
|
||||
}
|
||||
|
||||
private IActionResult RedirectToWalletPSBT(WalletId walletId, PSBT psbt, string fileName = null)
|
||||
[HttpPost]
|
||||
[Route("{walletId}/vault")]
|
||||
public async Task<IActionResult> SubmitVault([ModelBinder(typeof(WalletIdModelBinder))]
|
||||
WalletId walletId, WalletSendVaultModel model)
|
||||
{
|
||||
|
||||
return RedirectToWalletPSBTReady(model.PSBT);
|
||||
}
|
||||
private IActionResult RedirectToWalletPSBTReady(string psbt, string signingKey= null, string signingKeyPath = null)
|
||||
{
|
||||
var vm = new PostRedirectViewModel()
|
||||
{
|
||||
AspController = "Wallets",
|
||||
AspAction = nameof(WalletPSBTReady),
|
||||
Parameters =
|
||||
{
|
||||
new KeyValuePair<string, string>("psbt", psbt),
|
||||
new KeyValuePair<string, string>("SigningKey", signingKey),
|
||||
new KeyValuePair<string, string>("SigningKeyPath", signingKeyPath)
|
||||
}
|
||||
};
|
||||
return View("PostRedirect", vm);
|
||||
}
|
||||
|
||||
private IActionResult RedirectToWalletPSBT(PSBT psbt, string fileName = null)
|
||||
{
|
||||
var vm = new PostRedirectViewModel()
|
||||
{
|
||||
|
@ -700,6 +716,14 @@ namespace BTCPayServer.Controllers
|
|||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("{walletId}/ledger")]
|
||||
public async Task<IActionResult> SubmitLedger([ModelBinder(typeof(WalletIdModelBinder))]
|
||||
WalletId walletId, WalletSendLedgerModel model)
|
||||
{
|
||||
return RedirectToWalletPSBTReady(model.PSBT);
|
||||
}
|
||||
|
||||
[HttpGet("{walletId}/psbt/seed")]
|
||||
public IActionResult SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
|
||||
WalletId walletId,string psbt)
|
||||
|
@ -773,7 +797,7 @@ namespace BTCPayServer.Controllers
|
|||
return View(viewModel);
|
||||
}
|
||||
ModelState.Remove(nameof(viewModel.PSBT));
|
||||
return await WalletPSBTReady(walletId, psbt.ToBase64(), signingKey.GetWif(network.NBitcoinNetwork).ToString(), rootedKeyPath?.ToString());
|
||||
return RedirectToWalletPSBTReady(psbt.ToBase64(), signingKey.GetWif(network.NBitcoinNetwork).ToString(), rootedKeyPath?.ToString());
|
||||
}
|
||||
|
||||
private bool PSBTChanged(PSBT psbt, Action act)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
{
|
||||
<h3>Decoded PSBT</h3>
|
||||
<div class="form-group">
|
||||
<form method="post" asp-action="WalletPSBT">
|
||||
<form method="post" asp-action="WalletPSBT" asp-route-walletId="@this.Context.GetRouteValue("walletId")">
|
||||
<input type="hidden" asp-for="CryptoCode" />
|
||||
<input type="hidden" asp-for="NBXSeedAvailable" />
|
||||
<input type="hidden" asp-for="PSBT" />
|
||||
|
@ -65,7 +65,7 @@
|
|||
<pre><code class="json">@Model.Decoded</code></pre>
|
||||
}
|
||||
<h3>PSBT to decode</h3>
|
||||
<form class="form-group" method="post" asp-action="WalletPSBT" enctype="multipart/form-data">
|
||||
<form class="form-group" method="post" asp-action="WalletPSBT" asp-route-walletId="@this.Context.GetRouteValue("walletId")" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="5" asp-for="PSBT"></textarea>
|
||||
<span asp-validation-for="PSBT" class="text-danger"></span>
|
||||
|
|
|
@ -2,13 +2,24 @@
|
|||
@{
|
||||
Layout = "../Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
@if (TempData.HasStatusMessage())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (Model.GlobalError != null)
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<span>@Model.GlobalError</span><br />
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<span>@Model.GlobalError</span><br/>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
|
@ -18,14 +29,16 @@
|
|||
@if (Model.CanCalculateBalance)
|
||||
{
|
||||
<p>
|
||||
If you broadcast this transaction, your balance will change: @if (Model.Positive)
|
||||
If you broadcast this transaction, your balance will change:
|
||||
@if (Model.Positive)
|
||||
{
|
||||
<span style="color:green;">@Model.BalanceChange</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span style="color:red;">@Model.BalanceChange</span>
|
||||
}, do you want to continue?
|
||||
}
|
||||
, do you want to continue?
|
||||
</p>
|
||||
}
|
||||
else
|
||||
|
@ -53,7 +66,9 @@
|
|||
<tr>
|
||||
@if (input.Error != null)
|
||||
{
|
||||
<td style="text-align:left">@input.Index <span class="fa fa-exclamation-triangle" style="color:red;" title="@input.Error"></span></td>
|
||||
<td style="text-align:left">
|
||||
@input.Index <span class="fa fa-exclamation-triangle" style="color:red;" title="@input.Error"></span>
|
||||
</td>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -122,12 +137,13 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<form method="post" asp-action="WalletPSBTReady" asp-route-walletId="@this.Context.GetRouteValue("walletId")">
|
||||
<input type="hidden" asp-for="PSBT" />
|
||||
<input type="hidden" asp-for="SigningKey" />
|
||||
<input type="hidden" asp-for="SigningKeyPath" />
|
||||
<input type="hidden" asp-for="PSBT"/>
|
||||
<input type="hidden" asp-for="SigningKey"/>
|
||||
<input type="hidden" asp-for="SigningKeyPath"/>
|
||||
@if (!Model.HasErrors)
|
||||
{
|
||||
<button type="submit" class="btn btn-primary" name="command" value="broadcast">Broadcast it</button> <span> or </span>
|
||||
<button type="submit" class="btn btn-primary" name="command" value="broadcast">Broadcast it</button>
|
||||
<span> or </span>
|
||||
}
|
||||
<button type="submit" class="btn btn-secondary" name="command" value="analyze-psbt">Export as PSBT</button>
|
||||
</form>
|
||||
|
|
|
@ -6,14 +6,22 @@
|
|||
}
|
||||
|
||||
<h4>Sign the transaction with Ledger</h4>
|
||||
@if (TempData.HasStatusMessage())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div id="walletAlert" class="alert alert-danger alert-dismissible" style="display:none;" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<span id="alertMessage"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<form id="broadcastForm" asp-action="WalletPSBTReady" asp-route-walletId="@this.Context.GetRouteValue("walletId")" method="post" style="display:none;">
|
||||
<input type="hidden" id="PSBT" asp-for="PSBT" />
|
||||
<form id="broadcastForm" asp-action="SubmitLedger" asp-route-walletId="@this.Context.GetRouteValue("walletId")" method="post" style="display:none;">
|
||||
<input type="hidden" id="PSBT" asp-for="PSBT" value="@Model.PSBT"/>
|
||||
<input type="hidden" asp-for="HintChange" />
|
||||
<input type="hidden" asp-for="WebsocketPath" />
|
||||
</form>
|
||||
|
|
|
@ -6,15 +6,23 @@
|
|||
}
|
||||
|
||||
<h4>Sign the transaction with BTCPayServer Vault</h4>
|
||||
@if (TempData.HasStatusMessage())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div id="walletAlert" class="alert alert-danger alert-dismissible" style="display:none;" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<span id="alertMessage"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="body" class="col-md-10">
|
||||
<form id="broadcastForm" asp-action="WalletPSBTReady" asp-route-walletId="@this.Context.GetRouteValue("walletId")" method="post" style="display:none;">
|
||||
<form id="broadcastForm" asp-action="SubmitVault" asp-route-walletId="@this.Context.GetRouteValue("walletId")" method="post" style="display:none;">
|
||||
<input type="hidden" id="WalletId" asp-for="WalletId" />
|
||||
<input type="hidden" id="PSBT" asp-for="PSBT" />
|
||||
<input type="hidden" id="PSBT" asp-for="PSBT" value="@Model.PSBT"/>
|
||||
<input type="hidden" asp-for="WebsocketPath" />
|
||||
</form>
|
||||
<div id="vaultPlaceholder"></div>
|
||||
|
|
Loading…
Add table
Reference in a new issue