From d270cbc9d2f45b6dae184efbe6c405889ee8cba5 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 9 Mar 2017 13:07:38 -0800 Subject: Create distinct labels and names for addresses. --- app/scripts/controllers/preferences.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 18fccf11b..c7f675a41 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -5,7 +5,9 @@ const extend = require('xtend') class PreferencesController { constructor (opts = {}) { - const initState = extend({ frequentRpcList: [] }, opts.initState) + const initState = extend({ + frequentRpcList: [], + }, opts.initState) this.store = new ObservableStore(initState) } -- cgit From 9f6c04055419f54a730bcbd3f1da4c5f992db94d Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 9 Mar 2017 13:58:42 -0800 Subject: Create persistence address book. --- app/scripts/controllers/address-book.js | 46 +++++++++++++++++++++++++++++++++ app/scripts/metamask-controller.js | 11 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 app/scripts/controllers/address-book.js (limited to 'app') diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js new file mode 100644 index 000000000..824a256d1 --- /dev/null +++ b/app/scripts/controllers/address-book.js @@ -0,0 +1,46 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +class AddressBookController { + + constructor (opts = {}) { + const initState = extend({ + addressBook: [], + }, opts.initState) + this.store = new ObservableStore(initState) + } + + // + // PUBLIC METHODS + // + + setAddressList (address, name) { + return this.addToAddressList(address, name) + .then((addressBook) => { + this.store.updateState({ + addressBook, + }) + return Promise.resolve() + }) + } + + addToAddressList (address, name) { + let addressBook = this.getAddressList() + let index = addressBook.findIndex((element) => { return element.address === address }) + if (index !== -1) { + addressBook.splice(index, 1) + } + addressBook.push({ + address, + name, + }) + return Promise.resolve(addressBook) + } + + getAddressList () { + return this.store.getState().addressBook + } + +} + +module.exports = AddressBookController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 536891dc6..6cdd8e96f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -15,6 +15,7 @@ const PreferencesController = require('./controllers/preferences') const CurrencyController = require('./controllers/currency') const NoticeController = require('./notice-controller') const ShapeShiftController = require('./controllers/shapeshift') +const AddressBookController = require('./controllers/address-book') const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') const TxManager = require('./transaction-manager') @@ -50,6 +51,11 @@ module.exports = class MetamaskController extends EventEmitter { initState: initState.PreferencesController, }) + // address book controller + this.addressBookController = new AddressBookController({ + initState: initState.AddressBookController, + }) + // currency controller this.currencyController = new CurrencyController({ initState: initState.CurrencyController, @@ -124,6 +130,9 @@ module.exports = class MetamaskController extends EventEmitter { this.preferencesController.store.subscribe((state) => { this.store.updateState({ PreferencesController: state }) }) + this.addressBookController.store.subscribe((state) => { + this.store.updateState({ AddressBookController: state }) + }) this.currencyController.store.subscribe((state) => { this.store.updateState({ CurrencyController: state }) }) @@ -142,6 +151,7 @@ module.exports = class MetamaskController extends EventEmitter { this.personalMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) this.keyringController.memStore.subscribe(this.sendUpdate.bind(this)) this.preferencesController.store.subscribe(this.sendUpdate.bind(this)) + this.addressBookController.store.subscribe(this.sendUpdate.bind(this)) this.currencyController.store.subscribe(this.sendUpdate.bind(this)) this.noticeController.memStore.subscribe(this.sendUpdate.bind(this)) this.shapeshiftController.store.subscribe(this.sendUpdate.bind(this)) @@ -219,6 +229,7 @@ module.exports = class MetamaskController extends EventEmitter { this.personalMessageManager.memStore.getState(), this.keyringController.memStore.getState(), this.preferencesController.store.getState(), + this.addressBookController.store.getState(), this.currencyController.store.getState(), this.noticeController.memStore.getState(), // config manager -- cgit From b296640f1b2e8cb808297715146a9370ff4f41ec Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 9 Mar 2017 15:09:50 -0800 Subject: Rename functions for consistency. --- app/scripts/controllers/address-book.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js index 824a256d1..3c2a73dd7 100644 --- a/app/scripts/controllers/address-book.js +++ b/app/scripts/controllers/address-book.js @@ -14,8 +14,8 @@ class AddressBookController { // PUBLIC METHODS // - setAddressList (address, name) { - return this.addToAddressList(address, name) + setAddressBook (address, name) { + return this.addToAddressBook(address, name) .then((addressBook) => { this.store.updateState({ addressBook, @@ -24,9 +24,9 @@ class AddressBookController { }) } - addToAddressList (address, name) { - let addressBook = this.getAddressList() - let index = addressBook.findIndex((element) => { return element.address === address }) + addToAddressBook (address, name) { + let addressBook = this.getAddressBook() + let index = addressBook.findIndex((element) => { return element.address === address || element.name === name }) if (index !== -1) { addressBook.splice(index, 1) } @@ -37,7 +37,7 @@ class AddressBookController { return Promise.resolve(addressBook) } - getAddressList () { + getAddressBook () { return this.store.getState().addressBook } -- cgit From b34ee4daa145c1d4eea2da6fd0cba0763e5c6483 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 9 Mar 2017 15:10:27 -0800 Subject: Allow for adding recently used addresses to address book. --- app/scripts/metamask-controller.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 6cdd8e96f..45905db72 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -251,6 +251,7 @@ module.exports = class MetamaskController extends EventEmitter { const preferencesController = this.preferencesController const txManager = this.txManager const noticeController = this.noticeController + const addressBookController = this.addressBookController return { // etc @@ -278,6 +279,9 @@ module.exports = class MetamaskController extends EventEmitter { setDefaultRpc: nodeify(this.setDefaultRpc).bind(this), setCustomRpc: nodeify(this.setCustomRpc).bind(this), + // AddressController + setAddressBook: nodeify(addressBookController.setAddressBook).bind(addressBookController), + // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain).bind(keyringController), -- cgit From 2ab86b001dfc4ade4fc6df030175e64359b757e6 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 10 Mar 2017 09:34:13 -0800 Subject: Add comments. --- app/scripts/controllers/address-book.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js index 3c2a73dd7..a75ef06ce 100644 --- a/app/scripts/controllers/address-book.js +++ b/app/scripts/controllers/address-book.js @@ -3,6 +3,10 @@ const extend = require('xtend') class AddressBookController { + + // Controller in charge of managing the address book functionality from the + // recipients field on the send screen. Manages a history of all saved + // addresses and all currently owned addresses. constructor (opts = {}) { const initState = extend({ addressBook: [], @@ -14,8 +18,9 @@ class AddressBookController { // PUBLIC METHODS // + // Sets a new address book in store by accepting a new address and nickname. setAddressBook (address, name) { - return this.addToAddressBook(address, name) + return this._addToAddressBook(address, name) .then((addressBook) => { this.store.updateState({ addressBook, @@ -24,8 +29,16 @@ class AddressBookController { }) } - addToAddressBook (address, name) { - let addressBook = this.getAddressBook() + // + // PRIVATE METHODS + // + + + // Performs the logic to add the address and name into the address book. The + // pushed object is an object of two fields. Current behavior does not set an + // upper limit to the number of addresses. + _addToAddressBook (address, name) { + let addressBook = this._getAddressBook() let index = addressBook.findIndex((element) => { return element.address === address || element.name === name }) if (index !== -1) { addressBook.splice(index, 1) @@ -37,7 +50,9 @@ class AddressBookController { return Promise.resolve(addressBook) } - getAddressBook () { + // Internal method to get the address book. Current persistence behavior + // should not require that this method be called from the UI directly. + _getAddressBook () { return this.store.getState().addressBook } -- cgit From 7182a2be4332e7802c8d2375b9380490aed7ca0b Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 10 Mar 2017 10:05:10 -0800 Subject: Improve duplicate checking in address book. --- app/scripts/controllers/address-book.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js index a75ef06ce..914fbded2 100644 --- a/app/scripts/controllers/address-book.js +++ b/app/scripts/controllers/address-book.js @@ -39,12 +39,12 @@ class AddressBookController { // upper limit to the number of addresses. _addToAddressBook (address, name) { let addressBook = this._getAddressBook() - let index = addressBook.findIndex((element) => { return element.address === address || element.name === name }) + let index = addressBook.findIndex((element) => { return element.address.toLowerCase() === address.toLowerCase() || element.name === name }) if (index !== -1) { addressBook.splice(index, 1) } addressBook.push({ - address, + address: address, name, }) return Promise.resolve(addressBook) -- cgit From 7dcab52a9e6aa0532a712cb4e502846a383efc94 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 10 Mar 2017 10:34:46 -0800 Subject: Connect keyring controller to address book to prevent additional duplicates. --- app/scripts/controllers/address-book.js | 22 ++++++++++++++++++---- app/scripts/metamask-controller.js | 10 +++++----- 2 files changed, 23 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js index 914fbded2..0e97cc477 100644 --- a/app/scripts/controllers/address-book.js +++ b/app/scripts/controllers/address-book.js @@ -7,11 +7,12 @@ class AddressBookController { // Controller in charge of managing the address book functionality from the // recipients field on the send screen. Manages a history of all saved // addresses and all currently owned addresses. - constructor (opts = {}) { + constructor (opts = {}, keyringController) { const initState = extend({ addressBook: [], }, opts.initState) this.store = new ObservableStore(initState) + this.keyringController = keyringController } // @@ -39,9 +40,16 @@ class AddressBookController { // upper limit to the number of addresses. _addToAddressBook (address, name) { let addressBook = this._getAddressBook() - let index = addressBook.findIndex((element) => { return element.address.toLowerCase() === address.toLowerCase() || element.name === name }) - if (index !== -1) { - addressBook.splice(index, 1) + let identities = this._getIdentities() + + let addressBookIndex = addressBook.findIndex((element) => { return element.address.toLowerCase() === address.toLowerCase() || element.name === name }) + let identitiesIndex = Object.keys(identities).findIndex((element) => { return element.toLowerCase() === address.toLowerCase() }) + // trigger this condition if we own this address--no need to overwrite. + if (identitiesIndex !== -1) { + return Promise.resolve(addressBook) + // trigger this condition if we've seen this address before--may need to update nickname. + } else if (addressBookIndex !== -1) { + addressBook.splice(addressBookIndex, 1) } addressBook.push({ address: address, @@ -56,6 +64,12 @@ class AddressBookController { return this.store.getState().addressBook } + // Retrieves identities from the keyring controller in order to avoid + // duplication + _getIdentities () { + return this.keyringController.memStore.getState().identities + } + } module.exports = AddressBookController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 45905db72..1fcee61da 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -51,11 +51,6 @@ module.exports = class MetamaskController extends EventEmitter { initState: initState.PreferencesController, }) - // address book controller - this.addressBookController = new AddressBookController({ - initState: initState.AddressBookController, - }) - // currency controller this.currencyController = new CurrencyController({ initState: initState.CurrencyController, @@ -86,6 +81,11 @@ module.exports = class MetamaskController extends EventEmitter { autoFaucet(address) }) + // address book controller + this.addressBookController = new AddressBookController({ + initState: initState.AddressBookController, + }, this.keyringController) + // tx mgmt this.txManager = new TxManager({ initState: initState.TransactionManager, -- cgit From 4933e2e2eefa103d6b0d3f3ce264aaf661b50291 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 13 Mar 2017 16:37:53 -0700 Subject: Limit the number of addresses stored in our book. --- app/scripts/controllers/address-book.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js index 0e97cc477..c66eb2bd4 100644 --- a/app/scripts/controllers/address-book.js +++ b/app/scripts/controllers/address-book.js @@ -50,7 +50,11 @@ class AddressBookController { // trigger this condition if we've seen this address before--may need to update nickname. } else if (addressBookIndex !== -1) { addressBook.splice(addressBookIndex, 1) + } else if (addressBook.length > 15) { + addressBook.shift() } + + addressBook.push({ address: address, name, -- cgit From 177f2dc948f794f6796d74e3ef2a581048625bb1 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 14 Mar 2017 17:05:47 -0700 Subject: Fix description of some migrations. --- app/scripts/migrations/010.js | 2 +- app/scripts/migrations/011.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index 48a841bc1..c0cc56ae4 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -2,7 +2,7 @@ const version = 10 /* -This migration breaks out the CurrencyController substate +This migration breaks out the ShapeShiftController substate */ diff --git a/app/scripts/migrations/011.js b/app/scripts/migrations/011.js index bf283ef98..0d5d6d307 100644 --- a/app/scripts/migrations/011.js +++ b/app/scripts/migrations/011.js @@ -2,7 +2,7 @@ const version = 11 /* -This migration breaks out the CurrencyController substate +This migration removes the discaimer state from our app, which was integrated into our notices. */ -- cgit From 37ffcfcf0e518ed8843022cd079ce09d0b2239ff Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 14 Mar 2017 17:06:16 -0700 Subject: Rename variables to proper currency state variables. --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 536891dc6..2eaa53200 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -621,7 +621,7 @@ module.exports = class MetamaskController extends EventEmitter { this.currencyController.updateConversionRate() const data = { conversionRate: this.currencyController.getConversionRate(), - currentFiat: this.currencyController.getCurrentCurrency(), + currentCurrency: this.currencyController.getCurrentCurrency(), conversionDate: this.currencyController.getConversionDate(), } cb(null, data) -- cgit From b6e2eaf7b1d14fcca8ed614791937a5ccbfc00dd Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 16 Mar 2017 11:16:03 -0700 Subject: Remove eth-lightwallet --- app/scripts/lib/id-management.js | 90 ---------- app/scripts/lib/idStore-migrator.js | 80 --------- app/scripts/lib/idStore.js | 343 ------------------------------------ app/scripts/metamask-controller.js | 38 +--- 4 files changed, 1 insertion(+), 550 deletions(-) delete mode 100644 app/scripts/lib/id-management.js delete mode 100644 app/scripts/lib/idStore-migrator.js delete mode 100644 app/scripts/lib/idStore.js (limited to 'app') diff --git a/app/scripts/lib/id-management.js b/app/scripts/lib/id-management.js deleted file mode 100644 index 90b3fdb13..000000000 --- a/app/scripts/lib/id-management.js +++ /dev/null @@ -1,90 +0,0 @@ -/* ID Management - * - * This module exists to hold the decrypted credentials for the current session. - * It therefore exposes sign methods, because it is able to perform these - * with noa dditional authentication, because its very instantiation - * means the vault is unlocked. - */ - -const ethUtil = require('ethereumjs-util') -const Transaction = require('ethereumjs-tx') - -module.exports = IdManagement - -function IdManagement (opts) { - if (!opts) opts = {} - - this.keyStore = opts.keyStore - this.derivedKey = opts.derivedKey - this.configManager = opts.configManager - this.hdPathString = "m/44'/60'/0'/0" - - this.getAddresses = function () { - return this.keyStore.getAddresses(this.hdPathString).map(function (address) { return '0x' + address }) - } - - this.signTx = function (txParams) { - - // normalize values - txParams.gasPrice = ethUtil.intToHex(txParams.gasPrice) - txParams.to = ethUtil.addHexPrefix(txParams.to) - txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase()) - txParams.value = ethUtil.addHexPrefix(txParams.value) - txParams.data = ethUtil.addHexPrefix(txParams.data) - txParams.gasLimit = ethUtil.addHexPrefix(txParams.gasLimit || txParams.gas) - txParams.nonce = ethUtil.addHexPrefix(txParams.nonce) - var tx = new Transaction(txParams) - - // sign tx - var privKeyHex = this.exportPrivateKey(txParams.from) - var privKey = ethUtil.toBuffer(privKeyHex) - tx.sign(privKey) - - // Add the tx hash to the persisted meta-tx object - var txHash = ethUtil.bufferToHex(tx.hash()) - var metaTx = this.configManager.getTx(txParams.metamaskId) - metaTx.hash = txHash - this.configManager.updateTx(metaTx) - - // return raw serialized tx - var rawTx = ethUtil.bufferToHex(tx.serialize()) - return rawTx - } - - this.signMsg = function (address, message) { - // sign message - var privKeyHex = this.exportPrivateKey(address.toLowerCase()) - var privKey = ethUtil.toBuffer(privKeyHex) - var msgSig = ethUtil.ecsign(new Buffer(message.replace('0x', ''), 'hex'), privKey) - var rawMsgSig = ethUtil.bufferToHex(concatSig(msgSig.v, msgSig.r, msgSig.s)) - return rawMsgSig - } - - this.getSeed = function () { - return this.keyStore.getSeed(this.derivedKey) - } - - this.exportPrivateKey = function (address) { - var privKeyHex = ethUtil.addHexPrefix(this.keyStore.exportPrivateKey(address, this.derivedKey, this.hdPathString)) - return privKeyHex - } -} - -function padWithZeroes (number, length) { - var myString = '' + number - while (myString.length < length) { - myString = '0' + myString - } - return myString -} - -function concatSig (v, r, s) { - const rSig = ethUtil.fromSigned(r) - const sSig = ethUtil.fromSigned(s) - const vSig = ethUtil.bufferToInt(v) - const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) - const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) - const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) - return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') -} - diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js deleted file mode 100644 index 62d21eee7..000000000 --- a/app/scripts/lib/idStore-migrator.js +++ /dev/null @@ -1,80 +0,0 @@ -const IdentityStore = require('./idStore') -const HdKeyring = require('eth-hd-keyring') -const sigUtil = require('eth-sig-util') -const normalize = sigUtil.normalize -const denodeify = require('denodeify') - -module.exports = class IdentityStoreMigrator { - - constructor ({ configManager }) { - this.configManager = configManager - const hasOldVault = this.hasOldVault() - if (!hasOldVault) { - this.idStore = new IdentityStore({ configManager }) - } - } - - migratedVaultForPassword (password) { - const hasOldVault = this.hasOldVault() - const configManager = this.configManager - - if (!this.idStore) { - this.idStore = new IdentityStore({ configManager }) - } - - if (!hasOldVault) { - return Promise.resolve(null) - } - - const idStore = this.idStore - const submitPassword = denodeify(idStore.submitPassword.bind(idStore)) - - return submitPassword(password) - .then(() => { - const serialized = this.serializeVault() - return this.checkForLostAccounts(serialized) - }) - } - - serializeVault () { - const mnemonic = this.idStore._idmgmt.getSeed() - const numberOfAccounts = this.idStore._getAddresses().length - - return { - type: 'HD Key Tree', - data: { mnemonic, numberOfAccounts }, - } - } - - checkForLostAccounts (serialized) { - const hd = new HdKeyring() - return hd.deserialize(serialized.data) - .then((hexAccounts) => { - const newAccounts = hexAccounts.map(normalize) - const oldAccounts = this.idStore._getAddresses().map(normalize) - const lostAccounts = oldAccounts.reduce((result, account) => { - if (newAccounts.includes(account)) { - return result - } else { - result.push(account) - return result - } - }, []) - - return { - serialized, - lostAccounts: lostAccounts.map((address) => { - return { - address, - privateKey: this.idStore.exportAccount(address), - } - }), - } - }) - } - - hasOldVault () { - const wallet = this.configManager.getWallet() - return wallet - } -} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js deleted file mode 100644 index 01474035e..000000000 --- a/app/scripts/lib/idStore.js +++ /dev/null @@ -1,343 +0,0 @@ -const EventEmitter = require('events').EventEmitter -const inherits = require('util').inherits -const ethUtil = require('ethereumjs-util') -const KeyStore = require('eth-lightwallet').keystore -const clone = require('clone') -const extend = require('xtend') -const autoFaucet = require('./auto-faucet') -const DEFAULT_RPC = 'https://testrpc.metamask.io/' -const IdManagement = require('./id-management') - - -module.exports = IdentityStore - -inherits(IdentityStore, EventEmitter) -function IdentityStore (opts = {}) { - EventEmitter.call(this) - - // we just use the ethStore to auto-add accounts - this._ethStore = opts.ethStore - this.configManager = opts.configManager - // lightwallet key store - this._keyStore = null - // lightwallet wrapper - this._idmgmt = null - - this.hdPathString = "m/44'/60'/0'/0" - - this._currentState = { - selectedAddress: null, - identities: {}, - } - // not part of serilized metamask state - only kept in memory -} - -// -// public -// - -IdentityStore.prototype.createNewVault = function (password, cb) { - delete this._keyStore - var serializedKeystore = this.configManager.getWallet() - - if (serializedKeystore) { - this.configManager.setData({}) - } - - this.purgeCache() - this._createVault(password, null, (err) => { - if (err) return cb(err) - - this._autoFaucet() - - this.configManager.setShowSeedWords(true) - var seedWords = this._idmgmt.getSeed() - - this._loadIdentities() - - cb(null, seedWords) - }) -} - -IdentityStore.prototype.recoverSeed = function (cb) { - this.configManager.setShowSeedWords(true) - if (!this._idmgmt) return cb(new Error('Unauthenticated. Please sign in.')) - var seedWords = this._idmgmt.getSeed() - cb(null, seedWords) -} - -IdentityStore.prototype.recoverFromSeed = function (password, seed, cb) { - this.purgeCache() - - this._createVault(password, seed, (err) => { - if (err) return cb(err) - - this._loadIdentities() - cb(null, this.getState()) - }) -} - -IdentityStore.prototype.setStore = function (store) { - this._ethStore = store -} - -IdentityStore.prototype.clearSeedWordCache = function (cb) { - const configManager = this.configManager - configManager.setShowSeedWords(false) - cb(null, configManager.getSelectedAccount()) -} - -IdentityStore.prototype.getState = function () { - const configManager = this.configManager - var seedWords = this.getSeedIfUnlocked() - return clone(extend(this._currentState, { - isInitialized: !!configManager.getWallet() && !seedWords, - isUnlocked: this._isUnlocked(), - seedWords: seedWords, - selectedAddress: configManager.getSelectedAccount(), - })) -} - -IdentityStore.prototype.getSeedIfUnlocked = function () { - const configManager = this.configManager - var showSeed = configManager.getShouldShowSeedWords() - var idmgmt = this._idmgmt - var shouldShow = showSeed && !!idmgmt - var seedWords = shouldShow ? idmgmt.getSeed() : null - return seedWords -} - -IdentityStore.prototype.getSelectedAddress = function () { - const configManager = this.configManager - return configManager.getSelectedAccount() -} - -IdentityStore.prototype.setSelectedAddressSync = function (address) { - const configManager = this.configManager - if (!address) { - var addresses = this._getAddresses() - address = addresses[0] - } - - configManager.setSelectedAccount(address) - return address -} - -IdentityStore.prototype.setSelectedAddress = function (address, cb) { - const resultAddress = this.setSelectedAddressSync(address) - if (cb) return cb(null, resultAddress) -} - -IdentityStore.prototype.revealAccount = function (cb) { - const derivedKey = this._idmgmt.derivedKey - const keyStore = this._keyStore - const configManager = this.configManager - - keyStore.setDefaultHdDerivationPath(this.hdPathString) - keyStore.generateNewAddress(derivedKey, 1) - const addresses = keyStore.getAddresses() - const address = addresses[ addresses.length - 1 ] - - this._ethStore.addAccount(ethUtil.addHexPrefix(address)) - - configManager.setWallet(keyStore.serialize()) - - this._loadIdentities() - this._didUpdate() - cb(null) -} - -IdentityStore.prototype.getNetwork = function (err) { - if (err) { - this._currentState.network = 'loading' - this._didUpdate() - } - - this.web3.version.getNetwork((err, network) => { - if (err) { - this._currentState.network = 'loading' - return this._didUpdate() - } - if (global.METAMASK_DEBUG) { - console.log('web3.getNetwork returned ' + network) - } - this._currentState.network = network - this._didUpdate() - }) -} - -IdentityStore.prototype.setLocked = function (cb) { - delete this._keyStore - delete this._idmgmt - cb() -} - -IdentityStore.prototype.submitPassword = function (password, cb) { - const configManager = this.configManager - this.tryPassword(password, (err) => { - if (err) return cb(err) - // load identities before returning... - this._loadIdentities() - cb(null, configManager.getSelectedAccount()) - }) -} - -IdentityStore.prototype.exportAccount = function (address, cb) { - var privateKey = this._idmgmt.exportPrivateKey(address) - if (cb) cb(null, privateKey) - return privateKey -} - -// private -// - -IdentityStore.prototype._didUpdate = function () { - this.emit('update', this.getState()) -} - -IdentityStore.prototype._isUnlocked = function () { - var result = Boolean(this._keyStore) && Boolean(this._idmgmt) - return result -} - -// load identities from keyStoreet -IdentityStore.prototype._loadIdentities = function () { - const configManager = this.configManager - if (!this._isUnlocked()) throw new Error('not unlocked') - - var addresses = this._getAddresses() - addresses.forEach((address, i) => { - // // add to ethStore - if (this._ethStore) { - this._ethStore.addAccount(ethUtil.addHexPrefix(address)) - } - // add to identities - const defaultLabel = 'Account ' + (i + 1) - const nickname = configManager.nicknameForWallet(address) - var identity = { - name: nickname || defaultLabel, - address: address, - mayBeFauceting: this._mayBeFauceting(i), - } - this._currentState.identities[address] = identity - }) - this._didUpdate() -} - -IdentityStore.prototype.saveAccountLabel = function (account, label, cb) { - const configManager = this.configManager - configManager.setNicknameForWallet(account, label) - this._loadIdentities() - cb(null, label) -} - -// mayBeFauceting -// If on testnet, index 0 may be fauceting. -// The UI will have to check the balance to know. -// If there is no balance and it mayBeFauceting, -// then it is in fact fauceting. -IdentityStore.prototype._mayBeFauceting = function (i) { - const configManager = this.configManager - var config = configManager.getProvider() - if (i === 0 && - config.type === 'rpc' && - config.rpcTarget === DEFAULT_RPC) { - return true - } - return false -} - -// -// keyStore managment - unlocking + deserialization -// - -IdentityStore.prototype.tryPassword = function (password, cb) { - var serializedKeystore = this.configManager.getWallet() - var keyStore = KeyStore.deserialize(serializedKeystore) - - keyStore.keyFromPassword(password, (err, pwDerivedKey) => { - if (err) return cb(err) - - const isCorrect = keyStore.isDerivedKeyCorrect(pwDerivedKey) - if (!isCorrect) return cb(new Error('Lightwallet - password incorrect')) - - this._keyStore = keyStore - this._createIdMgmt(pwDerivedKey) - cb() - }) -} - -IdentityStore.prototype._createVault = function (password, seedPhrase, cb) { - const opts = { - password, - hdPathString: this.hdPathString, - } - - if (seedPhrase) { - opts.seedPhrase = seedPhrase - } - - KeyStore.createVault(opts, (err, keyStore) => { - if (err) return cb(err) - - this._keyStore = keyStore - - keyStore.keyFromPassword(password, (err, derivedKey) => { - if (err) return cb(err) - - this.purgeCache() - - keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}) - - this._createFirstWallet(derivedKey) - this._createIdMgmt(derivedKey) - this.setSelectedAddressSync() - - cb() - }) - }) -} - -IdentityStore.prototype._createIdMgmt = function (derivedKey) { - this._idmgmt = new IdManagement({ - keyStore: this._keyStore, - derivedKey: derivedKey, - configManager: this.configManager, - }) -} - -IdentityStore.prototype.purgeCache = function () { - this._currentState.identities = {} - let accounts - try { - accounts = Object.keys(this._ethStore._currentState.accounts) - } catch (e) { - accounts = [] - } - accounts.forEach((address) => { - this._ethStore.removeAccount(address) - }) -} - -IdentityStore.prototype._createFirstWallet = function (derivedKey) { - const keyStore = this._keyStore - keyStore.setDefaultHdDerivationPath(this.hdPathString) - keyStore.generateNewAddress(derivedKey, 1) - this.configManager.setWallet(keyStore.serialize()) - var addresses = keyStore.getAddresses() - this._ethStore.addAccount(ethUtil.addHexPrefix(addresses[0])) -} - -// get addresses and normalize address hexString -IdentityStore.prototype._getAddresses = function () { - return this._keyStore.getAddresses(this.hdPathString).map((address) => { - return ethUtil.addHexPrefix(address) - }) -} - -IdentityStore.prototype._autoFaucet = function () { - var addresses = this._getAddresses() - autoFaucet(addresses[0]) -} - -// util diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 25f9d9e5d..92533e022 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -23,7 +23,6 @@ const ConfigManager = require('./lib/config-manager') const extension = require('./lib/extension') const autoFaucet = require('./lib/auto-faucet') const nodeify = require('./lib/nodeify') -const IdStoreMigrator = require('./lib/idStore-migrator') const accountImporter = require('./account-import-strategies') const version = require('../manifest.json').version @@ -115,11 +114,6 @@ module.exports = class MetamaskController extends EventEmitter { this.personalMessageManager = new PersonalMessageManager() this.publicConfigStore = this.initPublicConfigStore() - // TEMPORARY UNTIL FULL DEPRECATION: - this.idStoreMigrator = new IdStoreMigrator({ - configManager: this.configManager, - }) - // manual disk state subscriptions this.txManager.store.subscribe((state) => { this.store.updateState({ TransactionManager: state }) @@ -366,8 +360,7 @@ module.exports = class MetamaskController extends EventEmitter { // submitPassword (password, cb) { - this.migrateOldVaultIfAny(password) - .then(this.keyringController.submitPassword.bind(this.keyringController, password)) + return this.keyringController.submitPassword(password) .then((newState) => { cb(null, newState) }) .catch((reason) => { cb(reason) }) } @@ -562,35 +555,6 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.getState()) } - // 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) - } - - 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) - } - - checkIfShouldMigrate() { - return !!this.configManager.getWallet() && !this.configManager.getVault() - } - restoreOldVaultAccounts(migratorOutput) { const { serialized } = migratorOutput return this.keyringController.restoreKeyring(serialized) -- cgit From 8c7be4340349032655503b4137147e1978b0f0bd Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 22 Mar 2017 09:48:41 -0700 Subject: Have better error messages --- app/scripts/transaction-manager.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index c6cfdf11d..31c1c8431 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -172,7 +172,10 @@ module.exports = class TransactionManager extends EventEmitter { ], (err) => { self.nonceLock.leave() if (err) { - this.setTxStatusFailed(txId) + this.setTxStatusFailed(txId, { + errCode: err.errCode || err, + message: err.message || 'Transaction failed during approval', + }) return cb(err) } cb() @@ -291,7 +294,10 @@ module.exports = class TransactionManager extends EventEmitter { this._setTxStatus(txId, 'confirmed') } - setTxStatusFailed (txId) { + setTxStatusFailed (txId, reason) { + let txMeta = this.getTx(txId) + txMeta.err = reason + this.updateTx(txMeta) this._setTxStatus(txId, 'failed') } @@ -312,12 +318,11 @@ module.exports = class TransactionManager extends EventEmitter { var txHash = txMeta.hash var txId = txMeta.id if (!txHash) { - txMeta.err = { + let errReason = { errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', } - this.updateTx(txMeta) - return this.setTxStatusFailed(txId) + return this.setTxStatusFailed(txId, errReason) } this.txProviderUtils.query.getTransactionByHash(txHash, (err, txParams) => { if (err || !txParams) { -- cgit From 9906da86a4669c1eaf7f693398de380b2973bfe8 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 14:25:56 -0400 Subject: Modify logic for injection conditions. --- app/scripts/contentscript.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index ab64dc9fa..020208ceb 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -69,14 +69,10 @@ function shouldInjectWeb3 () { } function isAllowedSuffix (testCase) { - var prohibitedTypes = ['xml', 'pdf'] - var currentUrl = window.location.href - var currentRegex - for (let i = 0; i < prohibitedTypes.length; i++) { - currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`) - if (currentRegex.test(currentUrl)) { - return false - } + const doctype = window.document.doctype + if (doctype) { + return doctype.name === 'html' + } else { + return false } - return true } -- cgit From c5f96be98d7fe36a369c48b775d0b1fe857844c6 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 15:59:46 -0400 Subject: Add kovan to config file. --- app/scripts/config.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index b4541a04a..ec421744d 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,5 +1,6 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask' const TESTNET_RPC_URL = 'https://ropsten.infura.io/metamask' +const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' const DEFAULT_RPC_URL = TESTNET_RPC_URL global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -10,5 +11,6 @@ module.exports = { mainnet: MAINET_RPC_URL, testnet: TESTNET_RPC_URL, morden: TESTNET_RPC_URL, + kovan: KOVAN_RPC_URL, }, } -- cgit From 33dd7954a72797d23a0d8ed652a626addb1af55d Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 16:00:50 -0400 Subject: Add kovan config settings to config manager. --- app/scripts/lib/config-manager.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 6868637e5..e31cb45ed 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -5,6 +5,7 @@ const normalize = require('eth-sig-util').normalize const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet const MORDEN_RPC = MetamaskConfig.network.morden +const KOVAN_RPC = MetamaskConfig.network.kovan /* The config-manager is a convenience object * wrapping a pojo-migrator. @@ -150,6 +151,9 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'morden': return MORDEN_RPC + case 'kovan': + return KOVAN_RPC + default: return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC } -- cgit From 1b7326048db25afc36baea84ebcf9ece0847f3c3 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 16:41:19 -0400 Subject: Add current block number and hash to the state. --- app/scripts/lib/eth-store.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/eth-store.js b/app/scripts/lib/eth-store.js index 8812a507b..243253df2 100644 --- a/app/scripts/lib/eth-store.js +++ b/app/scripts/lib/eth-store.js @@ -19,6 +19,8 @@ class EthereumStore extends ObservableStore { super({ accounts: {}, transactions: {}, + currentBlockNumber: '0', + currentBlockHash: '', }) this._provider = opts.provider this._query = new EthQuery(this._provider) @@ -69,6 +71,8 @@ class EthereumStore extends ObservableStore { _updateForBlock (block) { const blockNumber = '0x' + block.number.toString('hex') this._currentBlockNumber = blockNumber + this.updateState({ currentBlockNumber: parseInt(blockNumber) }) + this.updateState({ currentBlockHash: `0x${block.hash.toString('hex')}`}) async.parallel([ this._updateAccounts.bind(this), this._updateTransactions.bind(this, blockNumber), @@ -129,4 +133,4 @@ class EthereumStore extends ObservableStore { } -module.exports = EthereumStore \ No newline at end of file +module.exports = EthereumStore -- cgit