@trezor/utxo-lib
Version:
Client-side Bitcoin-like JavaScript library
174 lines • 5.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.fromBase58Check = fromBase58Check;
exports.fromBech32 = fromBech32;
exports.toBech32 = toBech32;
exports.fromOutputScript = fromOutputScript;
exports.getAddressType = getAddressType;
exports.toOutputScript = toOutputScript;
const tslib_1 = require("tslib");
const bech32_1 = require("bech32");
const bs58check = tslib_1.__importStar(require("./bs58check"));
const networks_1 = require("./networks");
const payments = tslib_1.__importStar(require("./payments"));
const bscript = tslib_1.__importStar(require("./script"));
function fromBase58Check(address, network = networks_1.bitcoin) {
return bs58check.decodeAddress(address, network);
}
function fromBech32(address) {
let result;
let version;
try {
result = bech32_1.bech32.decode(address);
}
catch {
}
if (result) {
[version] = result.words;
if (version !== 0)
throw new TypeError(`${address} uses wrong encoding`);
}
else {
result = bech32_1.bech32m.decode(address);
[version] = result.words;
if (version === 0)
throw new TypeError(`${address} uses wrong encoding`);
}
const data = bech32_1.bech32.fromWords(result.words.slice(1));
return {
version,
prefix: result.prefix,
data: Buffer.from(data),
};
}
function toBech32(data, version, prefix) {
const words = bech32_1.bech32.toWords(data);
words.unshift(version);
return version === 0 ? bech32_1.bech32.encode(prefix, words) : bech32_1.bech32m.encode(prefix, words);
}
const FUTURE_SEGWIT_MAX_SIZE = 40;
const FUTURE_SEGWIT_MIN_SIZE = 2;
const FUTURE_SEGWIT_MAX_VERSION = 16;
const FUTURE_SEGWIT_MIN_VERSION = 1;
const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
function toFutureSegwitAddress(output, network = networks_1.bitcoin) {
const data = output.subarray(2);
if (data.length < FUTURE_SEGWIT_MIN_SIZE || data.length > FUTURE_SEGWIT_MAX_SIZE)
throw new TypeError('Invalid program length for segwit address');
const version = output[0] - FUTURE_SEGWIT_VERSION_DIFF;
if (version < FUTURE_SEGWIT_MIN_VERSION || version > FUTURE_SEGWIT_MAX_VERSION)
throw new TypeError('Invalid version for segwit address');
if (output[1] !== data.length)
throw new TypeError('Invalid script for segwit address');
return toBech32(data, version, network.bech32);
}
function fromOutputScript(output, network = networks_1.bitcoin) {
try {
return payments.p2pkh({ output, network }).address;
}
catch {
}
try {
return payments.p2sh({ output, network }).address;
}
catch {
}
try {
return payments.p2wpkh({ output, network }).address;
}
catch {
}
try {
return payments.p2wsh({ output, network }).address;
}
catch {
}
try {
return payments.p2tr({ output, network }).address;
}
catch {
}
try {
return toFutureSegwitAddress(output, network);
}
catch {
}
throw new Error(`${bscript.toASM(output)} has no matching Address`);
}
function decodeAddress(address, network) {
try {
const { hash, version } = fromBase58Check(address, network);
return { success: true, format: 'base58', version, hash };
}
catch {
try {
const { data, prefix, version } = fromBech32(address);
if (prefix === network.bech32) {
return { success: true, format: 'bech32', version, hash: data };
}
return { success: false, error: 'bech32-invalid-prefix' };
}
catch {
}
}
return { success: false, error: 'unknown-format' };
}
function identifyAddressType(format, version, hash, network) {
if (format === 'base58') {
if (version === network.pubKeyHash)
return 'p2pkh';
if (version === network.scriptHash)
return 'p2sh';
}
else if (format === 'bech32') {
if (version === 0) {
if (hash.length === 20)
return 'p2wpkh';
if (hash.length === 32)
return 'p2wsh';
}
else if (version === 1 && hash.length === 32) {
return 'p2tr';
}
else if (version >= FUTURE_SEGWIT_MIN_VERSION &&
version <= FUTURE_SEGWIT_MAX_VERSION &&
hash.length >= FUTURE_SEGWIT_MIN_SIZE &&
hash.length <= FUTURE_SEGWIT_MAX_SIZE) {
return 'p2w-unknown';
}
}
return 'unknown';
}
function createOutputScript(type, hash, version) {
switch (type) {
case 'p2pkh':
return payments.p2pkh({ hash }).output;
case 'p2sh':
return payments.p2sh({ hash }).output;
case 'p2wpkh':
return payments.p2wpkh({ hash }).output;
case 'p2wsh':
return payments.p2wsh({ hash }).output;
case 'p2tr':
case 'p2w-unknown':
return bscript.compile([version + FUTURE_SEGWIT_VERSION_DIFF, hash]);
}
}
function getAddressType(address, network = networks_1.bitcoin) {
const { success, format, version, hash } = decodeAddress(address, network);
return success ? identifyAddressType(format, version, hash, network) : 'unknown';
}
function toOutputScript(address, network = networks_1.bitcoin) {
const { success, format, version, hash, error } = decodeAddress(address, network);
if (success) {
const type = identifyAddressType(format, version, hash, network);
if (type !== 'unknown') {
return createOutputScript(type, hash, version);
}
}
else if (error === 'bech32-invalid-prefix') {
throw new Error(`${address} has an invalid prefix`);
}
throw new Error(`${address} has no matching Script`);
}
//# sourceMappingURL=address.js.map