UNPKG

bitverse-atomicals-js

Version:

Atomicals Javascript Library and CLI - atomicals.xyz

322 lines (321 loc) 12.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.detectAddressTypeToScripthash2 = exports.getNetwork = exports.utxoToInput = exports.getAddressType = exports.AddressTypeString = exports.GetUtxoPartialFromLocation = exports.IsAtomicalOwnedByWalletRecord = exports.performAddressAliasReplacement = exports.hash160HexToAddress = exports.hash160BufToAddress = exports.addressToHash160 = exports.addressToP2PKH = exports.addressToScripthash = exports.detectScriptToAddressType = exports.detectAddressTypeToScripthash = void 0; const bs58check = require("bs58check"); const js_sha256_1 = require("js-sha256"); const ecc = require("tiny-secp256k1"); const command_helpers_1 = require("../commands/command-helpers"); const bitcoin = require('bitcoinjs-lib'); bitcoin.initEccLib(ecc); const dotenv = require("dotenv"); const create_key_pair_1 = require("./create-key-pair"); dotenv.config(); function detectAddressTypeToScripthash(address) { // Detect legacy address try { bitcoin.address.fromBase58Check(address, command_helpers_1.NETWORK); const p2pkh = addressToP2PKH(address); const p2pkhBuf = Buffer.from(p2pkh, "hex"); return { output: p2pkh, scripthash: Buffer.from((0, js_sha256_1.sha256)(p2pkhBuf), "hex").reverse().toString("hex"), address }; } catch (err) { } // Detect segwit or taproot // const detected = bitcoin.address.fromBech32(address); if (address.indexOf('bc1p') === 0) { const output = bitcoin.address.toOutputScript(address, command_helpers_1.NETWORK); return { output, scripthash: Buffer.from((0, js_sha256_1.sha256)(output), "hex").reverse().toString("hex"), address }; } else if (address.indexOf('bc1') === 0) { const output = bitcoin.address.toOutputScript(address, command_helpers_1.NETWORK); return { output, scripthash: Buffer.from((0, js_sha256_1.sha256)(output), "hex").reverse().toString("hex"), address }; } else if (address.indexOf('tb1') === 0) { const output = bitcoin.address.toOutputScript(address, command_helpers_1.NETWORK); return { output, scripthash: Buffer.from((0, js_sha256_1.sha256)(output), "hex").reverse().toString("hex"), address }; } else if (address.indexOf('bcrt1p') === 0) { const output = bitcoin.address.toOutputScript(address, command_helpers_1.NETWORK); return { output, scripthash: Buffer.from((0, js_sha256_1.sha256)(output), "hex").reverse().toString("hex"), address }; } else { throw "unrecognized address"; } } exports.detectAddressTypeToScripthash = detectAddressTypeToScripthash; function detectScriptToAddressType(script) { const address = bitcoin.address.fromOutputScript(Buffer.from(script, 'hex'), command_helpers_1.NETWORK); return address; } exports.detectScriptToAddressType = detectScriptToAddressType; function addressToScripthash(address) { const p2pkh = addressToP2PKH(address); const p2pkhBuf = Buffer.from(p2pkh, "hex"); return Buffer.from((0, js_sha256_1.sha256)(p2pkhBuf), "hex").reverse().toString("hex"); } exports.addressToScripthash = addressToScripthash; function addressToP2PKH(address) { const addressDecoded = bs58check.decode(address); const addressDecodedSub = addressDecoded.toString().substr(2); const p2pkh = `76a914${addressDecodedSub}88ac`; return p2pkh; } exports.addressToP2PKH = addressToP2PKH; function addressToHash160(address) { const addressDecoded = bs58check.decode(address); const addressDecodedSub = addressDecoded.toString().substr(2); return addressDecodedSub; } exports.addressToHash160 = addressToHash160; function hash160BufToAddress(hash160) { const addressEncoded = bs58check.encode(hash160); return addressEncoded; } exports.hash160BufToAddress = hash160BufToAddress; function hash160HexToAddress(hash160) { const addressEncoded = bs58check.encode(Buffer.from(hash160, "hex")); return addressEncoded; } exports.hash160HexToAddress = hash160HexToAddress; function performAddressAliasReplacement(walletInfo, address) { let addressToReturn; if (address === 'primary') { addressToReturn = walletInfo.primary.address; } else if (address === 'funding') { addressToReturn = walletInfo.funding.address; } else if (walletInfo.imported && walletInfo.imported[address]) { addressToReturn = walletInfo.imported[address].address; } else { addressToReturn = address; } if (!addressToReturn) { return addressToReturn; } return detectAddressTypeToScripthash(addressToReturn); } exports.performAddressAliasReplacement = performAddressAliasReplacement; /** * Whether the atomical for the mint is owned by the provided wallet or not * @param ownerRecord The proposed wallet that owns the atomical * @param atomical * @returns */ function IsAtomicalOwnedByWalletRecord(address, atomical) { if (!atomical.location_info_obj) { console.log(atomical); throw new Error('Error: location_info_obj not found'); } const locationInfo = atomical.location_info_obj; const currentLocation = locationInfo.locations[0] || {}; return GetUtxoPartialFromLocation(address, currentLocation, false); } exports.IsAtomicalOwnedByWalletRecord = IsAtomicalOwnedByWalletRecord; function GetUtxoPartialFromLocation(addressToCheck, location, throwOnMismatch = true) { if (!location) { throw new Error('Error: location not found'); } // Just in case populate the address on locationInfo if it was not set // It can be deduced from the script field let detectedAddress; try { detectedAddress = detectScriptToAddressType(location.script); } catch (err) { throw new Error('Error: invalid script address'); } location.address = detectedAddress; if (addressToCheck !== location.address) { if (throwOnMismatch) { throw new Error('location_info not match expected address. expectedAddress=' + addressToCheck + ', foundAddress=' + location.address); } return null; } return { hash: location.txid, index: Number(location.index), address: detectedAddress, witnessUtxo: { value: Number(location.value), script: Buffer.from(location.script, 'hex') } }; } exports.GetUtxoPartialFromLocation = GetUtxoPartialFromLocation; var AddressTypeString; (function (AddressTypeString) { AddressTypeString["p2pkh"] = "p2pkh"; AddressTypeString["p2tr"] = "p2tr"; AddressTypeString["p2sh"] = "p2sh"; AddressTypeString["p2wpkh"] = "p2wpkh"; AddressTypeString["p2wpkh_testnet"] = "p2wpkh_testnet"; AddressTypeString["p2tr_testnet"] = "p2tr_testnet"; AddressTypeString["p2sh_testnet"] = "p2sh_testnet"; AddressTypeString["p2pkh_testnet"] = "p2pkh_testnet"; AddressTypeString["p2tr_regtest"] = "p2tr_regtest"; AddressTypeString["unknown"] = "unknown"; })(AddressTypeString = exports.AddressTypeString || (exports.AddressTypeString = {})); function getAddressType(address) { if (address.startsWith('bc1q')) { return AddressTypeString.p2wpkh; } else if (address.startsWith('bc1p')) { return AddressTypeString.p2tr; } else if (address.startsWith('1')) { return AddressTypeString.p2pkh; } else if (address.startsWith('3')) { return AddressTypeString.p2sh; } else if (address.startsWith('tb1q')) { return AddressTypeString.p2wpkh_testnet; } else if (address.startsWith('m')) { return AddressTypeString.p2pkh_testnet; } else if (address.startsWith('2')) { return AddressTypeString.p2sh_testnet; } else if (address.startsWith('tb1p')) { return AddressTypeString.p2tr_testnet; } else if (address.startsWith('bcrt1p')) { return AddressTypeString.p2tr_regtest; } else { return AddressTypeString.unknown; } } exports.getAddressType = getAddressType; function utxoToInput(utxo, address, publicKey, option) { var _a, _b, _c, _d; const addressType = getAddressType(address); let script; if (option.override.script !== undefined) { script = Buffer.isBuffer(option.override.script) ? option.override.script : Buffer.from(option.override.script, 'hex'); } else { script = utxo.script ? Buffer.from(utxo.script, 'hex') : undefined; } switch (addressType) { case AddressTypeString.p2pkh || AddressTypeString.p2pkh_testnet: { const { output } = detectAddressTypeToScripthash(address); // have transform script to scripthash, use witnessScript return { hash: utxo.txid, index: (_a = option.override.vout) !== null && _a !== void 0 ? _a : utxo.vout, witnessUtxo: { value: utxo.value, script: Buffer.from(output, 'hex'), }, }; } case AddressTypeString.p2sh || AddressTypeString.p2sh_testnet: { const redeemData = bitcoin.payments.p2wpkh({ pubkey: Buffer.from(publicKey, 'hex') }); return { hash: utxo.txid, index: (_b = option.override.vout) !== null && _b !== void 0 ? _b : utxo.vout, witnessUtxo: { value: utxo.value, script, }, redeemScript: redeemData.output, }; } case AddressTypeString.p2wpkh || AddressTypeString.p2wpkh_testnet: { return { hash: utxo.txid, index: (_c = option.override.vout) !== null && _c !== void 0 ? _c : utxo.vout, witnessUtxo: { value: utxo.value, script, }, }; } case AddressTypeString.p2tr || AddressTypeString.p2tr_testnet || AddressTypeString.p2tr_regtest: { return { hash: utxo.txid, index: (_d = option.override.vout) !== null && _d !== void 0 ? _d : utxo.vout, witnessUtxo: { value: utxo.value, script, }, tapInternalKey: (0, create_key_pair_1.toXOnly)(Buffer.from(publicKey, 'hex')), }; } } } exports.utxoToInput = utxoToInput; function getNetwork(network) { if (typeof network === 'string') { if (network === 'testnet') { return bitcoin.networks.testnet; } else { return bitcoin.networks.bitcoin; } } else { return network; } } exports.getNetwork = getNetwork; function detectAddressTypeToScripthash2(address, network) { const _network = getNetwork(network); // Detect legacy address try { bitcoin.address.fromBase58Check(address); } catch (err) { /* empty */ } const addressType = getAddressType(address); switch (addressType) { case AddressTypeString.p2pkh: { const p2pkh = addressToP2PKH(address); const p2pkhBuf = Buffer.from(p2pkh, 'hex'); return { output: p2pkh, scripthash: Buffer.from((0, js_sha256_1.sha256)(p2pkhBuf), 'hex').reverse().toString('hex'), address, }; } case AddressTypeString.unknown: { throw 'unrecognized address'; } default: { const output = bitcoin.address.toOutputScript(address, _network); return { output, scripthash: Buffer.from((0, js_sha256_1.sha256)(output), 'hex').reverse().toString('hex'), address, }; } } } exports.detectAddressTypeToScripthash2 = detectAddressTypeToScripthash2;