@roochnetwork/rooch-sdk
Version:
183 lines (182 loc) • 6.77 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var keypair_exports = {};
__export(keypair_exports, {
DEFAULT_SECP256K1_DERIVATION_PATH: () => DEFAULT_SECP256K1_DERIVATION_PATH,
Secp256k1Keypair: () => Secp256k1Keypair
});
module.exports = __toCommonJS(keypair_exports);
var import_bip32 = require("@scure/bip32");
var import_bip39 = require("@scure/bip39");
var import_english = require("@scure/bip39/wordlists/english");
var import_secp256k1 = require("@noble/curves/secp256k1");
var import_crypto = require("../../crypto/index.js");
var import_utils = require("../../utils/index.js");
var import_publickey = require("./publickey.js");
const DEFAULT_SECP256K1_DERIVATION_PATH = "m/86'/0'/0'/0/1";
class Secp256k1Keypair extends import_crypto.Keypair {
/**
* Create a new keypair instance.
* Generate random keypair if no {@link Secp256k1Keypair} is provided.
*
* @param keypair secp256k1 keypair
*/
constructor(keypair) {
super();
if (keypair) {
this.keypair = keypair;
} else {
const secretKey = import_secp256k1.secp256k1.utils.randomPrivateKey();
const publicKey = import_secp256k1.secp256k1.getPublicKey(secretKey, true);
this.keypair = { publicKey, secretKey };
}
}
getBitcoinAddress() {
return this.getSchnorrPublicKey().toAddress().bitcoinAddress;
}
getBitcoinAddressWith(network) {
return this.getSchnorrPublicKey().toAddressWith(network).bitcoinAddress;
}
getRoochAddress() {
return this.getSchnorrPublicKey().toAddress().roochAddress;
}
/**
* Get the key scheme of the keypair Secp256k1
*/
getKeyScheme() {
return "Secp256k1";
}
/**
* Generate a new random keypair
*/
static generate() {
return new Secp256k1Keypair();
}
/**
* Create a keypair from a raw secret key byte array.
*
* This method should only be used to recreate a keypair from a previously
* generated secret key. Generating keypairs from a random seed should be done
* with the {@link Keypair.fromSeed} method.
*
* @throws error if the provided secret key is invalid and validation is not skipped.
*
* @param secretKey secret key byte array
* @param skipValidation skip secret key validation
*/
static fromSecretKey(secretKey, skipValidation) {
const decodeSecretKey = typeof secretKey === "string" ? (() => {
const decoded = (0, import_crypto.decodeRoochSercetKey)(secretKey);
if (decoded.schema !== "Secp256k1") {
throw new Error("provided secretKey is invalid");
}
return decoded.secretKey;
})() : secretKey;
const publicKey = import_secp256k1.secp256k1.getPublicKey(decodeSecretKey, true);
if (!skipValidation) {
const encoder = new TextEncoder();
const signData = encoder.encode("rooch validation");
const msgHash = (0, import_utils.toHEX)((0, import_utils.blake2b)(signData, { dkLen: 32 }));
const signature = import_secp256k1.secp256k1.sign(msgHash, decodeSecretKey);
if (!import_secp256k1.secp256k1.verify(signature, msgHash, publicKey, { lowS: true })) {
throw new Error("Provided secretKey is invalid");
}
}
return new Secp256k1Keypair({ publicKey, secretKey: decodeSecretKey });
}
/**
* Generate a keypair from a 32 byte seed.
*
* @param seed seed byte array
*/
static fromSeed(seed) {
let publicKey = import_secp256k1.secp256k1.getPublicKey(seed, true);
return new Secp256k1Keypair({ publicKey, secretKey: seed });
}
/**
* The public key for this keypair
*/
getPublicKey() {
return new import_publickey.Secp256k1PublicKey(this.keypair.publicKey);
}
getSchnorrPublicKey() {
return new import_publickey.Secp256k1PublicKey(import_secp256k1.schnorr.getPublicKey(this.keypair.secretKey));
}
/**
* The Bech32 secret key string for this Secp256k1 keypair
*/
getSecretKey() {
return (0, import_crypto.encodeRoochSercetKey)(this.keypair.secretKey, this.getKeyScheme());
}
/**
* Return the ecdsa signature for the provided data.
*/
async sign(input) {
const msgHash = (0, import_utils.sha256)(input);
const sig = import_secp256k1.secp256k1.sign(msgHash, this.keypair.secretKey, {
lowS: true
});
return sig.toCompactRawBytes();
}
/**
* Return the schnorr signature for the provided data.
*/
async sign_schnorr(input, auxRand) {
const sig = import_secp256k1.schnorr.sign(input, this.keypair.secretKey, auxRand);
return sig;
}
async signTransaction(input) {
return await import_crypto.Authenticator.bitcoin(
new import_crypto.BitcoinSignMessage(input.hashData(), input.getInfo() ?? "sdk"),
this
);
}
/**
* Derive Secp256k1 keypair from mnemonics and path. The mnemonics must be normalized
* and validated against the english wordlist.
*
* If path is none, it will default to m/86'/0'/0'/0/1, otherwise the path must
* be compliant to BIP-32 in form m/86'/0'/{account_index}'/{change_index}/{address_index}.
*/
static deriveKeypair(mnemonics, path) {
if (path == null) {
path = DEFAULT_SECP256K1_DERIVATION_PATH;
}
if (!(0, import_crypto.isValidBIP86Path)(path)) {
throw new Error("Invalid derivation path");
}
const key = import_bip32.HDKey.fromMasterSeed((0, import_crypto.mnemonicToSeed)(mnemonics)).derive(path);
if (key.publicKey == null || key.privateKey == null) {
throw new Error("Invalid key");
}
return Secp256k1Keypair.fromSecretKey(key.privateKey);
}
/**
* Generate a new mnemonic and derive a keypair from it.
*
* @param path Optional derivation path. If not provided, will use DEFAULT_SECP256K1_DERIVATION_PATH
* @returns An object containing the mnemonic and the derived keypair
*/
static generateWithMnemonic(path) {
const mnemonic = (0, import_bip39.generateMnemonic)(import_english.wordlist);
const keypair = this.deriveKeypair(mnemonic, path);
return { mnemonic, keypair };
}
}
//# sourceMappingURL=keypair.js.map