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 encryptor = require('./lib/encryptor')
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 {
@ -9,14 +15,15 @@ module.exports = class KeyringController extends EventEmitter {
super()
this.configManager = opts.configManager
this.ethStore = opts.ethStore
this.keyChains = []
this.keyrings = []
this.identities = {} // Essentially a nickname hash
}
getState() {
return {
isInitialized: !!this.configManager.getVault(),
isUnlocked: !!this.key,
isConfirmed: true, // this.configManager.getConfirmed(),
isConfirmed: true, // AUDIT this.configManager.getConfirmed(),
isEthConfirmed: this.configManager.getShouldntShowWarning(),
unconfTxs: this.configManager.unconfirmedTxs(),
transactions: this.configManager.getTxList(),
@ -27,6 +34,8 @@ module.exports = class KeyringController extends EventEmitter {
currentFiat: this.configManager.getCurrentFiat(),
conversionRate: this.configManager.getConversionRate(),
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.loadKey(password)
.then((key) => {
return encryptor.encryptWithKey(key, {})
return encryptor.encryptWithKey(key, [])
})
.then((encryptedString) => {
this.configManager.setVault(encryptedString)
@ -53,6 +62,10 @@ module.exports = class KeyringController extends EventEmitter {
submitPassword(password, cb) {
this.loadKey(password)
.then((key) => {
return this.unlockKeyrings(key)
})
.then((keyrings) => {
this.keyrings = keyrings
cb(null, this.getState())
})
.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) {
this.selectedAddress = address
this.configManager.setSelectedAccount(address)
cb(null, address)
}
@ -102,10 +201,6 @@ module.exports = class KeyringController extends EventEmitter {
cb(null, '0xPrivateKey')
}
saveAccountLabel(account, label, cb) {
cb(/* null, label */)
}
tryPassword(password, 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(),
conversionDate: configManager.getConversionDate(),
gasMultiplier: configManager.getGasMultiplier(),
}))
}

View File

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

View File

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

View File

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

View File

@ -25,6 +25,7 @@ var actions = {
showInitializeMenu: showInitializeMenu,
createNewVault: createNewVault,
createNewVaultInProgress: createNewVaultInProgress,
addNewKeyring: addNewKeyring,
showNewVaultSeed: showNewVaultSeed,
showInfoPage: showInfoPage,
// unlock screen
@ -136,6 +137,7 @@ var actions = {
SHOW_NEW_KEYCHAIN: 'SHOW_NEW_KEYCHAIN',
showNewKeychain: showNewKeychain,
}
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 () {
return {
type: actions.SHOW_INFO_PAGE,

View File

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