UNPKG

@bigmi/core

Version:

TypeScript library for Bitcoin apps.

120 lines 3.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getUTXOAddress = exports.UTXOAddressType = exports.UTXONetwork = void 0; const sha256_1 = require("@noble/hashes/sha256"); const bech32_1 = require("bech32"); const bs58_1 = require("bs58"); var UTXONetwork; (function (UTXONetwork) { UTXONetwork["Mainnet"] = "mainnet"; UTXONetwork["Testnet"] = "testnet"; UTXONetwork["Regtest"] = "regtest"; })(UTXONetwork || (exports.UTXONetwork = UTXONetwork = {})); var UTXOAddressType; (function (UTXOAddressType) { UTXOAddressType["p2pkh"] = "p2pkh"; UTXOAddressType["p2sh"] = "p2sh"; UTXOAddressType["p2wpkh"] = "p2wpkh"; UTXOAddressType["p2wsh"] = "p2wsh"; UTXOAddressType["p2tr"] = "p2tr"; })(UTXOAddressType || (exports.UTXOAddressType = UTXOAddressType = {})); const addressTypes = { 0: { type: UTXOAddressType.p2pkh, network: UTXONetwork.Mainnet, }, 111: { type: UTXOAddressType.p2pkh, network: UTXONetwork.Testnet, }, 5: { type: UTXOAddressType.p2sh, network: UTXONetwork.Mainnet, }, 196: { type: UTXOAddressType.p2sh, network: UTXONetwork.Testnet, }, }; const parseBech32 = (address) => { let decoded; try { if (address.startsWith('bc1p') || address.startsWith('tb1p') || address.startsWith('bcrt1p')) { decoded = bech32_1.bech32m.decode(address); } else { decoded = bech32_1.bech32.decode(address); } } catch (_error) { throw new Error('Invalid address'); } const mapPrefixToNetwork = { bc: UTXONetwork.Mainnet, tb: UTXONetwork.Testnet, bcrt: UTXONetwork.Regtest, }; const network = mapPrefixToNetwork[decoded.prefix]; if (network === undefined) { throw new Error('Invalid address'); } const witnessVersion = decoded.words[0]; if (witnessVersion < 0 || witnessVersion > 16) { throw new Error('Invalid address'); } const data = bech32_1.bech32.fromWords(decoded.words.slice(1)); let type; if (data.length === 20) { type = UTXOAddressType.p2wpkh; } else if (witnessVersion === 1) { type = UTXOAddressType.p2tr; } else { type = UTXOAddressType.p2wsh; } return { bech32: true, network, address, type, }; }; const getUTXOAddress = (address) => { let decoded; const prefix = address.substring(0, 2).toLowerCase(); if (prefix === 'bc' || prefix === 'tb') { return parseBech32(address); } try { decoded = bs58_1.default.decode(address); } catch (_error) { throw new Error('Invalid address'); } const { length } = decoded; if (length !== 25) { throw new Error('Invalid address'); } const version = decoded[0]; const checksum = decoded.slice(length - 4, length); const body = decoded.slice(0, length - 4); const expectedChecksum = (0, sha256_1.sha256)((0, sha256_1.sha256)(body)).slice(0, 4); if (checksum.some((value, index) => value !== expectedChecksum[index])) { throw new Error('Invalid address'); } const validVersions = Object.keys(addressTypes).map(Number); if (!validVersions.includes(version)) { throw new Error('Invalid address'); } const addressType = addressTypes[version]; return { ...addressType, address, bech32: false, }; }; exports.getUTXOAddress = getUTXOAddress; //# sourceMappingURL=getUTXOAddress.js.map