mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge pull request #73 from MetaMask/Bip44
Bip44-compliant HD Tree Generation
This commit is contained in:
commit
9fbf40e702
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_appName__",
|
"name": "__MSG_appName__",
|
||||||
"version": "0.15.0",
|
"version": "1.0.0",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "__MSG_appDescription__",
|
"description": "__MSG_appDescription__",
|
||||||
"icons": {
|
"icons": {
|
||||||
|
@ -14,23 +14,24 @@ module.exports = IdentityStore
|
|||||||
|
|
||||||
inherits(IdentityStore, EventEmitter)
|
inherits(IdentityStore, EventEmitter)
|
||||||
function IdentityStore(ethStore) {
|
function IdentityStore(ethStore) {
|
||||||
const self = this
|
EventEmitter.call(this)
|
||||||
EventEmitter.call(self)
|
|
||||||
|
|
||||||
// we just use the ethStore to auto-add accounts
|
// we just use the ethStore to auto-add accounts
|
||||||
self._ethStore = ethStore
|
this._ethStore = ethStore
|
||||||
// lightwallet key store
|
// lightwallet key store
|
||||||
self._keyStore = null
|
this._keyStore = null
|
||||||
// lightwallet wrapper
|
// lightwallet wrapper
|
||||||
self._idmgmt = null
|
this._idmgmt = null
|
||||||
|
|
||||||
self._currentState = {
|
this.hdPathString = "m/44'/60'/0'/0"
|
||||||
|
|
||||||
|
this._currentState = {
|
||||||
selectedAddress: null,
|
selectedAddress: null,
|
||||||
identities: {},
|
identities: {},
|
||||||
unconfTxs: {},
|
unconfTxs: {},
|
||||||
}
|
}
|
||||||
// not part of serilized metamask state - only kept in memory
|
// not part of serilized metamask state - only kept in memory
|
||||||
self._unconfTxCbs = {}
|
this._unconfTxCbs = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -51,18 +52,17 @@ IdentityStore.prototype.createNewVault = function(password, entropy, cb){
|
|||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
||||||
const self = this
|
this._createIdmgmt(password, seed, null, (err) => {
|
||||||
self._createIdmgmt(password, seed, null, function(err){
|
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
self._loadIdentities()
|
|
||||||
self._didUpdate()
|
this._loadIdentities()
|
||||||
|
this._didUpdate()
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.setStore = function(store){
|
IdentityStore.prototype.setStore = function(store){
|
||||||
const self = this
|
this._ethStore = store
|
||||||
self._ethStore = store
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.clearSeedWordCache = function(cb) {
|
IdentityStore.prototype.clearSeedWordCache = function(cb) {
|
||||||
@ -71,46 +71,40 @@ IdentityStore.prototype.clearSeedWordCache = function(cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.getState = function(){
|
IdentityStore.prototype.getState = function(){
|
||||||
const self = this
|
|
||||||
const cachedSeeds = window.localStorage['seedWords']
|
const cachedSeeds = window.localStorage['seedWords']
|
||||||
return clone(extend(self._currentState, {
|
return clone(extend(this._currentState, {
|
||||||
isInitialized: !!window.localStorage['lightwallet'] && !cachedSeeds,
|
isInitialized: !!window.localStorage['lightwallet'] && !cachedSeeds,
|
||||||
isUnlocked: self._isUnlocked(),
|
isUnlocked: this._isUnlocked(),
|
||||||
seedWords: cachedSeeds,
|
seedWords: cachedSeeds,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.getSelectedAddress = function(){
|
IdentityStore.prototype.getSelectedAddress = function(){
|
||||||
const self = this
|
return this._currentState.selectedAddress
|
||||||
return self._currentState.selectedAddress
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.setSelectedAddress = function(address){
|
IdentityStore.prototype.setSelectedAddress = function(address){
|
||||||
const self = this
|
this._currentState.selectedAddress = address
|
||||||
self._currentState.selectedAddress = address
|
this._didUpdate()
|
||||||
self._didUpdate()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.setLocked = function(cb){
|
IdentityStore.prototype.setLocked = function(cb){
|
||||||
const self = this
|
delete this._keyStore
|
||||||
delete self._keyStore
|
delete this._idmgmt
|
||||||
delete self._idmgmt
|
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.submitPassword = function(password, cb){
|
IdentityStore.prototype.submitPassword = function(password, cb){
|
||||||
const self = this
|
this._tryPassword(password, (err) => {
|
||||||
self._tryPassword(password, function(err){
|
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
// load identities before returning...
|
// load identities before returning...
|
||||||
self._loadIdentities()
|
this._loadIdentities()
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// comes from dapp via zero-client hooked-wallet provider
|
// comes from dapp via zero-client hooked-wallet provider
|
||||||
IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){
|
IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){
|
||||||
var self = this
|
|
||||||
|
|
||||||
// create txData obj with parameters and meta data
|
// create txData obj with parameters and meta data
|
||||||
var time = (new Date()).getTime()
|
var time = (new Date()).getTime()
|
||||||
@ -121,56 +115,51 @@ IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){
|
|||||||
time: time,
|
time: time,
|
||||||
status: 'unconfirmed',
|
status: 'unconfirmed',
|
||||||
}
|
}
|
||||||
self._currentState.unconfTxs[txId] = txData
|
this._currentState.unconfTxs[txId] = txData
|
||||||
console.log('addUnconfirmedTransaction:', txData)
|
console.log('addUnconfirmedTransaction:', txData)
|
||||||
|
|
||||||
// keep the cb around for after approval (requires user interaction)
|
// keep the cb around for after approval (requires user interaction)
|
||||||
self._unconfTxCbs[txId] = cb
|
this._unconfTxCbs[txId] = cb
|
||||||
|
|
||||||
// signal update
|
// signal update
|
||||||
self._didUpdate()
|
this._didUpdate()
|
||||||
|
|
||||||
return txId
|
return txId
|
||||||
}
|
}
|
||||||
|
|
||||||
// comes from metamask ui
|
// comes from metamask ui
|
||||||
IdentityStore.prototype.approveTransaction = function(txId, cb){
|
IdentityStore.prototype.approveTransaction = function(txId, cb){
|
||||||
const self = this
|
var txData = this._currentState.unconfTxs[txId]
|
||||||
|
|
||||||
var txData = self._currentState.unconfTxs[txId]
|
|
||||||
var txParams = txData.txParams
|
var txParams = txData.txParams
|
||||||
var approvalCb = self._unconfTxCbs[txId] || noop
|
var approvalCb = this._unconfTxCbs[txId] || noop
|
||||||
|
|
||||||
// accept tx
|
// accept tx
|
||||||
cb()
|
cb()
|
||||||
approvalCb(null, true)
|
approvalCb(null, true)
|
||||||
// clean up
|
// clean up
|
||||||
delete self._currentState.unconfTxs[txId]
|
delete this._currentState.unconfTxs[txId]
|
||||||
delete self._unconfTxCbs[txId]
|
delete this._unconfTxCbs[txId]
|
||||||
self._didUpdate()
|
this._didUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// comes from metamask ui
|
// comes from metamask ui
|
||||||
IdentityStore.prototype.cancelTransaction = function(txId){
|
IdentityStore.prototype.cancelTransaction = function(txId){
|
||||||
const self = this
|
var txData = this._currentState.unconfTxs[txId]
|
||||||
|
var approvalCb = this._unconfTxCbs[txId] || noop
|
||||||
var txData = self._currentState.unconfTxs[txId]
|
|
||||||
var approvalCb = self._unconfTxCbs[txId] || noop
|
|
||||||
|
|
||||||
// reject tx
|
// reject tx
|
||||||
approvalCb(null, false)
|
approvalCb(null, false)
|
||||||
// clean up
|
// clean up
|
||||||
delete self._currentState.unconfTxs[txId]
|
delete this._currentState.unconfTxs[txId]
|
||||||
delete self._unconfTxCbs[txId]
|
delete this._unconfTxCbs[txId]
|
||||||
self._didUpdate()
|
this._didUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// performs the actual signing, no autofill of params
|
// performs the actual signing, no autofill of params
|
||||||
IdentityStore.prototype.signTransaction = function(txParams, cb){
|
IdentityStore.prototype.signTransaction = function(txParams, cb){
|
||||||
const self = this
|
|
||||||
try {
|
try {
|
||||||
console.log('signing tx...', txParams)
|
console.log('signing tx...', txParams)
|
||||||
var rawTx = self._idmgmt.signTx(txParams)
|
var rawTx = this._idmgmt.signTx(txParams)
|
||||||
cb(null, rawTx)
|
cb(null, rawTx)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
cb(err)
|
cb(err)
|
||||||
@ -182,13 +171,11 @@ IdentityStore.prototype.signTransaction = function(txParams, cb){
|
|||||||
//
|
//
|
||||||
|
|
||||||
IdentityStore.prototype._didUpdate = function(){
|
IdentityStore.prototype._didUpdate = function(){
|
||||||
const self = this
|
this.emit('update', this.getState())
|
||||||
self.emit('update', self.getState())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype._isUnlocked = function(){
|
IdentityStore.prototype._isUnlocked = function(){
|
||||||
const self = this
|
var result = Boolean(this._keyStore) && Boolean(this._idmgmt)
|
||||||
var result = Boolean(self._keyStore) && Boolean(self._idmgmt)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,22 +185,21 @@ IdentityStore.prototype._cacheSeedWordsUntilConfirmed = function(seedWords) {
|
|||||||
|
|
||||||
// load identities from keyStoreet
|
// load identities from keyStoreet
|
||||||
IdentityStore.prototype._loadIdentities = function(){
|
IdentityStore.prototype._loadIdentities = function(){
|
||||||
const self = this
|
if (!this._isUnlocked()) throw new Error('not unlocked')
|
||||||
if (!self._isUnlocked()) throw new Error('not unlocked')
|
|
||||||
// get addresses and normalize address hexString
|
// get addresses and normalize address hexString
|
||||||
var addresses = self._keyStore.getAddresses().map(function(address){ return '0x'+address })
|
var addresses = this._keyStore.getAddresses(this.hdPathString).map((address) => { return '0x'+address })
|
||||||
addresses.forEach(function(address){
|
addresses.forEach((address) => {
|
||||||
// // add to ethStore
|
// // add to ethStore
|
||||||
self._ethStore.addAccount(address)
|
this._ethStore.addAccount(address)
|
||||||
// add to identities
|
// add to identities
|
||||||
var identity = {
|
var identity = {
|
||||||
name: 'Wally',
|
name: 'Wally',
|
||||||
img: 'QmW6hcwYzXrNkuHrpvo58YeZvbZxUddv69ATSHY3BHpPdd',
|
img: 'QmW6hcwYzXrNkuHrpvo58YeZvbZxUddv69ATSHY3BHpPdd',
|
||||||
address: address,
|
address: address,
|
||||||
}
|
}
|
||||||
self._currentState.identities[address] = identity
|
this._currentState.identities[address] = identity
|
||||||
})
|
})
|
||||||
self._didUpdate()
|
this._didUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -221,8 +207,7 @@ IdentityStore.prototype._loadIdentities = function(){
|
|||||||
//
|
//
|
||||||
|
|
||||||
IdentityStore.prototype._tryPassword = function(password, cb){
|
IdentityStore.prototype._tryPassword = function(password, cb){
|
||||||
const self = this
|
this._createIdmgmt(password, null, null, cb)
|
||||||
self._createIdmgmt(password, null, null, cb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
|
IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
|
||||||
@ -232,7 +217,7 @@ IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
|
|||||||
var serializedKeystore = window.localStorage['lightwallet']
|
var serializedKeystore = window.localStorage['lightwallet']
|
||||||
|
|
||||||
if (seed) {
|
if (seed) {
|
||||||
this._restoreFromSeed(keyStore, seed, derivedKey)
|
keyStore = this._restoreFromSeed(password, seed, derivedKey)
|
||||||
|
|
||||||
// returning user, recovering from localStorage
|
// returning user, recovering from localStorage
|
||||||
} else if (serializedKeystore) {
|
} else if (serializedKeystore) {
|
||||||
@ -249,17 +234,22 @@ IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
|
|||||||
this._idmgmt = new IdManagement({
|
this._idmgmt = new IdManagement({
|
||||||
keyStore: keyStore,
|
keyStore: keyStore,
|
||||||
derivedKey: derivedKey,
|
derivedKey: derivedKey,
|
||||||
|
hdPathSTring: this.hdPathString,
|
||||||
})
|
})
|
||||||
|
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype._restoreFromSeed = function(keyStore, seed, derivedKey) {
|
IdentityStore.prototype._restoreFromSeed = function(password, seed, derivedKey) {
|
||||||
keyStore = new LightwalletKeyStore(seed, derivedKey)
|
var keyStore = new LightwalletKeyStore(seed, derivedKey, this.hdPathString)
|
||||||
|
keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'});
|
||||||
|
keyStore.setDefaultHdDerivationPath(this.hdPathString)
|
||||||
|
|
||||||
keyStore.generateNewAddress(derivedKey, 3)
|
keyStore.generateNewAddress(derivedKey, 3)
|
||||||
window.localStorage['lightwallet'] = keyStore.serialize()
|
window.localStorage['lightwallet'] = keyStore.serialize()
|
||||||
console.log('restored from seed. saved to keystore localStorage')
|
console.log('restored from seed. saved to keystore localStorage')
|
||||||
|
return keyStore
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype._loadFromLocalStorage = function(serializedKeystore, derivedKey) {
|
IdentityStore.prototype._loadFromLocalStorage = function(serializedKeystore, derivedKey) {
|
||||||
@ -268,19 +258,23 @@ IdentityStore.prototype._loadFromLocalStorage = function(serializedKeystore, der
|
|||||||
|
|
||||||
IdentityStore.prototype._createFirstWallet = function(entropy, derivedKey) {
|
IdentityStore.prototype._createFirstWallet = function(entropy, derivedKey) {
|
||||||
var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy)
|
var secretSeed = LightwalletKeyStore.generateRandomSeed(entropy)
|
||||||
var keyStore = new LightwalletKeyStore(secretSeed, derivedKey)
|
var keyStore = new LightwalletKeyStore(secretSeed, derivedKey, this.hdPathString)
|
||||||
|
keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'});
|
||||||
|
keyStore.setDefaultHdDerivationPath(this.hdPathString)
|
||||||
|
|
||||||
keyStore.generateNewAddress(derivedKey, 3)
|
keyStore.generateNewAddress(derivedKey, 3)
|
||||||
window.localStorage['lightwallet'] = keyStore.serialize()
|
window.localStorage['lightwallet'] = keyStore.serialize()
|
||||||
console.log('saved to keystore localStorage')
|
console.log('saved to keystore localStorage')
|
||||||
return keyStore
|
return keyStore
|
||||||
}
|
}
|
||||||
|
|
||||||
function IdManagement( opts = { keyStore: null, derivedKey: null } ) {
|
function IdManagement( opts = { keyStore: null, derivedKey: null, hdPathString: null } ) {
|
||||||
this.keyStore = opts.keyStore
|
this.keyStore = opts.keyStore
|
||||||
this.derivedKey = opts.derivedKey
|
this.derivedKey = opts.derivedKey
|
||||||
|
this.hdPathString = opts.hdPathString
|
||||||
|
|
||||||
this.getAddresses = function(){
|
this.getAddresses = function(){
|
||||||
return keyStore.getAddresses().map(function(address){ return '0x'+address })
|
return keyStore.getAddresses(this.hdPathString).map(function(address){ return '0x'+address })
|
||||||
}
|
}
|
||||||
|
|
||||||
this.signTx = function(txParams){
|
this.signTx = function(txParams){
|
||||||
|
10
package.json
10
package.json
@ -4,7 +4,8 @@
|
|||||||
"public": false,
|
"public": false,
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "gulp dev"
|
"start": "gulp dev",
|
||||||
|
"test": "mocha --compilers js:babel-register --recursive"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^1.5.2",
|
"async": "^1.5.2",
|
||||||
@ -28,6 +29,8 @@
|
|||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel-preset-es2015": "^6.6.0",
|
||||||
|
"babel-register": "^6.7.2",
|
||||||
"browserify": "^13.0.0",
|
"browserify": "^13.0.0",
|
||||||
"del": "^2.2.0",
|
"del": "^2.2.0",
|
||||||
"gulp": "github:gulpjs/gulp#4.0",
|
"gulp": "github:gulpjs/gulp#4.0",
|
||||||
@ -35,8 +38,13 @@
|
|||||||
"gulp-sourcemaps": "^1.6.0",
|
"gulp-sourcemaps": "^1.6.0",
|
||||||
"gulp-util": "^3.0.7",
|
"gulp-util": "^3.0.7",
|
||||||
"gulp-watch": "^4.3.5",
|
"gulp-watch": "^4.3.5",
|
||||||
|
"jsdom": "^8.1.0",
|
||||||
"jshint-stylish": "~0.1.5",
|
"jshint-stylish": "~0.1.5",
|
||||||
"lodash.assign": "^4.0.6",
|
"lodash.assign": "^4.0.6",
|
||||||
|
"mocha": "^2.4.5",
|
||||||
|
"mocha-jsdom": "^1.1.0",
|
||||||
|
"mocha-sinon": "^1.1.5",
|
||||||
|
"sinon": "^1.17.3",
|
||||||
"vinyl-buffer": "^1.0.0",
|
"vinyl-buffer": "^1.0.0",
|
||||||
"vinyl-source-stream": "^1.1.0",
|
"vinyl-source-stream": "^1.1.0",
|
||||||
"watchify": "^3.7.0"
|
"watchify": "^3.7.0"
|
||||||
|
4
test/helper.js
Normal file
4
test/helper.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
require('mocha-sinon')()
|
||||||
|
var jsdom = require('mocha-jsdom')
|
||||||
|
jsdom()
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Mocha Spec Runner</title>
|
|
||||||
<link rel="stylesheet" href="../bower_components/mocha/mocha.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="mocha"></div>
|
|
||||||
<script src="../bower_components/mocha/mocha.js"></script>
|
|
||||||
<script>mocha.setup('bdd');</script>
|
|
||||||
<script src="../bower_components/chai/chai.js"></script>
|
|
||||||
<script>
|
|
||||||
var assert = chai.assert;
|
|
||||||
var expect = chai.expect;
|
|
||||||
var should = chai.should();
|
|
||||||
</script>
|
|
||||||
<!-- bower:js -->
|
|
||||||
<!-- endbower -->
|
|
||||||
<!-- include source files here... -->
|
|
||||||
<!-- include spec files here... -->
|
|
||||||
<script src="spec/test.js"></script>
|
|
||||||
<script>
|
|
||||||
if (navigator.userAgent.indexOf('PhantomJS') === -1) {
|
|
||||||
mocha.run();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,11 +0,0 @@
|
|||||||
(function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
describe('Give it some context', function () {
|
|
||||||
describe('maybe a bit more context here', function () {
|
|
||||||
it('should run here few assertions', function () {
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})();
|
|
81
test/unit/idStore-test.js
Normal file
81
test/unit/idStore-test.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
var assert = require('assert')
|
||||||
|
var IdentityStore = require('../../app/scripts/lib/idStore')
|
||||||
|
|
||||||
|
describe('IdentityStore', function() {
|
||||||
|
|
||||||
|
describe('#createNewVault', function () {
|
||||||
|
let idStore
|
||||||
|
let password = 'password123'
|
||||||
|
let entropy = 'entripppppyy duuude'
|
||||||
|
let seedWords
|
||||||
|
let accounts = []
|
||||||
|
let originalKeystore
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||||
|
|
||||||
|
idStore = new IdentityStore({
|
||||||
|
addAccount(acct) { accounts.push(acct) },
|
||||||
|
})
|
||||||
|
|
||||||
|
idStore.createNewVault(password, entropy, (err, seeds) => {
|
||||||
|
seedWords = seeds
|
||||||
|
originalKeystore = idStore._idmgmt.keyStore
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#recoverFromSeed', function() {
|
||||||
|
let newAccounts = []
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||||
|
|
||||||
|
idStore = new IdentityStore({
|
||||||
|
addAccount(acct) { newAccounts.push(acct) },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return the expected keystore', function (done) {
|
||||||
|
|
||||||
|
idStore.recoverFromSeed(password, seedWords, (err) => {
|
||||||
|
assert.ifError(err)
|
||||||
|
|
||||||
|
let newKeystore = idStore._idmgmt.keyStore
|
||||||
|
assert.equal(newAccounts[0], accounts[0])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#recoverFromSeed BIP44 compliance', function() {
|
||||||
|
let seedWords = 'picnic injury awful upper eagle junk alert toss flower renew silly vague'
|
||||||
|
let firstAccount = '0x5d8de92c205279c10e5669f797b853ccef4f739a'
|
||||||
|
|
||||||
|
let password = 'secret!'
|
||||||
|
let accounts = []
|
||||||
|
let idStore
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||||
|
|
||||||
|
idStore = new IdentityStore({
|
||||||
|
addAccount(acct) {
|
||||||
|
accounts.push(acct)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return the expected first account', function (done) {
|
||||||
|
|
||||||
|
idStore.recoverFromSeed(password, seedWords, (err) => {
|
||||||
|
assert.ifError(err)
|
||||||
|
|
||||||
|
let newKeystore = idStore._idmgmt.keyStore
|
||||||
|
assert.equal(accounts[0], firstAccount)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user