Skip to content

Commit

Permalink
feat(account): init AccountMnemonicFactory by seed
Browse files Browse the repository at this point in the history
  • Loading branch information
davidyuk committed Jan 16, 2025
1 parent 995c7b4 commit d254c94
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 9 deletions.
25 changes: 16 additions & 9 deletions src/account/MnemonicFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AccountBaseFactory from './BaseFactory.js';
import AccountMemory from './Memory.js';
import { encode, Encoding, Encoded, decode } from '../utils/encoder.js';
import { concatBuffers } from '../utils/other.js';
import { ArgumentError } from '../utils/errors.js';

export const ED25519_CURVE = Buffer.from('ed25519 seed');
const HARDENED_OFFSET = 0x80000000;
Expand Down Expand Up @@ -41,14 +42,14 @@ interface Wallet {
* A factory class that generates instances of AccountMemory based on provided mnemonic phrase.
*/
export default class AccountMnemonicFactory extends AccountBaseFactory {
#mnemonicOrWallet: string | Wallet;
#mnemonicOrWalletOrSeed: string | Wallet | Uint8Array;

/**
* @param mnemonicOrWallet - BIP39-compatible mnemonic phrase or a wallet derived from mnemonic
* @param mnemonicOrWallet - BIP39-compatible mnemonic phrase or a wallet/seed derived from mnemonic
*/
constructor(mnemonicOrWallet: string | Wallet) {
constructor(mnemonicOrWalletOrSeed: string | Wallet | Uint8Array) {
super();
this.#mnemonicOrWallet = mnemonicOrWallet;
this.#mnemonicOrWalletOrSeed = mnemonicOrWalletOrSeed;
}

#getWallet(sync: true): Wallet;
Expand All @@ -57,17 +58,23 @@ export default class AccountMnemonicFactory extends AccountBaseFactory {
const setWalletBySeed = (seed: Uint8Array): Wallet => {
const masterKey = deriveKey(seed, ED25519_CURVE);
const walletKey = derivePathFromKey(masterKey, [44, 457]);
this.#mnemonicOrWallet = {
this.#mnemonicOrWalletOrSeed = {
secretKey: encode(walletKey.secretKey, Encoding.Bytearray),
chainCode: encode(walletKey.chainCode, Encoding.Bytearray),
};
return this.#mnemonicOrWallet;
return this.#mnemonicOrWalletOrSeed;
};

if (typeof this.#mnemonicOrWallet === 'object') return this.#mnemonicOrWallet;
if (ArrayBuffer.isView(this.#mnemonicOrWalletOrSeed)) {
if (this.#mnemonicOrWalletOrSeed.length !== 64) {
throw new ArgumentError('seed length', 64, this.#mnemonicOrWalletOrSeed.length);
}
return setWalletBySeed(this.#mnemonicOrWalletOrSeed);
}
if (typeof this.#mnemonicOrWalletOrSeed === 'object') return this.#mnemonicOrWalletOrSeed;
return sync
? setWalletBySeed(mnemonicToSeedSync(this.#mnemonicOrWallet))
: mnemonicToSeed(this.#mnemonicOrWallet).then(setWalletBySeed);
? setWalletBySeed(mnemonicToSeedSync(this.#mnemonicOrWalletOrSeed))
: mnemonicToSeed(this.#mnemonicOrWalletOrSeed).then(setWalletBySeed);
}

/**
Expand Down
19 changes: 19 additions & 0 deletions test/unit/mnemonic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { Node, Encoded, AccountMnemonicFactory, MemoryAccount } from '../../src'

const mnemonic = 'eye quarter chapter suit cruel scrub verify stuff volume control learn dust';

const seed = new Uint8Array([
26, 43, 123, 108, 82, 100, 153, 240, 181, 30, 143, 186, 96, 84, 133, 187, 20, 179, 152, 54, 114,
118, 104, 243, 147, 193, 110, 110, 179, 195, 207, 131, 230, 174, 67, 145, 148, 16, 229, 126, 115,
211, 147, 77, 150, 171, 211, 227, 217, 151, 80, 229, 196, 192, 209, 44, 71, 40, 106, 234, 223, 20,
163, 59,
]);

const wallet = {
secretKey: 'ba_I1lro/ANfEKuBUal0Glo++D5abkcFLIIihTDLcC8l3My1PuP',
chainCode: 'ba_XZL45EKIQiLe9v/pkY37Bn3GiqLXZ5v2hIya6llA0QOlYf6i',
Expand All @@ -15,6 +22,11 @@ describe('Account mnemonic factory', () => {
expect(await factory.getWallet()).to.be.eql(wallet);
});

it('derives wallet by seed', async () => {
const factory = new AccountMnemonicFactory(seed);
expect(await factory.getWallet()).to.be.eql(wallet);
});

it('derives wallet by wallet', async () => {
const factory = new AccountMnemonicFactory(wallet);
expect(await factory.getWallet()).to.be.eql(wallet);
Expand All @@ -32,6 +44,13 @@ describe('Account mnemonic factory', () => {
expect(account.address).to.be.equal('ak_2HteeujaJzutKeFZiAmYTzcagSoRErSXpBFV179xYgqT4teakv');
});

it('initializes an account by seed', async () => {
const factory = new AccountMnemonicFactory(seed);
const account = await factory.initialize(42);
expect(account).to.be.instanceOf(MemoryAccount);
expect(account.address).to.be.equal('ak_2HteeujaJzutKeFZiAmYTzcagSoRErSXpBFV179xYgqT4teakv');
});

it('initializes an account by wallet', async () => {
const factory = new AccountMnemonicFactory(wallet);
const account = await factory.initialize(42);
Expand Down

0 comments on commit d254c94

Please sign in to comment.