Skip to content

Commit

Permalink
feat: update readme, add jsdoc for generateMnemonic, rename chinese w…
Browse files Browse the repository at this point in the history
…ordlist files, remove utils/download logic
  • Loading branch information
Nesopie committed Aug 19, 2024
1 parent cc756cc commit 61c4e0d
Show file tree
Hide file tree
Showing 32 changed files with 118 additions and 182 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [18, 'lts/*']
node-version: [20, 'lts/*']
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2
Expand Down
98 changes: 27 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# BIP39

[![Build Status](https://travis-ci.org/bitcoinjs/bip39.png?branch=master)](https://travis-ci.org/bitcoinjs/bip39)
![](https://github.com/bitcoinjs/bip39/actions/workflows/main_ci.yml/badge.svg)
[![NPM](https://img.shields.io/npm/v/bip39.svg)](https://www.npmjs.org/package/bip39)

[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
Expand All @@ -16,80 +16,31 @@ 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`

## Removing wordlists from webpack/browserify
***Note that the `generateMnemonic()` function uses crypto.getRandomValues() under the hood which is still an experimental feature as of Node.js 18.19.0***. To make use of `generateMnemonic()` you can:
1. Use a polyfill for crypto.getRandomValues()
2. Use the `--experimental-global-webcrypto` flag when running node.js.
3. Pass in a custom function to generate random values. This can be done as follows:
```js
import * as bip39 from 'bip39'
import * as crypto from 'crypto'

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/czech.json \
--exclude=./wordlists/portuguese.json \
--exclude=./wordlists/chinese_traditional.json \
> bip39.browser.js
bip39.setDefaultWordlist(bip39.english)
bip39.generateMnemonic(128, (size) => (crypto.randomBytes(size)))
```

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.

You can also do this in Webpack 5 using the `IgnorePlugin`. Here is an example of excluding all non-English wordlists

```javascript
...
plugins: [
new webpack.IgnorePlugin({
checkResource(resource) {
return /.*\/wordlists\/(?!english).*\.json/.test(resource)
}
}),
],
...
```

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.czech
undefined
> bip39.wordlists.portuguese
undefined
> bip39.wordlists.chinese_traditional
undefined
```
## Removing wordlists from the bundle

BIP39 is treeshakeable, this means that if you're using webpack or vite or any modern bundler, they will be removed from the bundle when it is built.

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.
For a list of supported wordlists check the wordlists folder. The name of the js 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.
***Note that unlike the previous versions there is no default wordlist, so you will need to set one before using the library.*** This is how it would look like:

```javascript
> bip39.entropyToMnemonic('00000000000000000000000000000fff')
"あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あまい ろんり"
> bip39.setDefaultWordlist('italian')
undefined
> bip39.entropyToMnemonic('00000000000000000000000000000fff')
"abaco abaco abaco abaco abaco abaco abaco abaco abaco abaco aforisma zibetto"
```javascript
import bip39 from 'bip39'
bip39.setDefaultWordlist(bip39.english)
bip39.entropyToMnemonic('00000000000000000000000000000000')
// => abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
```

## Installation
Expand All @@ -99,7 +50,12 @@ npm install bip39

## Examples
``` js
// Generate a random mnemonic (uses crypto.randomBytes under the hood), defaults to 128-bits of entropy
import * as bip39 from "bip39"

// Sets the default wordlist to english
bip39.setDefaultWordlist(bip39.english)

// Generate a random mnemonic (uses crypto.getRandomValues() under the hood), defaults to 128-bits of entropy
const mnemonic = bip39.generateMnemonic()
// => 'seed sock milk update focus rotate barely fade car face mechanic mercy'

Expand Down Expand Up @@ -130,8 +86,8 @@ bip39.validateMnemonic('basket actual')

``` js
const bip39 = require('bip39')
bip39.setDefaultWordlist(bip39.english)

// defaults to BIP39 English word list
// uses HEX strings for entropy
const mnemonic = bip39.entropyToMnemonic('00000000000000000000000000000000')
// => abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
Expand Down
17 changes: 16 additions & 1 deletion src/cjs/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -21411,6 +21411,7 @@ function mnemonicToEntropy(mnemonic, wordlist) {
if (words.length % 3 !== 0) {
throw new Error(INVALID_MNEMONIC);
}
// convert word indices to 11 bit binary strings
const bits = words
.map((word) => {
const index = wordlist.indexOf(word);
Expand All @@ -21420,9 +21421,11 @@ function mnemonicToEntropy(mnemonic, wordlist) {
return lpad(index.toString(2), '0', 11);
})
.join('');
// split the binary string into ENT/CS
const dividerIndex = Math.floor(bits.length / 33) * 32;
const entropyBits = bits.slice(0, dividerIndex);
const checksumBits = bits.slice(dividerIndex);
// calculate the checksum and compare
const entropyBytes = entropyBits.match(/(.{1,8})/g).map(binaryToByte);
if (entropyBytes.length < 16) {
throw new Error(INVALID_ENTROPY);
Expand All @@ -21448,6 +21451,7 @@ function entropyToMnemonic(entropy, wordlist) {
if (!wordlist) {
throw new Error(WORDLIST_REQUIRED);
}
// 128 <= ENT <= 256
if (entropy.length < 16) {
throw new TypeError(INVALID_ENTROPY);
}
Expand All @@ -21465,10 +21469,21 @@ function entropyToMnemonic(entropy, wordlist) {
const index = binaryToByte(binary);
return wordlist[index];
});
return wordlist[0] === '\u3042\u3044\u3053\u304f\u3057\u3093'
return wordlist[0] === '\u3042\u3044\u3053\u304f\u3057\u3093' // Japanese wordlist
? words.join('\u3000')
: words.join(' ');
}
/**
* Generates a mnemonic phrase based on the provided strength, random number generator, and wordlist.
* Uses `crypto.getRandomValues` under the hood, which is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following:
* 1. Use a polyfill for crypto.getRandomValues()
* 2. Use the `--experimental-global-webcrypto` flag when running node.js.
* 3. Pass in a custom rng function to generate random values.
* @param {number} [strength=128] - The strength of the mnemonic phrase, must be a multiple of 32.
* @param {(size: number) => Uint8Array} [rng] - A custom random number generator, defaults to crypto.getRandomValues.
* @param {string[]} [wordlist] - A custom wordlist, defaults to the standard wordlist.
* @return {string} The generated mnemonic phrase.
*/
function generateMnemonic(strength, rng, wordlist) {
strength = strength || 128;
if (strength % 32 !== 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/cjs/index.cjs.map

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/cjs/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ export declare function mnemonicToSeedSync(mnemonic: string, password?: string):
export declare function mnemonicToSeed(mnemonic: string, password?: string): Promise<Uint8Array>;
export declare function mnemonicToEntropy(mnemonic: string, wordlist?: string[]): string;
export declare function entropyToMnemonic(entropy: Uint8Array | string, wordlist?: string[]): string;
/**
* Generates a mnemonic phrase based on the provided strength, random number generator, and wordlist.
* Uses `crypto.getRandomValues` under the hood, which is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following:
* 1. Use a polyfill for crypto.getRandomValues()
* 2. Use the `--experimental-global-webcrypto` flag when running node.js.
* 3. Pass in a custom rng function to generate random values.
* @param {number} [strength=128] - The strength of the mnemonic phrase, must be a multiple of 32.
* @param {(size: number) => Uint8Array} [rng] - A custom random number generator, defaults to crypto.getRandomValues.
* @param {string[]} [wordlist] - A custom wordlist, defaults to the standard wordlist.
* @return {string} The generated mnemonic phrase.
*/
export declare function generateMnemonic(strength?: number, rng?: (size: number) => Uint8Array, wordlist?: string[]): string;
export declare function validateMnemonic(mnemonic: string, wordlist?: string[]): boolean;
export declare function setDefaultWordlist(wordlist: string[]): void;
Expand Down
2 changes: 1 addition & 1 deletion src/cjs/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/cjs/wordlists/chineseSimplified.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare const chineseSimplified: string[];
//# sourceMappingURL=chineseSimplified.d.ts.map
1 change: 1 addition & 0 deletions src/cjs/wordlists/chineseSimplified.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/cjs/wordlists/chineseTraditional.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare const chineseTraditional: string[];
//# sourceMappingURL=chineseTraditional.d.ts.map
1 change: 1 addition & 0 deletions src/cjs/wordlists/chineseTraditional.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/cjs/wordlists/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { chineseSimplified } from './chinese_simplified.js';
export { chineseTraditional } from './chinese_traditional.js';
export { chineseSimplified } from './chineseSimplified.js';
export { chineseTraditional } from './chineseTraditional.js';
export { czech } from './czech.js';
export { english } from './english.js';
export { french } from './french.js';
Expand Down
2 changes: 1 addition & 1 deletion src/cjs/wordlists/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions src/esm/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ export declare function mnemonicToSeedSync(mnemonic: string, password?: string):
export declare function mnemonicToSeed(mnemonic: string, password?: string): Promise<Uint8Array>;
export declare function mnemonicToEntropy(mnemonic: string, wordlist?: string[]): string;
export declare function entropyToMnemonic(entropy: Uint8Array | string, wordlist?: string[]): string;
/**
* Generates a mnemonic phrase based on the provided strength, random number generator, and wordlist.
* Uses `crypto.getRandomValues` under the hood, which is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following:
* 1. Use a polyfill for crypto.getRandomValues()
* 2. Use the `--experimental-global-webcrypto` flag when running node.js.
* 3. Pass in a custom rng function to generate random values.
* @param {number} [strength=128] - The strength of the mnemonic phrase, must be a multiple of 32.
* @param {(size: number) => Uint8Array} [rng] - A custom random number generator, defaults to crypto.getRandomValues.
* @param {string[]} [wordlist] - A custom wordlist, defaults to the standard wordlist.
* @return {string} The generated mnemonic phrase.
*/
export declare function generateMnemonic(strength?: number, rng?: (size: number) => Uint8Array, wordlist?: string[]): string;
export declare function validateMnemonic(mnemonic: string, wordlist?: string[]): boolean;
export declare function setDefaultWordlist(wordlist: string[]): void;
Expand Down
2 changes: 1 addition & 1 deletion src/esm/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion src/esm/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/esm/index.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/esm/wordlists/chineseSimplified.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare const chineseSimplified: string[];
//# sourceMappingURL=chineseSimplified.d.ts.map
Loading

0 comments on commit 61c4e0d

Please sign in to comment.