Browse Source

Add bip39 vanity seed key format

master
Luke Childs 6 years ago
parent
commit
ccec9cfdae
  1. 1
      package.json
  2. 3
      src/address-formats/p2pkh.js
  3. 3
      src/address-formats/p2wpkh-p2sh.js
  4. 3
      src/address-formats/p2wpkh.js
  5. 9
      src/index.js
  6. 20
      src/key-formats/bip39.js
  7. 57
      test/unit.js

1
package.json

@ -35,6 +35,7 @@
"xo": "^0.24.0"
},
"dependencies": {
"bip39": "^3.0.2",
"bitcoinjs-lib": "^5.0.3",
"tiny-emitter": "^2.1.0"
}

3
src/address-formats/p2pkh.js

@ -3,7 +3,8 @@ const {base58} = require('./charsets');
const p2pkh = {
prefix: '1',
charset: base58
charset: base58,
bip39: '44'
};
p2pkh.derive = pubkey => {

3
src/address-formats/p2wpkh-p2sh.js

@ -3,7 +3,8 @@ const {base58} = require('./charsets');
const p2wpkhp2sh = {
prefix: '3',
charset: base58
charset: base58,
bip39: '49'
};
p2wpkhp2sh.derive = pubkey => {

3
src/address-formats/p2wpkh.js

@ -3,7 +3,8 @@ const {bech32} = require('./charsets');
const p2wpkh = {
prefix: 'bc1q',
charset: bech32
charset: bech32,
bip39: '84'
};
p2wpkh.derive = pubkey => {

9
src/index.js

@ -3,7 +3,8 @@ const Emitter = require('tiny-emitter');
const ONE_SECOND = 1000;
const keyFormats = new Map(Object.entries({
wif: require('./key-formats/wif')
wif: require('./key-formats/wif'),
bip39: require('./key-formats/bip39')
}));
const addressFormats = new Map(Object.entries({
@ -35,6 +36,8 @@ class Vain extends Emitter {
return new Promise(resolve => {
const startTime = Date.now();
const {generateKey, addressFormat} = this;
let found;
let attempts = 0;
let keyData;
@ -44,8 +47,8 @@ class Vain extends Emitter {
while (!found) {
attempts++;
keyData = this.generateKey();
address = this.addressFormat.derive(keyData.publicKey);
keyData = generateKey({addressFormat});
address = addressFormat.derive(keyData.publicKey);
if (address.startsWith(this.prefix)) {
found = true;

20
src/key-formats/bip39.js

@ -0,0 +1,20 @@
const bip39 = require('bip39');
const bitcoin = require('bitcoinjs-lib');
const generatebip39Key = ({addressFormat}) => {
const mnemonic = bip39.generateMnemonic();
const seed = bip39.mnemonicToSeedSync(mnemonic);
const node = bitcoin.bip32.fromSeed(seed);
const derivationPath = `m/${addressFormat.bip39}'/0'/0'/0/0`;
const {publicKey} = node.derivePath(derivationPath);
const format = () => ({
derivationPath,
mnemonic
});
return {publicKey, format};
};
module.exports = generatebip39Key;

57
test/unit.js

@ -1,5 +1,6 @@
import test from 'ava';
import * as bitcoin from 'bitcoinjs-lib';
import * as bip39 from 'bip39';
import Vain from '..';
test('Vain is exported', t => {
@ -53,6 +54,62 @@ test('Vain derives a p2wpkh vanity address', async t => {
t.is(address, wifAddress);
});
test('Vain derives a p2pkh vanity seed', async t => {
const options = {
keyFormat: 'bip39',
addressFormat: 'p2pkh',
prefix: 'A'
};
const vain = new Vain(options);
const {address, derivationPath, mnemonic} = await vain.start();
const seed = await bip39.mnemonicToSeed(mnemonic);
const node = bitcoin.bip32.fromSeed(seed);
const {publicKey} = node.derivePath(derivationPath);
const {address: seedAddress} = bitcoin.payments.p2pkh({pubkey: publicKey});
t.true(address.startsWith(`1${options.prefix}`));
t.is(address, seedAddress);
});
test('Vain derives a p2wpkh-p2sh vanity seed', async t => {
const options = {
keyFormat: 'bip39',
addressFormat: 'p2wpkh-p2sh',
prefix: 'A'
};
const vain = new Vain(options);
const {address, derivationPath, mnemonic} = await vain.start();
const seed = await bip39.mnemonicToSeed(mnemonic);
const node = bitcoin.bip32.fromSeed(seed);
const {publicKey} = node.derivePath(derivationPath);
const {address: seedAddress} = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({pubkey: publicKey})
});
t.true(address.startsWith(`3${options.prefix}`));
t.is(address, seedAddress);
});
test('Vain derives a p2wpkh vanity seed', async t => {
const options = {
keyFormat: 'bip39',
addressFormat: 'p2wpkh',
prefix: 'a'
};
const vain = new Vain(options);
const {address, derivationPath, mnemonic} = await vain.start();
const seed = await bip39.mnemonicToSeed(mnemonic);
const node = bitcoin.bip32.fromSeed(seed);
const {publicKey} = node.derivePath(derivationPath);
const {address: seedAddress} = bitcoin.payments.p2wpkh({pubkey: publicKey});
t.true(address.startsWith(`bc1q${options.prefix}`));
t.is(address, seedAddress);
});
test('Vain defaults to p2pkh if no address format is set', async t => {
const options = {
prefix: 'A'

Loading…
Cancel
Save