btcpayserver/BTCPayServer/Views/UIWallets/WalletPSBT.cshtml
Dennis Reimann c97b859963 Refactor QR functionality
Based on the `ur-registry` upgrade I refactored the `CameraScanner` and `ShowQR` partials: Besides general code changes, the main change is that most of the configuration and result handling now happens on the outer view.
Those partials and functions are now generalized and don't know about their purpose (like handling PSBTs): They can be instantiated with simple data (e.g. for displaying a plain QR code) or different modes (like showing a static and the UR version of a QR code) and the result handling is done via callback.

The callbacks can now also distinguish between the different results (data as plain string vs. UR-type objects for wallet data or PSBT) and also handle the specific type of data. For instance: Before it wasn't possible to strip the leading derivation path from an xpub when scanning the QR code, because the scanner didn't know about the type of data it was handling. Now that the data is handled in the callback, we can implement that functionality for the scan view only.
2022-09-13 10:17:12 +02:00

100 lines
4.1 KiB
Text

@using BTCPayServer.Controllers
@model WalletPSBTViewModel
@{
var walletId = Context.GetRouteValue("walletId").ToString();
var cancelUrl = Model.ReturnUrl ?? Url.Action(nameof(UIWalletsController.WalletTransactions), new { walletId });
var backUrl = Model.BackUrl != null ? $"{Model.BackUrl}?returnUrl={Model.ReturnUrl}" : null;
Layout = "_LayoutWizard";
ViewData.SetActivePage(WalletsNavPages.PSBT, "Decode PSBT", walletId);
}
@section Navbar {
@if (backUrl != null)
{
<a href="@backUrl" id="GoBack">
<vc:icon symbol="back" />
</a>
}
<a href="@cancelUrl" id="CancelWizard" class="cancel">
<vc:icon symbol="close" />
</a>
}
@section PageHeadContent {
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
}
@section PageFootContent {
<bundle name="wwwroot/bundles/camera-bundle.min.js"></bundle>
<script>
document.addEventListener("DOMContentLoaded", function () {
const psbtHex = @Json.Serialize(Model.PSBTHex);
if (psbtHex) {
const buffer = new window.URlib.Buffer.from(psbtHex, "hex");
const cryptoPSBT = new window.URlib.CryptoPSBT(buffer);
const encoder = cryptoPSBT.toUREncoder();
const modes = {
ur: { title: "UR", fragments: encoder.encodeWhole() },
static: { title: "Static", fragments: [psbtHex] }
};
initQRShow({ title: "Scan the PSBT", modes });
}
initCameraScanningApp("Scan PSBT", data => {
let hex = data;
if (typeof(data) === "object") {
if (data.type === "crypto-psbt") {
const psbt = window.URlib.CryptoPSBT.fromCBOR(data.cbor);
hex = psbt.getPSBT().toString('hex');
} else {
console.error('Unexpected UR type', data.type)
}
} else if (typeof(data) === 'string') {
hex = data;
}
document.getElementById("PSBT").value = hex;
document.getElementById("Decode").click();
}, "scanModal");
});
</script>
}
<header class="text-center">
<h1>@ViewData["Title"]</h1>
<p class="lead text-secondary mt-3 mx-md-5">You can decode a PSBT by either pasting its content, uploading the file or scanning the wallet QR code.</p>
</header>
<div class="my-5">
@if (Model.Errors != null && Model.Errors.Count != 0)
{
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
<vc:icon symbol="close" />
</button>
@foreach (var error in Model.Errors)
{
<span>@error</span>
<br/>
}
</div>
}
<form class="form-group" method="post" asp-action="WalletPSBT" asp-route-walletId="@walletId" enctype="multipart/form-data">
<input type="hidden" asp-for="ReturnUrl" />
<input type="hidden" asp-for="BackUrl" />
<div class="form-group">
<label asp-for="PSBT" class="form-label"></label>
<textarea class="form-control" rows="5" asp-for="PSBT"></textarea>
<span asp-validation-for="PSBT" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="UploadedPSBTFile" class="form-label"></label>
<input asp-for="UploadedPSBTFile" type="file" class="form-control">
</div>
<div class="d-flex">
<button type="submit" name="command" value="decode" class="btn btn-primary mt-2" id="Decode">Decode PSBT</button>
<button type="button" id="scanqrcode" class="btn btn-secondary only-for-js ms-3 mt-2" data-bs-toggle="modal" data-bs-target="#scanModal">Scan wallet QR with camera</button>
</div>
</form>
</div>
<partial name="ShowQR"/>
<partial name="CameraScanner"/>