@roochnetwork/rooch-sdk
Version:
242 lines (241 loc) • 9.07 kB
JavaScript
;
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