bitcoin-tx-lib
Version:
A Typescript library for building and signing Bitcoin transactions
161 lines • 5.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bech32 = void 0;
const utils_1 = require("../utils");
class Bech32 {
constructor(options = {}) {
var _a;
this.version = 0;
this.network = "mainnet";
this.encoding = "bech32";
this.encodings = { BECH32: "bech32", BECH32M: "bech32m" };
this.chars = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
this.generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
if (options === null || options === void 0 ? void 0 : options.network)
this.network = options.network;
if (options === null || options === void 0 ? void 0 : options.version) {
this.version = options.version;
this.encoding = options.version > 0 ? "bech32m" : "bech32";
}
this.publicKey = (_a = options.publicKey) !== null && _a !== void 0 ? _a : "";
}
// convert a ripemd160 hexadecimal in a bech32 hexadecimal 32 bytes
convert(ripemd160) {
let binary = "";
let hexadecimal = typeof (ripemd160) == "string" ? (0, utils_1.hexToBytes)(ripemd160) : ripemd160;
// convert the bytes in int binary 8 bits string binary
hexadecimal.forEach(num => {
let bits = num.toString(2);
while (bits.length < 8)
bits = "0" + bits;
binary += bits;
});
let int5Array = [this.version];
// breaks the string into 5-bit ints in an array
for (let i = 0; i < binary.length; i += 5)
int5Array.push(parseInt(binary.slice(i, i + 5), 2));
// convert int5 into 1-byte hexadecimal and return the string of concatenating bytes
return int5Array;
}
getAddress() {
let sha2 = (0, utils_1.sha256)(this.publicKey);
let ripemd = (0, utils_1.ripemd160)(sha2);
let hex = this.convert(ripemd);
return this.encode(hex);
}
getEncodingConst(enc) {
if (enc == this.encodings.BECH32) {
return 1;
}
else if (enc == this.encodings.BECH32M) {
return 0x2bc830a3;
}
return 1;
}
polymod(values) {
var chk = 1;
for (var p = 0; p < values.length; ++p) {
var top = chk >> 25;
chk = (chk & 0x1ffffff) << 5 ^ values[p];
for (var i = 0; i < 5; ++i) {
if ((top >> i) & 1) {
chk ^= this.generator[i];
}
}
}
return chk;
}
hrpExpand(hrp) {
var p;
var ret = [];
for (p = 0; p < hrp.length; ++p) {
ret.push(hrp.charCodeAt(p) >> 5);
}
ret.push(0);
for (p = 0; p < hrp.length; ++p) {
ret.push(hrp.charCodeAt(p) & 31);
}
return ret;
}
verifyChecksum(data) {
let hrp = this.network === "mainnet" ? "bc" : "tb";
return this.polymod(this.hrpExpand(hrp).concat(data)) === this.getEncodingConst(this.encoding);
}
createChecksum(data) {
let hrp = this.network === "mainnet" ? "bc" : "tb";
var values = this.hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
var mod = this.polymod(values) ^ this.getEncodingConst(this.encoding);
var ret = [];
for (var p = 0; p < 6; ++p) {
ret.push((mod >> 5 * (5 - p)) & 31);
}
return ret;
}
encode(data) {
let hrp = this.network === "mainnet" ? "bc" : "tb";
let combined = data.concat(this.createChecksum(data));
var ret = hrp + '1';
for (let p = 0; p < combined.length; ++p) {
ret += this.chars.charAt(combined[p]);
}
return ret;
}
decode(bechString) {
var p;
var has_lower = false;
var has_upper = false;
for (p = 0; p < bechString.length; ++p) {
if (bechString.charCodeAt(p) < 33 || bechString.charCodeAt(p) > 126) {
return null;
}
if (bechString.charCodeAt(p) >= 97 && bechString.charCodeAt(p) <= 122) {
has_lower = true;
}
if (bechString.charCodeAt(p) >= 65 && bechString.charCodeAt(p) <= 90) {
has_upper = true;
}
}
if (has_lower && has_upper) {
return null;
}
bechString = bechString.toLowerCase();
var pos = bechString.lastIndexOf('1');
if (pos < 1 || pos + 7 > bechString.length || bechString.length > 90) {
return null;
}
// var hrp = bechString.substring(0, pos)
var data = [];
for (p = pos + 1; p < bechString.length; ++p) {
var d = this.chars.indexOf(bechString.charAt(p));
if (d === -1) {
return null;
}
data.push(d);
}
if (!this.verifyChecksum(data)) {
return null;
}
var program = data.slice(0, data.length - 6);
var hash = new Uint8Array(program.length);
program.forEach((num, index) => hash[index] = num);
return hash;
}
getScriptPubkey(bech32Address) {
let bytesint5 = this.decode(bech32Address);
let int8string = "";
bytesint5 === null || bytesint5 === void 0 ? void 0 : bytesint5.forEach((num, index) => {
if (index > 0) { // ignore byte version
let binary = num.toString(2);
while (binary.length < 5)
binary = "0" + binary;
int8string += binary;
}
});
let int8array = new Uint8Array(int8string.length / 8);
for (let i = 0; i < int8string.length; i += 8)
int8array[i == 0 ? 0 : i / 8] = parseInt(int8string.slice(i, i + 8), 2);
return (0, utils_1.bytesToHex)(int8array);
}
}
exports.Bech32 = Bech32;
//# sourceMappingURL=bech32.js.map