include node_modules so release .zip is deployable
This commit is contained in:
+346
@@ -0,0 +1,346 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||
<meta name="keywords" content="bech32, base32, bitcoin">
|
||||
<meta name="description" content="Demo of bech32-buffer package capabilities">
|
||||
|
||||
<title>Bech32 Demo</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous">
|
||||
<style>
|
||||
textarea {
|
||||
resize: none;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
input[type=number] {
|
||||
max-width: 5rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 1080px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.body-header {
|
||||
padding: 1rem;
|
||||
background: #f4f4f4;
|
||||
border-bottom: 1px solid #eee;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.page-footer {
|
||||
margin: 4rem -0.5rem 0 -0.5rem;
|
||||
padding: 2rem 0 1.5rem;
|
||||
border-top: 1px solid rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.align-height {
|
||||
min-height: 152px;
|
||||
}
|
||||
.card-header.align-header-height {
|
||||
height: 49px;
|
||||
}
|
||||
|
||||
.qr-placeholder {
|
||||
display: inline-block;
|
||||
width: 132px;
|
||||
height: 132px;
|
||||
background: rgba(0,0,0,0.15);
|
||||
color: white;
|
||||
}
|
||||
.qr-placeholder:before {
|
||||
content: '?';
|
||||
font-size: 72px;
|
||||
line-height: 1;
|
||||
height: 72px;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
margin-top: -36px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#encode:after {
|
||||
content: ' ↓';
|
||||
}
|
||||
#decode:after {
|
||||
content: ' ↑';
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
#encode:after {
|
||||
content: ' →';
|
||||
}
|
||||
#decode:after {
|
||||
content: ' ←';
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="body-header">
|
||||
<div class="content">
|
||||
<h1>bech32-buffer</h1>
|
||||
<p class="lead">Bech32 is a Bitcoin address format proposed by Pieter Wuille and Greg Maxwell in <a href="https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki">BIP 173</a> and later amended by <a href="https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki">BIP 350</a>.
|
||||
Besides Bitcoin addresses, Bech32 can encode any short binary data.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<div class="card">
|
||||
<div class="card-header align-header-height">
|
||||
<ul class="nav nav-tabs card-header-tabs">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="encode-btc-tab" data-bs-toggle="tab" data-bs-target="#encode-btc" type="button" role="tab" aria-controls="home" aria-selected="true">BTC Address</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" id="encode-data-tab" data-bs-toggle="tab" data-bs-target="#encode-data" type="button" role="tab" aria-controls="home" aria-selected="false">Data</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-block p-2">
|
||||
<form>
|
||||
<div class="align-height tab-content">
|
||||
<div class="tab-pane" id="encode-data" role="tabpanel" aria-labelledby="encode-data-tab">
|
||||
<div class="mb-3 row">
|
||||
<label for="hrp" class="col-3 col-form-label">Tag</label>
|
||||
<div class="col-9">
|
||||
<input type="text" id="hrp" class="form-control" placeholder="Tag"/>
|
||||
</div>
|
||||
<div class="col-12 form-text text-muted small">A short tag describing what a Bech32-encoded string is used for.</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label class="col-3 col-form-label">Encoding</label>
|
||||
<div class="col-9">
|
||||
<div class="btn-group" role="group">
|
||||
<input type="radio" class="btn-check" name="encoding-options" id="encoding-bech32" autocomplete="off">
|
||||
<label for="encoding-bech32" class="btn btn-outline-primary" title="Original encoding proposed in BIP 173">Bech32</label>
|
||||
<input type="radio" class="btn-check" name="encoding-options" id="encoding-bech32m" autocomplete="off" checked>
|
||||
<label for="encoding-bech32m" class="btn btn-outline-primary" title="Amended encoding from BIP 350">Bech32m</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane active" id="encode-btc" role="tabpanel" aria-labelledby="encode-btc-tab">
|
||||
<div class="mb-3 row">
|
||||
<label class="col-3 col-form-label">Network</label>
|
||||
<div class="col-9">
|
||||
<div class="btn-group" role="group">
|
||||
<input type="radio" class="btn-check" name="btc-network-options" id="btc-mainnet" autocomplete="off" checked>
|
||||
<label for="btc-mainnet" class="btn btn-outline-primary">Mainnet</label>
|
||||
<input type="radio" class="btn-check" name="btc-network-options" id="btc-testnet" autocomplete="off">
|
||||
<label for="btc-testnet" class="btn btn-outline-primary">Testnet</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="script-version" class="col-3 col-form-label">Script ver.</label>
|
||||
<div class="col-9">
|
||||
<input type="number" id="script-version" min="0" max="16" size="6" value="0">
|
||||
</div>
|
||||
<div class="col-12 form-text">Note that version 0 scripts should have length 20 or 32 bytes.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="data" class="form-label">Data</label>
|
||||
<textarea id="data" class="form-control" placeholder="Hex data"></textarea>
|
||||
<div class="form-text text-muted small">Binary data (in hex) to be encoded into Bech32.</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="encode" class="btn btn-primary" data-container="body" data-toggle="popover" data-placement="bottom" data-content="">Encode</button>
|
||||
<a id="random" title="Generate random data" class="ms-3" href="#">Random data</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<h3 class="card-header align-header-height">Bech32</h3>
|
||||
<div id="qrcode" class="card-img-top text-center py-2 align-height" title="QR code with the latest encoded or decoded message"><div class="qr-placeholder"></div></div>
|
||||
<div class="card-block p-2">
|
||||
<form>
|
||||
<div class="mb-4">
|
||||
<label for="encoded" class="form-label">Encoded data</label>
|
||||
<textarea id="encoded" class="form-control" placeholder="Bech32 string"></textarea>
|
||||
<div class="form-text text-muted small">Encoded Bech32 string.</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="decode" class="btn btn-primary" data-container="body" data-toggle="popover" data-placement="top" data-content="">Decode</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="page-footer small text-muted">
|
||||
<span class="copyright">© 2021 Alex Ostrovski</span>
|
||||
<div class="float-none float-sm-end">
|
||||
<a href="https://github.com/slowli/bech32-buffer">GitHub</a> •
|
||||
<a href="https://npmjs.com/package/bech32-buffer">Npm</a> •
|
||||
<a href="../dist/bech32-buffer.min.js" download="bech32-buffer.min.js">Browser version</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="qrcode.min.js"></script>
|
||||
<script src="../dist/bech32-buffer.min.js"></script>
|
||||
|
||||
<script>
|
||||
/* eslint-env browser, jquery */
|
||||
/* global bech32 */
|
||||
(function () {
|
||||
/**
|
||||
* Converts a byte array into a hex string.
|
||||
*/
|
||||
function toHexString(buffer) {
|
||||
return buffer.reduce((s, byte) => {
|
||||
let hex = byte.toString(16);
|
||||
if (hex.length === 1) hex = '0' + hex;
|
||||
return s + hex;
|
||||
}, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hex string into a byte array.
|
||||
*
|
||||
* @returns {?Uint8Array}
|
||||
* decoded array, or `null` if the supplied string is not a valid hex string
|
||||
*/
|
||||
function fromHexString(str) {
|
||||
if (str.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(str)) {
|
||||
return null;
|
||||
}
|
||||
let buffer = new Uint8Array(str.length / 2);
|
||||
for (let i = 0; i < buffer.length; i++) {
|
||||
buffer[i] = parseInt(str.substr(2 * i, 2), 16);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const hrp = $('#hrp');
|
||||
const data = $('#data');
|
||||
const encoded = $('#encoded');
|
||||
const encodeBtn = $('#encode');
|
||||
const decodeBtn = $('#decode');
|
||||
const randomBtn = $('#random');
|
||||
const scriptVersion = $('#script-version');
|
||||
|
||||
const timeouts = {};
|
||||
|
||||
function report(type, btn, message) {
|
||||
const id = btn[0].id;
|
||||
const timeout = timeouts[id];
|
||||
if (timeout) clearTimeout(timeout);
|
||||
|
||||
btn.attr('data-bs-content', '<span class="text-' + type + '">' + message + '</span>');
|
||||
btn[0].popover.show();
|
||||
timeouts[id] = setTimeout(function() {
|
||||
btn[0].popover.hide();
|
||||
delete timeouts[id];
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
encodeBtn.click(function() {
|
||||
let enc;
|
||||
const btc = $('#encode-btc').hasClass('active');
|
||||
|
||||
try {
|
||||
const buffer = fromHexString(data.val());
|
||||
if (!buffer) throw new TypeError('Invalid hex encoding of data');
|
||||
|
||||
if (btc) {
|
||||
const prefix = $('#btc-mainnet').prop('checked') ? 'bc' : 'tb';
|
||||
const version = parseInt(scriptVersion.val());
|
||||
const btcAddress = new bech32.BitcoinAddress(prefix, version, buffer);
|
||||
enc = btcAddress.encode();
|
||||
} else {
|
||||
const encoding = $('#encoding-bech32').prop('checked') ? 'bech32' : 'bech32m';
|
||||
enc = bech32.encode(hrp.val(), buffer, encoding);
|
||||
}
|
||||
encoded.val(enc);
|
||||
} catch (e) {
|
||||
report('danger', encodeBtn, 'Error: ' + e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
report('success', encodeBtn, 'Data encoded (' + enc.length + ' chars)');
|
||||
const qr = qrcode(0, 'M');
|
||||
qr.addData(enc.toUpperCase(), 'Alphanumeric');
|
||||
qr.make();
|
||||
$('#qrcode').html(qr.createSvgTag(4, 0));
|
||||
});
|
||||
|
||||
decodeBtn.click(function() {
|
||||
let dec;
|
||||
const btc = $('#encode-btc').hasClass('active');
|
||||
|
||||
try {
|
||||
if (btc) {
|
||||
dec = bech32.BitcoinAddress.decode(encoded.val());
|
||||
scriptVersion.val(dec.scriptVersion);
|
||||
|
||||
var selectedNetwork = (dec.prefix === 'bc') ? $('#btc-mainnet') : $('#btc-testnet');
|
||||
$('input[name=btc-network-options]').parent().removeClass('active');
|
||||
selectedNetwork.prop('checked', true);
|
||||
selectedNetwork.parent().addClass('active');
|
||||
} else {
|
||||
dec = bech32.decode(encoded.val());
|
||||
hrp.val(dec.prefix);
|
||||
|
||||
var selectedEncoding = (dec.encoding === 'bech32') ? $('#encoding-bech32') : $('#encoding-bech32m');
|
||||
$('input[name=encoding-options]').parent().removeClass('active');
|
||||
selectedEncoding.prop('checked', true);
|
||||
selectedEncoding.parent().addClass('active');
|
||||
}
|
||||
data.val(toHexString(dec.data));
|
||||
} catch (e) {
|
||||
report('danger', decodeBtn, 'Error: ' + e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
report('success', decodeBtn, 'Data decoded (' + dec.data.length + ' bytes)');
|
||||
const qr = qrcode(0, 'M');
|
||||
qr.addData(encoded.val().toUpperCase(), 'Alphanumeric');
|
||||
qr.make();
|
||||
$('#qrcode').html(qr.createSvgTag(4, 0));
|
||||
});
|
||||
|
||||
$('#encode,#decode').each(function () {
|
||||
this.popover = new bootstrap.Popover(this, {
|
||||
trigger: 'manual',
|
||||
html: true
|
||||
});
|
||||
});
|
||||
|
||||
randomBtn.click(function(e) {
|
||||
e.preventDefault();
|
||||
const btc = $('#encode-btc').hasClass('active');
|
||||
|
||||
// Not secure! Don't use in production.
|
||||
const length = (btc && parseInt(scriptVersion.val()) === 0)
|
||||
? (Math.random() > 0.5 ? 32 : 20)
|
||||
: 8 + Math.floor(Math.random() * 32);
|
||||
const buffer = new Uint8Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
buffer[i] = Math.floor(Math.random() * 256);
|
||||
}
|
||||
data.val(toHexString(buffer));
|
||||
});
|
||||
|
||||
scriptVersion.change(function() {
|
||||
const version = parseInt(scriptVersion.val());
|
||||
if (version < 0) scriptVersion.val(0);
|
||||
if (version > 16) scriptVersion.val(16);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+1991
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user