Refactor parameter passing in wallet functions

This commit is contained in:
nicolas.dorier
2020-05-25 04:55:28 +09:00
parent d22993871f
commit 25e6f82aa3
15 changed files with 130 additions and 74 deletions

View File

@@ -5,7 +5,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NBitcoin" Version="5.0.35" /> <PackageReference Include="NBitcoin" Version="5.0.38" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup> </ItemGroup>

View File

@@ -4,6 +4,6 @@
<ItemGroup> <ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="NBXplorer.Client" Version="3.0.11" /> <PackageReference Include="NBXplorer.Client" Version="3.0.15" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -120,7 +120,10 @@ namespace BTCPayServer.Tests
Assert.True(signedPSBT2.TryFinalize(out _)); Assert.True(signedPSBT2.TryFinalize(out _));
Assert.Equal(signedPSBT, signedPSBT2); Assert.Equal(signedPSBT, signedPSBT2);
var ready = (await walletController.WalletPSBTReady(walletId, signedPSBT.ToBase64())).AssertViewModel<WalletPSBTReadyViewModel>(); var ready = (await walletController.WalletPSBTReady(walletId, new WalletPSBTReadyViewModel()
{
PSBT = signedPSBT.ToBase64()
})).AssertViewModel<WalletPSBTReadyViewModel>();
Assert.Equal(signedPSBT.ToBase64(), ready.PSBT); Assert.Equal(signedPSBT.ToBase64(), ready.PSBT);
psbt = AssertRedirectedPSBT(await walletController.WalletPSBTReady(walletId, ready, command: "analyze-psbt"), nameof(walletController.WalletPSBT)); psbt = AssertRedirectedPSBT(await walletController.WalletPSBTReady(walletId, ready, command: "analyze-psbt"), nameof(walletController.WalletPSBT));
Assert.Equal(signedPSBT.ToBase64(), psbt); Assert.Equal(signedPSBT.ToBase64(), psbt);

View File

@@ -2,8 +2,8 @@
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" /> <Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
<Import Project="../Build/Common.csproj" /> <Import Project="../Build/Common.csproj" />
<PropertyGroup Condition="'$(Configuration)' == 'Debug' And '$(RazorCompileOnBuild)' != 'true'"> <PropertyGroup Condition="'$(Configuration)' == 'Debug' And '$(RazorCompileOnBuild)' != 'true'">
<RazorCompileOnBuild>false</RazorCompileOnBuild> <!--<RazorCompileOnBuild>false</RazorCompileOnBuild>
<DefineConstants>$(DefineConstants);RAZOR_RUNTIME_COMPILE</DefineConstants> <DefineConstants>$(DefineConstants);RAZOR_RUNTIME_COMPILE</DefineConstants>-->
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>

View File

@@ -101,7 +101,7 @@ namespace BTCPayServer.Controllers
return View(vm); return View(vm);
} }
var res = await TryHandleSigningCommands(walletId, psbt, command, vm.PayJoinEndpointUrl, null); var res = await TryHandleSigningCommands(walletId, psbt, command, vm.SigningContext, null);
if (res != null) if (res != null)
{ {
return res; return res;
@@ -126,11 +126,19 @@ namespace BTCPayServer.Controllers
return View(vm); return View(vm);
} }
TempData[WellKnownTempData.SuccessMessage] = "PSBT updated!"; TempData[WellKnownTempData.SuccessMessage] = "PSBT updated!";
return RedirectToWalletPSBT(psbt, vm.FileName); return RedirectToWalletPSBT(new WalletPSBTViewModel()
{
PSBT = psbt.ToBase64(),
FileName = vm.FileName,
SigningContext = vm.SigningContext
});
case "broadcast": case "broadcast":
{ {
return RedirectToWalletPSBTReady(psbt.ToBase64()); return RedirectToWalletPSBTReady(new WalletPSBTReadyViewModel()
{
PSBT = psbt.ToBase64()
});
} }
case "combine": case "combine":
ModelState.Remove(nameof(vm.PSBT)); ModelState.Remove(nameof(vm.PSBT));
@@ -156,18 +164,12 @@ namespace BTCPayServer.Controllers
[Route("{walletId}/psbt/ready")] [Route("{walletId}/psbt/ready")]
public async Task<IActionResult> WalletPSBTReady( public async Task<IActionResult> WalletPSBTReady(
[ModelBinder(typeof(WalletIdModelBinder))] [ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, string psbt = null, WalletId walletId,
string signingKey = null, WalletPSBTReadyViewModel vm)
string signingKeyPath = null,
string originalPsbt = null,
string payJoinEndpointUrl = null)
{ {
if (vm is null)
return NotFound();
var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode); var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode);
var vm = new WalletPSBTReadyViewModel() { PSBT = psbt };
vm.SigningKey = signingKey;
vm.SigningKeyPath = signingKeyPath;
vm.OriginalPSBT = originalPsbt;
vm.PayJoinEndpointUrl = payJoinEndpointUrl;
var derivationSchemeSettings = GetDerivationSchemeSettings(walletId); var derivationSchemeSettings = GetDerivationSchemeSettings(walletId);
if (derivationSchemeSettings == null) if (derivationSchemeSettings == null)
return NotFound(); return NotFound();
@@ -288,7 +290,7 @@ namespace BTCPayServer.Controllers
WalletId walletId, WalletPSBTReadyViewModel vm, string command = null, CancellationToken cancellationToken = default) WalletId walletId, WalletPSBTReadyViewModel vm, string command = null, CancellationToken cancellationToken = default)
{ {
if (command == null) if (command == null)
return await WalletPSBTReady(walletId, vm.PSBT, vm.SigningKey, vm.SigningKeyPath, vm.OriginalPSBT, vm.PayJoinEndpointUrl); return await WalletPSBTReady(walletId, vm);
PSBT psbt = null; PSBT psbt = null;
var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode); var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode);
DerivationSchemeSettings derivationSchemeSettings = null; DerivationSchemeSettings derivationSchemeSettings = null;
@@ -312,7 +314,7 @@ namespace BTCPayServer.Controllers
string error = null; string error = null;
try try
{ {
var proposedPayjoin = await GetPayjoinProposedTX(vm.PayJoinEndpointUrl, psbt, var proposedPayjoin = await GetPayjoinProposedTX(vm.SigningContext.PayJoinEndpointUrl, psbt,
derivationSchemeSettings, network, cancellationToken); derivationSchemeSettings, network, cancellationToken);
try try
{ {
@@ -357,7 +359,7 @@ namespace BTCPayServer.Controllers
$"The amount being sent may appear higher but is in fact almost same.<br/><br/>" + $"The amount being sent may appear higher but is in fact almost same.<br/><br/>" +
$"If you cancel or refuse to sign this transaction, the payment will proceed without payjoin" $"If you cancel or refuse to sign this transaction, the payment will proceed without payjoin"
}); });
return ViewVault(walletId, proposedPayjoin, vm.PayJoinEndpointUrl, psbt); return ViewVault(walletId, proposedPayjoin, vm.SigningContext, psbt);
} }
} }
catch (PayjoinReceiverException ex) catch (PayjoinReceiverException ex)
@@ -425,7 +427,11 @@ namespace BTCPayServer.Controllers
return RedirectToWalletTransaction(walletId, transaction); return RedirectToWalletTransaction(walletId, transaction);
} }
case "analyze-psbt": case "analyze-psbt":
return RedirectToWalletPSBT(psbt); return RedirectToWalletPSBT(new WalletPSBTViewModel()
{
PSBT = psbt.ToBase64(),
SigningContext = vm.SigningContext
});
default: default:
vm.GlobalError = "Unknown command"; vm.GlobalError = "Unknown command";
return View(nameof(WalletPSBTReady),vm); return View(nameof(WalletPSBTReady),vm);
@@ -457,20 +463,23 @@ namespace BTCPayServer.Controllers
} }
sourcePSBT = sourcePSBT.Combine(psbt); sourcePSBT = sourcePSBT.Combine(psbt);
TempData[WellKnownTempData.SuccessMessage] = "PSBT Successfully combined!"; TempData[WellKnownTempData.SuccessMessage] = "PSBT Successfully combined!";
return RedirectToWalletPSBT(sourcePSBT); return RedirectToWalletPSBT(new WalletPSBTViewModel()
{
PSBT = sourcePSBT.ToBase64()
});
} }
private async Task<IActionResult> TryHandleSigningCommands(WalletId walletId, PSBT psbt, string command, private async Task<IActionResult> TryHandleSigningCommands(WalletId walletId, PSBT psbt, string command,
string payjoinEndpointUrl, BitcoinAddress changeAddress) SigningContextModel signingContext, BitcoinAddress changeAddress)
{ {
switch (command ) switch (command )
{ {
case "vault": case "vault":
return ViewVault(walletId, psbt, payjoinEndpointUrl); return ViewVault(walletId, psbt, signingContext);
case "ledger": case "ledger":
return ViewWalletSendLedger(walletId, psbt, changeAddress); return ViewWalletSendLedger(walletId, psbt, changeAddress);
case "seed": case "seed":
return SignWithSeed(walletId, psbt.ToBase64(), payjoinEndpointUrl); return SignWithSeed(walletId, psbt.ToBase64(), signingContext);
case "nbx-seed": case "nbx-seed":
if (await CanUseHotWallet()) if (await CanUseHotWallet())
{ {
@@ -480,7 +489,7 @@ namespace BTCPayServer.Controllers
WellknownMetadataKeys.MasterHDKey); WellknownMetadataKeys.MasterHDKey);
return SignWithSeed(walletId, return SignWithSeed(walletId,
new SignWithSeedViewModel() {SeedOrKey = extKey, PSBT = psbt.ToBase64(), PayJoinEndpointUrl = payjoinEndpointUrl}); new SignWithSeedViewModel() {SeedOrKey = extKey, PSBT = psbt.ToBase64(), SigningContext = signingContext });
} }
TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {

View File

@@ -53,6 +53,7 @@ namespace BTCPayServer.Controllers
private readonly DelayedTransactionBroadcaster _broadcaster; private readonly DelayedTransactionBroadcaster _broadcaster;
private readonly PayjoinClient _payjoinClient; private readonly PayjoinClient _payjoinClient;
private readonly LabelFactory _labelFactory; private readonly LabelFactory _labelFactory;
public RateFetcher RateFetcher { get; } public RateFetcher RateFetcher { get; }
CurrencyNameTable _currencyTable; CurrencyNameTable _currencyTable;
@@ -654,8 +655,13 @@ namespace BTCPayServer.Controllers
} }
derivationScheme.RebaseKeyPaths(psbt.PSBT); derivationScheme.RebaseKeyPaths(psbt.PSBT);
var signingContext = new SigningContextModel()
{
PayJoinEndpointUrl = vm.PayJoinEndpointUrl,
EnforceLowR = psbt.Suggestions?.ShouldEnforceLowR
};
var res = await TryHandleSigningCommands(walletId, psbt.PSBT, command, vm.PayJoinEndpointUrl, psbt.ChangeAddress); var res = await TryHandleSigningCommands(walletId, psbt.PSBT, command, signingContext, psbt.ChangeAddress);
if (res != null) if (res != null)
{ {
return res; return res;
@@ -666,7 +672,12 @@ namespace BTCPayServer.Controllers
case "analyze-psbt": case "analyze-psbt":
var name = var name =
$"Send-{string.Join('_', vm.Outputs.Select(output => $"{output.Amount}->{output.DestinationAddress}{(output.SubtractFeesFromOutput ? "-Fees" : string.Empty)}"))}.psbt"; $"Send-{string.Join('_', vm.Outputs.Select(output => $"{output.Amount}->{output.DestinationAddress}{(output.SubtractFeesFromOutput ? "-Fees" : string.Empty)}"))}.psbt";
return RedirectToWalletPSBT(psbt.PSBT, name, vm.PayJoinEndpointUrl); return RedirectToWalletPSBT(new WalletPSBTViewModel()
{
PSBT = psbt.PSBT.ToBase64(),
FileName = name,
SigningContext = signingContext
});
default: default:
return View(vm); return View(vm);
} }
@@ -729,11 +740,11 @@ namespace BTCPayServer.Controllers
ModelState.Clear(); ModelState.Clear();
} }
private IActionResult ViewVault(WalletId walletId, PSBT psbt, string payJoinEndpointUrl, PSBT originalPSBT = null) private IActionResult ViewVault(WalletId walletId, PSBT psbt, SigningContextModel signingContext, PSBT originalPSBT = null)
{ {
return View(nameof(WalletSendVault), new WalletSendVaultModel() return View(nameof(WalletSendVault), new WalletSendVaultModel()
{ {
PayJoinEndpointUrl = payJoinEndpointUrl, SigningContext = signingContext,
WalletId = walletId.ToString(), WalletId = walletId.ToString(),
OriginalPSBT = originalPSBT?.ToBase64(), OriginalPSBT = originalPSBT?.ToBase64(),
PSBT = psbt.ToBase64(), PSBT = psbt.ToBase64(),
@@ -746,42 +757,48 @@ namespace BTCPayServer.Controllers
public IActionResult WalletSendVault([ModelBinder(typeof(WalletIdModelBinder))] public IActionResult WalletSendVault([ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, WalletSendVaultModel model) WalletId walletId, WalletSendVaultModel model)
{ {
return RedirectToWalletPSBTReady(model.PSBT, originalPsbt: model.OriginalPSBT, payJoinEndpointUrl: model.PayJoinEndpointUrl); return RedirectToWalletPSBTReady(new WalletPSBTReadyViewModel()
}
private IActionResult RedirectToWalletPSBTReady(string psbt, string signingKey= null, string signingKeyPath = null, string originalPsbt = null, string payJoinEndpointUrl = null)
{ {
var vm = new PostRedirectViewModel() PSBT = model.PSBT,
OriginalPSBT = model.OriginalPSBT,
SigningContext = model.SigningContext
});
}
private IActionResult RedirectToWalletPSBTReady(WalletPSBTReadyViewModel vm)
{
var redirectVm = new PostRedirectViewModel()
{ {
AspController = "Wallets", AspController = "Wallets",
AspAction = nameof(WalletPSBTReady), AspAction = nameof(WalletPSBTReady),
Parameters = Parameters =
{ {
new KeyValuePair<string, string>("psbt", psbt), new KeyValuePair<string, string>("psbt", vm.PSBT),
new KeyValuePair<string, string>("originalPsbt", originalPsbt), new KeyValuePair<string, string>("originalPsbt", vm.OriginalPSBT),
new KeyValuePair<string, string>("payJoinEndpointUrl", payJoinEndpointUrl), new KeyValuePair<string, string>("SigningContext.PayJoinEndpointUrl", vm.SigningContext?.PayJoinEndpointUrl),
new KeyValuePair<string, string>("SigningKey", signingKey), new KeyValuePair<string, string>("SigningContext.EnforceLowR", vm.SigningContext?.EnforceLowR?.ToString(CultureInfo.InvariantCulture)),
new KeyValuePair<string, string>("SigningKeyPath", signingKeyPath) new KeyValuePair<string, string>("SigningKey", vm.SigningKey),
new KeyValuePair<string, string>("SigningKeyPath", vm.SigningKeyPath)
} }
}; };
return View("PostRedirect", vm);
return View("PostRedirect", redirectVm);
} }
private IActionResult RedirectToWalletPSBT(PSBT psbt, string fileName = null, string payJoinEndpointUrl = null) private IActionResult RedirectToWalletPSBT(WalletPSBTViewModel vm)
{ {
var vm = new PostRedirectViewModel() var redirectVm = new PostRedirectViewModel()
{ {
AspController = "Wallets", AspController = "Wallets",
AspAction = nameof(WalletPSBT), AspAction = nameof(WalletPSBT),
Parameters = Parameters =
{ {
new KeyValuePair<string, string>("psbt", psbt.ToBase64()) new KeyValuePair<string, string>("psbt", vm.PSBT),
new KeyValuePair<string, string>("fileName", vm.FileName),
new KeyValuePair<string, string>("SigningContext.PayJoinEndpointUrl", vm.SigningContext?.PayJoinEndpointUrl),
new KeyValuePair<string, string>("SigningContext.EnforceLowR", vm.SigningContext?.EnforceLowR?.ToString(CultureInfo.InvariantCulture)),
} }
}; };
if (!string.IsNullOrEmpty(fileName)) return View("PostRedirect", redirectVm);
vm.Parameters.Add(new KeyValuePair<string, string>("fileName", fileName));
if (!string.IsNullOrEmpty(payJoinEndpointUrl))
vm.Parameters.Add(new KeyValuePair<string, string>("payJoinEndpointUrl", payJoinEndpointUrl));
return View("PostRedirect", vm);
} }
void SetAmbientPSBT(PSBT psbt) void SetAmbientPSBT(PSBT psbt)
@@ -822,16 +839,19 @@ namespace BTCPayServer.Controllers
public IActionResult SubmitLedger([ModelBinder(typeof(WalletIdModelBinder))] public IActionResult SubmitLedger([ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, WalletSendLedgerModel model) WalletId walletId, WalletSendLedgerModel model)
{ {
return RedirectToWalletPSBTReady(model.PSBT); return RedirectToWalletPSBTReady(new WalletPSBTReadyViewModel()
{
PSBT = model.PSBT
});
} }
[HttpGet("{walletId}/psbt/seed")] [HttpGet("{walletId}/psbt/seed")]
public IActionResult SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))] public IActionResult SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId,string psbt, string payJoinEndpointUrl) WalletId walletId,string psbt, SigningContextModel signingContext)
{ {
return View(nameof(SignWithSeed), new SignWithSeedViewModel() return View(nameof(SignWithSeed), new SignWithSeedViewModel()
{ {
PayJoinEndpointUrl = payJoinEndpointUrl, SigningContext = signingContext,
PSBT = psbt PSBT = psbt
}); });
} }
@@ -899,7 +919,14 @@ namespace BTCPayServer.Controllers
return View(viewModel); return View(viewModel);
} }
ModelState.Remove(nameof(viewModel.PSBT)); ModelState.Remove(nameof(viewModel.PSBT));
return RedirectToWalletPSBTReady(psbt.ToBase64(), signingKey.GetWif(network.NBitcoinNetwork).ToString(), rootedKeyPath?.ToString(), viewModel.OriginalPSBT, viewModel.PayJoinEndpointUrl); return RedirectToWalletPSBTReady(new WalletPSBTReadyViewModel()
{
PSBT = psbt.ToBase64(),
SigningKey = signingKey.GetWif(network.NBitcoinNetwork).ToString(),
SigningKeyPath = rootedKeyPath?.ToString(),
OriginalPSBT = viewModel.OriginalPSBT,
SigningContext = viewModel.SigningContext
});
} }

View File

@@ -8,7 +8,7 @@ namespace BTCPayServer.Models.WalletViewModels
public class SignWithSeedViewModel public class SignWithSeedViewModel
{ {
public string OriginalPSBT { get; set; } public string OriginalPSBT { get; set; }
public string PayJoinEndpointUrl { get; set; } public SigningContextModel SigningContext { get; set; } = new SigningContextModel();
[Required] [Required]
public string PSBT { get; set; } public string PSBT { get; set; }
[Required][Display(Name = "BIP39 Seed (12/24 word mnemonic phrase) or HD private key (xprv...)")] [Required][Display(Name = "BIP39 Seed (12/24 word mnemonic phrase) or HD private key (xprv...)")]

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Models.WalletViewModels
{
public class SigningContextModel
{
public string PayJoinEndpointUrl { get; set; }
public bool? EnforceLowR { get; set; }
}
}

View File

@@ -8,7 +8,7 @@ namespace BTCPayServer.Models.WalletViewModels
{ {
public class WalletPSBTReadyViewModel public class WalletPSBTReadyViewModel
{ {
public string PayJoinEndpointUrl { get; set; } public SigningContextModel SigningContext { get; set; } = new SigningContextModel();
public string OriginalPSBT { get; set; } public string OriginalPSBT { get; set; }
public string PSBT { get; set; } public string PSBT { get; set; }
public string SigningKey { get; set; } public string SigningKey { get; set; }

View File

@@ -10,7 +10,7 @@ namespace BTCPayServer.Models.WalletViewModels
{ {
public class WalletPSBTViewModel public class WalletPSBTViewModel
{ {
public string PayJoinEndpointUrl { get; set; } public SigningContextModel SigningContext { get; set; } = new SigningContextModel();
public string CryptoCode { get; set; } public string CryptoCode { get; set; }
public string Decoded { get; set; } public string Decoded { get; set; }
string _FileName; string _FileName;

View File

@@ -11,6 +11,6 @@ namespace BTCPayServer.Models.WalletViewModels
public string WalletId { get; set; } public string WalletId { get; set; }
public string PSBT { get; set; } public string PSBT { get; set; }
public string WebsocketPath { get; set; } public string WebsocketPath { get; set; }
public string PayJoinEndpointUrl { get; set; } public SigningContextModel SigningContext { get; set; } = new SigningContextModel();
} }
} }

View File

@@ -29,7 +29,8 @@
<form method="post" asp-action="SignWithSeed" asp-route-walletId="@this.Context.GetRouteValue("walletId")"> <form method="post" asp-action="SignWithSeed" asp-route-walletId="@this.Context.GetRouteValue("walletId")">
<input type="hidden" asp-for="OriginalPSBT" /> <input type="hidden" asp-for="OriginalPSBT" />
<input type="hidden" asp-for="PSBT" /> <input type="hidden" asp-for="PSBT" />
<input type="hidden" asp-for="PayJoinEndpointUrl" /> <input type="hidden" asp-for="SigningContext.PayJoinEndpointUrl" />
<input type="hidden" asp-for="SigningContext.EnforceLowR" />
<div class="form-group"> <div class="form-group">
<label asp-for="SeedOrKey"></label> <label asp-for="SeedOrKey"></label>
<input asp-for="SeedOrKey" class="form-control" /> <input asp-for="SeedOrKey" class="form-control" />

View File

@@ -29,13 +29,14 @@
<h3>Decoded PSBT</h3> <h3>Decoded PSBT</h3>
<div class="form-group"> <div class="form-group">
<form method="post" asp-action="WalletPSBT" asp-route-walletId="@this.Context.GetRouteValue("walletId")"> <form method="post" asp-action="WalletPSBT" asp-route-walletId="@this.Context.GetRouteValue("walletId")">
<input type="hidden" asp-for="CryptoCode"/> <input type="hidden" asp-for="CryptoCode" />
<input type="hidden" asp-for="PayJoinEndpointUrl"/> <input type="hidden" asp-for="SigningContext.PayJoinEndpointUrl" />
<input type="hidden" asp-for="NBXSeedAvailable"/> <input type="hidden" asp-for="SigningContext.EnforceLowR" />
<input type="hidden" asp-for="PSBT"/> <input type="hidden" asp-for="NBXSeedAvailable" />
<input type="hidden" asp-for="FileName"/> <input type="hidden" asp-for="PSBT" />
<input type="hidden" asp-for="FileName" />
<partial name="WalletSigningMenu" model="@((Model.CryptoCode, Model.NBXSeedAvailable))"/> <partial name="WalletSigningMenu" model="@((Model.CryptoCode, Model.NBXSeedAvailable))" />
<div class="dropdown d-inline-block"> <div class="dropdown d-inline-block">
<button class="btn btn-secondary dropdown-toggle" type="button" id="OtherActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button class="btn btn-secondary dropdown-toggle" type="button" id="OtherActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Other actions... Other actions...

View File

@@ -137,14 +137,15 @@
<div class="row"> <div class="row">
<div class="col-lg-12 text-center"> <div class="col-lg-12 text-center">
<form method="post" asp-action="WalletPSBTReady" asp-route-walletId="@this.Context.GetRouteValue("walletId")"> <form method="post" asp-action="WalletPSBTReady" asp-route-walletId="@this.Context.GetRouteValue("walletId")">
<input type="hidden" asp-for="PSBT" value="@Model.PSBT"/> <input type="hidden" asp-for="PSBT" value="@Model.PSBT" />
<input type="hidden" asp-for="OriginalPSBT"/> <input type="hidden" asp-for="OriginalPSBT" />
<input type="hidden" asp-for="SigningKey"/> <input type="hidden" asp-for="SigningKey" />
<input type="hidden" asp-for="SigningKeyPath"/> <input type="hidden" asp-for="SigningKeyPath" />
<input type="hidden" asp-for="PayJoinEndpointUrl"/> <input type="hidden" asp-for="SigningContext.PayJoinEndpointUrl" />
<input type="hidden" asp-for="SigningContext.EnforceLowR" />
@if (!Model.HasErrors) @if (!Model.HasErrors)
{ {
@if (!string.IsNullOrEmpty(Model.PayJoinEndpointUrl)) @if (!string.IsNullOrEmpty(Model.SigningContext?.PayJoinEndpointUrl))
{ {
<button type="submit" class="btn btn-primary" name="command" value="payjoin">Broadcast (Payjoin)</button> <button type="submit" class="btn btn-primary" name="command" value="payjoin">Broadcast (Payjoin)</button>
<span> or </span> <span> or </span>

View File

@@ -22,10 +22,11 @@
<div id="body" class="col-md-10"> <div id="body" class="col-md-10">
<form id="broadcastForm" asp-action="WalletSendVault" asp-route-walletId="@this.Context.GetRouteValue("walletId")" method="post" style="display:none;"> <form id="broadcastForm" asp-action="WalletSendVault" asp-route-walletId="@this.Context.GetRouteValue("walletId")" method="post" style="display:none;">
<input type="hidden" id="WalletId" asp-for="WalletId" /> <input type="hidden" id="WalletId" asp-for="WalletId" />
<input type="hidden" id="PSBT" asp-for="PSBT" value="@Model.PSBT"/> <input type="hidden" id="PSBT" asp-for="PSBT" value="@Model.PSBT" />
<input type="hidden" id="OriginalPSBT" asp-for="OriginalPSBT" value="@Model.OriginalPSBT"/> <input type="hidden" id="OriginalPSBT" asp-for="OriginalPSBT" value="@Model.OriginalPSBT" />
<input type="hidden" asp-for="WebsocketPath" /> <input type="hidden" asp-for="WebsocketPath" />
<input type="hidden" asp-for="PayJoinEndpointUrl" /> <input type="hidden" asp-for="SigningContext.PayJoinEndpointUrl" />
<input type="hidden" asp-for="SigningContext.EnforceLowR" />
</form> </form>
<div id="vaultPlaceholder"></div> <div id="vaultPlaceholder"></div>
<button id="vault-confirm" class="btn btn-primary" style="display:none;"></button> <button id="vault-confirm" class="btn btn-primary" style="display:none;"></button>