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

Began adding first basic keyring

This commit is contained in:
Dan Finlay 2016-10-20 16:44:31 -07:00
parent 351c8e2086
commit 55d56f77cf
8 changed files with 166 additions and 13 deletions

View File

@ -1,7 +1,13 @@
const EventEmitter = require('events').EventEmitter const EventEmitter = require('events').EventEmitter
const encryptor = require('./lib/encryptor') const encryptor = require('./lib/encryptor')
const messageManager = require('./lib/message-manager') const messageManager = require('./lib/message-manager')
const ethUtil = require('ethereumjs-util')
// Keyrings:
const SimpleKeyring = require('./keyrings/simple')
const keyringTypes = [
SimpleKeyring,
]
module.exports = class KeyringController extends EventEmitter { module.exports = class KeyringController extends EventEmitter {
@ -9,14 +15,15 @@ module.exports = class KeyringController extends EventEmitter {
super() super()
this.configManager = opts.configManager this.configManager = opts.configManager
this.ethStore = opts.ethStore this.ethStore = opts.ethStore
this.keyChains = [] this.keyrings = []
this.identities = {} // Essentially a nickname hash
} }
getState() { getState() {
return { return {
isInitialized: !!this.configManager.getVault(), isInitialized: !!this.configManager.getVault(),
isUnlocked: !!this.key, isUnlocked: !!this.key,
isConfirmed: true, // this.configManager.getConfirmed(), isConfirmed: true, // AUDIT this.configManager.getConfirmed(),
isEthConfirmed: this.configManager.getShouldntShowWarning(), isEthConfirmed: this.configManager.getShouldntShowWarning(),
unconfTxs: this.configManager.unconfirmedTxs(), unconfTxs: this.configManager.unconfirmedTxs(),
transactions: this.configManager.getTxList(), transactions: this.configManager.getTxList(),
@ -27,6 +34,8 @@ module.exports = class KeyringController extends EventEmitter {
currentFiat: this.configManager.getCurrentFiat(), currentFiat: this.configManager.getCurrentFiat(),
conversionRate: this.configManager.getConversionRate(), conversionRate: this.configManager.getConversionRate(),
conversionDate: this.configManager.getConversionDate(), conversionDate: this.configManager.getConversionDate(),
keyringTypes: keyringTypes.map((krt) => krt.type()),
identities: this.identities,
} }
} }
@ -39,7 +48,7 @@ module.exports = class KeyringController extends EventEmitter {
this.configManager.setSalt(salt) this.configManager.setSalt(salt)
this.loadKey(password) this.loadKey(password)
.then((key) => { .then((key) => {
return encryptor.encryptWithKey(key, {}) return encryptor.encryptWithKey(key, [])
}) })
.then((encryptedString) => { .then((encryptedString) => {
this.configManager.setVault(encryptedString) this.configManager.setVault(encryptedString)
@ -53,6 +62,10 @@ module.exports = class KeyringController extends EventEmitter {
submitPassword(password, cb) { submitPassword(password, cb) {
this.loadKey(password) this.loadKey(password)
.then((key) => { .then((key) => {
return this.unlockKeyrings(key)
})
.then((keyrings) => {
this.keyrings = keyrings
cb(null, this.getState()) cb(null, this.getState())
}) })
.catch((err) => { .catch((err) => {
@ -69,8 +82,94 @@ module.exports = class KeyringController extends EventEmitter {
}) })
} }
addNewKeyring(type, opts, cb) {
const i = this.getAccounts().length
const Keyring = this.getKeyringClassForType(type)
const keyring = new Keyring(opts)
const accounts = keyring.addAccounts(1)
accounts.forEach((account) => {
this.createBalanceAndNickname(account, i)
})
this.persistAllKeyrings()
.then(() => {
cb(this.getState())
})
.catch((reason) => {
cb(reason)
})
}
// Takes an account address and an iterator representing
// the current number of nicknamed accounts.
createBalanceAndNickname(account, i) {
this.ethStore.addAccount(ethUtil.addHexPrefix(account))
const oldNickname = this.configManager.nicknameForWallet(account)
const nickname = oldNickname || `Account ${++i}`
this.identities[account] = {
address: account,
nickname,
}
this.saveAccountLabel(account, nickname)
}
saveAccountLabel (account, label, cb) {
const configManager = this.configManager
configManager.setNicknameForWallet(account, label)
if (cb) {
cb(null, label)
}
}
persistAllKeyrings() {
const serialized = this.keyrings.map(k => k.serialize())
return encryptor.encryptWithKey(this.key, serialized)
.then((encryptedString) => {
this.configManager.setVault(encryptedString)
return true
})
.catch((reason) => {
console.error('Failed to persist keyrings.', reason)
})
}
unlockKeyrings(key) {
const encryptedVault = this.configManager.getVault()
return encryptor.decryptWithKey(key, encryptedVault)
.then((vault) => {
this.keyrings = vault.map(this.restoreKeyring)
return this.keyrings
})
}
restoreKeyring(serialized) {
const { type } = serialized
const Keyring = this.getKeyringClassForType(type)
const keyring = new Keyring(serialized)
return keyring
}
getKeyringClassForType(type) {
const Keyring = keyringTypes.reduce((res, kr) => {
if (kr.type() === type) {
return kr
} else {
return res
}
})
return Keyring
}
getAccounts() {
return this.keyrings.map(kr => kr.getAccounts())
.reduce((res, arr) => {
return res.concat(arr)
}, [])
}
setSelectedAddress(address, cb) { setSelectedAddress(address, cb) {
this.selectedAddress = address this.configManager.setSelectedAccount(address)
cb(null, address) cb(null, address)
} }
@ -102,10 +201,6 @@ module.exports = class KeyringController extends EventEmitter {
cb(null, '0xPrivateKey') cb(null, '0xPrivateKey')
} }
saveAccountLabel(account, label, cb) {
cb(/* null, label */)
}
tryPassword(password, cb) { tryPassword(password, cb) {
cb() cb()
} }

View File

@ -0,0 +1,41 @@
const EventEmitter = require('events').EventEmitter
const Wallet = require('ethereumjs-wallet')
const type = 'Simple Key Pair'
module.exports = class SimpleKeyring extends EventEmitter {
static type() {
return type
}
constructor(opts) {
super()
this.type = type
this.opts = opts || {}
const walletData = this.opts.wallets || []
this.wallets = walletData.map((w) => {
return Wallet.fromPrivateKey(w)
})
}
serialize() {
return {
type,
wallets: this.wallets.map(w => w.getPrivateKey()),
}
}
addAccounts(n = 1) {
var newWallets = []
for (var i = 0; i < n; i++) {
newWallets.push(Wallet.generate())
}
this.wallets.concat(newWallets)
return newWallets.map(w => w.getAddress())
}
getAccounts() {
return this.wallets.map(w => w.getAddress())
}
}

View File

@ -114,7 +114,6 @@ IdentityStore.prototype.getState = function () {
conversionRate: configManager.getConversionRate(), conversionRate: configManager.getConversionRate(),
conversionDate: configManager.getConversionDate(), conversionDate: configManager.getConversionDate(),
gasMultiplier: configManager.getGasMultiplier(), gasMultiplier: configManager.getGasMultiplier(),
})) }))
} }

View File

@ -61,6 +61,7 @@ module.exports = class MetamaskController {
// forward directly to idStore // forward directly to idStore
createNewVault: idStore.createNewVault.bind(idStore), createNewVault: idStore.createNewVault.bind(idStore),
addNewKeyring: idStore.addNewKeyring.bind(idStore),
submitPassword: idStore.submitPassword.bind(idStore), submitPassword: idStore.submitPassword.bind(idStore),
setSelectedAddress: idStore.setSelectedAddress.bind(idStore), setSelectedAddress: idStore.setSelectedAddress.bind(idStore),
approveTransaction: idStore.approveTransaction.bind(idStore), approveTransaction: idStore.approveTransaction.bind(idStore),
@ -183,6 +184,7 @@ module.exports = class MetamaskController {
}) })
this.idStore.on('update', function (state) { this.idStore.on('update', function (state) {
storeSetFromObj(publicConfigStore, idStoreToPublic(state)) storeSetFromObj(publicConfigStore, idStoreToPublic(state))
this.sendUpdate()
}) })
// idStore substate // idStore substate

View File

@ -47,6 +47,7 @@
"eth-store": "^1.1.0", "eth-store": "^1.1.0",
"ethereumjs-tx": "^1.0.0", "ethereumjs-tx": "^1.0.0",
"ethereumjs-util": "^4.4.0", "ethereumjs-util": "^4.4.0",
"ethereumjs-wallet": "^0.6.0",
"express": "^4.14.0", "express": "^4.14.0",
"gulp-eslint": "^2.0.0", "gulp-eslint": "^2.0.0",
"hat": "0.0.3", "hat": "0.0.3",

View File

@ -87,7 +87,7 @@ AccountsScreen.prototype.render = function () {
h('div.footer.hover-white.pointer', { h('div.footer.hover-white.pointer', {
key: 'reveal-account-bar', key: 'reveal-account-bar',
onClick: () => { onClick: () => {
this.onRevealAccount() this.addNewKeyring()
}, },
style: { style: {
display: 'flex', display: 'flex',
@ -146,8 +146,8 @@ AccountsScreen.prototype.onShowDetail = function (address, event) {
this.props.dispatch(actions.showAccountDetail(address)) this.props.dispatch(actions.showAccountDetail(address))
} }
AccountsScreen.prototype.onRevealAccount = function () { AccountsScreen.prototype.addNewKeyring = function () {
this.props.dispatch(actions.revealAccount()) this.props.dispatch(actions.addNewKeyring('Simple Key Pair'))
} }
AccountsScreen.prototype.goHome = function () { AccountsScreen.prototype.goHome = function () {

View File

@ -25,6 +25,7 @@ var actions = {
showInitializeMenu: showInitializeMenu, showInitializeMenu: showInitializeMenu,
createNewVault: createNewVault, createNewVault: createNewVault,
createNewVaultInProgress: createNewVaultInProgress, createNewVaultInProgress: createNewVaultInProgress,
addNewKeyring: addNewKeyring,
showNewVaultSeed: showNewVaultSeed, showNewVaultSeed: showNewVaultSeed,
showInfoPage: showInfoPage, showInfoPage: showInfoPage,
// unlock screen // unlock screen
@ -136,6 +137,7 @@ var actions = {
SHOW_NEW_KEYCHAIN: 'SHOW_NEW_KEYCHAIN', SHOW_NEW_KEYCHAIN: 'SHOW_NEW_KEYCHAIN',
showNewKeychain: showNewKeychain, showNewKeychain: showNewKeychain,
} }
module.exports = actions module.exports = actions
@ -187,6 +189,20 @@ function createNewVault (password, entropy) {
} }
} }
function addNewKeyring (type, opts) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
background.addNewKeyring(type, opts, (err, newState) => {
dispatch(this.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
}
dispatch(this.updateMetamaskState(newState))
dispatch(this.showAccountsPage())
})
}
}
function showInfoPage () { function showInfoPage () {
return { return {
type: actions.SHOW_INFO_PAGE, type: actions.SHOW_INFO_PAGE,

View File

@ -405,7 +405,6 @@ App.prototype.renderPrimary = function () {
// show current view // show current view
switch (props.currentView.name) { switch (props.currentView.name) {
case 'createVault': case 'createVault':
return h(CreateVaultScreen, {key: 'createVault'}) return h(CreateVaultScreen, {key: 'createVault'})