All files / src/wallet-sdk/wallet generate.ts

93.75% Statements 15/16
75% Branches 3/4
100% Functions 3/3
93.75% Lines 15/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 581x 1x 1x 1x   1x 1x 1x                           1x 4x           4x               1x 1x       1x 1x                 1x            
import { generateMnemonic, mnemonicToSeed } from '@scure/bip39';
import { HDKey } from '@scure/bip32';
import { wordlist } from '@scure/bip39/wordlists/english';
import { bytesToHex } from 'micro-stacks/common';
 
import { deriveWalletKeys } from './derive';
import { encryptMnemonic } from '../encryption/encrypt-mnemonic';
import { deriveNextAccountFromWallet } from '../account/derive-account';
 
import type { AllowedKeyEntropyBits, Wallet } from '../types';
 
/**
 * Generates a bip39 mnemonic phrase of 24 or 12 word length.
 *
 * This function is basically a type guard wrapper for
 * `generateMnemonic` from `micro-stacks/bip39`
 * to enforce either 256 or 128 bits of entropy.
 *
 * @param entropy {AllowedKeyEntropyBits} - 256 (24 words) or 128 (12 words)
 * @return mnemonic - 24 or 12 word mnemonic phrase
 */
export function generateSecretKey(entropy: AllowedKeyEntropyBits = 256): string {
  Iif (entropy !== 256 && entropy !== 128)
    throw TypeError(
      `Incorrect entropy bits provided, expected 256 or 128 (24 or 12 word results), got: "${String(
        entropy
      )}".`
    );
  return generateMnemonic(wordlist, entropy);
}
 
/**
 * Generate a new [[Wallet]].
 * @param mnemonic A 12 or 24 word mnemonic phrase. Must be a valid bip39 mnemonic.
 * @param password A password used to encrypt the wallet
 */
export async function generateWallet(mnemonic: string, password: string): Promise<Wallet> {
  const [seed, encryptedBytes] = await Promise.all([
    mnemonicToSeed(mnemonic),
    encryptMnemonic(mnemonic, password),
  ]);
  const encryptedSecretKey = bytesToHex(encryptedBytes);
  const walletKeys = deriveWalletKeys(HDKey.fromMasterSeed(seed));
 
  return generateAndInsertNewAccount({
    ...walletKeys,
    encryptedSecretKey,
    accounts: [],
  });
}
 
export function generateAndInsertNewAccount(wallet: Wallet): Wallet {
  return {
    ...wallet,
    accounts: [...wallet.accounts, deriveNextAccountFromWallet(wallet)],
  };
}