UNPKG

@alephium/web3-wallet

Version:
158 lines (154 loc) 8.11 kB
"use strict"; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HDWallet = exports.getSchnorrPath = exports.getSecp259K1Path = exports.getHDWalletPath = exports.deriveSchnorrPrivateKeyForGroup = exports.deriveSecp256K1PrivateKeyForGroup = exports.deriveHDWalletPrivateKeyForGroup = exports.deriveSchnorrPrivateKey = exports.deriveSecp256K1PrivateKey = exports.deriveHDWalletPrivateKey = exports.generateMnemonic = void 0; const web3_1 = require("@alephium/web3"); const web3_2 = require("@alephium/web3"); const web3_3 = require("@alephium/web3"); const web3_4 = require("@alephium/web3"); const bip39 = __importStar(require("bip39")); const noble_wrapper_1 = require("./noble-wrapper"); const privatekey_wallet_1 = require("./privatekey-wallet"); function generateMnemonic(wordLength) { return bip39.generateMnemonic(wordLength === 12 ? 128 : 256); } exports.generateMnemonic = generateMnemonic; function deriveHDWalletPrivateKey(mnemonic, keyType, _fromAddressIndex, passphrase) { const seed = bip39.mnemonicToSeedSync(mnemonic, passphrase); const masterKey = noble_wrapper_1.bip32.fromSeed(seed); const fromAddressIndex = _fromAddressIndex ?? 0; const keyPair = masterKey.derivePath(getHDWalletPath(keyType, fromAddressIndex)); if (!keyPair.privateKey) throw new Error('Missing private key'); return keyPair.privateKey.toString('hex'); } exports.deriveHDWalletPrivateKey = deriveHDWalletPrivateKey; function deriveSecp256K1PrivateKey(mnemonic, fromAddressIndex, passphrase) { return deriveHDWalletPrivateKey(mnemonic, 'default', fromAddressIndex, passphrase); } exports.deriveSecp256K1PrivateKey = deriveSecp256K1PrivateKey; function deriveSchnorrPrivateKey(mnemonic, fromAddressIndex, passphrase) { return deriveHDWalletPrivateKey(mnemonic, 'bip340-schnorr', fromAddressIndex, passphrase); } exports.deriveSchnorrPrivateKey = deriveSchnorrPrivateKey; function deriveHDWalletPrivateKeyForGroup(mnemonic, targetGroup, keyType, _fromAddressIndex, passphrase) { if (targetGroup < 0 || targetGroup > web3_4.TOTAL_NUMBER_OF_GROUPS) { throw Error(`Invalid target group for HD wallet derivation: ${targetGroup}`); } const fromAddressIndex = _fromAddressIndex ?? 0; const privateKey = deriveHDWalletPrivateKey(mnemonic, keyType, fromAddressIndex, passphrase); if ((0, web3_4.groupOfPrivateKey)(privateKey, keyType) === targetGroup) { return [privateKey, fromAddressIndex]; } else { return deriveHDWalletPrivateKeyForGroup(mnemonic, targetGroup, keyType, fromAddressIndex + 1, passphrase); } } exports.deriveHDWalletPrivateKeyForGroup = deriveHDWalletPrivateKeyForGroup; function deriveSecp256K1PrivateKeyForGroup(mnemonic, targetGroup, _fromAddressIndex, passphrase) { return deriveHDWalletPrivateKeyForGroup(mnemonic, targetGroup, 'default', _fromAddressIndex, passphrase); } exports.deriveSecp256K1PrivateKeyForGroup = deriveSecp256K1PrivateKeyForGroup; function deriveSchnorrPrivateKeyForGroup(mnemonic, targetGroup, _fromAddressIndex, passphrase) { return deriveHDWalletPrivateKeyForGroup(mnemonic, targetGroup, 'bip340-schnorr', _fromAddressIndex, passphrase); } exports.deriveSchnorrPrivateKeyForGroup = deriveSchnorrPrivateKeyForGroup; function getHDWalletPath(keyType, addressIndex) { if (addressIndex < 0 || !Number.isInteger(addressIndex) || addressIndex.toString().includes('e')) { throw new Error('Invalid address index path level'); } // Being explicit: we always use coinType 1234 no matter the network. const coinType = "1234'"; const keyTypeNum = keyType === 'default' ? 0 : 1; return `m/44'/${coinType}/${keyTypeNum}'/0/${addressIndex}`; } exports.getHDWalletPath = getHDWalletPath; function getSecp259K1Path(addressIndex) { return getHDWalletPath('default', addressIndex); } exports.getSecp259K1Path = getSecp259K1Path; function getSchnorrPath(addressIndex) { return getHDWalletPath('bip340-schnorr', addressIndex); } exports.getSchnorrPath = getSchnorrPath; // In-memory HDWallet for simple use cases. Advanced wallet better used the derivation functions above. class HDWallet extends web3_4.SignerProviderWithCachedAccounts { constructor({ mnemonic, keyType, nodeProvider, explorerProvider, passphrase }) { super(); this.mnemonic = mnemonic; this.keyType = keyType ?? 'default'; this.passphrase = passphrase; this.nodeProvider = nodeProvider ?? web3_4.web3.getCurrentNodeProvider(); this.explorerProvider = explorerProvider ?? web3_4.web3.getCurrentExplorerProvider(); } getNextFromAddressIndex(targetGroup) { let usedAddressIndex = -1; for (const account of this._accounts.values()) { if ((targetGroup === undefined || account.group == targetGroup) && account.addressIndex > usedAddressIndex) { usedAddressIndex = account.addressIndex; } } return usedAddressIndex + 1; } deriveAndAddNewAccount(targetGroup) { const fromAddressIndex = this.getNextFromAddressIndex(targetGroup); let priKey; let addressIndex = fromAddressIndex; if (targetGroup !== undefined) { const [_priKey, _addressIndex] = deriveHDWalletPrivateKeyForGroup(this.mnemonic, targetGroup, this.keyType, fromAddressIndex, this.passphrase); priKey = _priKey; addressIndex = _addressIndex; } else { priKey = deriveHDWalletPrivateKey(this.mnemonic, this.keyType, fromAddressIndex, this.passphrase); } const publicKey = (0, web3_1.publicKeyFromPrivateKey)(priKey, this.keyType); const address = (0, web3_2.addressFromPublicKey)(publicKey, this.keyType); const group = (0, web3_3.groupOfAddress)(address); const account = { keyType: this.keyType, address, group, publicKey, addressIndex }; this._accounts.set(account.address, account); return account; } async signRaw(signerAddress, hexString) { const account = await this.getAccount(signerAddress); const privateKey = deriveHDWalletPrivateKey(this.mnemonic, account.keyType, account.addressIndex, this.passphrase); return privatekey_wallet_1.PrivateKeyWallet.sign(privateKey, hexString, this.keyType); } } exports.HDWallet = HDWallet;