|
|
@ -2,17 +2,17 @@ const EventEmitter = require('events').EventEmitter |
|
|
|
const hdkey = require('ethereumjs-wallet/hdkey') |
|
|
|
const hdkey = require('ethereumjs-wallet/hdkey') |
|
|
|
const bip39 = require('bip39') |
|
|
|
const bip39 = require('bip39') |
|
|
|
const ethUtil = require('ethereumjs-util') |
|
|
|
const ethUtil = require('ethereumjs-util') |
|
|
|
const sigUtil = require('../lib/sig-util') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const type = 'HD Key Tree' |
|
|
|
// *Internal Deps
|
|
|
|
|
|
|
|
const sigUtil = require('../lib/sig-util') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Options:
|
|
|
|
const hdPathString = `m/44'/60'/0'/0` |
|
|
|
const hdPathString = `m/44'/60'/0'/0` |
|
|
|
|
|
|
|
const type = 'HD Key Tree' |
|
|
|
|
|
|
|
|
|
|
|
module.exports = class HdKeyring extends EventEmitter { |
|
|
|
class HdKeyring extends EventEmitter { |
|
|
|
|
|
|
|
|
|
|
|
static type () { |
|
|
|
/* PUBLIC METHODS */ |
|
|
|
return type |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor (opts = {}) { |
|
|
|
constructor (opts = {}) { |
|
|
|
super() |
|
|
|
super() |
|
|
@ -20,6 +20,13 @@ module.exports = class HdKeyring extends EventEmitter { |
|
|
|
this.deserialize(opts) |
|
|
|
this.deserialize(opts) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serialize () { |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
mnemonic: this.mnemonic, |
|
|
|
|
|
|
|
numberOfAccounts: this.wallets.length, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
deserialize (opts = {}) { |
|
|
|
deserialize (opts = {}) { |
|
|
|
this.opts = opts || {} |
|
|
|
this.opts = opts || {} |
|
|
|
this.wallets = [] |
|
|
|
this.wallets = [] |
|
|
@ -27,7 +34,7 @@ module.exports = class HdKeyring extends EventEmitter { |
|
|
|
this.root = null |
|
|
|
this.root = null |
|
|
|
|
|
|
|
|
|
|
|
if ('mnemonic' in opts) { |
|
|
|
if ('mnemonic' in opts) { |
|
|
|
this.initFromMnemonic(opts.mnemonic) |
|
|
|
this._initFromMnemonic(opts.mnemonic) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ('numberOfAccounts' in opts) { |
|
|
|
if ('numberOfAccounts' in opts) { |
|
|
@ -35,28 +42,9 @@ module.exports = class HdKeyring extends EventEmitter { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
initFromMnemonic (mnemonic) { |
|
|
|
|
|
|
|
this.mnemonic = mnemonic |
|
|
|
|
|
|
|
const seed = bip39.mnemonicToSeed(mnemonic) |
|
|
|
|
|
|
|
this.hdWallet = hdkey.fromMasterSeed(seed) |
|
|
|
|
|
|
|
this.root = this.hdWallet.derivePath(hdPathString) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serialize () { |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
mnemonic: this.mnemonic, |
|
|
|
|
|
|
|
numberOfAccounts: this.wallets.length, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exportAccount (address) { |
|
|
|
|
|
|
|
const wallet = this.getWalletForAccount(address) |
|
|
|
|
|
|
|
return wallet.getPrivateKey().toString('hex') |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addAccounts (numberOfAccounts = 1) { |
|
|
|
addAccounts (numberOfAccounts = 1) { |
|
|
|
if (!this.root) { |
|
|
|
if (!this.root) { |
|
|
|
this.initFromMnemonic(bip39.generateMnemonic()) |
|
|
|
this._initFromMnemonic(bip39.generateMnemonic()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const oldLen = this.wallets.length |
|
|
|
const oldLen = this.wallets.length |
|
|
@ -76,7 +64,7 @@ module.exports = class HdKeyring extends EventEmitter { |
|
|
|
|
|
|
|
|
|
|
|
// tx is an instance of the ethereumjs-transaction class.
|
|
|
|
// tx is an instance of the ethereumjs-transaction class.
|
|
|
|
signTransaction (address, tx) { |
|
|
|
signTransaction (address, tx) { |
|
|
|
const wallet = this.getWalletForAccount(address) |
|
|
|
const wallet = this._getWalletForAccount(address) |
|
|
|
var privKey = wallet.getPrivateKey() |
|
|
|
var privKey = wallet.getPrivateKey() |
|
|
|
tx.sign(privKey) |
|
|
|
tx.sign(privKey) |
|
|
|
return tx |
|
|
|
return tx |
|
|
@ -84,7 +72,7 @@ module.exports = class HdKeyring extends EventEmitter { |
|
|
|
|
|
|
|
|
|
|
|
// For eth_sign, we need to sign transactions:
|
|
|
|
// For eth_sign, we need to sign transactions:
|
|
|
|
signMessage (withAccount, data) { |
|
|
|
signMessage (withAccount, data) { |
|
|
|
const wallet = this.getWalletForAccount(withAccount) |
|
|
|
const wallet = this._getWalletForAccount(withAccount) |
|
|
|
const message = ethUtil.removeHexPrefix(data) |
|
|
|
const message = ethUtil.removeHexPrefix(data) |
|
|
|
var privKey = wallet.getPrivateKey() |
|
|
|
var privKey = wallet.getPrivateKey() |
|
|
|
var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) |
|
|
|
var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) |
|
|
@ -92,10 +80,29 @@ module.exports = class HdKeyring extends EventEmitter { |
|
|
|
return rawMsgSig |
|
|
|
return rawMsgSig |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
getWalletForAccount (account) { |
|
|
|
exportAccount (address) { |
|
|
|
|
|
|
|
const wallet = this._getWalletForAccount(address) |
|
|
|
|
|
|
|
return wallet.getPrivateKey().toString('hex') |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* PRIVATE METHODS */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_initFromMnemonic (mnemonic) { |
|
|
|
|
|
|
|
this.mnemonic = mnemonic |
|
|
|
|
|
|
|
const seed = bip39.mnemonicToSeed(mnemonic) |
|
|
|
|
|
|
|
this.hdWallet = hdkey.fromMasterSeed(seed) |
|
|
|
|
|
|
|
this.root = this.hdWallet.derivePath(hdPathString) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_getWalletForAccount (account) { |
|
|
|
return this.wallets.find((w) => { |
|
|
|
return this.wallets.find((w) => { |
|
|
|
const address = w.getAddress().toString('hex') |
|
|
|
const address = w.getAddress().toString('hex') |
|
|
|
return ((address === account) || (sigUtil.normalize(address) === account)) |
|
|
|
return ((address === account) || (sigUtil.normalize(address) === account)) |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HdKeyring.type = type |
|
|
|
|
|
|
|
module.exports = HdKeyring |
|
|
|