mirror of
https://github.com/cryptoadvance/specter-desktop.git
synced 2026-08-13 12:33:29 +02:00
178 lines
9.7 KiB
HTML
178 lines
9.7 KiB
HTML
<template id="address-data">
|
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='output.css') }}">
|
|
|
|
<style>
|
|
.address-data-table td {
|
|
text-align: left;
|
|
margin-top: 0;
|
|
}
|
|
.descriptor {
|
|
max-width: 500px;
|
|
white-space: -moz-pre-wrap;
|
|
white-space: -o-pre-wrap;
|
|
white-space: pre-wrap;
|
|
word-wrap: break-word;
|
|
}
|
|
.service-icon {
|
|
margin-top: -5px;
|
|
margin-right: 0.5em;
|
|
height: 24px;
|
|
vertical-align: middle;
|
|
}
|
|
.service-btn, .signing-btn {
|
|
background: var(--cmap-border);
|
|
border: 1px solid transparent;
|
|
border-radius: 4px;
|
|
padding: 8px 15px 8px 10px;
|
|
color: #fff;
|
|
font-size: 1em;
|
|
text-align: center;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
min-height: 33px;
|
|
}
|
|
.signing-btn {
|
|
max-width: 315px;
|
|
}
|
|
.service-btn:hover, .signing-btn:hover {
|
|
border: 1px solid var(--main-color);
|
|
background: var(--cmap-border);
|
|
}
|
|
</style>
|
|
<div class="address-data bg-dark-800 rounded-xl p-4">
|
|
<div class="flex justify-between mb-2">
|
|
<h3 class="mb-0">{{ _("Address Data") }}</h3>
|
|
<p class="m-0 cursor-pointer" onclick="hidePageOverlay()" class="cursor-pointer" data-cy="address-data-screen-close-btn">Close</p>
|
|
</div>
|
|
<div class="address-data-info"></div>
|
|
<div class="note"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script type="text/javascript">
|
|
class AddressDataElement extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
// Create a shadow root
|
|
var shadow = this.attachShadow({mode: 'open'});
|
|
var style = document.getElementById('address-data').content;
|
|
var clone = style.cloneNode(true);
|
|
|
|
this.el = clone.querySelector(".address-data");
|
|
this.note = clone.querySelector(".note");
|
|
this.info = clone.querySelector(".address-data-info");
|
|
this.popupContent = document.querySelector('#page_overlay_popup_content')
|
|
this.popupContent.style.justifySelf = "start";
|
|
this.popupContent.parentElement.style.display = "flex";
|
|
|
|
// Read input "data-*" attributes
|
|
this.isVerifyQR = this.getAttribute('data-verify-qr') == 'True';
|
|
this.isVerifyHwi = this.getAttribute('data-verify-hwi') == 'True';
|
|
this.used = (this.getAttribute('data-used') == 'true');
|
|
this.utxo = this.getAttribute('data-utxo');
|
|
this.amount = this.getAttribute('data-amount');
|
|
this.amountPrice = this.getAttribute('data-amount-price');
|
|
this.address = this.getAttribute('data-address');
|
|
this.label = this.getAttribute('data-label');
|
|
this.serviceId = this.getAttribute('data-service-id');
|
|
this.wallet = this.getAttribute('data-address-wallet');
|
|
|
|
this.note.innerText = `{{ _("Loading address") }}: ${this.address} {{ _("details") }}...`;
|
|
this.fetchAddressData();
|
|
|
|
// Attach the created element to the shadow dom
|
|
shadow.appendChild(clone);
|
|
}
|
|
|
|
async fetchAddressData() {
|
|
let url = `{{ url_for('wallets_endpoint_api.addressinfo', wallet_alias='WALLET_ALIAS') }}`.replace("WALLET_ALIAS", this.wallet);
|
|
var formData = new FormData();
|
|
formData.append('address', this.address);
|
|
const jsonResponse = await send_request(url, 'POST', "{{ csrf_token() }}", formData);
|
|
if (jsonResponse.success) {
|
|
let descriptor = jsonResponse.descriptor;
|
|
let xpubs_descriptor = jsonResponse.xpubs_descriptor;
|
|
let derivation_path = jsonResponse.derivation_path;
|
|
let addressIndex = jsonResponse.index;
|
|
let isChange = jsonResponse.change;
|
|
let walletName = jsonResponse.wallet_name;
|
|
let address = jsonResponse.address;
|
|
let walletLink = `{{ url_for('wallets_endpoint.wallet', wallet_alias='WALLET_ALIAS') }}`.replace("WALLET_ALIAS", this.wallet);
|
|
let addressInfoHTML = `
|
|
<qr-code style="margin: auto;" value="bitcoin:${address}" width="256"></qr-code>
|
|
<table class="address-data-table -mx-4 mt-8">
|
|
<tbody>
|
|
<tr><td>{{ _("Address") }}:</td><td style="word-break: break-all;"><explorer-link data-type="address" data-value="${address}"></explorer-link></td></tr>
|
|
<tr><td>{{ _("Label") }}:</td><td><address-label data-copy-hidden="true" data-address="${address}" data-wallet="${this.wallet}" data-label="${this.label}" data-service-id="${this.serviceId}"></address-label><br></td></tr>
|
|
<tr><td>{{ _("From wallet") }}:</td><td><a href=${walletLink}>${walletName}<a></td></tr>
|
|
<tr><td>{{ _("Address index") }}:</td><td>${addressIndex}</td></tr>
|
|
<tr><td>{{ _("Is change address") }}:</td><td>${isChange ? '{{ _("Yes") }}' : '{{ _("No") }}'}</td></tr>
|
|
<tr><td>{{ _("Used") }}:</td><td>${this.used ? 'Yes' : 'No'}</td></tr>
|
|
<tr><td>{{ _("UTXO count") }}:</td><td>${this.utxo}</td></tr>
|
|
<tr><td>{{ _("Amount") }}:</td><td>${this.amount} <span class="amount-price note ${this.amountPrice ? '' : 'hidden'}">${this.amountPrice}</span></td></tr>
|
|
`;
|
|
|
|
if ((typeof services !== 'undefined') && (this.serviceId in services)) {
|
|
// `services` obj made globally available in services-data.html
|
|
addressInfoHTML += `<tr><td>{{ _("Service") }}:</td><td><img class="service-icon" src='{{ext_url_prefix}}/${this.serviceId}/static/${services[this.serviceId].icon}'>${services[this.serviceId].name}</td></tr>`;
|
|
} else {
|
|
let associateServiceUrl = `{{ url_for('services_endpoint.associate_addr', wallet_alias='WALLET_ALIAS', address='ADDRESS') }}`.replace('WALLET_ALIAS', this.wallet).replace('ADDRESS', jsonResponse.address);
|
|
addressInfoHTML += `<tr><td>{{ _("Service") }}:</td><td><button type="button" id="associate-btn" class="service-btn" onclick="location.href='${associateServiceUrl}';">📥 {{ _("Associate with a service") }}</button></td></tr>`;
|
|
};
|
|
|
|
// Message signing feature restricted to singlesig wallets using a Specter DIY
|
|
{% set device = wallet.devices[0] %}
|
|
{% if wallet.is_singlesig and device.hwi_support or wallet.is_singlesig and device.supports_qr_message_signing %}
|
|
let redirectUrl = `{{ url_for('devices_endpoint.device', device_alias=device.alias, origin='wallet', address='ADDRESS', derivation_path='DERIVATION_PATH') }}`.replace('ADDRESS', address).replace('DERIVATION_PATH', derivation_path);
|
|
addressInfoHTML += `<tr><td>{{ _("Message signing") }}:</td><td>
|
|
<button type="button" id="msg-signing-btn" class="signing-btn" onclick="location.href='${redirectUrl}';">
|
|
<div style="word-wrap: anywhere">🖌 {{ _("Sign a message with your") }} {{ device.name }} {{ _("device") }}</div>
|
|
</button></td></tr>`;
|
|
{% endif %}
|
|
|
|
addressInfoHTML += `
|
|
</td></tr>
|
|
</tbody>
|
|
</table>
|
|
`;
|
|
|
|
if (this.isVerifyHwi) {
|
|
addressInfoHTML += `
|
|
<button type="button" onclick='hidePageOverlay();displayAddressOnDevice("${address}", "${descriptor}", "${xpubs_descriptor}")' class="btn" style="min-width:200px; max-width:300px; margin: auto;">{{ _("Verify address on device") }}</button>`;
|
|
}
|
|
|
|
if (this.isVerifyQR) {
|
|
addressInfoHTML += `
|
|
<p>{{ _("Or scan this QR code") }}:</p>
|
|
<qr-code value="bitcoin:${address}?index=${addressIndex}" width="256" scalable></qr-code>`;
|
|
}
|
|
|
|
addressInfoHTML += `
|
|
<h2>{{ _("Address descriptor") }}</h2>
|
|
<div>
|
|
<label class="switch mb-8 flex items-center">
|
|
<input type="checkbox" class="descriptor-switch" checked>
|
|
<span class="switch-text">{{ _("Show raw public keys") }}</span>
|
|
</label>
|
|
</div>
|
|
<pre class="descriptor"><code class="explorer-link" onclick='copyText(unescape("${escape(descriptor)}"), "{{ _("Copied address descriptor") }}")'>${descriptor}</code></pre>
|
|
`;
|
|
this.info.innerHTML = addressInfoHTML;
|
|
this.note.innerText = "";
|
|
|
|
this.info.querySelector('.descriptor-switch').onchange = (e) => {
|
|
if (e.target.checked) {
|
|
this.info.querySelector(".descriptor").innerHTML = `<code class="explorer-link" onclick='copyText(unescape("${escape(descriptor)}"), "{{ _("Copied address descriptor") }}")'>${descriptor}</code>`;
|
|
} else {
|
|
this.info.querySelector(".descriptor").innerHTML = `<code class="explorer-link" onclick='copyText(unescape("${escape(xpubs_descriptor)}"), "{{ _("Copied address descriptor") }}")'>${xpubs_descriptor}</code>`;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
customElements.define('address-data', AddressDataElement);
|
|
</script>
|