aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrankie <frankie.diamond@gmail.com>2017-01-29 14:59:28 +0800
committerFrankie <frankie.diamond@gmail.com>2017-01-29 14:59:28 +0800
commitfdee1e3701a84fe1321de348ec2d11bf5361a62d (patch)
tree1844d6c25cc824c9303ab79103525cab08d5e0b3
parent8be68575bbef1dcc89b51355abaee90dbf018387 (diff)
parent47b48c0e02b2b9508813abfda0d89a1bbe677694 (diff)
downloadtangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.tar
tangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.tar.gz
tangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.tar.bz2
tangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.tar.lz
tangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.tar.xz
tangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.tar.zst
tangerine-wallet-browser-fdee1e3701a84fe1321de348ec2d11bf5361a62d.zip
Merge branch 'dev' into messageManagerCleanUp
-rw-r--r--app/scripts/keyring-controller.js101
-rw-r--r--app/scripts/lib/config-manager.js10
-rw-r--r--app/scripts/metamask-controller.js257
-rw-r--r--app/scripts/migrations/005.js41
-rw-r--r--app/scripts/migrations/index.js1
-rw-r--r--package.json2
-rw-r--r--test/unit/idStore-migration-test.js61
-rw-r--r--test/unit/keyring-controller-test.js56
-rw-r--r--test/unit/metamask-controller-test.js68
-rw-r--r--ui/app/account-detail.js5
-rw-r--r--ui/app/accounts/account-list-item.js5
-rw-r--r--ui/app/first-time/init-menu.js1
12 files changed, 274 insertions, 334 deletions
diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js
index b6c9aa3a7..b56b5520f 100644
--- a/app/scripts/keyring-controller.js
+++ b/app/scripts/keyring-controller.js
@@ -1,12 +1,12 @@
const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
const bip39 = require('bip39')
const EventEmitter = require('events').EventEmitter
+const ObservableStore = require('obs-store')
const filter = require('promise-filter')
const encryptor = require('browser-passworder')
-
-const normalize = require('./lib/sig-util').normalize
-const BN = ethUtil.BN
-
+const normalizeAddress = require('./lib/sig-util').normalize
+function noop () {}
// Keyrings:
const SimpleKeyring = require('./keyrings/simple')
const HdKeyring = require('./keyrings/hd')
@@ -15,7 +15,7 @@ const keyringTypes = [
HdKeyring,
]
-module.exports = class KeyringController extends EventEmitter {
+class KeyringController extends EventEmitter {
// PUBLIC METHODS
//
@@ -26,6 +26,8 @@ module.exports = class KeyringController extends EventEmitter {
constructor (opts) {
super()
+ const initState = opts.initState || {}
+ this.store = new ObservableStore(initState)
this.configManager = opts.configManager
this.ethStore = opts.ethStore
this.encryptor = encryptor
@@ -65,27 +67,29 @@ module.exports = class KeyringController extends EventEmitter {
// in this class, but will need to be Promisified when we move our
// persistence to an async model.
getState () {
- const configManager = this.configManager
- const address = configManager.getSelectedAccount()
- const wallet = configManager.getWallet() // old style vault
- const vault = configManager.getVault() // new style vault
- const keyrings = this.keyrings
-
- return Promise.all(keyrings.map(this.displayForKeyring))
+ return Promise.all(this.keyrings.map(this.displayForKeyring))
.then((displayKeyrings) => {
+ const state = this.store.getState()
+ // old wallet
+ const wallet = this.configManager.getWallet()
return {
+ // computed
+ isInitialized: (!!wallet || !!state.vault),
+ isUnlocked: (!!this.password),
+ keyrings: displayKeyrings,
+ // hard coded
+ keyringTypes: this.keyringTypes.map(krt => krt.type),
+ // memStore
+ identities: this.identities,
+ // diskStore
+ selectedAccount: state.selectedAccount,
+ // configManager
seedWords: this.configManager.getSeedWords(),
- isInitialized: (!!wallet || !!vault),
- isUnlocked: Boolean(this.password),
isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(),
- selectedAccount: address,
- shapeShiftTxList: this.configManager.getShapeShiftTxList(),
currentFiat: this.configManager.getCurrentFiat(),
conversionRate: this.configManager.getConversionRate(),
conversionDate: this.configManager.getConversionDate(),
- keyringTypes: this.keyringTypes.map(krt => krt.type),
- identities: this.identities,
- keyrings: displayKeyrings,
+ // messageManager
}
})
}
@@ -138,8 +142,8 @@ module.exports = class KeyringController extends EventEmitter {
.then((accounts) => {
const firstAccount = accounts[0]
if (!firstAccount) throw new Error('KeyringController - First Account not found.')
- const hexAccount = normalize(firstAccount)
- this.configManager.setSelectedAccount(hexAccount)
+ const hexAccount = normalizeAddress(firstAccount)
+ this.setSelectedAccount(hexAccount)
return this.setupAccounts(accounts)
})
.then(this.persistAllKeyrings.bind(this, password))
@@ -236,9 +240,9 @@ module.exports = class KeyringController extends EventEmitter {
//
// Sets the state's `selectedAccount` value
// to the specified address.
- setSelectedAccount (address) {
- var addr = normalize(address)
- this.configManager.setSelectedAccount(addr)
+ setSelectedAccount (account) {
+ var address = normalizeAddress(account)
+ this.store.updateState({ selectedAccount: address })
return this.fullUpdate()
}
@@ -250,11 +254,19 @@ module.exports = class KeyringController extends EventEmitter {
//
// Persists a nickname equal to `label` for the specified account.
saveAccountLabel (account, label) {
- const address = normalize(account)
- const configManager = this.configManager
- configManager.setNicknameForWallet(address, label)
- this.identities[address].name = label
- return Promise.resolve(label)
+ try {
+ const hexAddress = normalizeAddress(account)
+ // update state on diskStore
+ const state = this.store.getState()
+ const walletNicknames = state.walletNicknames || {}
+ walletNicknames[hexAddress] = label
+ this.store.updateState({ walletNicknames })
+ // update state on memStore
+ this.identities[hexAddress].name = label
+ return Promise.resolve(label)
+ } catch (err) {
+ return Promise.reject(err)
+ }
}
// Export Account
@@ -270,7 +282,7 @@ module.exports = class KeyringController extends EventEmitter {
try {
return this.getKeyringForAccount(address)
.then((keyring) => {
- return keyring.exportAccount(normalize(address))
+ return keyring.exportAccount(normalizeAddress(address))
})
} catch (e) {
return Promise.reject(e)
@@ -284,7 +296,7 @@ module.exports = class KeyringController extends EventEmitter {
// TX Manager to update the state after signing
signTransaction (ethTx, _fromAddress) {
- const fromAddress = normalize(_fromAddress)
+ const fromAddress = normalizeAddress(_fromAddress)
return this.getKeyringForAccount(fromAddress)
.then((keyring) => {
return keyring.signTransaction(fromAddress, ethTx)
@@ -328,8 +340,8 @@ module.exports = class KeyringController extends EventEmitter {
.then((accounts) => {
const firstAccount = accounts[0]
if (!firstAccount) throw new Error('KeyringController - No account found on keychain.')
- const hexAccount = normalize(firstAccount)
- this.configManager.setSelectedAccount(hexAccount)
+ const hexAccount = normalizeAddress(firstAccount)
+ this.setSelectedAccount(hexAccount)
this.emit('newAccount', hexAccount)
return this.setupAccounts(accounts)
})
@@ -365,7 +377,7 @@ module.exports = class KeyringController extends EventEmitter {
if (!account) {
throw new Error('Problem loading account.')
}
- const address = normalize(account)
+ const address = normalizeAddress(account)
this.ethStore.addAccount(address)
return this.createNickname(address)
}
@@ -377,10 +389,11 @@ module.exports = class KeyringController extends EventEmitter {
//
// Takes an address, and assigns it an incremented nickname, persisting it.
createNickname (address) {
- const hexAddress = normalize(address)
- var i = Object.keys(this.identities).length
- const oldNickname = this.configManager.nicknameForWallet(address)
- const name = oldNickname || `Account ${++i}`
+ const hexAddress = normalizeAddress(address)
+ const currentIdentityCount = Object.keys(this.identities).length + 1
+ const nicknames = this.store.getState().walletNicknames || {}
+ const existingNickname = nicknames[hexAddress]
+ const name = existingNickname || `Account ${currentIdentityCount}`
this.identities[hexAddress] = {
address: hexAddress,
name,
@@ -415,7 +428,7 @@ module.exports = class KeyringController extends EventEmitter {
return this.encryptor.encrypt(this.password, serializedKeyrings)
})
.then((encryptedString) => {
- this.configManager.setVault(encryptedString)
+ this.store.updateState({ vault: encryptedString })
return true
})
}
@@ -428,7 +441,7 @@ module.exports = class KeyringController extends EventEmitter {
// Attempts to unlock the persisted encrypted storage,
// initializing the persisted keyrings to RAM.
unlockKeyrings (password) {
- const encryptedVault = this.configManager.getVault()
+ const encryptedVault = this.store.getState().vault
if (!encryptedVault) {
throw new Error('Cannot unlock without a previous vault.')
}
@@ -508,7 +521,7 @@ module.exports = class KeyringController extends EventEmitter {
// Returns the currently initialized keyring that manages
// the specified `address` if one exists.
getKeyringForAccount (address) {
- const hexed = normalize(address)
+ const hexed = normalizeAddress(address)
return Promise.all(this.keyrings.map((keyring) => {
return Promise.all([
@@ -517,7 +530,7 @@ module.exports = class KeyringController extends EventEmitter {
])
}))
.then(filter((candidate) => {
- const accounts = candidate[1].map(normalize)
+ const accounts = candidate[1].map(normalizeAddress)
return accounts.includes(hexed)
}))
.then((winners) => {
@@ -575,7 +588,9 @@ module.exports = class KeyringController extends EventEmitter {
this.keyrings = []
this.identities = {}
- this.configManager.setSelectedAccount()
+ this.setSelectedAccount()
}
}
+
+module.exports = KeyringController
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index fd4ac511a..357e081b1 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -29,15 +29,7 @@ ConfigManager.prototype.setConfig = function (config) {
ConfigManager.prototype.getConfig = function () {
var data = this.getData()
- if ('config' in data) {
- return data.config
- } else {
- return {
- provider: {
- type: 'testnet',
- },
- }
- }
+ return data.config
}
ConfigManager.prototype.setRpcTarget = function (rpcUrl) {
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 571968b65..a76d5cd86 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -29,9 +29,10 @@ module.exports = class MetamaskController extends EventEmitter {
super()
this.opts = opts
this.state = { network: 'loading' }
+ let initState = opts.initState || {}
// observable state store
- this.store = new ObservableStore(opts.initState)
+ this.store = new ObservableStore(initState)
// config manager
this.configManager = new ConfigManager({
@@ -41,7 +42,7 @@ module.exports = class MetamaskController extends EventEmitter {
// rpc provider
this.provider = this.initializeProvider(opts)
- this.provider.on('block', this.processBlock.bind(this))
+ this.provider.on('block', this.logBlock.bind(this))
this.provider.on('error', this.getNetwork.bind(this))
// eth data query tools
@@ -50,6 +51,7 @@ module.exports = class MetamaskController extends EventEmitter {
// key mgmt
this.keyringController = new KeyringController({
+ initState: initState.KeyringController,
ethStore: this.ethStore,
configManager: this.configManager,
getNetwork: this.getStateNetwork.bind(this),
@@ -97,6 +99,9 @@ module.exports = class MetamaskController extends EventEmitter {
this.keyringController.on('update', this.sendUpdate.bind(this))
this.txManager.on('update', this.sendUpdate.bind(this))
this.messageManager.on('update', this.sendUpdate.bind(this))
+ this.keyringController.store.subscribe((state) => {
+ this.store.updateState({ KeyringController: state })
+ })
}
//
@@ -139,9 +144,7 @@ module.exports = class MetamaskController extends EventEmitter {
const result = { selectedAccount: undefined }
try {
result.selectedAccount = state.config.selectedAccount
- } catch (_) {
- // thats fine, im sure it will be there next time...
- }
+ } catch (_) {}
return result
}
@@ -162,7 +165,9 @@ module.exports = class MetamaskController extends EventEmitter {
this.txManager.getState(),
this.messageManager.getState(),
keyringControllerState,
- this.noticeController.getState(), {
+ this.noticeController.getState(),
+ {
+ shapeShiftTxList: this.configManager.getShapeShiftTxList(),
lostAccounts: this.configManager.getLostAccounts(),
}
)
@@ -268,6 +273,13 @@ module.exports = class MetamaskController extends EventEmitter {
}
}
+ setupPublicConfig (outStream) {
+ pipe(
+ this.publicConfigStore,
+ outStream
+ )
+ }
+
sendUpdate () {
this.getState()
.then((state) => {
@@ -388,31 +400,90 @@ module.exports = class MetamaskController extends EventEmitter {
}).catch((err) => cb(err))
}
- setupPublicConfig (outStream) {
- pipe(
- this.publicConfigStore,
- outStream
- )
+
+ markAccountsFound (cb) {
+ this.configManager.setLostAccounts([])
+ this.sendUpdate()
+ cb(null, this.getState())
}
- // Log blocks
- processBlock (block) {
- if (global.METAMASK_DEBUG) {
- console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`)
+ // Migrate Old Vault If Any
+ // @string password
+ //
+ // returns Promise()
+ //
+ // Temporary step used when logging in.
+ // Checks if old style (pre-3.0.0) Metamask Vault exists.
+ // If so, persists that vault in the new vault format
+ // with the provided password, so the other unlock steps
+ // may be completed without interruption.
+ migrateOldVaultIfAny (password) {
+
+ if (!this.checkIfShouldMigrate()) {
+ return Promise.resolve(password)
}
- this.verifyNetwork()
+
+ const keyringController = this.keyringController
+
+ return this.idStoreMigrator.migratedVaultForPassword(password)
+ .then(this.restoreOldVaultAccounts.bind(this))
+ .then(this.restoreOldLostAccounts.bind(this))
+ .then(keyringController.persistAllKeyrings.bind(keyringController, password))
+ .then(() => password)
}
- verifyNetwork () {
- // Check network when restoring connectivity:
- if (this.state.network === 'loading') {
- this.getNetwork()
+ checkIfShouldMigrate() {
+ return !!this.configManager.getWallet() && !this.configManager.getVault()
+ }
+
+ restoreOldVaultAccounts(migratorOutput) {
+ const { serialized } = migratorOutput
+ return this.keyringController.restoreKeyring(serialized)
+ .then(() => migratorOutput)
+ }
+
+ restoreOldLostAccounts(migratorOutput) {
+ const { lostAccounts } = migratorOutput
+ if (lostAccounts) {
+ this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address))
+ return this.importLostAccounts(migratorOutput)
}
+ return Promise.resolve(migratorOutput)
}
- // config
+ // IMPORT LOST ACCOUNTS
+ // @Object with key lostAccounts: @Array accounts <{ address, privateKey }>
+ // Uses the array's private keys to create a new Simple Key Pair keychain
+ // and add it to the keyring controller.
+ importLostAccounts ({ lostAccounts }) {
+ const privKeys = lostAccounts.map(acct => acct.privateKey)
+ return this.keyringController.restoreKeyring({
+ type: 'Simple Key Pair',
+ data: privKeys,
+ })
+ }
+
+ //
+ // disclaimer
//
+ agreeToDisclaimer (cb) {
+ try {
+ this.configManager.setConfirmedDisclaimer(true)
+ cb()
+ } catch (err) {
+ cb(err)
+ }
+ }
+
+ resetDisclaimer () {
+ try {
+ this.configManager.setConfirmedDisclaimer(false)
+ } catch (e) {
+ console.error(e)
+ }
+ }
+
setTOSHash (hash) {
try {
this.configManager.setTOSHash(hash)
@@ -433,23 +504,16 @@ module.exports = class MetamaskController extends EventEmitter {
}
}
- // disclaimer
-
- agreeToDisclaimer (cb) {
- try {
- this.configManager.setConfirmedDisclaimer(true)
- cb()
- } catch (err) {
- cb(err)
- }
- }
+ //
+ // config
+ //
- resetDisclaimer () {
- try {
- this.configManager.setConfirmedDisclaimer(false)
- } catch (e) {
- console.error(e)
+ // Log blocks
+ logBlock (block) {
+ if (global.METAMASK_DEBUG) {
+ console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`)
}
+ this.verifyNetwork()
}
setCurrentFiat (fiat, cb) {
@@ -477,24 +541,6 @@ module.exports = class MetamaskController extends EventEmitter {
}, 300000)
}
- // called from popup
- setRpcTarget (rpcTarget) {
- this.configManager.setRpcTarget(rpcTarget)
- extension.runtime.reload()
- this.getNetwork()
- }
-
- setProviderType (type) {
- this.configManager.setProviderType(type)
- extension.runtime.reload()
- this.getNetwork()
- }
-
- useEtherscanProvider () {
- this.configManager.useEtherscanProvider()
- extension.runtime.reload()
- }
-
buyEth (address, amount) {
if (!amount) amount = '5'
@@ -514,25 +560,6 @@ module.exports = class MetamaskController extends EventEmitter {
this.configManager.createShapeShiftTx(depositAddress, depositType)
}
- getNetwork (err) {
- if (err) {
- this.state.network = 'loading'
- this.sendUpdate()
- }
-
- this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
- if (err) {
- this.state.network = 'loading'
- return this.sendUpdate()
- }
- if (global.METAMASK_DEBUG) {
- console.log('web3.getNetwork returned ' + network)
- }
- this.state.network = network
- this.sendUpdate()
- })
- }
-
setGasMultiplier (gasMultiplier, cb) {
try {
this.configManager.setGasMultiplier(gasMultiplier)
@@ -542,69 +569,55 @@ module.exports = class MetamaskController extends EventEmitter {
}
}
- getStateNetwork () {
- return this.state.network
- }
-
- markAccountsFound (cb) {
- this.configManager.setLostAccounts([])
- this.sendUpdate()
- cb(null, this.getState())
- }
-
- // Migrate Old Vault If Any
- // @string password
//
- // returns Promise()
+ // network
//
- // Temporary step used when logging in.
- // Checks if old style (pre-3.0.0) Metamask Vault exists.
- // If so, persists that vault in the new vault format
- // with the provided password, so the other unlock steps
- // may be completed without interruption.
- migrateOldVaultIfAny (password) {
- if (!this.checkIfShouldMigrate()) {
- return Promise.resolve(password)
+ verifyNetwork () {
+ // Check network when restoring connectivity:
+ if (this.state.network === 'loading') {
+ this.getNetwork()
}
+ }
- const keyringController = this.keyringController
+ setRpcTarget (rpcTarget) {
+ this.configManager.setRpcTarget(rpcTarget)
+ extension.runtime.reload()
+ this.getNetwork()
+ }
- return this.idStoreMigrator.migratedVaultForPassword(password)
- .then(this.restoreOldVaultAccounts.bind(this))
- .then(this.restoreOldLostAccounts.bind(this))
- .then(keyringController.persistAllKeyrings.bind(keyringController, password))
- .then(() => password)
+ setProviderType (type) {
+ this.configManager.setProviderType(type)
+ extension.runtime.reload()
+ this.getNetwork()
}
- checkIfShouldMigrate() {
- return !!this.configManager.getWallet() && !this.configManager.getVault()
+ useEtherscanProvider () {
+ this.configManager.useEtherscanProvider()
+ extension.runtime.reload()
}
- restoreOldVaultAccounts(migratorOutput) {
- const { serialized } = migratorOutput
- return this.keyringController.restoreKeyring(serialized)
- .then(() => migratorOutput)
+ getStateNetwork () {
+ return this.state.network
}
- restoreOldLostAccounts(migratorOutput) {
- const { lostAccounts } = migratorOutput
- if (lostAccounts) {
- this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address))
- return this.importLostAccounts(migratorOutput)
+ getNetwork (err) {
+ if (err) {
+ this.state.network = 'loading'
+ this.sendUpdate()
}
- return Promise.resolve(migratorOutput)
- }
- // IMPORT LOST ACCOUNTS
- // @Object with key lostAccounts: @Array accounts <{ address, privateKey }>
- // Uses the array's private keys to create a new Simple Key Pair keychain
- // and add it to the keyring controller.
- importLostAccounts ({ lostAccounts }) {
- const privKeys = lostAccounts.map(acct => acct.privateKey)
- return this.keyringController.restoreKeyring({
- type: 'Simple Key Pair',
- data: privKeys,
+ this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
+ if (err) {
+ this.state.network = 'loading'
+ return this.sendUpdate()
+ }
+ if (global.METAMASK_DEBUG) {
+ console.log('web3.getNetwork returned ' + network)
+ }
+ this.state.network = network
+ this.sendUpdate()
})
}
+
}
diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js
new file mode 100644
index 000000000..65f62a861
--- /dev/null
+++ b/app/scripts/migrations/005.js
@@ -0,0 +1,41 @@
+const version = 5
+
+/*
+
+This migration moves state from the flat state trie into KeyringController substate
+
+*/
+
+const extend = require('xtend')
+
+module.exports = {
+ version,
+
+ migrate: function (versionedData) {
+ versionedData.meta.version = version
+ try {
+ const state = versionedData.data
+ const newState = selectSubstateForKeyringController(state)
+ versionedData.data = newState
+ } catch (err) {
+ console.warn('MetaMask Migration #5' + err.stack)
+ }
+ return Promise.resolve(versionedData)
+ },
+}
+
+function selectSubstateForKeyringController (state) {
+ const config = state.config
+ const newState = extend(state, {
+ KeyringController: {
+ vault: state.vault,
+ selectedAccount: config.selectedAccount,
+ walletNicknames: state.walletNicknames,
+ },
+ })
+ delete newState.vault
+ delete newState.walletNicknames
+ delete newState.config.selectedAccount
+
+ return newState
+}
diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js
index d2ac221b9..a7ce745e7 100644
--- a/app/scripts/migrations/index.js
+++ b/app/scripts/migrations/index.js
@@ -15,4 +15,5 @@ module.exports = [
require('./002'),
require('./003'),
require('./004'),
+ require('./005'),
]
diff --git a/package.json b/package.json
index 005da5c89..770318214 100644
--- a/package.json
+++ b/package.json
@@ -70,7 +70,7 @@
"mississippi": "^1.2.0",
"mkdirp": "^0.5.1",
"multiplex": "^6.7.0",
- "obs-store": "^2.2.3",
+ "obs-store": "^2.3.0",
"once": "^1.3.3",
"ping-pong-stream": "^1.0.0",
"pojo-migrator": "^2.1.0",
diff --git a/test/unit/idStore-migration-test.js b/test/unit/idStore-migration-test.js
index 38667fc3e..3aaf4bb94 100644
--- a/test/unit/idStore-migration-test.js
+++ b/test/unit/idStore-migration-test.js
@@ -4,12 +4,13 @@ const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const ConfigManager = require('../../app/scripts/lib/config-manager')
+const firstTimeState = require('../../app/scripts/first-time-state')
const delegateCallCode = require('../lib/example-code.json').delegateCallCode
+const clone = require('clone')
// The old way:
const IdentityStore = require('../../app/scripts/lib/idStore')
const STORAGE_KEY = 'metamask-config'
-const extend = require('xtend')
// The new ways:
var KeyringController = require('../../app/scripts/keyring-controller')
@@ -42,12 +43,9 @@ describe('IdentityStore to KeyringController migration', function() {
// and THEN create a new one, before we can run tests on it.
beforeEach(function(done) {
this.sinon = sinon.sandbox.create()
- window.localStorage = {} // Hacking localStorage support into JSDom
- let store = new ObservableStore(loadData())
- store.subscribe(setData)
+ let store = new ObservableStore(clone(firstTimeState))
configManager = new ConfigManager({ store })
-
idStore = new IdentityStore({
configManager: configManager,
ethStore: {
@@ -91,56 +89,9 @@ describe('IdentityStore to KeyringController migration', function() {
assert(!state.lostAccounts, 'no lost accounts')
done()
})
+ .catch((err) => {
+ done(err)
+ })
})
})
})
-
-function loadData () {
- var oldData = getOldStyleData()
- var newData
- try {
- newData = JSON.parse(window.localStorage[STORAGE_KEY])
- } catch (e) {}
-
- var data = extend({
- meta: {
- version: 0,
- },
- data: {
- config: {
- provider: {
- type: 'testnet',
- },
- },
- },
- }, oldData || null, newData || null)
- return data
-}
-
-function setData (data) {
- window.localStorage[STORAGE_KEY] = JSON.stringify(data)
-}
-
-function getOldStyleData () {
- var config, wallet, seedWords
-
- var result = {
- meta: { version: 0 },
- data: {},
- }
-
- try {
- config = JSON.parse(window.localStorage['config'])
- result.data.config = config
- } catch (e) {}
- try {
- wallet = JSON.parse(window.localStorage['lightwallet'])
- result.data.wallet = wallet
- } catch (e) {}
- try {
- seedWords = window.localStorage['seedWords']
- result.data.seedWords = seedWords
- } catch (e) {}
-
- return result
-}
diff --git a/test/unit/keyring-controller-test.js b/test/unit/keyring-controller-test.js
index d6d2db817..347aa2bdf 100644
--- a/test/unit/keyring-controller-test.js
+++ b/test/unit/keyring-controller-test.js
@@ -1,6 +1,6 @@
-var assert = require('assert')
-var KeyringController = require('../../app/scripts/keyring-controller')
-var configManagerGen = require('../lib/mock-config-manager')
+const assert = require('assert')
+const KeyringController = require('../../app/scripts/keyring-controller')
+const configManagerGen = require('../lib/mock-config-manager')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const async = require('async')
@@ -55,17 +55,16 @@ describe('KeyringController', function() {
this.timeout(10000)
it('should set a vault on the configManager', function(done) {
- keyringController.configManager.setVault(null)
- assert(!keyringController.configManager.getVault(), 'no previous vault')
+ keyringController.store.updateState({ vault: null })
+ assert(!keyringController.store.getState().vault, 'no previous vault')
keyringController.createNewVaultAndKeychain(password)
.then(() => {
- const vault = keyringController.configManager.getVault()
+ const vault = keyringController.store.getState().vault
assert(vault, 'vault created')
done()
})
.catch((reason) => {
- assert.ifError(reason)
- done()
+ done(reason)
})
})
})
@@ -96,8 +95,7 @@ describe('KeyringController', function() {
done()
})
.catch((reason) => {
- assert.ifError(reason)
- done()
+ done(reason)
})
})
})
@@ -109,9 +107,6 @@ describe('KeyringController', function() {
const identities = keyringController.identities
const identity = identities[fakeAddress]
assert.equal(identity.address, fakeAddress)
-
- const nick = keyringController.configManager.nicknameForWallet(fakeAddress)
- assert.equal(typeof nick, 'string')
})
})
@@ -122,34 +117,17 @@ describe('KeyringController', function() {
keyringController.identities[ethUtil.addHexPrefix(account)] = {}
keyringController.saveAccountLabel(account, nick)
.then((label) => {
- assert.equal(label, nick)
- const persisted = keyringController.configManager.nicknameForWallet(account)
- assert.equal(persisted, nick)
- done()
- })
- .catch((reason) => {
- assert.ifError(reason)
- done()
- })
- })
-
- this.timeout(10000)
- it('retrieves the persisted nickname', function(done) {
- const account = addresses[0]
- var nick = 'Test nickname'
- keyringController.configManager.setNicknameForWallet(account, nick)
- keyringController.createNewVaultAndRestore(password, seedWords)
- .then((state) => {
-
- const identity = keyringController.identities['0x' + account]
- assert.equal(identity.name, nick)
-
- assert(accounts)
- done()
+ try {
+ assert.equal(label, nick)
+ const persisted = keyringController.store.getState().walletNicknames[account]
+ assert.equal(persisted, nick)
+ done()
+ } catch (err) {
+ done()
+ }
})
.catch((reason) => {
- assert.ifError(reason)
- done()
+ done(reason)
})
})
})
diff --git a/test/unit/metamask-controller-test.js b/test/unit/metamask-controller-test.js
index 24d9ddd67..78b9e9df7 100644
--- a/test/unit/metamask-controller-test.js
+++ b/test/unit/metamask-controller-test.js
@@ -1,7 +1,9 @@
-var assert = require('assert')
-var MetaMaskController = require('../../app/scripts/metamask-controller')
-var sinon = require('sinon')
-var extend = require('xtend')
+const assert = require('assert')
+const sinon = require('sinon')
+const clone = require('clone')
+const MetaMaskController = require('../../app/scripts/metamask-controller')
+const firstTimeState = require('../../app/scripts/first-time-state')
+
const STORAGE_KEY = 'metamask-config'
describe('MetaMaskController', function() {
@@ -11,15 +13,12 @@ describe('MetaMaskController', function() {
unlockAccountMessage: noop,
showUnapprovedTx: noop,
// initial state
- initState: loadData(),
+ initState: clone(firstTimeState),
})
- // setup state persistence
- controller.store.subscribe(setData)
beforeEach(function() {
// sinon allows stubbing methods that are easily verified
this.sinon = sinon.sandbox.create()
- window.localStorage = {} // Hacking localStorage support into JSDom
})
afterEach(function() {
@@ -27,55 +26,4 @@ describe('MetaMaskController', function() {
this.sinon.restore()
})
-})
-
-
-function loadData () {
- var oldData = getOldStyleData()
- var newData
- try {
- newData = JSON.parse(window.localStorage[STORAGE_KEY])
- } catch (e) {}
-
- var data = extend({
- meta: {
- version: 0,
- },
- data: {
- config: {
- provider: {
- type: 'testnet',
- },
- },
- },
- }, oldData || null, newData || null)
- return data
-}
-
-function getOldStyleData () {
- var config, wallet, seedWords
-
- var result = {
- meta: { version: 0 },
- data: {},
- }
-
- try {
- config = JSON.parse(window.localStorage['config'])
- result.data.config = config
- } catch (e) {}
- try {
- wallet = JSON.parse(window.localStorage['lightwallet'])
- result.data.wallet = wallet
- } catch (e) {}
- try {
- seedWords = window.localStorage['seedWords']
- result.data.seedWords = seedWords
- } catch (e) {}
-
- return result
-}
-
-function setData (data) {
- window.localStorage[STORAGE_KEY] = JSON.stringify(data)
-}
+}) \ No newline at end of file
diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js
index 7f6f155f3..72a2b23df 100644
--- a/ui/app/account-detail.js
+++ b/ui/app/account-detail.js
@@ -41,6 +41,7 @@ function AccountDetailScreen () {
AccountDetailScreen.prototype.render = function () {
var props = this.props
var selected = props.address || Object.keys(props.accounts)[0]
+ var checksumAddress = selected && ethUtil.toChecksumAddress(selected)
var identity = props.identities[selected]
var account = props.accounts[selected]
const { network } = props
@@ -116,7 +117,7 @@ AccountDetailScreen.prototype.render = function () {
marginBottom: '15px',
color: '#AEAEAE',
},
- }, ethUtil.toChecksumAddress(selected)),
+ }, checksumAddress),
// copy and export
@@ -129,7 +130,7 @@ AccountDetailScreen.prototype.render = function () {
h(AccountInfoLink, { selected, network }),
h(CopyButton, {
- value: ethUtil.toChecksumAddress(selected),
+ value: checksumAddress,
}),
h(Tooltip, {
diff --git a/ui/app/accounts/account-list-item.js b/ui/app/accounts/account-list-item.js
index 16019c88a..74ecef07f 100644
--- a/ui/app/accounts/account-list-item.js
+++ b/ui/app/accounts/account-list-item.js
@@ -17,6 +17,7 @@ function AccountListItem () {
AccountListItem.prototype.render = function () {
const { identity, selectedAccount, accounts, onShowDetail } = this.props
+ const checksumAddress = identity && identity.address && ethUtil.toChecksumAddress(identity.address)
const isSelected = selectedAccount === identity.address
const account = accounts[identity.address]
const selectedClass = isSelected ? '.selected' : ''
@@ -48,7 +49,7 @@ AccountListItem.prototype.render = function () {
overflow: 'hidden',
textOverflow: 'ellipsis',
},
- }, ethUtil.toChecksumAddress(identity.address)),
+ }, checksumAddress),
h(EthBalance, {
value: account && account.balance,
style: {
@@ -65,7 +66,7 @@ AccountListItem.prototype.render = function () {
},
}, [
h(CopyButton, {
- value: ethUtil.toChecksumAddress(identity.address),
+ value: checksumAddress,
}),
]),
])
diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js
index 152d28809..cc7c51bd3 100644
--- a/ui/app/first-time/init-menu.js
+++ b/ui/app/first-time/init-menu.js
@@ -152,7 +152,6 @@ InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () {
var password = passwordBox.value
var passwordConfirmBox = document.getElementById('password-box-confirm')
var passwordConfirm = passwordConfirmBox.value
- // var entropy = document.getElementById('entropy-text-entry').value
if (password.length < 8) {
this.warning = 'password not long enough'