357 lines
9.0 KiB
TypeScript
357 lines
9.0 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { Bytes } from '../src/bytes';
|
|
import { Mnemonic, MnemonicRaw } from '../src/mnemonic';
|
|
|
|
describe('Success cases', () => {
|
|
// Simple array of cases
|
|
const testCases: Array<{
|
|
fromPhrase: string;
|
|
fromWords: Array<string>;
|
|
passphrase?: string;
|
|
raw: MnemonicRaw;
|
|
toEntropy: Uint8Array;
|
|
toSeed: Uint8Array;
|
|
toPhrase: string;
|
|
toPhraseWithoutPassphrase: string;
|
|
toWords: Array<string>;
|
|
toWordsWithoutPassphrase: Array<string>;
|
|
}> = [
|
|
// No pass-phrase
|
|
{
|
|
fromPhrase:
|
|
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
|
|
fromWords: [
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'about',
|
|
],
|
|
raw: {
|
|
words: [
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'about',
|
|
],
|
|
},
|
|
toEntropy: Bytes.fromHex(
|
|
'00000000000000000000000000000000',
|
|
).toUint8Array(),
|
|
toSeed: Bytes.fromHex(
|
|
'5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4',
|
|
).toUint8Array(),
|
|
toPhrase:
|
|
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
|
|
toPhraseWithoutPassphrase:
|
|
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
|
|
toWords: [
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'about',
|
|
],
|
|
toWordsWithoutPassphrase: [
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'about',
|
|
],
|
|
},
|
|
// Passphrase
|
|
{
|
|
fromPhrase:
|
|
'legal winner thank year wave sausage worth useful legal winner thank yellow Libauth',
|
|
fromWords: [
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'year',
|
|
'wave',
|
|
'sausage',
|
|
'worth',
|
|
'useful',
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'yellow',
|
|
'Libauth',
|
|
],
|
|
passphrase: 'Libauth',
|
|
raw: {
|
|
words: [
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'year',
|
|
'wave',
|
|
'sausage',
|
|
'worth',
|
|
'useful',
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'yellow',
|
|
],
|
|
passphrase: 'Libauth',
|
|
},
|
|
toEntropy: Bytes.fromHex(
|
|
'7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f',
|
|
).toUint8Array(),
|
|
toSeed: Bytes.fromHex(
|
|
'0199495e71f9e7f40b52febf82dcb1a6c342e9178a5e8cfea4204cf6b2071e89345ab83e8a5f0ea3ae59025e5e2e8dd2c965752541912f28ead8a33ff7dd11dd',
|
|
).toUint8Array(),
|
|
toPhrase:
|
|
'legal winner thank year wave sausage worth useful legal winner thank yellow Libauth',
|
|
toPhraseWithoutPassphrase:
|
|
'legal winner thank year wave sausage worth useful legal winner thank yellow',
|
|
toWords: [
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'year',
|
|
'wave',
|
|
'sausage',
|
|
'worth',
|
|
'useful',
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'yellow',
|
|
'Libauth',
|
|
],
|
|
toWordsWithoutPassphrase: [
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'year',
|
|
'wave',
|
|
'sausage',
|
|
'worth',
|
|
'useful',
|
|
'legal',
|
|
'winner',
|
|
'thank',
|
|
'yellow',
|
|
],
|
|
},
|
|
];
|
|
|
|
it.each(testCases)('from(string)', ({ fromPhrase: phrase, raw }) => {
|
|
const mnemonic = Mnemonic.from(phrase);
|
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
it.each(testCases)('from(words)', ({ fromWords, raw }) => {
|
|
const mnemonic = Mnemonic.from(fromWords);
|
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
it.each(testCases)('fromPhrase', ({ fromPhrase, raw }) => {
|
|
const mnemonic = Mnemonic.fromPhrase(fromPhrase);
|
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
it.each(testCases)('fromWords', ({ fromWords, raw }) => {
|
|
const mnemonic = Mnemonic.fromWords(fromWords);
|
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
it.each(testCases)('fromWords', ({ fromWords, raw }) => {
|
|
const mnemonic = Mnemonic.fromWords(fromWords);
|
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
|
});
|
|
|
|
it.each(testCases)('toSeed', ({ toSeed, raw }) => {
|
|
const mnemonic = Mnemonic.fromRaw(raw);
|
|
expect(mnemonic.toSeed()).toStrictEqual(toSeed);
|
|
});
|
|
|
|
it.each(testCases)('toPhrase', ({ toPhrase, raw }) => {
|
|
const mnemonic = Mnemonic.fromRaw(raw);
|
|
expect(mnemonic.toPhrase()).toStrictEqual(toPhrase);
|
|
});
|
|
|
|
it.each(testCases)(
|
|
'toPhrase(withoutPassphrase)',
|
|
({ toPhraseWithoutPassphrase, raw }) => {
|
|
const mnemonic = Mnemonic.fromRaw(raw);
|
|
expect(mnemonic.toPhrase(false)).toStrictEqual(toPhraseWithoutPassphrase);
|
|
},
|
|
);
|
|
|
|
it.each(testCases)('toWords', ({ toWords, raw }) => {
|
|
const mnemonic = Mnemonic.fromRaw(raw);
|
|
expect(mnemonic.toWords()).toStrictEqual(toWords);
|
|
});
|
|
|
|
it.each(testCases)(
|
|
'toWords(withoutPassphrase)',
|
|
({ toWordsWithoutPassphrase, _passphrase, raw }) => {
|
|
const mnemonic = Mnemonic.fromRaw(raw);
|
|
expect(mnemonic.toWords(false)).toStrictEqual(toWordsWithoutPassphrase);
|
|
},
|
|
);
|
|
|
|
it.each(testCases)('getPassphrase', ({ passphrase, raw }) => {
|
|
const mnemonic = Mnemonic.fromRaw(raw);
|
|
expect(mnemonic.getPassphrase()).toStrictEqual(passphrase);
|
|
});
|
|
});
|
|
|
|
describe('Generate Cases', () => {
|
|
it('generateRandom should return instance of Mnemonic', () => {
|
|
const mnemonic = Mnemonic.generateRandom();
|
|
expect(mnemonic).toBeInstanceOf(Mnemonic);
|
|
});
|
|
|
|
it('generateRandom should return instance of Mnemonic with passphrase', () => {
|
|
const mnemonic = Mnemonic.generateRandom('GeneralProtocols!');
|
|
expect(mnemonic).toBeInstanceOf(Mnemonic);
|
|
expect(mnemonic.getPassphrase()).toBe('GeneralProtocols!');
|
|
});
|
|
});
|
|
|
|
describe('Validations', () => {
|
|
it('isValid should succeed if valid mnemonic', () => {
|
|
const isValid = Mnemonic.isValid(
|
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
|
);
|
|
expect(isValid).toBe(true);
|
|
});
|
|
|
|
it('isValid should fail if invalid mnemonic', () => {
|
|
// 11 words.
|
|
const isValid = Mnemonic.isValid(
|
|
'goose just fan kidney barrel album wave crowd movie flame cousin',
|
|
);
|
|
expect(isValid).toBe(false);
|
|
});
|
|
|
|
it('isValidWord should succeed if word is in word list', () => {
|
|
const isValid = Mnemonic.isValidWord('goose');
|
|
expect(isValid).toBe(true);
|
|
});
|
|
|
|
it('isValidWord should fail if word is not in word list', () => {
|
|
const isValid = Mnemonic.isValidWord('fnord');
|
|
expect(isValid).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('Fail cases', () => {
|
|
it('fromPhrase should fail if invalid number of words', () => {
|
|
expect(() => {
|
|
// 11 words.
|
|
Mnemonic.fromPhrase(
|
|
'goose just fan kidney barrel album wave crowd movie flame cousin',
|
|
);
|
|
}).toThrow();
|
|
});
|
|
|
|
it('generateRandom should fail if invalid wordList contains invalid number of words', () => {
|
|
expect(() => {
|
|
// 11 words.
|
|
Mnemonic.generateRandom('GeneralProtocols!', ['one', 'two', 'three']);
|
|
}).toThrow();
|
|
});
|
|
|
|
it('fromWords should fail if invalid number of words', () => {
|
|
expect(() => {
|
|
// 11 words.
|
|
Mnemonic.fromWords([
|
|
'goose',
|
|
'just',
|
|
'fan',
|
|
'kidney',
|
|
'barrel',
|
|
'album',
|
|
'wave',
|
|
'crowd',
|
|
'movie',
|
|
'flame',
|
|
'cousin',
|
|
]);
|
|
}).toThrow();
|
|
});
|
|
|
|
it('fromPhrase should fail if word not in dictionary', () => {
|
|
expect(() => {
|
|
// Invalid word "fnord".
|
|
Mnemonic.fromPhrase(
|
|
'fnord just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
|
);
|
|
}).toThrow();
|
|
});
|
|
|
|
it('fromWord should fail if word not in dictionary', () => {
|
|
expect(() => {
|
|
// Invalid word "fnord".
|
|
Mnemonic.fromWords([
|
|
'fnord',
|
|
'just',
|
|
'fan',
|
|
'kidney',
|
|
'barrel',
|
|
'album',
|
|
'wave',
|
|
'crowd',
|
|
'movie',
|
|
'flame',
|
|
'cousin',
|
|
'exhaust',
|
|
]);
|
|
}).toThrow();
|
|
});
|
|
|
|
it('fromWord should fail if checksum is invalid', () => {
|
|
expect(() => {
|
|
// Invalid word "fnord".
|
|
Mnemonic.fromWords([
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'abandon',
|
|
'banana',
|
|
]);
|
|
}).toThrow();
|
|
});
|
|
});
|