Files
btcpayserver/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml
Andrew Camilleri 4176f3659b Add QR code scan/show for PSBT + Import wallet via QR (#1931)
* Add PSBT QR code scan/show

This PR introduces support to show and read PSBTs in BC-UR format via animated QR codes.  This allows you to use BTCPay with HW devices such as Cobo Vault and Blue wallet to sign transactions without ever exposing the keys outside of that device.
Spec: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md
I've also bumped the QR code library we sue as it had a bug with large datasets.

* Reuse same code for all and allow wallet import via QR code scan

* remove unecessary js vendor files

* Allow export wallet from settings via QR

* formatting

* bundle

* fix wallet receive bundle
2020-10-21 14:03:11 +02:00

234 lines
11 KiB
Plaintext

@model DerivationSchemeViewModel
@addTagHelper *, BundlerMinifier.TagHelpers
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActivePageAndTitle(StoreNavPages.Index, $"{Model.CryptoCode} Derivation scheme");
}
@section HeadScripts {
<style type="text/css">
.hw-fields {
display: none;
}
</style>
}
<partial name="_StatusMessage" />
@if (!ViewContext.ModelState.IsValid)
{
<div class="row">
<div class="col-md-6">
<div asp-validation-summary="All" class="text-danger"></div>
</div>
</div>
}
<div class="modal fade" id="btcpayservervault" tabindex="-1" role="dialog" aria-labelledby="btcpayservervault" aria-hidden="true"></div>
<partial name="VaultElements" />
<div class="row">
<div class="col-md-8">
<div id="WebsocketPath" style="display:none;">@Url.Action("VaultBridgeConnection", "Vault", new { cryptoCode = Model.CryptoCode })</div>
@if (!Model.Confirmation)
{
<partial name="AddDerivationSchemes_HardwareWalletDialogs" model="@Model" />
}
else
{
<template id="btcpayservervault_template">
<div class="modal-dialog" role="document">
<form class="modal-content" method="post" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Address verification</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>Confirm on the device that you see address <b id="displayedAddress"></b></p>
<div class="form-group">
<div id="vaultPlaceholder"></div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button id="vault-confirm" class="btn btn-primary" style="display:none;"></button>
</div>
</form>
</div>
</template>
}
<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" />
@if (!Model.Confirmation)
{
<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">
<h5>Derivation scheme</h5>
<p>
The derivation scheme represents the destination of the funds received by your invoice.
It is generated by your wallet software.
</p>
</div>
<div class="form-group">
<label asp-for="DerivationScheme"></label>
<textarea asp-for="DerivationScheme" class="form-control store-derivation-scheme text-monospace py-2" rows="2"></textarea>
<span asp-validation-for="DerivationScheme" class="text-danger"></span>
<div class="dropdown mt-2 text-right">
<div class="btn-group">
<button class="btn btn-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="import-from-btn">
Import from...
</button>
<div class="dropdown-menu dropdown-menu-right">
@if (Model.CryptoCode == "BTC")
{
<button class="dropdown-item check-for-vault" type="button">... a hardware wallet</button>
}
<button class="dropdown-item" type="button" data-toggle="modal" data-target="#electrumimport">... a wallet file (Electrum, Wasabi, Cobo Vault, ColdCard)</button>
<button class="dropdown-item" type="button" data-toggle="modal" data-target="#scanqrModal">... a QR code</button>
@if (Model.CanUseHotWallet)
{
<button class="dropdown-item" data-toggle="modal" data-target="#nbxplorergeneratewallet" type="button" id="nbxplorergeneratewalletbtn">... a new/existing seed.</button>
}
</div>
</div>
</div>
</div>
<table class="table table-sm table-responsive-md">
<thead>
<tr>
<th>Address type</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td>P2WPKH</td>
<td>xpub...</td>
</tr>
<tr>
<td>P2SH-P2WPKH</td>
<td>xpub...-[p2sh]</td>
</tr>
<tr>
<td>P2PKH</td>
<td>xpub...-[legacy]</td>
</tr>
<tr>
<td>Multi-sig P2WSH</td>
<td>2-of-xpub1...-xpub2...</td>
</tr>
<tr>
<td>Multi-sig P2SH-P2WSH</td>
<td>2-of-xpub1...-xpub2...-[p2sh]</td>
</tr>
<tr>
<td>Multi-sig P2SH</td>
<td>2-of-xpub1...-xpub2...-[legacy]</td>
</tr>
</tbody>
</table>
<div class="form-group hw-fields">
<h5>Additional pairing information</h5>
</div>
<div class="form-group hw-fields">
<label asp-for="Source"></label>
<input asp-for="Source" class="form-control" readonly />
</div>
<div class="form-group hw-fields">
<label asp-for="RootFingerprint"></label>
<input asp-for="RootFingerprint" class="form-control" readonly />
</div>
<div class="form-group hw-fields">
<label asp-for="KeyPath"></label>
<input asp-for="KeyPath" class="form-control" readonly />
</div>
<div class="form-group">
<div class="form-check">
<input asp-for="Enabled" type="checkbox" class="form-check-input" />
<label asp-for="Enabled" class="form-check-label"></label>
</div>
</div>
<button name="command" type="submit" class="btn btn-primary" value="save" id="Continue">Continue</button>
}
else
{
<div class="form-group">
<h5>Confirm the addresses (@Model.CryptoCode)</h5>
<span>Please check that your @Model.CryptoCode wallet is generating the same addresses as below.</span>
</div>
<input asp-for="Confirmation" type="hidden" />
<input type="hidden" asp-for="DerivationScheme" />
<input type="hidden" asp-for="Enabled" />
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<tr>
<th>Key path</th>
<th>Address</th>
@if (Model.Source == "Vault")
{
<th>Actions</th>
}
</tr>
</thead>
<tbody>
@foreach (var sample in Model.AddressSamples)
{
<tr>
<td>@sample.KeyPath</td>
<td>@sample.Address</td>
@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>
}
</tr>
}
</tbody>
</table>
</div>
<div class="form-group">
<h5>Wrong addresses?</h5>
<span>Help us to find the correct settings by telling us the first address of your wallet</span>
</div>
<div class="form-group">
<label asp-for="HintAddress"></label>
<input asp-for="HintAddress" class="form-control" />
<span asp-validation-for="HintAddress" class="text-danger"></span>
</div>
<button name="command" type="submit" class="btn btn-primary" value="save" id="Confirm">Confirm</button>
}
</form>
</div>
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
<script src="~/js/StoreAddDerivationScheme.js" type="text/javascript" defer="defer" asp-append-version="true"></script>
<script src="~/js/vaultbridge.js" type="text/javascript" defer="defer" asp-append-version="true"></script>
<script src="~/js/vaultbridge.ui.js" type="text/javascript" defer="defer" asp-append-version="true"></script>
<bundle name="wwwroot/bundles/camera-bundle.min.js"></bundle>
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
<script>
window.coinName = "@Model.Network.DisplayName.ToLowerInvariant()";
$(function () {
initCameraScanningApp("Scan wallet QR", function(data){
$("#WalletFileContent").val(data);
$("#qr-import-form").submit();
},"scanqrModal");
});
</script>
}