View seed option if available (#1518)

This commit is contained in:
Andrew Camilleri
2020-04-28 17:55:53 +02:00
committed by GitHub
parent ff99ab1239
commit e75b4ec6bf
3 changed files with 141 additions and 76 deletions

View File

@@ -26,6 +26,7 @@ using Newtonsoft.Json.Linq;
using BTCPayServer.Logging; using BTCPayServer.Logging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using BTCPayServer.Client; using BTCPayServer.Client;
using NBXplorer;
namespace BTCPayServer.Controllers namespace BTCPayServer.Controllers
{ {
@@ -53,6 +54,9 @@ namespace BTCPayServer.Controllers
{ {
vm.DerivationScheme = derivation.AccountDerivation.ToString(); vm.DerivationScheme = derivation.AccountDerivation.ToString();
vm.Config = derivation.ToJson(); vm.Config = derivation.ToJson();
vm.NBXSeedAvailable = (await CanUseHotWallet() ).HotWallet && !string.IsNullOrEmpty(await _ExplorerProvider.GetExplorerClient(network)
.GetMetadataAsync<string>(derivation.AccountDerivation,
WellknownMetadataKeys.Mnemonic));
} }
vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike)); vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike));
var hotWallet = await CanUseHotWallet(); var hotWallet = await CanUseHotWallet();
@@ -60,6 +64,50 @@ namespace BTCPayServer.Controllers
vm.CanUseRPCImport = hotWallet.RPCImport; vm.CanUseRPCImport = hotWallet.RPCImport;
return View(vm); return View(vm);
} }
[HttpPost]
[Route("{storeId}/derivations/{cryptoCode}/seed")]
[ApiExplorerSettings(IgnoreApi = true)]
public async Task<IActionResult> ViewSeed(string storeId, string cryptoCode)
{
var store = HttpContext.GetStoreData();
if (store == null)
return NotFound();
var network = cryptoCode == null ? null : _ExplorerProvider.GetNetwork(cryptoCode);
if (network == null)
{
return NotFound();
}
var derivation = GetExistingDerivationStrategy(cryptoCode, store);
if (derivation == null)
{
return NotFound();
}
var canExtract = (await CanUseHotWallet()).HotWallet;
var seed = await _ExplorerProvider.GetExplorerClient(network)
.GetMetadataAsync<string>(derivation.AccountDerivation,
WellknownMetadataKeys.Mnemonic);
if (string.IsNullOrEmpty(seed))
{
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Severity = StatusMessageModel.StatusSeverity.Error,
Message = "The seed was not found"
});
}
else
{
TempData.SetStatusMessageModel(new StatusMessageModel()
{
Severity = StatusMessageModel.StatusSeverity.Success,
Html = $"Please store your seed securely! <br/><code class=\"alert-link\">{seed}</code>"
});
}
return RedirectToAction(nameof(UpdateStore), new { storeId });
}
class GetXPubs class GetXPubs
{ {
@@ -163,6 +211,7 @@ namespace BTCPayServer.Controllers
return NotFound(); return NotFound();
} }
vm.NBXSeedAvailable = false;
vm.Network = network; vm.Network = network;
vm.RootKeyPath = network.GetRootKeyPath(); vm.RootKeyPath = network.GetRootKeyPath();
DerivationSchemeSettings strategy = null; DerivationSchemeSettings strategy = null;

View File

@@ -24,7 +24,7 @@ namespace BTCPayServer.Models.StoreViewModels
{ {
get; set; get; set;
} = new List<(string KeyPath, string Address, RootedKeyPath RootedKeyPath)>(); } = new List<(string KeyPath, string Address, RootedKeyPath RootedKeyPath)>();
public bool NBXSeedAvailable { get; set; }
public string CryptoCode { get; set; } public string CryptoCode { get; set; }
public string KeyPath { get; set; } public string KeyPath { get; set; }
public string RootFingerprint { get; set; } public string RootFingerprint { get; set; }

View File

@@ -13,7 +13,7 @@
</style> </style>
} }
<partial name="_StatusMessage" /> <partial name="_StatusMessage"/>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div asp-validation-summary="All" class="text-danger"></div> <div asp-validation-summary="All" class="text-danger"></div>
@@ -22,13 +22,13 @@
<div class="modal fade" id="btcpayservervault" tabindex="-1" role="dialog" aria-labelledby="btcpayservervault" aria-hidden="true"> <div class="modal fade" id="btcpayservervault" tabindex="-1" role="dialog" aria-labelledby="btcpayservervault" aria-hidden="true">
</div> </div>
<partial name="VaultElements" /> <partial name="VaultElements"/>
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<div id="WebsocketPath" style="display:none;">@Url.Action("VaultBridgeConnection", "Vault", new { cryptoCode = Model.CryptoCode })</div> <div id="WebsocketPath" style="display:none;">@Url.Action("VaultBridgeConnection", "Vault", new {cryptoCode = Model.CryptoCode})</div>
@if (!Model.Confirmation) @if (!Model.Confirmation)
{ {
<partial name="AddDerivationSchemes_HardwareWalletDialogs" model="@Model" /> <partial name="AddDerivationSchemes_HardwareWalletDialogs" model="@Model"/>
} }
else else
{ {
@@ -55,24 +55,25 @@
</div> </div>
</template> </template>
} }
@if (!Model.Confirmation)
{
<form method="post" asp-action="AddDerivationScheme" <form method="post" asp-action="AddDerivationScheme"
asp-route-cryptoCode="@Model.CryptoCode" asp-route-cryptoCode="@Model.CryptoCode"
asp-route-storeId="@this.Context.GetRouteValue("storeId")"> asp-route-storeId="@this.Context.GetRouteValue("storeId")">
<input id="Config" asp-for="Config" type="hidden" /> <input id="Config" asp-for="Config" type="hidden"/>
<input id="CryptoCurrency" asp-for="CryptoCode" type="hidden"/>
@if (!Model.Confirmation) <input id="DerivationSchemeFormat" asp-for="DerivationSchemeFormat" type="hidden"/>
{ <input id="AccountKey" asp-for="AccountKey" type="hidden"/>
<input id="CryptoCurrency" asp-for="CryptoCode" type="hidden" />
<input id="DerivationSchemeFormat" asp-for="DerivationSchemeFormat" type="hidden" />
<input id="AccountKey" asp-for="AccountKey" type="hidden" />
<div class="form-group"> <div class="form-group">
<h5>Derivation Scheme</h5> <h5>Derivation Scheme</h5>
<span>The DerivationScheme represents the destination of the funds received by your invoice. It is generated by your wallet software. Please, verify that you are generating the right addresses by clicking on 'Check ExtPubKey'</span> <span>The DerivationScheme represents the destination of the funds received by your invoice. It is generated by your wallet software. Please, verify that you are generating the right addresses by clicking on 'Check ExtPubKey'</span>
</div> </div>
<div class="form-group"> <div class="form-group">
<label asp-for="DerivationScheme"></label> <label asp-for="DerivationScheme"></label>
<input asp-for="DerivationScheme" class="form-control store-derivation-scheme" /> <input asp-for="DerivationScheme" class="form-control store-derivation-scheme"/>
<span asp-validation-for="DerivationScheme" class="text-danger"></span> <span asp-validation-for="DerivationScheme" class="text-danger"></span>
<div class="dropdown mt-2 text-right"> <div class="dropdown mt-2 text-right">
@@ -138,33 +139,45 @@
</div> </div>
<div class="form-group hw-fields"> <div class="form-group hw-fields">
<label asp-for="Source"></label> <label asp-for="Source"></label>
<input asp-for="Source" class="form-control" readonly /> <input asp-for="Source" class="form-control" readonly/>
</div> </div>
<div class="form-group hw-fields"> <div class="form-group hw-fields">
<label asp-for="RootFingerprint"></label> <label asp-for="RootFingerprint"></label>
<input asp-for="RootFingerprint" class="form-control" readonly /> <input asp-for="RootFingerprint" class="form-control" readonly/>
</div> </div>
<div class="form-group hw-fields"> <div class="form-group hw-fields">
<label asp-for="KeyPath"></label> <label asp-for="KeyPath"></label>
<input asp-for="KeyPath" class="form-control" readonly /> <input asp-for="KeyPath" class="form-control" readonly/>
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="form-check"> <div class="form-check">
<input asp-for="Enabled" type="checkbox" class="form-check-input" /> <input asp-for="Enabled" type="checkbox" class="form-check-input"/>
<label asp-for="Enabled" class="form-check-label"></label> <label asp-for="Enabled" class="form-check-label"></label>
</div> </div>
</div> </div>
<button name="command" type="submit" class="btn btn-primary" value="save" id="Continue">Continue</button> <button name="command" type="submit" class="btn btn-primary" value="save" id="Continue">Continue</button>
</form>
@if (Model.NBXSeedAvailable)
{
<form asp-action="ViewSeed" asp-route-cryptoCode="@Model.CryptoCode" asp-route-storeId="@Context.GetRouteValue("storeId")">
<button type="submit" class="btn btn-link">View seed</button>
</form>
}
} }
else else
{ {
<form method="post" asp-action="AddDerivationScheme"
asp-route-cryptoCode="@Model.CryptoCode"
asp-route-storeId="@this.Context.GetRouteValue("storeId")">
<input id="Config" asp-for="Config" type="hidden"/>
<div class="form-group"> <div class="form-group">
<h5>Confirm the addresses (@Model.CryptoCode)</h5> <h5>Confirm the addresses (@Model.CryptoCode)</h5>
<span>Please check that your @Model.CryptoCode wallet is generating the same addresses as below.</span> <span>Please check that your @Model.CryptoCode wallet is generating the same addresses as below.</span>
</div> </div>
<input asp-for="Confirmation" type="hidden" /> <input asp-for="Confirmation" type="hidden"/>
<input type="hidden" asp-for="DerivationScheme" /> <input type="hidden" asp-for="DerivationScheme"/>
<input type="hidden" asp-for="Enabled" /> <input type="hidden" asp-for="Enabled"/>
<div class="form-group"> <div class="form-group">
<table class="table table-sm table-responsive-md"> <table class="table table-sm table-responsive-md">
<thead> <thead>
@@ -185,7 +198,9 @@
<td>@sample.Address</td> <td>@sample.Address</td>
@if (Model.Source == "Vault") @if (Model.Source == "Vault")
{ {
<td><a class="showaddress" href="#" onclick='showAddress(@Safe.Json(sample.RootedKeyPath.ToString()), @Safe.Json(sample.Address)); return false;'>Show on device</a></td> <td>
<a class="showaddress" href="#" onclick='showAddress(@Safe.Json(sample.RootedKeyPath.ToString()), @Safe.Json(sample.Address)); return false;'>Show on device</a>
</td>
} }
</tr> </tr>
} }
@@ -199,14 +214,15 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label asp-for="HintAddress"></label> <label asp-for="HintAddress"></label>
<input asp-for="HintAddress" class="form-control" /> <input asp-for="HintAddress" class="form-control"/>
<span asp-validation-for="HintAddress" class="text-danger"></span> <span asp-validation-for="HintAddress" class="text-danger"></span>
</div> </div>
<button name="command" type="submit" class="btn btn-primary" value="save" id="Confirm">Confirm</button> <button name="command" type="submit" class="btn btn-primary" value="save" id="Confirm">Confirm</button>
}
</form> </form>
}
</div> </div>
</div> </div>
@section Scripts { @section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial") @await Html.PartialAsync("_ValidationScriptsPartial")
<script src="~/js/ledgerwebsocket.js" type="text/javascript" defer="defer" asp-append-version="true"></script> <script src="~/js/ledgerwebsocket.js" type="text/javascript" defer="defer" asp-append-version="true"></script>