mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Implemented BIP44 compliance test.
Also added the hdPath that Christian had told me to our calls to the LightWallet, but this does not seem to have made us generate the same accounts as `testrpc` yet.
This commit is contained in:
parent
37fd45e5b7
commit
a2c7ccafa6
@ -53,18 +53,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) {
|
||||||
@ -73,46 +72,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()
|
||||||
@ -123,55 +116,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)
|
||||||
|
|
||||||
// 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)
|
||||||
@ -183,13 +172,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,22 +186,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(this.hdPathString).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()
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -222,8 +208,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){
|
||||||
@ -233,7 +218,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(seed, derivedKey)
|
||||||
|
|
||||||
// returning user, recovering from localStorage
|
// returning user, recovering from localStorage
|
||||||
} else if (serializedKeystore) {
|
} else if (serializedKeystore) {
|
||||||
@ -256,11 +241,12 @@ IdentityStore.prototype._createIdmgmt = function(password, seed, entropy, cb){
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype._restoreFromSeed = function(keyStore, seed, derivedKey) {
|
IdentityStore.prototype._restoreFromSeed = function(seed, derivedKey) {
|
||||||
keyStore = new LightwalletKeyStore(seed, derivedKey)
|
var keyStore = new LightwalletKeyStore(seed, derivedKey, this.hdPathString)
|
||||||
keyStore.generateNewAddress(derivedKey, 3, hdPathString)
|
keyStore.generateNewAddress(derivedKey, 3, this.hdPathString)
|
||||||
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) {
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "gulp dev",
|
"start": "gulp dev",
|
||||||
"test": "mocha --compilers js:babel-register",
|
"test": "mocha --compilers js:babel-register --recursive",
|
||||||
"watch": "mocha watch --compilers js:babel-register"
|
"watch": "mocha watch --compilers js:babel-register --recursive"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^1.5.2",
|
"async": "^1.5.2",
|
||||||
@ -44,6 +44,8 @@
|
|||||||
"lodash.assign": "^4.0.6",
|
"lodash.assign": "^4.0.6",
|
||||||
"mocha": "^2.4.5",
|
"mocha": "^2.4.5",
|
||||||
"mocha-jsdom": "^1.1.0",
|
"mocha-jsdom": "^1.1.0",
|
||||||
|
"mocha-sinon": "^1.1.5",
|
||||||
|
"sinon": "^1.17.3",
|
||||||
"tape": "^4.5.1",
|
"tape": "^4.5.1",
|
||||||
"vinyl-buffer": "^1.0.0",
|
"vinyl-buffer": "^1.0.0",
|
||||||
"vinyl-source-stream": "^1.1.0",
|
"vinyl-source-stream": "^1.1.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,7 +1,5 @@
|
|||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var IdentityStore = require('../app/scripts/lib/idStore')
|
var IdentityStore = require('../../app/scripts/lib/idStore')
|
||||||
var jsdom = require('mocha-jsdom')
|
|
||||||
jsdom()
|
|
||||||
|
|
||||||
describe('IdentityStore', function() {
|
describe('IdentityStore', function() {
|
||||||
|
|
||||||
@ -38,15 +36,46 @@ describe('IdentityStore', function() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return the expected keystore', function () {
|
it('should return the expected keystore', function (done) {
|
||||||
|
|
||||||
idStore.recoverFromSeed(password, seedWords, (err) => {
|
idStore.recoverFromSeed(password, seedWords, (err) => {
|
||||||
assert.ifError(err)
|
assert.ifError(err)
|
||||||
|
|
||||||
let newKeystore = idStore._idmgmt.keyStore
|
let newKeystore = idStore._idmgmt.keyStore
|
||||||
assert.equal(newKeystore, originalKeystore)
|
assert.equal(newKeystore, originalKeystore)
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#recoverFromSeed BIP44 compliance', function() {
|
||||||
|
let seedWords = 'picnic injury awful upper eagle junk alert toss flower renew silly vague'
|
||||||
|
let firstAccount = '0xaceef0221414801dde7f732196b1c9d8ea60b637'
|
||||||
|
let password = 'secret!'
|
||||||
|
let accounts = []
|
||||||
|
let idStore
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||||
|
|
||||||
|
idStore = new IdentityStore({
|
||||||
|
addAccount(acct) {
|
||||||
|
console.log(`pushing account ${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