From db48f8984f8e16b2831aab36cd538d241cb41402 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 21 Feb 2017 12:32:13 -0800 Subject: [PATCH 01/19] Basic infrasture for RPC list added. --- app/scripts/lib/controllers/preferences.js | 26 +++++++++++++++++++--- app/scripts/metamask-controller.js | 1 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/lib/controllers/preferences.js index dc9464c4e..2d5a1addd 100644 --- a/app/scripts/lib/controllers/preferences.js +++ b/app/scripts/lib/controllers/preferences.js @@ -4,7 +4,7 @@ const normalizeAddress = require('../sig-util').normalize class PreferencesController { constructor (opts = {}) { - const initState = opts.initState || {} + const initState = opts.initState || { frequentRPCList: [] } this.store = new ObservableStore(initState) } @@ -12,7 +12,7 @@ class PreferencesController { // PUBLIC METHODS // - setSelectedAddress(_address) { + setSelectedAddress (_address) { return new Promise((resolve, reject) => { const address = normalizeAddress(_address) this.store.updateState({ selectedAddress: address }) @@ -20,10 +20,30 @@ class PreferencesController { }) } - getSelectedAddress(_address) { + getSelectedAddress (_address) { return this.store.getState().selectedAddress } + addToFrequentRPCList (_url) { + return new Promise((resolve, reject) => { + let rpcList = this.getFrequentRPCList() + let index = rpcList.findIndex((element) => { element === _url }) + if (index) { + rpcList.splice(index, 1) + } + if (rpcList.length >= 3) { + rpcList.shift() + } + rpcList.push(_url) + this.store.updateState({ frequentRPCList: rpcList }) + resolve() + }) + } + + getFrequentRPCList () { + return this.store.getState().frequentRPCList + } + // // PRIVATE METHODS // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 29b13dc62..54c2ebb2c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -259,6 +259,7 @@ module.exports = class MetamaskController extends EventEmitter { // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), + setFrequentRPCList: nodeify(preferencesController.setFrequentRPCList).bind(preferencesController), // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), From 026e0e3383cedf290b2cb55e663f158e7f1c1a68 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 21 Feb 2017 12:51:46 -0800 Subject: [PATCH 02/19] Fix naming --- app/scripts/lib/controllers/preferences.js | 4 ++-- app/scripts/metamask-controller.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/lib/controllers/preferences.js index 2d5a1addd..b28f31b4b 100644 --- a/app/scripts/lib/controllers/preferences.js +++ b/app/scripts/lib/controllers/preferences.js @@ -24,7 +24,7 @@ class PreferencesController { return this.store.getState().selectedAddress } - addToFrequentRPCList (_url) { + addToFrequentRpcList (_url) { return new Promise((resolve, reject) => { let rpcList = this.getFrequentRPCList() let index = rpcList.findIndex((element) => { element === _url }) @@ -40,7 +40,7 @@ class PreferencesController { }) } - getFrequentRPCList () { + getFrequentRpcList () { return this.store.getState().frequentRPCList } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 54c2ebb2c..da186d958 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -259,7 +259,7 @@ module.exports = class MetamaskController extends EventEmitter { // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), - setFrequentRPCList: nodeify(preferencesController.setFrequentRPCList).bind(preferencesController), + addToFrequentRpcList: nodeify(preferencesController.addToFrequentRpcList).bind(preferencesController), // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), From 17a7436602191d11bb02771a87bd74f7baeb49ea Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 21 Feb 2017 12:51:56 -0800 Subject: [PATCH 03/19] Connect to actions. --- ui/app/actions.js | 1 + ui/app/config.js | 1 + 2 files changed, 2 insertions(+) diff --git a/ui/app/actions.js b/ui/app/actions.js index 6552e7f5c..a39646f33 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -628,6 +628,7 @@ function markAccountsFound() { function setRpcTarget (newRpc) { if (global.METAMASK_DEBUG) console.log(`background.setRpcTarget`) background.setRpcTarget(newRpc) + background.addToFrequentRpcList(newRpc) return { type: actions.SET_RPC_TARGET, value: newRpc, diff --git a/ui/app/config.js b/ui/app/config.js index 65b1ed712..00a4cba88 100644 --- a/ui/app/config.js +++ b/ui/app/config.js @@ -5,6 +5,7 @@ const connect = require('react-redux').connect const actions = require('./actions') const currencies = require('./conversion.json').rows const validUrl = require('valid-url') + module.exports = connect(mapStateToProps)(ConfigScreen) function mapStateToProps (state) { From 7a0ce31bd31a3d6f1a92bbaded71b040ca765065 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Feb 2017 15:12:56 -0800 Subject: [PATCH 04/19] Implemented functionality for displaying recent custom RPCs --- app/scripts/lib/controllers/preferences.js | 29 +++++++++++----------- ui/app/actions.js | 5 ++-- ui/app/app.js | 23 +++++++++++++++++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/lib/controllers/preferences.js index b28f31b4b..8cc320179 100644 --- a/app/scripts/lib/controllers/preferences.js +++ b/app/scripts/lib/controllers/preferences.js @@ -1,10 +1,11 @@ const ObservableStore = require('obs-store') const normalizeAddress = require('../sig-util').normalize +const extend = require('xtend') class PreferencesController { constructor (opts = {}) { - const initState = opts.initState || { frequentRPCList: [] } + const initState = extend({ frequentRpcList: [] }, opts.initState) this.store = new ObservableStore(initState) } @@ -25,23 +26,23 @@ class PreferencesController { } addToFrequentRpcList (_url) { - return new Promise((resolve, reject) => { - let rpcList = this.getFrequentRPCList() - let index = rpcList.findIndex((element) => { element === _url }) - if (index) { - rpcList.splice(index, 1) - } - if (rpcList.length >= 3) { - rpcList.shift() - } + let rpcList = this.getFrequentRpcList() + let index = rpcList.findIndex((element) => { return element === _url }) + if (index !== -1) { + rpcList.splice(index, 1) + } + if (_url !== 'http://localhost:8545') { rpcList.push(_url) - this.store.updateState({ frequentRPCList: rpcList }) - resolve() - }) + } + if (rpcList.length > 2) { + rpcList.shift() + } + this.store.updateState({ frequentRpcList: rpcList }) + return Promise.resolve() } getFrequentRpcList () { - return this.store.getState().frequentRPCList + return this.store.getState().frequentRpcList } // diff --git a/ui/app/actions.js b/ui/app/actions.js index a39646f33..86638fc91 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -627,8 +627,9 @@ function markAccountsFound() { function setRpcTarget (newRpc) { if (global.METAMASK_DEBUG) console.log(`background.setRpcTarget`) - background.setRpcTarget(newRpc) - background.addToFrequentRpcList(newRpc) + background.addToFrequentRpcList(newRpc, () => { + background.setRpcTarget(newRpc) + }) return { type: actions.SET_RPC_TARGET, value: newRpc, diff --git a/ui/app/app.js b/ui/app/app.js index 6e249b09e..08a4326fe 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -58,6 +58,7 @@ function mapStateToProps (state) { forgottenPassword: state.appState.forgottenPassword, lastUnreadNotice: state.metamask.lastUnreadNotice, lostAccounts: state.metamask.lostAccounts, + frequentRpcList: state.metamask.frequentRpcList } } @@ -210,6 +211,7 @@ App.prototype.renderAppBar = function () { App.prototype.renderNetworkDropdown = function () { const props = this.props + const rpcList = props.frequentRpcList const state = this.state || {} const isOpen = state.isNetworkMenuOpen @@ -261,6 +263,7 @@ App.prototype.renderNetworkDropdown = function () { }), this.renderCustomOption(props.provider), + this.renderCommonRpc(rpcList, props.provider), props.isUnlocked && h(DropMenuItem, { label: 'Custom RPC', @@ -508,3 +511,23 @@ App.prototype.renderCustomOption = function (provider) { }) } } + +App.prototype.renderCommonRpc = function (rpcList, provider) { + const { rpcTarget } = provider + const props = this.props + + return rpcList.map((rpc) => { + if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) { + return null + } else { + return h(DropMenuItem, { + label: rpc, + closeMenu: () => this.setState({ isNetworkMenuOpen: false }), + action: () => props.dispatch(actions.setRpcTarget(rpc)), + icon: h('i.fa.fa-question-circle.fa-lg'), + activeNetworkRender: rpc, + }) + } + }) + +} From 761eb49586664f8abc62ee89271a6cea95cd23f5 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Feb 2017 15:13:29 -0800 Subject: [PATCH 05/19] Changelog. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d347d2333..c98fa69c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Current Master +- Add two most recently used custom RPCs to network dropdown menu. + ## 3.3.0 2017-2-20 - Add personal_sign and personal_ecRecover support. From 1d0f5fb51c355e6833d2e935a63d4957f0971f1e Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Feb 2017 15:13:59 -0800 Subject: [PATCH 06/19] Linto --- ui/app/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/app.js b/ui/app/app.js index 08a4326fe..c1358f50f 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -58,7 +58,7 @@ function mapStateToProps (state) { forgottenPassword: state.appState.forgottenPassword, lastUnreadNotice: state.metamask.lastUnreadNotice, lostAccounts: state.metamask.lostAccounts, - frequentRpcList: state.metamask.frequentRpcList + frequentRpcList: state.metamask.frequentRpcList, } } From 3be6ee5f6cc5e7b79a8eeea182f91a15eb9ed989 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Feb 2017 15:32:01 -0800 Subject: [PATCH 07/19] Make the UI play nice with empty RPC lists. --- development/states/first-time.json | 1 + ui/app/app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/development/states/first-time.json b/development/states/first-time.json index 108af9117..3554ee911 100644 --- a/development/states/first-time.json +++ b/development/states/first-time.json @@ -4,6 +4,7 @@ "isUnlocked": false, "rpcTarget": "https://rawtestrpc.metamask.io/", "identities": {}, + "frequentRpcList": [], "unapprovedTxs": {}, "currentFiat": "USD", "conversionRate": 12.7527416, diff --git a/ui/app/app.js b/ui/app/app.js index c1358f50f..d61f93dd2 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -58,7 +58,7 @@ function mapStateToProps (state) { forgottenPassword: state.appState.forgottenPassword, lastUnreadNotice: state.metamask.lastUnreadNotice, lostAccounts: state.metamask.lostAccounts, - frequentRpcList: state.metamask.frequentRpcList, + frequentRpcList: state.metamask.frequentRpcList || [], } } From 62854398f1d3c72a82ae9d4feb03d9a1a947534e Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 23 Feb 2017 13:56:58 -0800 Subject: [PATCH 08/19] Tested against code to play nice with unit tests. --- app/scripts/lib/controllers/preferences.js | 13 ++++++++-- app/scripts/metamask-controller.js | 2 +- test/unit/actions/config_test.js | 28 +++++++++++++++++++--- ui/app/actions.js | 18 +++++++++----- ui/app/app.js | 4 +++- ui/app/reducers/metamask.js | 3 ++- 6 files changed, 54 insertions(+), 14 deletions(-) diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/lib/controllers/preferences.js index 8cc320179..7bd2e5631 100644 --- a/app/scripts/lib/controllers/preferences.js +++ b/app/scripts/lib/controllers/preferences.js @@ -25,6 +25,14 @@ class PreferencesController { return this.store.getState().selectedAddress } + updateFrequentRpcList (_url) { + return this.addToFrequentRpcList(_url) + .then((rpcList) => { + this.store.updateState({ frequentRpcList: rpcList }) + return rpcList + }) + } + addToFrequentRpcList (_url) { let rpcList = this.getFrequentRpcList() let index = rpcList.findIndex((element) => { return element === _url }) @@ -37,8 +45,7 @@ class PreferencesController { if (rpcList.length > 2) { rpcList.shift() } - this.store.updateState({ frequentRpcList: rpcList }) - return Promise.resolve() + return Promise.resolve(rpcList) } getFrequentRpcList () { @@ -49,6 +56,8 @@ class PreferencesController { // PRIVATE METHODS // + + } module.exports = PreferencesController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index da186d958..ad67a5875 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -259,7 +259,7 @@ module.exports = class MetamaskController extends EventEmitter { // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), - addToFrequentRpcList: nodeify(preferencesController.addToFrequentRpcList).bind(preferencesController), + updateFrequentRpcList: nodeify(preferencesController.updateFrequentRpcList).bind(preferencesController), // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index f851e4102..fea0cf0ba 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -11,6 +11,7 @@ describe ('config view actions', function() { var initialState = { metamask: { rpcTarget: 'foo', + frequentRpcList: [] }, appState: { currentView: { @@ -30,15 +31,36 @@ describe ('config view actions', function() { describe('SET_RPC_TARGET', function() { it('sets the state.metamask.rpcTarget property of the state to the action.value', function() { + const value = { + rpcTarget: 'foo', + frequentRpcList: ['foo'] + } const action = { type: actions.SET_RPC_TARGET, - value: 'bar', + value, } var result = reducers(initialState, action) assert.equal(result.metamask.provider.type, 'rpc') - assert.equal(result.metamask.provider.rpcTarget, action.value) + assert.equal(result.metamask.provider.rpcTarget, value.rpcTarget) + assert.equal(result.metamask.frequentRpcList[0], value.frequentRpcList[0]) + }) + + it('should handle multiple requests to change the rpc gracefully', function() { + const value = { + rpcTarget: 'foo', + frequentRpcList: ['foo'] + } + + const action = { + type: actions.SET_RPC_TARGET, + value, + } + + var result = reducers(initialState, action) + var secondResult = reducers(result, action) + assert.equal(secondResult.metamask.frequentRpcList.length, 1) }) }) -}) +}) diff --git a/ui/app/actions.js b/ui/app/actions.js index 86638fc91..7e5add1d0 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -626,13 +626,19 @@ function markAccountsFound() { // function setRpcTarget (newRpc) { - if (global.METAMASK_DEBUG) console.log(`background.setRpcTarget`) - background.addToFrequentRpcList(newRpc, () => { + return (dispatch) => { + if (global.METAMASK_DEBUG) console.log(`background.setRpcTarget`) background.setRpcTarget(newRpc) - }) - return { - type: actions.SET_RPC_TARGET, - value: newRpc, + background.updateFrequentRpcList(newRpc, (frequentRpcList) => { + const value = { + rpcTarget: newRpc, + frequentRpcList, + } + dispatch({ + type: actions.SET_RPC_TARGET, + value, + }) + }) } } diff --git a/ui/app/app.js b/ui/app/app.js index d61f93dd2..cf865f23f 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -257,7 +257,9 @@ App.prototype.renderNetworkDropdown = function () { h(DropMenuItem, { label: 'Localhost 8545', closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - action: () => props.dispatch(actions.setRpcTarget('http://localhost:8545')), + action: () => { + props.dispatch(actions.setRpcTarget('http://localhost:8545')) + }, icon: h('i.fa.fa-question-circle.fa-lg'), activeNetworkRender: props.provider.rpcTarget, }), diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 3875cf6d1..7bf2969e7 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -55,9 +55,10 @@ function reduceMetamask (state, action) { case actions.SET_RPC_TARGET: return extend(metamaskState, { + frequentRpcList: action.value.frequentRpcList, provider: { type: 'rpc', - rpcTarget: action.value, + rpcTarget: action.value.rpcTarget, }, }) From 930dafc4b0648353f847c529cdc19e2d762553ad Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 24 Feb 2017 15:30:18 -0800 Subject: [PATCH 09/19] Fix spelling error. --- test/unit/notice-controller-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/notice-controller-test.js b/test/unit/notice-controller-test.js index cf00daeba..73fdb2f2e 100644 --- a/test/unit/notice-controller-test.js +++ b/test/unit/notice-controller-test.js @@ -4,7 +4,7 @@ const rp = require('request-promise') const nock = require('nock') const configManagerGen = require('../lib/mock-config-manager') const NoticeController = require('../../app/scripts/notice-controller') -const STORAGE_KEY = 'metamask-persistance-key' +const STORAGE_KEY = 'metamask-persistence-key' describe('notice-controller', function() { var noticeController From ca5cf06ae9e3e417dd3488bb0d94cdeec74ca18c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 27 Feb 2017 10:25:10 -0800 Subject: [PATCH 10/19] Concatenate custom RPC labels that are too long --- ui/app/app.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui/app/app.js b/ui/app/app.js index cf865f23f..a05a42516 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -499,6 +499,12 @@ App.prototype.renderCustomOption = function (provider) { const { rpcTarget, type } = provider if (type !== 'rpc') return null + // Concatenate long URLs + let label = rpcTarget + if (rpcTarget.length > 31) { + label = label.substr(0, 34) + '...' + } + switch (rpcTarget) { case 'http://localhost:8545': @@ -506,7 +512,8 @@ App.prototype.renderCustomOption = function (provider) { default: return h(DropMenuItem, { - label: `${rpcTarget}`, + label, + key: rpcTarget, closeMenu: () => this.setState({ isNetworkMenuOpen: false }), icon: h('i.fa.fa-question-circle.fa-lg'), activeNetworkRender: 'custom', @@ -524,6 +531,7 @@ App.prototype.renderCommonRpc = function (rpcList, provider) { } else { return h(DropMenuItem, { label: rpc, + key: rpc, closeMenu: () => this.setState({ isNetworkMenuOpen: false }), action: () => props.dispatch(actions.setRpcTarget(rpc)), icon: h('i.fa.fa-question-circle.fa-lg'), From b5d03cd52418cfd09ce51a23c01e78262d3ffc9b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 27 Feb 2017 10:39:48 -0800 Subject: [PATCH 11/19] add controllers to root scripts folder --- app/scripts/{lib => }/controllers/currency.js | 0 app/scripts/{lib => }/controllers/preferences.js | 0 app/scripts/{lib => }/controllers/shapeshift.js | 0 app/scripts/metamask-controller.js | 6 +++--- 4 files changed, 3 insertions(+), 3 deletions(-) rename app/scripts/{lib => }/controllers/currency.js (100%) rename app/scripts/{lib => }/controllers/preferences.js (100%) rename app/scripts/{lib => }/controllers/shapeshift.js (100%) diff --git a/app/scripts/lib/controllers/currency.js b/app/scripts/controllers/currency.js similarity index 100% rename from app/scripts/lib/controllers/currency.js rename to app/scripts/controllers/currency.js diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/controllers/preferences.js similarity index 100% rename from app/scripts/lib/controllers/preferences.js rename to app/scripts/controllers/preferences.js diff --git a/app/scripts/lib/controllers/shapeshift.js b/app/scripts/controllers/shapeshift.js similarity index 100% rename from app/scripts/lib/controllers/shapeshift.js rename to app/scripts/controllers/shapeshift.js diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index d8136667f..bdffc87ac 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -11,10 +11,10 @@ const streamIntoProvider = require('web3-stream-provider/handler') const MetaMaskProvider = require('web3-provider-engine/zero.js') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const KeyringController = require('./keyring-controller') -const PreferencesController = require('./lib/controllers/preferences') -const CurrencyController = require('./lib/controllers/currency') +const PreferencesController = require('./controllers/preferences') +const CurrencyController = require('./controllers/currency') const NoticeController = require('./notice-controller') -const ShapeShiftController = require('./lib/controllers/shapeshift') +const ShapeShiftController = require('./controllers/shapeshift') const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') const TxManager = require('./transaction-manager') From 6fb33853f2ceeb6ef48988a7ee9334dfc87a8223 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 27 Feb 2017 10:53:36 -0800 Subject: [PATCH 12/19] Fix test reference --- test/unit/currency-controller-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/currency-controller-test.js b/test/unit/currency-controller-test.js index c57b522c7..dd7fa91e0 100644 --- a/test/unit/currency-controller-test.js +++ b/test/unit/currency-controller-test.js @@ -5,7 +5,7 @@ const assert = require('assert') const extend = require('xtend') const rp = require('request-promise') const nock = require('nock') -const CurrencyController = require('../../app/scripts/lib/controllers/currency') +const CurrencyController = require('../../app/scripts/controllers/currency') describe('config-manager', function() { var currencyController From 2a98beb87877619ad123281facab3e22dec64fab Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 7 Mar 2017 10:25:50 -0800 Subject: [PATCH 13/19] Break out rpc update and rpclist into two reducers. --- ui/app/actions.js | 30 ++++++++++++++++++++++++------ ui/app/app.js | 4 +--- ui/app/reducers/metamask.js | 8 ++++++-- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index cda987cad..4172ea5df 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -112,11 +112,13 @@ var actions = { // config screen SHOW_CONFIG_PAGE: 'SHOW_CONFIG_PAGE', SET_RPC_TARGET: 'SET_RPC_TARGET', + SET_DEFAULT_RPC_TARGET: 'SET_DEFAULT_RPC_TARGET', SET_PROVIDER_TYPE: 'SET_PROVIDER_TYPE', USE_ETHERSCAN_PROVIDER: 'USE_ETHERSCAN_PROVIDER', useEtherscanProvider: useEtherscanProvider, showConfigPage: showConfigPage, setRpcTarget: setRpcTarget, + setDefaultRpcTarget: setDefaultRpcTarget, setProviderType: setProviderType, // loading overlay SHOW_LOADING: 'SHOW_LOADING_INDICATION', @@ -669,18 +671,34 @@ function markAccountsFound() { // config // +// default rpc target refers to localhost:8545 in this instance. +function setDefaultRpcTarget (rpcList) { + log.debug(`background.setDefaultRpcTarget`) + background.setRpcTarget('http://localhost:8545') + return (dispatch) => { + dispatch({ + type: actions.SET_RPC_TARGET, + value: 'http://localhost:8545', + }) + dispatch({ + type: actions.SET_RPC_LIST, + value: rpcList, + }) + } +} + function setRpcTarget (newRpc) { return (dispatch) => { log.debug(`background.setRpcTarget`) background.setRpcTarget(newRpc) - background.updateFrequentRpcList(newRpc, (frequentRpcList) => { - const value = { - rpcTarget: newRpc, - frequentRpcList, - } + background.updateFrequentRpcList(newRpc, (rpcList) => { dispatch({ type: actions.SET_RPC_TARGET, - value, + value: newRpc, + }) + dispatch({ + type: actions.SET_RPC_LIST, + value: rpcList, }) }) } diff --git a/ui/app/app.js b/ui/app/app.js index 20f948770..2bc92b54c 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -258,9 +258,7 @@ App.prototype.renderNetworkDropdown = function () { h(DropMenuItem, { label: 'Localhost 8545', closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - action: () => { - props.dispatch(actions.setRpcTarget('http://localhost:8545')) - }, + action: () => props.dispatch(actions.setDefaultRpcTarget(rpcList)), icon: h('i.fa.fa-question-circle.fa-lg'), activeNetworkRender: props.provider.rpcTarget, }), diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 7bf2969e7..c09556c91 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -53,12 +53,16 @@ function reduceMetamask (state, action) { isUnlocked: false, }) + case actions.SET_RPC_LIST: + return extend(metamaskState, { + frequentRpcList: action.value, + }) + case actions.SET_RPC_TARGET: return extend(metamaskState, { - frequentRpcList: action.value.frequentRpcList, provider: { type: 'rpc', - rpcTarget: action.value.rpcTarget, + rpcTarget: action.value, }, }) From 01f2ec4823e83d986e7ecfd268f6b293f38a13e8 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 7 Mar 2017 10:37:01 -0800 Subject: [PATCH 14/19] Modify tests.' --- test/unit/actions/config_test.js | 34 ++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index fea0cf0ba..eca2f7c8f 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -31,35 +31,39 @@ describe ('config view actions', function() { describe('SET_RPC_TARGET', function() { it('sets the state.metamask.rpcTarget property of the state to the action.value', function() { - const value = { - rpcTarget: 'foo', - frequentRpcList: ['foo'] - } const action = { type: actions.SET_RPC_TARGET, - value, + value: 'foo', + } + + const secondAction = { + type: actions.SET_RPC_LIST, + value: ['foo'], } var result = reducers(initialState, action) + result = reducers(result, secondAction) assert.equal(result.metamask.provider.type, 'rpc') - assert.equal(result.metamask.provider.rpcTarget, value.rpcTarget) - assert.equal(result.metamask.frequentRpcList[0], value.frequentRpcList[0]) + assert.equal(result.metamask.provider.rpcTarget, 'foo') + assert.equal(result.metamask.frequentRpcList[0], 'foo') }) it('should handle multiple requests to change the rpc gracefully', function() { - const value = { - rpcTarget: 'foo', - frequentRpcList: ['foo'] - } - const action = { type: actions.SET_RPC_TARGET, - value, + value: 'foo', + } + + const secondAction = { + type: actions.SET_RPC_LIST, + value: ['foo'], } var result = reducers(initialState, action) - var secondResult = reducers(result, action) - assert.equal(secondResult.metamask.frequentRpcList.length, 1) + var secondResult = reducers(result, secondAction) + var thirdResult = reducers(secondResult, action) + var fourthResult = reducers(thirdResult, secondAction) + assert.equal(fourthResult.metamask.frequentRpcList.length, 1) }) }) From e7e024bcdd2c93b34a0baf8bc27e6c571c098476 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 7 Mar 2017 16:01:51 -0800 Subject: [PATCH 15/19] Refactor of code into separate reducers and actions. --- app/scripts/controllers/preferences.js | 2 +- app/scripts/metamask-controller.js | 17 +++++++++++---- test/unit/actions/config_test.js | 12 ++--------- ui/app/actions.js | 30 ++++++++------------------ ui/app/reducers/metamask.js | 1 + 5 files changed, 26 insertions(+), 36 deletions(-) diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 8fd5fb8a0..18fccf11b 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -29,7 +29,7 @@ class PreferencesController { return this.addToFrequentRpcList(_url) .then((rpcList) => { this.store.updateState({ frequentRpcList: rpcList }) - return rpcList + return Promise.resolve() }) } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f6dbf899d..3b3329b58 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -244,7 +244,8 @@ module.exports = class MetamaskController extends EventEmitter { return { // etc getState: (cb) => cb(null, this.getState()), - setRpcTarget: this.setRpcTarget.bind(this), + setDefaultRpc: this.setDefaultRpc.bind(this), + setCustomRpc: this.setCustomRpc.bind(this), setProviderType: this.setProviderType.bind(this), useEtherscanProvider: this.useEtherscanProvider.bind(this), setCurrentCurrency: this.setCurrentCurrency.bind(this), @@ -265,7 +266,6 @@ module.exports = class MetamaskController extends EventEmitter { // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), - updateFrequentRpcList: nodeify(preferencesController.updateFrequentRpcList).bind(preferencesController), // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), @@ -662,12 +662,21 @@ module.exports = class MetamaskController extends EventEmitter { if (this.isNetworkLoading()) this.lookupNetwork() } - setRpcTarget (rpcTarget) { - this.configManager.setRpcTarget(rpcTarget) + setDefaultRpc () { + this.configManager.setRpcTarget('http://localhost:8545') extension.runtime.reload() this.lookupNetwork() } + setCustomRpc (rpcTarget, rpcList) { + this.configManager.setRpcTarget(rpcTarget) + return this.preferencesController.updateFrequentRpcList(rpcTarget) + .then(() => { + extension.runtime.reload() + this.lookupNetwork() + }) + } + setProviderType (type) { this.configManager.setProviderType(type) extension.runtime.reload() diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index eca2f7c8f..02704cb42 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -36,16 +36,10 @@ describe ('config view actions', function() { value: 'foo', } - const secondAction = { - type: actions.SET_RPC_LIST, - value: ['foo'], - } - var result = reducers(initialState, action) result = reducers(result, secondAction) assert.equal(result.metamask.provider.type, 'rpc') assert.equal(result.metamask.provider.rpcTarget, 'foo') - assert.equal(result.metamask.frequentRpcList[0], 'foo') }) it('should handle multiple requests to change the rpc gracefully', function() { @@ -60,10 +54,8 @@ describe ('config view actions', function() { } var result = reducers(initialState, action) - var secondResult = reducers(result, secondAction) - var thirdResult = reducers(secondResult, action) - var fourthResult = reducers(thirdResult, secondAction) - assert.equal(fourthResult.metamask.frequentRpcList.length, 1) + var secondResult = reducers(result, action) + assert.equal(secondResult.metamask.frequentRpcList.length, 1) }) }) diff --git a/ui/app/actions.js b/ui/app/actions.js index 4172ea5df..2fc0d3523 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -674,33 +674,21 @@ function markAccountsFound() { // default rpc target refers to localhost:8545 in this instance. function setDefaultRpcTarget (rpcList) { log.debug(`background.setDefaultRpcTarget`) - background.setRpcTarget('http://localhost:8545') - return (dispatch) => { - dispatch({ - type: actions.SET_RPC_TARGET, - value: 'http://localhost:8545', - }) - dispatch({ - type: actions.SET_RPC_LIST, - value: rpcList, - }) + background.setDefaultRpc() + return { + type: actions.SET_RPC_TARGET, + value: 'http://localhost:8545', } } function setRpcTarget (newRpc) { return (dispatch) => { log.debug(`background.setRpcTarget`) - background.setRpcTarget(newRpc) - background.updateFrequentRpcList(newRpc, (rpcList) => { - dispatch({ - type: actions.SET_RPC_TARGET, - value: newRpc, - }) - dispatch({ - type: actions.SET_RPC_LIST, - value: rpcList, - }) - }) + background.setCustomRpc(newRpc) + return { + type: actions.SET_RPC_TARGET, + value: newRpc, + } } } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index c09556c91..a3c07d977 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -18,6 +18,7 @@ function reduceMetamask (state, action) { conversionDate: 'N/A', noActiveNotices: true, lastUnreadNotice: undefined, + frequentRpcList: [], }, state.metamask) switch (action.type) { From 4562e41d33dfe81e305c20583983fba528ee1a9d Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 7 Mar 2017 16:10:06 -0800 Subject: [PATCH 16/19] Fix tests until new ones to-be-written. --- test/unit/actions/config_test.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index 02704cb42..14198fa8a 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -37,26 +37,9 @@ describe ('config view actions', function() { } var result = reducers(initialState, action) - result = reducers(result, secondAction) assert.equal(result.metamask.provider.type, 'rpc') assert.equal(result.metamask.provider.rpcTarget, 'foo') }) - - it('should handle multiple requests to change the rpc gracefully', function() { - const action = { - type: actions.SET_RPC_TARGET, - value: 'foo', - } - - const secondAction = { - type: actions.SET_RPC_LIST, - value: ['foo'], - } - - var result = reducers(initialState, action) - var secondResult = reducers(result, action) - assert.equal(secondResult.metamask.frequentRpcList.length, 1) - }) }) }) From cf2268c3d29d97afa22cd11663bb6e3e74c09b5a Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 09:06:41 -0800 Subject: [PATCH 17/19] Nodeify and promisify calls to background. --- app/scripts/metamask-controller.js | 6 ++++-- ui/app/actions.js | 34 ++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 3b3329b58..536891dc6 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -244,8 +244,6 @@ module.exports = class MetamaskController extends EventEmitter { return { // etc getState: (cb) => cb(null, this.getState()), - setDefaultRpc: this.setDefaultRpc.bind(this), - setCustomRpc: this.setCustomRpc.bind(this), setProviderType: this.setProviderType.bind(this), useEtherscanProvider: this.useEtherscanProvider.bind(this), setCurrentCurrency: this.setCurrentCurrency.bind(this), @@ -266,6 +264,8 @@ module.exports = class MetamaskController extends EventEmitter { // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), + setDefaultRpc: nodeify(this.setDefaultRpc).bind(this), + setCustomRpc: nodeify(this.setCustomRpc).bind(this), // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), @@ -666,6 +666,7 @@ module.exports = class MetamaskController extends EventEmitter { this.configManager.setRpcTarget('http://localhost:8545') extension.runtime.reload() this.lookupNetwork() + return Promise.resolve('http://localhost:8545') } setCustomRpc (rpcTarget, rpcList) { @@ -674,6 +675,7 @@ module.exports = class MetamaskController extends EventEmitter { .then(() => { extension.runtime.reload() this.lookupNetwork() + return Promise.resolve(rpcTarget) }) } diff --git a/ui/app/actions.js b/ui/app/actions.js index 2fc0d3523..062a691e2 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -674,21 +674,37 @@ function markAccountsFound() { // default rpc target refers to localhost:8545 in this instance. function setDefaultRpcTarget (rpcList) { log.debug(`background.setDefaultRpcTarget`) - background.setDefaultRpc() - return { - type: actions.SET_RPC_TARGET, - value: 'http://localhost:8545', + return (dispatch) => { + background.setDefaultRpc((err, result) => { + if (err) { + console.error(err) + return dispatch(self.displayWarning('Had a problem changing networks.')) + } + dispatch(self.setRpc(result)) + }) } + } function setRpcTarget (newRpc) { - return (dispatch) => { log.debug(`background.setRpcTarget`) - background.setCustomRpc(newRpc) - return { - type: actions.SET_RPC_TARGET, - value: newRpc, + return (dispatch) => { + background.setCustomRpc(newRpc, (err, result) => { + if (err) { + console.err(err) + return dispatch(self.displayWarning('Had a problem changing networks!')) + } + dispatch(self.setRpc(result)) + }) } + + +} + +function setRpc (newRpc) { + return { + type: actions.SET_RPC_TARGET, + value: 'http://localhost:8545', } } From 0ee8ca178e9240ab25454bafc88c58ebef6b69c3 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 09:08:28 -0800 Subject: [PATCH 18/19] Remove unneeded setrpc method. --- ui/app/actions.js | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index 062a691e2..82b6fac18 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -680,31 +680,19 @@ function setDefaultRpcTarget (rpcList) { console.error(err) return dispatch(self.displayWarning('Had a problem changing networks.')) } - dispatch(self.setRpc(result)) }) } - } function setRpcTarget (newRpc) { - log.debug(`background.setRpcTarget`) - return (dispatch) => { - background.setCustomRpc(newRpc, (err, result) => { - if (err) { - console.err(err) - return dispatch(self.displayWarning('Had a problem changing networks!')) - } - dispatch(self.setRpc(result)) - }) - } - - -} - -function setRpc (newRpc) { - return { - type: actions.SET_RPC_TARGET, - value: 'http://localhost:8545', + log.debug(`background.setRpcTarget`) + return (dispatch) => { + background.setCustomRpc(newRpc, (err, result) => { + if (err) { + console.err(err) + return dispatch(self.displayWarning('Had a problem changing networks!')) + } + }) } } From 21769a008ccc5fdc2ac5d23a37d401a1d2a20694 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 09:35:31 -0800 Subject: [PATCH 19/19] Fix typo, switch to log.error --- ui/app/actions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index 82b6fac18..d4fd7553b 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -677,7 +677,7 @@ function setDefaultRpcTarget (rpcList) { return (dispatch) => { background.setDefaultRpc((err, result) => { if (err) { - console.error(err) + log.error(err) return dispatch(self.displayWarning('Had a problem changing networks.')) } }) @@ -689,7 +689,7 @@ function setRpcTarget (newRpc) { return (dispatch) => { background.setCustomRpc(newRpc, (err, result) => { if (err) { - console.err(err) + log.error(err) return dispatch(self.displayWarning('Had a problem changing networks!')) } }) @@ -768,7 +768,7 @@ function exportAccount (address) { dispatch(self.hideLoadingIndication()) if (err) { - console.error(err) + log.error(err) return dispatch(self.displayWarning('Had a problem exporting the account.')) }