UNPKG

@roochnetwork/rooch-sdk

Version:
242 lines (241 loc) 9.07 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var bitcoin_exports = {}; __export(bitcoin_exports, { BitcoinAddress: () => BitcoinAddress, BitcoinNetowkType: () => BitcoinNetowkType, BitcoinNetwork: () => BitcoinNetwork }); module.exports = __toCommonJS(bitcoin_exports); var import_base = require("@scure/base"); var import_bcs = require("../bcs/index.js"); var import_types = require("../types/index.js"); var import_utils = require("../utils/index.js"); var import_address = require("./address.js"); var import_rooch = require("./rooch.js"); var import_types2 = require("./types.js"); var import_thirdparty_address = require("./thirdparty-address.js"); var import_buffer = require("buffer"); var import_bs58check = __toESM(require("bs58check"), 1); var import_secp256k1 = require("@noble/curves/secp256k1"); var BitcoinNetowkType = /* @__PURE__ */ ((BitcoinNetowkType2) => { BitcoinNetowkType2[BitcoinNetowkType2["Bitcoin"] = 0] = "Bitcoin"; BitcoinNetowkType2[BitcoinNetowkType2["Testnet"] = 1] = "Testnet"; BitcoinNetowkType2[BitcoinNetowkType2["Signet"] = 2] = "Signet"; BitcoinNetowkType2[BitcoinNetowkType2["Regtest"] = 3] = "Regtest"; return BitcoinNetowkType2; })(BitcoinNetowkType || {}); var BitcoinAddressType = /* @__PURE__ */ ((BitcoinAddressType2) => { BitcoinAddressType2[BitcoinAddressType2["pkh"] = 0] = "pkh"; BitcoinAddressType2[BitcoinAddressType2["sh"] = 1] = "sh"; BitcoinAddressType2[BitcoinAddressType2["witness"] = 2] = "witness"; return BitcoinAddressType2; })(BitcoinAddressType || {}); const PUBKEY_ADDRESS_PREFIX_MAIN = 0; const PUBKEY_ADDRESS_PREFIX_TEST = 111; const SCRIPT_ADDRESS_PREFIX_MAIN = 5; const SCRIPT_ADDRESS_PREFIX_TEST = 196; class BitcoinNetwork { constructor(network) { this.network = network ?? 0 /* Bitcoin */; } static fromBech32Prefix(prefix) { switch (prefix) { case "bc": return new BitcoinNetwork(0 /* Bitcoin */); case "tb": return new BitcoinNetwork(1 /* Testnet */); case "bcrt": return new BitcoinNetwork(3 /* Regtest */); default: return void 0; } } bech32HRP() { switch (this.network) { case 0 /* Bitcoin */: return "bc"; case 1 /* Testnet */: return "tb"; case 2 /* Signet */: return "tb"; case 3 /* Regtest */: return "bcrt"; } } } class BitcoinAddress extends import_thirdparty_address.ThirdPartyAddress { constructor(input, network) { super(input); if ((0, import_utils.isHex)(input)) { this.bytes = (0, import_utils.bytes)("hex", input.startsWith("0x") ? input.slice(2) : input); let prefixed; let version = this.bytes[1]; switch (this.bytes[0]) { case 0 /* pkh */: prefixed = new Uint8Array(22); prefixed[0] = version; prefixed[1] = this.getPubkeyAddressPrefix(network); prefixed.set(this.bytes.slice(2)); this.rawAddress = import_bs58check.default.encode(prefixed); break; case 1 /* sh */: prefixed = new Uint8Array(22); prefixed[0] = version; prefixed[1] = this.getScriptAddressPrefix(network); prefixed.set(this.bytes.slice(2)); this.rawAddress = import_bs58check.default.encode(prefixed); break; case 2 /* witness */: const hrp = new BitcoinNetwork(network).bech32HRP(); const words = import_base.bech32.toWords(import_buffer.Buffer.from(this.bytes.slice(2))); words.unshift(version); this.rawAddress = version === 0 ? import_base.bech32.encode(hrp, words, false) : import_base.bech32m.encode(hrp, words, false); } } else { let info = this.decode(); this.bytes = this.wrapAddress(info.type, info.bytes, info.version); } } static fromPublicKey(publicKey, network = 3 /* Regtest */) { const tapTweak = (a, b) => { const u2 = import_secp256k1.schnorr.utils; const t2 = u2.taggedHash("TapTweak", a, b); const tn = u2.bytesToNumberBE(t2); if (tn >= import_secp256k1.secp256k1.CURVE.n) throw new Error("tweak higher than curve order"); return tn; }; const u = import_secp256k1.schnorr.utils; const t = tapTweak(publicKey, import_types.EmptyBytes); const P = u.lift_x(u.bytesToNumberBE(publicKey)); const Q = P.add(import_secp256k1.secp256k1.ProjectivePoint.fromPrivateKey(t)); const tweakedPubkey = u.pointToBytes(Q); return new BitcoinAddress( import_base.bech32m.encode( new BitcoinNetwork(network).bech32HRP(), [1].concat(import_base.bech32m.toWords(tweakedPubkey)), false ) ); } getPubkeyAddressPrefix(network = 0 /* Bitcoin */) { return network === 0 /* Bitcoin */ ? PUBKEY_ADDRESS_PREFIX_MAIN : PUBKEY_ADDRESS_PREFIX_TEST; } getScriptAddressPrefix(network = 0 /* Bitcoin */) { return network === 0 /* Bitcoin */ ? SCRIPT_ADDRESS_PREFIX_MAIN : SCRIPT_ADDRESS_PREFIX_TEST; } toBytes() { return (0, import_utils.bytes)("utf8", this.rawAddress); } genMultiChainAddress() { return import_bcs.bcs.MultiChainAddress.serialize({ multiChainId: import_types2.MultiChainID.Bitcoin, rawAddress: this.bytes }).toBytes(); } genRoochAddress() { if (!this.roochAddress) { this.roochAddress = new import_rooch.RoochAddress((0, import_utils.blake2b)(this.bytes, { dkLen: import_address.ROOCH_ADDRESS_LENGTH })); } return this.roochAddress; } decode() { let input = this.rawAddress; if (input.length < 14 || input.length > 74) throw new Error("Invalid address length"); const bech32_network = (() => { const sep = input.lastIndexOf("1"); const bech32Prefix = sep === -1 ? input : input.substring(0, sep); return BitcoinNetwork.fromBech32Prefix(bech32Prefix); })(); if (bech32_network !== void 0) { let res; try { res = import_base.bech32.decode(input); if (res.words[0] !== 0) throw new Error(`bech32: wrong version=${res.words[0]}`); } catch (_) { res = import_base.bech32m.decode(input); if (res.words[0] === 0) throw new Error(`bech32m: wrong version=${res.words[0]}`); } const [version, ...program] = res.words; const data2 = import_base.bech32.fromWords(program); (0, import_utils.validateWitness)(version, data2); if (version === 0 && data2.length === 32) return { bytes: data2, type: 2 /* witness */, //wsh version }; else if (version === 0 && data2.length === 20) return { bytes: data2, type: 2 /* witness */, //wpkh version }; else if (version === 1 && data2.length === 32) return { bytes: data2, type: 2 /* witness */, //tr version }; else throw new Error("Unknown witness program"); } const data = import_bs58check.default.decode(input); if (data.length !== 21) throw new Error("Invalid base58 address"); if (data[0] === 0) { return { bytes: data.slice(1), type: 0 /* pkh */ }; } else if (data[0] === 5) { return { bytes: data.slice(1), type: 1 /* sh */ }; } throw new Error(`Invalid address prefix=${data[0]}`); } wrapAddress(type, bytes2, version) { const addr = new Uint8Array(bytes2.length + 1 + (version !== void 0 ? 1 : 0)); addr.set([type]); if (version !== void 0) { addr.set([version], 1); addr.set(bytes2, 2); } else { addr.set(bytes2, 1); } return addr; } } //# sourceMappingURL=bitcoin.js.map