@alephium/web3-wallet
Version:
Simple wallets for Alephium
154 lines • 7.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HDWallet = void 0;
exports.generateMnemonic = generateMnemonic;
exports.deriveHDWalletPrivateKey = deriveHDWalletPrivateKey;
exports.deriveSecp256K1PrivateKey = deriveSecp256K1PrivateKey;
exports.deriveSchnorrPrivateKey = deriveSchnorrPrivateKey;
exports.deriveHDWalletPrivateKeyForGroup = deriveHDWalletPrivateKeyForGroup;
exports.deriveSecp256K1PrivateKeyForGroup = deriveSecp256K1PrivateKeyForGroup;
exports.deriveSchnorrPrivateKeyForGroup = deriveSchnorrPrivateKeyForGroup;
exports.getHDWalletPath = getHDWalletPath;
exports.getSecp259K1Path = getSecp259K1Path;
exports.getSchnorrPath = getSchnorrPath;
exports.getGlSecp256K1Path = getGlSecp256K1Path;
exports.getGlSecp256R1Path = getGlSecp256R1Path;
exports.getGlEd25519Path = getGlEd25519Path;
exports.getGlWebauthnPath = getGlWebauthnPath;
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_1 = require("@scure/bip39");
const english_1 = require("@scure/bip39/wordlists/english");
const bip32_1 = require("@scure/bip32");
const privatekey_wallet_1 = require("./privatekey-wallet");
function generateMnemonic(wordLength) {
return (0, bip39_1.generateMnemonic)(english_1.wordlist, wordLength === 12 ? 128 : 256);
}
function deriveHDWalletPrivateKey(mnemonic, keyType, _fromAddressIndex, passphrase) {
const seed = (0, bip39_1.mnemonicToSeedSync)(mnemonic, passphrase);
const masterKey = bip32_1.HDKey.fromMasterSeed(seed);
const fromAddressIndex = _fromAddressIndex ?? 0;
const child = masterKey.derive(getHDWalletPath(keyType, fromAddressIndex));
if (!child.privateKey)
throw new Error('Missing private key');
return web3_1.utils.binToHex(child.privateKey);
}
function deriveSecp256K1PrivateKey(mnemonic, fromAddressIndex, passphrase) {
return deriveHDWalletPrivateKey(mnemonic, 'default', fromAddressIndex, passphrase);
}
function deriveSchnorrPrivateKey(mnemonic, fromAddressIndex, passphrase) {
return deriveHDWalletPrivateKey(mnemonic, 'bip340-schnorr', fromAddressIndex, passphrase);
}
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);
}
}
function deriveSecp256K1PrivateKeyForGroup(mnemonic, targetGroup, _fromAddressIndex, passphrase) {
return deriveHDWalletPrivateKeyForGroup(mnemonic, targetGroup, 'default', _fromAddressIndex, passphrase);
}
function deriveSchnorrPrivateKeyForGroup(mnemonic, targetGroup, _fromAddressIndex, passphrase) {
return deriveHDWalletPrivateKeyForGroup(mnemonic, targetGroup, 'bip340-schnorr', _fromAddressIndex, passphrase);
}
function getHDWalletPath(keyType, addressIndex) {
if (addressIndex < 0 || !Number.isInteger(addressIndex) || addressIndex.toString().includes('e')) {
throw new Error('Invalid address index path level');
}
const coinType = "1234'";
const keyTypeNum = (() => {
switch (keyType) {
case 'default':
return 0;
case 'bip340-schnorr':
return 1;
case 'gl-secp256k1':
return 2;
case 'gl-secp256r1':
return 3;
case 'gl-ed25519':
return 4;
case 'gl-webauthn':
return 5;
default:
throw new Error(`Unsupported key type: ${keyType}`);
}
})();
return `m/44'/${coinType}/${keyTypeNum}'/0/${addressIndex}`;
}
function getSecp259K1Path(addressIndex) {
return getHDWalletPath('default', addressIndex);
}
function getSchnorrPath(addressIndex) {
return getHDWalletPath('bip340-schnorr', addressIndex);
}
function getGlSecp256K1Path(addressIndex) {
return getHDWalletPath('gl-secp256k1', addressIndex);
}
function getGlSecp256R1Path(addressIndex) {
return getHDWalletPath('gl-secp256r1', addressIndex);
}
function getGlEd25519Path(addressIndex) {
return getHDWalletPath('gl-ed25519', addressIndex);
}
function getGlWebauthnPath(addressIndex) {
return getHDWalletPath('gl-webauthn', addressIndex);
}
class HDWallet extends web3_4.SignerProviderWithCachedAccounts {
constructor({ mnemonic, keyType, nodeProvider, explorerProvider, passphrase }) {
super();
this.mnemonic = mnemonic;
this.keyType = keyType ?? 'default';
if (this.keyType !== 'default' && this.keyType !== 'bip340-schnorr' && this.keyType !== 'gl-secp256k1') {
throw new Error(`Invalid key type ${keyType}`);
}
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()) {
const accountGroup = (0, web3_1.isGroupedAccount)(account) ? account.group : (0, web3_3.groupOfAddress)(account.address);
if ((targetGroup === undefined || accountGroup == 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;
//# sourceMappingURL=hd-wallet.js.map