mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
Began adding first basic keyring
This commit is contained in:
parent
351c8e2086
commit
55d56f77cf
@ -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()
|
||||||
}
|
}
|
||||||
|
41
app/scripts/keyrings/simple.js
Normal file
41
app/scripts/keyrings/simple.js
Normal 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())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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(),
|
||||||
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
|
@ -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 () {
|
||||||
|
@ -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,
|
||||||
|
@ -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'})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user