1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Merge pull request #2389 from MetaMask/i2348-SelectAccountOnNewVault

Select first account on create or restore vault
This commit is contained in:
Thomas Huang 2017-10-20 12:09:44 -04:00 committed by GitHub
commit e3a7da961d
7 changed files with 96 additions and 29 deletions

View File

@ -3,6 +3,7 @@
## Current Master
- Fix bug where web3 API was sometimes injected after the page loaded.
- Fix bug where first account was sometimes not selected correctly after creating or restoring a vault.
- Fix bug where imported accounts could not use new eth_signTypedData method.
## 3.11.0 2017-10-11

View File

@ -5,7 +5,9 @@ const BN = require('ethereumjs-util').BN
class BalanceController {
constructor (opts = {}) {
this._validateParams(opts)
const { address, accountTracker, txController, blockTracker } = opts
this.address = address
this.accountTracker = accountTracker
this.txController = txController
@ -65,6 +67,14 @@ class BalanceController {
return pending
}
_validateParams (opts) {
const { address, accountTracker, txController, blockTracker } = opts
if (!address || !accountTracker || !txController || !blockTracker) {
const error = 'Cannot construct a balance checker without address, accountTracker, txController, and blockTracker.'
throw new Error(error)
}
}
}
module.exports = BalanceController

View File

@ -20,23 +20,34 @@ class ComputedbalancesController {
}
updateAllBalances () {
for (let address in this.accountTracker.store.getState().accounts) {
Object.keys(this.balances).forEach((balance) => {
const address = balance.address
this.balances[address].updateBalance()
}
})
}
_initBalanceUpdating () {
const store = this.accountTracker.store.getState()
this.addAnyAccountsFromStore(store)
this.accountTracker.store.subscribe(this.addAnyAccountsFromStore.bind(this))
this.syncAllAccountsFromStore(store)
this.accountTracker.store.subscribe(this.syncAllAccountsFromStore.bind(this))
}
addAnyAccountsFromStore(store) {
const balances = store.accounts
syncAllAccountsFromStore(store) {
const upstream = Object.keys(store.accounts)
const balances = Object.keys(this.balances)
.map(address => this.balances[address])
// Follow new addresses
for (let address in balances) {
this.trackAddressIfNotAlready(address)
}
// Unfollow old ones
balances.forEach(({ address }) => {
if (!upstream.includes(address)) {
delete this.balances[address]
}
})
}
trackAddressIfNotAlready (address) {

View File

@ -38,6 +38,29 @@ class AccountTracker extends EventEmitter {
// public
//
syncWithAddresses (addresses) {
const accounts = this.store.getState().accounts
const locals = Object.keys(accounts)
const toAdd = []
addresses.forEach((upstream) => {
if (!locals.includes(upstream)) {
toAdd.push(upstream)
}
})
const toRemove = []
locals.forEach((local) => {
if (!addresses.includes(local)) {
toRemove.push(local)
}
})
toAdd.forEach(upstream => this.addAccount(upstream))
toRemove.forEach(local => this.removeAccount(local))
this._updateAccounts()
}
addAccount (address) {
const accounts = this.store.getState().accounts
accounts[address] = {}

View File

@ -1,6 +1,5 @@
const EventEmitter = require('events')
const extend = require('xtend')
const promiseToCallback = require('promise-to-callback')
const pump = require('pump')
const Dnode = require('dnode')
const ObservableStore = require('obs-store')
@ -96,25 +95,20 @@ module.exports = class MetamaskController extends EventEmitter {
// key mgmt
this.keyringController = new KeyringController({
initState: initState.KeyringController,
accountTracker: this.accountTracker,
getNetwork: this.networkController.getNetworkState.bind(this.networkController),
encryptor: opts.encryptor || undefined,
})
// If only one account exists, make sure it is selected.
this.keyringController.store.subscribe((state) => {
const addresses = Object.keys(state.walletNicknames || {})
this.keyringController.memStore.subscribe((state) => {
const addresses = state.keyrings.reduce((res, keyring) => {
return res.concat(keyring.accounts)
}, [])
if (addresses.length === 1) {
const address = addresses[0]
this.preferencesController.setSelectedAddress(address)
}
})
this.keyringController.on('newAccount', (address) => {
this.preferencesController.setSelectedAddress(address)
this.accountTracker.addAccount(address)
})
this.keyringController.on('removedAccount', (address) => {
this.accountTracker.removeAccount(address)
this.accountTracker.syncWithAddresses(addresses)
})
// address book controller
@ -329,13 +323,13 @@ module.exports = class MetamaskController extends EventEmitter {
createShapeShiftTx: this.createShapeShiftTx.bind(this),
// primary HD keyring management
addNewAccount: this.addNewAccount.bind(this),
addNewAccount: nodeify(this.addNewAccount, this),
placeSeedWords: this.placeSeedWords.bind(this),
clearSeedWordCache: this.clearSeedWordCache.bind(this),
importAccountWithStrategy: this.importAccountWithStrategy.bind(this),
// vault management
submitPassword: this.submitPassword.bind(this),
submitPassword: nodeify(keyringController.submitPassword, keyringController),
// network management
setProviderType: nodeify(networkController.setProviderType, networkController),
@ -351,8 +345,8 @@ module.exports = class MetamaskController extends EventEmitter {
// KeyringController
setLocked: nodeify(keyringController.setLocked, keyringController),
createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain, keyringController),
createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore, keyringController),
createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),
createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this),
addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController),
saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController),
exportAccount: nodeify(keyringController.exportAccount, keyringController),
@ -473,20 +467,43 @@ module.exports = class MetamaskController extends EventEmitter {
// Vault Management
//
submitPassword (password, cb) {
return this.keyringController.submitPassword(password)
.then((newState) => { cb(null, newState) })
.catch((reason) => { cb(reason) })
async createNewVaultAndKeychain (password, cb) {
const vault = await this.keyringController.createNewVaultAndKeychain(password)
this.selectFirstIdentity(vault)
return vault
}
async createNewVaultAndRestore (password, seed, cb) {
const vault = await this.keyringController.createNewVaultAndRestore(password, seed)
this.selectFirstIdentity(vault)
return vault
}
selectFirstIdentity (vault) {
const { identities } = vault
const address = Object.keys(identities)[0]
this.preferencesController.setSelectedAddress(address)
}
//
// Opinionated Keyring Management
//
addNewAccount (cb) {
async addNewAccount (cb) {
const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found'))
promiseToCallback(this.keyringController.addNewAccount(primaryKeyring))(cb)
const keyringController = this.keyringController
const oldAccounts = await keyringController.getAccounts()
const keyState = await keyringController.addNewAccount(primaryKeyring)
const newAccounts = await keyringController.getAccounts()
newAccounts.forEach((address) => {
if (!oldAccounts.includes(address)) {
this.preferencesController.setSelectedAddress(address)
}
})
return keyState
}
// Adds the current vault's seed words to the UI's state tree.

View File

@ -134,7 +134,7 @@
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0",
"request-promise": "^4.2.1",
"sandwich-expando": "^1.0.5",
"sandwich-expando": "^1.1.3",
"semaphore": "^1.0.5",
"sw-stream": "^2.0.0",
"textarea-caret": "^3.0.1",

View File

@ -43,7 +43,12 @@ function rootReducer (state, action) {
window.logState = function () {
let state = window.METAMASK_CACHED_LOG_STATE
const version = global.platform.getVersion()
let version
try {
version = global.platform.getVersion()
} catch (e) {
version = 'unable to load version.'
}
state.version = version
let stateString = JSON.stringify(state, removeSeedWords, 2)
return stateString