mirror of https://github.com/status-im/bip39.git
Allow excluding wordlists when building for browserify
This commit is contained in:
parent
6dedef08d4
commit
c30b47b63d
56
README.md
56
README.md
|
@ -16,6 +16,62 @@ When a checksum is invalid, warn the user that the phrase is not something gener
|
||||||
|
|
||||||
However, there should be other checks in place, such as checking to make sure the user is inputting 12 words or more separated by a space. ie. `phrase.trim().split(/\s+/g).length >= 12`
|
However, there should be other checks in place, such as checking to make sure the user is inputting 12 words or more separated by a space. ie. `phrase.trim().split(/\s+/g).length >= 12`
|
||||||
|
|
||||||
|
## Removing wordlists from webpack/browserify
|
||||||
|
|
||||||
|
Browserify/Webpack bundles can get very large if you include all the wordlists, so you can now exclude wordlists to make your bundle lighter.
|
||||||
|
|
||||||
|
For example, if we want to exclude all wordlists besides chinese_simplified, you could build using the browserify command below.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ browserify -r bip39 -s bip39 \
|
||||||
|
--exclude=./wordlists/english.json \
|
||||||
|
--exclude=./wordlists/japanese.json \
|
||||||
|
--exclude=./wordlists/spanish.json \
|
||||||
|
--exclude=./wordlists/italian.json \
|
||||||
|
--exclude=./wordlists/french.json \
|
||||||
|
--exclude=./wordlists/korean.json \
|
||||||
|
--exclude=./wordlists/chinese_traditional.json \
|
||||||
|
> bip39.browser.js
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a bundle that only contains the chinese_simplified wordlist, and it will be the default wordlist for all calls without explicit wordlists.
|
||||||
|
|
||||||
|
This is how it will look in the browser console.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
> bip39.entropyToMnemonic('00000000000000000000000000000000')
|
||||||
|
"的 的 的 的 的 的 的 的 的 的 的 在"
|
||||||
|
> bip39.wordlists.chinese_simplified
|
||||||
|
Array(2048) [ "的", "一", "是", "在", "不", "了", "有", "和", "人", "这", … ]
|
||||||
|
> bip39.wordlists.english
|
||||||
|
undefined
|
||||||
|
> bip39.wordlists.japanese
|
||||||
|
undefined
|
||||||
|
> bip39.wordlists.spanish
|
||||||
|
undefined
|
||||||
|
> bip39.wordlists.italian
|
||||||
|
undefined
|
||||||
|
> bip39.wordlists.french
|
||||||
|
undefined
|
||||||
|
> bip39.wordlists.korean
|
||||||
|
undefined
|
||||||
|
> bip39.wordlists.chinese_traditional
|
||||||
|
undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
For a list of supported wordlists check the wordlists folder. The name of the json file (minus the extension) is the name of the key to access the wordlist.
|
||||||
|
|
||||||
|
You can also change the default wordlist at runtime if you dislike the wordlist you were given as default.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
> bip39.entropyToMnemonic('00000000000000000000000000000fff')
|
||||||
|
"あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あまい ろんり"
|
||||||
|
> bip39.setDefaultWordlist('italian')
|
||||||
|
undefined
|
||||||
|
> bip39.entropyToMnemonic('00000000000000000000000000000fff')
|
||||||
|
"abaco abaco abaco abaco abaco abaco abaco abaco abaco abaco aforisma zibetto"
|
||||||
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
``` bash
|
``` bash
|
||||||
npm install bip39
|
npm install bip39
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
// browserify by default only pulls in files that are hard coded in requires
|
||||||
|
// In order of last to first in this file, the default wordlist will be chosen
|
||||||
|
// based on what is present. (Bundles may remove wordlists they don't need)
|
||||||
|
const wordlists = {};
|
||||||
|
exports.wordlists = wordlists;
|
||||||
|
let _default;
|
||||||
|
exports._default = _default;
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/chinese_simplified.json');
|
||||||
|
wordlists.chinese_simplified = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/chinese_traditional.json');
|
||||||
|
wordlists.chinese_traditional = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/korean.json');
|
||||||
|
wordlists.korean = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/french.json');
|
||||||
|
wordlists.french = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/italian.json');
|
||||||
|
wordlists.italian = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/spanish.json');
|
||||||
|
wordlists.spanish = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/japanese.json');
|
||||||
|
wordlists.japanese = _default;
|
||||||
|
wordlists.JA = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
||||||
|
try {
|
||||||
|
exports._default = _default = require('./wordlists/english.json');
|
||||||
|
wordlists.english = _default;
|
||||||
|
wordlists.EN = _default;
|
||||||
|
}
|
||||||
|
catch (err) { }
|
41
src/index.js
41
src/index.js
|
@ -5,18 +5,13 @@ const pbkdf2_1 = require("pbkdf2");
|
||||||
const randomBytes = require("randombytes");
|
const randomBytes = require("randombytes");
|
||||||
// use unorm until String.prototype.normalize gets better browser support
|
// use unorm until String.prototype.normalize gets better browser support
|
||||||
const unorm = require("unorm");
|
const unorm = require("unorm");
|
||||||
const CHINESE_SIMPLIFIED_WORDLIST = require("./wordlists/chinese_simplified.json");
|
const _wordlists_1 = require("./_wordlists");
|
||||||
const CHINESE_TRADITIONAL_WORDLIST = require("./wordlists/chinese_traditional.json");
|
let DEFAULT_WORDLIST = _wordlists_1._default;
|
||||||
const ENGLISH_WORDLIST = require("./wordlists/english.json");
|
|
||||||
const FRENCH_WORDLIST = require("./wordlists/french.json");
|
|
||||||
const ITALIAN_WORDLIST = require("./wordlists/italian.json");
|
|
||||||
const JAPANESE_WORDLIST = require("./wordlists/japanese.json");
|
|
||||||
const KOREAN_WORDLIST = require("./wordlists/korean.json");
|
|
||||||
const SPANISH_WORDLIST = require("./wordlists/spanish.json");
|
|
||||||
const DEFAULT_WORDLIST = ENGLISH_WORDLIST;
|
|
||||||
const INVALID_MNEMONIC = 'Invalid mnemonic';
|
const INVALID_MNEMONIC = 'Invalid mnemonic';
|
||||||
const INVALID_ENTROPY = 'Invalid entropy';
|
const INVALID_ENTROPY = 'Invalid entropy';
|
||||||
const INVALID_CHECKSUM = 'Invalid mnemonic checksum';
|
const INVALID_CHECKSUM = 'Invalid mnemonic checksum';
|
||||||
|
const WORDLIST_REQUIRED = 'A wordlist is required but a default could not be found.\n' +
|
||||||
|
'Please explicitly pass a 2048 word array explicitly.';
|
||||||
function lpad(str, padString, length) {
|
function lpad(str, padString, length) {
|
||||||
while (str.length < length)
|
while (str.length < length)
|
||||||
str = padString + str;
|
str = padString + str;
|
||||||
|
@ -74,6 +69,9 @@ async function mnemonicToSeedHexAsync(mnemonic, password) {
|
||||||
exports.mnemonicToSeedHexAsync = mnemonicToSeedHexAsync;
|
exports.mnemonicToSeedHexAsync = mnemonicToSeedHexAsync;
|
||||||
function mnemonicToEntropy(mnemonic, wordlist) {
|
function mnemonicToEntropy(mnemonic, wordlist) {
|
||||||
wordlist = wordlist || DEFAULT_WORDLIST;
|
wordlist = wordlist || DEFAULT_WORDLIST;
|
||||||
|
if (!wordlist) {
|
||||||
|
throw new Error(WORDLIST_REQUIRED);
|
||||||
|
}
|
||||||
const words = unorm.nfkd(mnemonic).split(' ');
|
const words = unorm.nfkd(mnemonic).split(' ');
|
||||||
if (words.length % 3 !== 0)
|
if (words.length % 3 !== 0)
|
||||||
throw new Error(INVALID_MNEMONIC);
|
throw new Error(INVALID_MNEMONIC);
|
||||||
|
@ -109,6 +107,9 @@ function entropyToMnemonic(entropy, wordlist) {
|
||||||
if (!Buffer.isBuffer(entropy))
|
if (!Buffer.isBuffer(entropy))
|
||||||
entropy = Buffer.from(entropy, 'hex');
|
entropy = Buffer.from(entropy, 'hex');
|
||||||
wordlist = wordlist || DEFAULT_WORDLIST;
|
wordlist = wordlist || DEFAULT_WORDLIST;
|
||||||
|
if (!wordlist) {
|
||||||
|
throw new Error(WORDLIST_REQUIRED);
|
||||||
|
}
|
||||||
// 128 <= ENT <= 256
|
// 128 <= ENT <= 256
|
||||||
if (entropy.length < 16)
|
if (entropy.length < 16)
|
||||||
throw new TypeError(INVALID_ENTROPY);
|
throw new TypeError(INVALID_ENTROPY);
|
||||||
|
@ -124,7 +125,7 @@ function entropyToMnemonic(entropy, wordlist) {
|
||||||
const index = binaryToByte(binary);
|
const index = binaryToByte(binary);
|
||||||
return wordlist[index];
|
return wordlist[index];
|
||||||
});
|
});
|
||||||
return wordlist === JAPANESE_WORDLIST
|
return wordlist[0] === '\u3042\u3044\u3053\u304f\u3057\u3093' // Japanese wordlist
|
||||||
? words.join('\u3000')
|
? words.join('\u3000')
|
||||||
: words.join(' ');
|
: words.join(' ');
|
||||||
}
|
}
|
||||||
|
@ -147,15 +148,11 @@ function validateMnemonic(mnemonic, wordlist) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
exports.validateMnemonic = validateMnemonic;
|
exports.validateMnemonic = validateMnemonic;
|
||||||
exports.wordlists = {
|
function setDefaultWordlist(language) {
|
||||||
EN: ENGLISH_WORDLIST,
|
const result = _wordlists_1.wordlists[language];
|
||||||
JA: JAPANESE_WORDLIST,
|
if (result)
|
||||||
chinese_simplified: CHINESE_SIMPLIFIED_WORDLIST,
|
DEFAULT_WORDLIST = result;
|
||||||
chinese_traditional: CHINESE_TRADITIONAL_WORDLIST,
|
}
|
||||||
english: ENGLISH_WORDLIST,
|
exports.setDefaultWordlist = setDefaultWordlist;
|
||||||
french: FRENCH_WORDLIST,
|
var _wordlists_2 = require("./_wordlists");
|
||||||
italian: ITALIAN_WORDLIST,
|
exports.wordlists = _wordlists_2.wordlists;
|
||||||
japanese: JAPANESE_WORDLIST,
|
|
||||||
korean: KOREAN_WORDLIST,
|
|
||||||
spanish: SPANISH_WORDLIST,
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
// browserify by default only pulls in files that are hard coded in requires
|
||||||
|
// In order of last to first in this file, the default wordlist will be chosen
|
||||||
|
// based on what is present. (Bundles may remove wordlists they don't need)
|
||||||
|
const wordlists: { [index: string]: string[] } = {};
|
||||||
|
let _default: string[] | undefined;
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/chinese_simplified.json');
|
||||||
|
wordlists.chinese_simplified = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/chinese_traditional.json');
|
||||||
|
wordlists.chinese_traditional = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/korean.json');
|
||||||
|
wordlists.korean = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/french.json');
|
||||||
|
wordlists.french = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/italian.json');
|
||||||
|
wordlists.italian = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/spanish.json');
|
||||||
|
wordlists.spanish = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/japanese.json');
|
||||||
|
wordlists.japanese = _default as string[];
|
||||||
|
wordlists.JA = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
try {
|
||||||
|
_default = require('./wordlists/english.json');
|
||||||
|
wordlists.english = _default as string[];
|
||||||
|
wordlists.EN = _default as string[];
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
// Last one to overwrite wordlist gets to be default.
|
||||||
|
export { wordlists, _default };
|
|
@ -1,23 +1,18 @@
|
||||||
import createHash = require('create-hash');
|
import * as createHash from 'create-hash';
|
||||||
import { pbkdf2 as pbkdf2Async, pbkdf2Sync as pbkdf2 } from 'pbkdf2';
|
import { pbkdf2 as pbkdf2Async, pbkdf2Sync as pbkdf2 } from 'pbkdf2';
|
||||||
import randomBytes = require('randombytes');
|
import * as randomBytes from 'randombytes';
|
||||||
|
|
||||||
// use unorm until String.prototype.normalize gets better browser support
|
// use unorm until String.prototype.normalize gets better browser support
|
||||||
import unorm = require('unorm');
|
import * as unorm from 'unorm';
|
||||||
|
import { _default as _DEFAULT_WORDLIST, wordlists } from './_wordlists';
|
||||||
|
|
||||||
import CHINESE_SIMPLIFIED_WORDLIST = require('./wordlists/chinese_simplified.json');
|
let DEFAULT_WORDLIST: string[] | undefined = _DEFAULT_WORDLIST;
|
||||||
import CHINESE_TRADITIONAL_WORDLIST = require('./wordlists/chinese_traditional.json');
|
|
||||||
import ENGLISH_WORDLIST = require('./wordlists/english.json');
|
|
||||||
import FRENCH_WORDLIST = require('./wordlists/french.json');
|
|
||||||
import ITALIAN_WORDLIST = require('./wordlists/italian.json');
|
|
||||||
import JAPANESE_WORDLIST = require('./wordlists/japanese.json');
|
|
||||||
import KOREAN_WORDLIST = require('./wordlists/korean.json');
|
|
||||||
import SPANISH_WORDLIST = require('./wordlists/spanish.json');
|
|
||||||
const DEFAULT_WORDLIST = ENGLISH_WORDLIST;
|
|
||||||
|
|
||||||
const INVALID_MNEMONIC = 'Invalid mnemonic';
|
const INVALID_MNEMONIC = 'Invalid mnemonic';
|
||||||
const INVALID_ENTROPY = 'Invalid entropy';
|
const INVALID_ENTROPY = 'Invalid entropy';
|
||||||
const INVALID_CHECKSUM = 'Invalid mnemonic checksum';
|
const INVALID_CHECKSUM = 'Invalid mnemonic checksum';
|
||||||
|
const WORDLIST_REQUIRED =
|
||||||
|
'A wordlist is required but a default could not be found.\n' +
|
||||||
|
'Please explicitly pass a 2048 word array explicitly.';
|
||||||
|
|
||||||
function lpad(str: string, padString: string, length: number): string {
|
function lpad(str: string, padString: string, length: number): string {
|
||||||
while (str.length < length) str = padString + str;
|
while (str.length < length) str = padString + str;
|
||||||
|
@ -97,6 +92,9 @@ export function mnemonicToEntropy(
|
||||||
wordlist?: string[],
|
wordlist?: string[],
|
||||||
): string {
|
): string {
|
||||||
wordlist = wordlist || DEFAULT_WORDLIST;
|
wordlist = wordlist || DEFAULT_WORDLIST;
|
||||||
|
if (!wordlist) {
|
||||||
|
throw new Error(WORDLIST_REQUIRED);
|
||||||
|
}
|
||||||
|
|
||||||
const words = unorm.nfkd(mnemonic).split(' ');
|
const words = unorm.nfkd(mnemonic).split(' ');
|
||||||
if (words.length % 3 !== 0) throw new Error(INVALID_MNEMONIC);
|
if (words.length % 3 !== 0) throw new Error(INVALID_MNEMONIC);
|
||||||
|
@ -135,6 +133,9 @@ export function entropyToMnemonic(
|
||||||
): string {
|
): string {
|
||||||
if (!Buffer.isBuffer(entropy)) entropy = Buffer.from(entropy, 'hex');
|
if (!Buffer.isBuffer(entropy)) entropy = Buffer.from(entropy, 'hex');
|
||||||
wordlist = wordlist || DEFAULT_WORDLIST;
|
wordlist = wordlist || DEFAULT_WORDLIST;
|
||||||
|
if (!wordlist) {
|
||||||
|
throw new Error(WORDLIST_REQUIRED);
|
||||||
|
}
|
||||||
|
|
||||||
// 128 <= ENT <= 256
|
// 128 <= ENT <= 256
|
||||||
if (entropy.length < 16) throw new TypeError(INVALID_ENTROPY);
|
if (entropy.length < 16) throw new TypeError(INVALID_ENTROPY);
|
||||||
|
@ -151,7 +152,7 @@ export function entropyToMnemonic(
|
||||||
return wordlist![index];
|
return wordlist![index];
|
||||||
});
|
});
|
||||||
|
|
||||||
return wordlist === JAPANESE_WORDLIST
|
return wordlist[0] === '\u3042\u3044\u3053\u304f\u3057\u3093' // Japanese wordlist
|
||||||
? words.join('\u3000')
|
? words.join('\u3000')
|
||||||
: words.join(' ');
|
: words.join(' ');
|
||||||
}
|
}
|
||||||
|
@ -181,16 +182,9 @@ export function validateMnemonic(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const wordlists = {
|
export function setDefaultWordlist(language: string): void {
|
||||||
EN: ENGLISH_WORDLIST,
|
const result = wordlists[language];
|
||||||
JA: JAPANESE_WORDLIST,
|
if (result) DEFAULT_WORDLIST = result;
|
||||||
|
}
|
||||||
|
|
||||||
chinese_simplified: CHINESE_SIMPLIFIED_WORDLIST,
|
export { wordlists } from './_wordlists';
|
||||||
chinese_traditional: CHINESE_TRADITIONAL_WORDLIST,
|
|
||||||
english: ENGLISH_WORDLIST,
|
|
||||||
french: FRENCH_WORDLIST,
|
|
||||||
italian: ITALIAN_WORDLIST,
|
|
||||||
japanese: JAPANESE_WORDLIST,
|
|
||||||
korean: KOREAN_WORDLIST,
|
|
||||||
spanish: SPANISH_WORDLIST,
|
|
||||||
};
|
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
"resolveJsonModule": true
|
"resolveJsonModule": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"ts_src/**/*.ts"
|
"ts_src/**/*.ts",
|
||||||
|
"ts_src/**/*.json"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"**/*.spec.ts",
|
"**/*.spec.ts",
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
declare const wordlists: {
|
||||||
|
[index: string]: string[];
|
||||||
|
};
|
||||||
|
declare let _default: string[] | undefined;
|
||||||
|
export { wordlists, _default };
|
|
@ -7,15 +7,5 @@ export declare function mnemonicToEntropy(mnemonic: string, wordlist?: string[])
|
||||||
export declare function entropyToMnemonic(entropy: Buffer | string, wordlist?: string[]): string;
|
export declare function entropyToMnemonic(entropy: Buffer | string, wordlist?: string[]): string;
|
||||||
export declare function generateMnemonic(strength?: number, rng?: (size: number) => Buffer, wordlist?: string[]): string;
|
export declare function generateMnemonic(strength?: number, rng?: (size: number) => Buffer, wordlist?: string[]): string;
|
||||||
export declare function validateMnemonic(mnemonic: string, wordlist?: string[]): boolean;
|
export declare function validateMnemonic(mnemonic: string, wordlist?: string[]): boolean;
|
||||||
export declare const wordlists: {
|
export declare function setDefaultWordlist(language: string): void;
|
||||||
EN: string[];
|
export { wordlists } from './_wordlists';
|
||||||
JA: string[];
|
|
||||||
chinese_simplified: string[];
|
|
||||||
chinese_traditional: string[];
|
|
||||||
english: string[];
|
|
||||||
french: string[];
|
|
||||||
italian: string[];
|
|
||||||
japanese: string[];
|
|
||||||
korean: string[];
|
|
||||||
spanish: string[];
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
declare const wordlists: {
|
||||||
|
[index: string]: string[];
|
||||||
|
};
|
||||||
|
declare let _default: string[] | undefined;
|
||||||
|
export { wordlists, _default };
|
Loading…
Reference in New Issue