From db48f8984f8e16b2831aab36cd538d241cb41402 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 21 Feb 2017 12:32:13 -0800 Subject: 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(-) (limited to 'app/scripts') 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), -- cgit v1.2.3 From 026e0e3383cedf290b2cb55e663f158e7f1c1a68 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 21 Feb 2017 12:51:46 -0800 Subject: Fix naming --- app/scripts/lib/controllers/preferences.js | 4 ++-- app/scripts/metamask-controller.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app/scripts') 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), -- cgit v1.2.3 From 7a0ce31bd31a3d6f1a92bbaded71b040ca765065 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Feb 2017 15:12:56 -0800 Subject: Implemented functionality for displaying recent custom RPCs --- app/scripts/lib/controllers/preferences.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'app/scripts') 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 } // -- cgit v1.2.3 From 62854398f1d3c72a82ae9d4feb03d9a1a947534e Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 23 Feb 2017 13:56:58 -0800 Subject: Tested against code to play nice with unit tests. --- app/scripts/lib/controllers/preferences.js | 13 +++++++++++-- app/scripts/metamask-controller.js | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'app/scripts') 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), -- cgit v1.2.3 From b5d03cd52418cfd09ce51a23c01e78262d3ffc9b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 27 Feb 2017 10:39:48 -0800 Subject: add controllers to root scripts folder --- app/scripts/controllers/currency.js | 70 +++++++++++++++++++ app/scripts/controllers/preferences.js | 64 ++++++++++++++++++ app/scripts/controllers/shapeshift.js | 104 +++++++++++++++++++++++++++++ app/scripts/lib/controllers/currency.js | 70 ------------------- app/scripts/lib/controllers/preferences.js | 64 ------------------ app/scripts/lib/controllers/shapeshift.js | 104 ----------------------------- app/scripts/metamask-controller.js | 6 +- 7 files changed, 241 insertions(+), 241 deletions(-) create mode 100644 app/scripts/controllers/currency.js create mode 100644 app/scripts/controllers/preferences.js create mode 100644 app/scripts/controllers/shapeshift.js delete mode 100644 app/scripts/lib/controllers/currency.js delete mode 100644 app/scripts/lib/controllers/preferences.js delete mode 100644 app/scripts/lib/controllers/shapeshift.js (limited to 'app/scripts') diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js new file mode 100644 index 000000000..c4904f8ac --- /dev/null +++ b/app/scripts/controllers/currency.js @@ -0,0 +1,70 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +// every ten minutes +const POLLING_INTERVAL = 600000 + +class CurrencyController { + + constructor (opts = {}) { + const initState = extend({ + currentCurrency: 'USD', + conversionRate: 0, + conversionDate: 'N/A', + }, opts.initState) + this.store = new ObservableStore(initState) + } + + // + // PUBLIC METHODS + // + + getCurrentCurrency () { + return this.store.getState().currentCurrency + } + + setCurrentCurrency (currentCurrency) { + this.store.updateState({ currentCurrency }) + } + + getConversionRate () { + return this.store.getState().conversionRate + } + + setConversionRate (conversionRate) { + this.store.updateState({ conversionRate }) + } + + getConversionDate () { + return this.store.getState().conversionDate + } + + setConversionDate (conversionDate) { + this.store.updateState({ conversionDate }) + } + + updateConversionRate () { + const currentCurrency = this.getCurrentCurrency() + return fetch(`https://www.cryptonator.com/api/ticker/eth-${currentCurrency}`) + .then(response => response.json()) + .then((parsedResponse) => { + this.setConversionRate(Number(parsedResponse.ticker.price)) + this.setConversionDate(Number(parsedResponse.timestamp)) + }).catch((err) => { + console.warn('MetaMask - Failed to query currency conversion.') + this.setConversionRate(0) + this.setConversionDate('N/A') + }) + } + + scheduleConversionInterval () { + if (this.conversionInterval) { + clearInterval(this.conversionInterval) + } + this.conversionInterval = setInterval(() => { + this.updateConversionRate() + }, POLLING_INTERVAL) + } +} + +module.exports = CurrencyController diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js new file mode 100644 index 000000000..9343fe67b --- /dev/null +++ b/app/scripts/controllers/preferences.js @@ -0,0 +1,64 @@ +const ObservableStore = require('obs-store') +const normalizeAddress = require('eth-sig-util').normalize +const extend = require('xtend') + + +class PreferencesController { + + constructor (opts = {}) { + const initState = extend({ frequentRpcList: [] }, opts.initState) + this.store = new ObservableStore(initState) + } + + // + // PUBLIC METHODS + // + + setSelectedAddress (_address) { + return new Promise((resolve, reject) => { + const address = normalizeAddress(_address) + this.store.updateState({ selectedAddress: address }) + resolve() + }) + } + + getSelectedAddress (_address) { + 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 }) + if (index !== -1) { + rpcList.splice(index, 1) + } + if (_url !== 'http://localhost:8545') { + rpcList.push(_url) + } + if (rpcList.length > 2) { + rpcList.shift() + } + return Promise.resolve(rpcList) + } + + getFrequentRpcList () { + return this.store.getState().frequentRpcList + } + + // + // PRIVATE METHODS + // + + + +} + +module.exports = PreferencesController diff --git a/app/scripts/controllers/shapeshift.js b/app/scripts/controllers/shapeshift.js new file mode 100644 index 000000000..3d955c01f --- /dev/null +++ b/app/scripts/controllers/shapeshift.js @@ -0,0 +1,104 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +// every three seconds when an incomplete tx is waiting +const POLLING_INTERVAL = 3000 + +class ShapeshiftController { + + constructor (opts = {}) { + const initState = extend({ + shapeShiftTxList: [], + }, opts.initState) + this.store = new ObservableStore(initState) + this.pollForUpdates() + } + + // + // PUBLIC METHODS + // + + getShapeShiftTxList () { + const shapeShiftTxList = this.store.getState().shapeShiftTxList + return shapeShiftTxList + } + + getPendingTxs () { + const txs = this.getShapeShiftTxList() + const pending = txs.filter(tx => tx.response && tx.response.status !== 'complete') + return pending + } + + pollForUpdates () { + const pendingTxs = this.getPendingTxs() + + if (pendingTxs.length === 0) { + return + } + + Promise.all(pendingTxs.map((tx) => { + return this.updateTx(tx) + })) + .then((results) => { + results.forEach(tx => this.saveTx(tx)) + this.timeout = setTimeout(this.pollForUpdates.bind(this), POLLING_INTERVAL) + }) + } + + updateTx (tx) { + const url = `https://shapeshift.io/txStat/${tx.depositAddress}` + return fetch(url) + .then((response) => { + return response.json() + }).then((json) => { + tx.response = json + if (tx.response.status === 'complete') { + tx.time = new Date().getTime() + } + return tx + }) + } + + saveTx (tx) { + const { shapeShiftTxList } = this.store.getState() + const index = shapeShiftTxList.indexOf(tx) + if (index !== -1) { + shapeShiftTxList[index] = tx + this.store.updateState({ shapeShiftTxList }) + } + } + + removeShapeShiftTx (tx) { + const { shapeShiftTxList } = this.store.getState() + const index = shapeShiftTxList.indexOf(index) + if (index !== -1) { + shapeShiftTxList.splice(index, 1) + } + this.updateState({ shapeShiftTxList }) + } + + createShapeShiftTx (depositAddress, depositType) { + const state = this.store.getState() + let { shapeShiftTxList } = state + + var shapeShiftTx = { + depositAddress, + depositType, + key: 'shapeshift', + time: new Date().getTime(), + response: {}, + } + + if (!shapeShiftTxList) { + shapeShiftTxList = [shapeShiftTx] + } else { + shapeShiftTxList.push(shapeShiftTx) + } + + this.store.updateState({ shapeShiftTxList }) + this.pollForUpdates() + } + +} + +module.exports = ShapeshiftController diff --git a/app/scripts/lib/controllers/currency.js b/app/scripts/lib/controllers/currency.js deleted file mode 100644 index c4904f8ac..000000000 --- a/app/scripts/lib/controllers/currency.js +++ /dev/null @@ -1,70 +0,0 @@ -const ObservableStore = require('obs-store') -const extend = require('xtend') - -// every ten minutes -const POLLING_INTERVAL = 600000 - -class CurrencyController { - - constructor (opts = {}) { - const initState = extend({ - currentCurrency: 'USD', - conversionRate: 0, - conversionDate: 'N/A', - }, opts.initState) - this.store = new ObservableStore(initState) - } - - // - // PUBLIC METHODS - // - - getCurrentCurrency () { - return this.store.getState().currentCurrency - } - - setCurrentCurrency (currentCurrency) { - this.store.updateState({ currentCurrency }) - } - - getConversionRate () { - return this.store.getState().conversionRate - } - - setConversionRate (conversionRate) { - this.store.updateState({ conversionRate }) - } - - getConversionDate () { - return this.store.getState().conversionDate - } - - setConversionDate (conversionDate) { - this.store.updateState({ conversionDate }) - } - - updateConversionRate () { - const currentCurrency = this.getCurrentCurrency() - return fetch(`https://www.cryptonator.com/api/ticker/eth-${currentCurrency}`) - .then(response => response.json()) - .then((parsedResponse) => { - this.setConversionRate(Number(parsedResponse.ticker.price)) - this.setConversionDate(Number(parsedResponse.timestamp)) - }).catch((err) => { - console.warn('MetaMask - Failed to query currency conversion.') - this.setConversionRate(0) - this.setConversionDate('N/A') - }) - } - - scheduleConversionInterval () { - if (this.conversionInterval) { - clearInterval(this.conversionInterval) - } - this.conversionInterval = setInterval(() => { - this.updateConversionRate() - }, POLLING_INTERVAL) - } -} - -module.exports = CurrencyController diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/lib/controllers/preferences.js deleted file mode 100644 index 9343fe67b..000000000 --- a/app/scripts/lib/controllers/preferences.js +++ /dev/null @@ -1,64 +0,0 @@ -const ObservableStore = require('obs-store') -const normalizeAddress = require('eth-sig-util').normalize -const extend = require('xtend') - - -class PreferencesController { - - constructor (opts = {}) { - const initState = extend({ frequentRpcList: [] }, opts.initState) - this.store = new ObservableStore(initState) - } - - // - // PUBLIC METHODS - // - - setSelectedAddress (_address) { - return new Promise((resolve, reject) => { - const address = normalizeAddress(_address) - this.store.updateState({ selectedAddress: address }) - resolve() - }) - } - - getSelectedAddress (_address) { - 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 }) - if (index !== -1) { - rpcList.splice(index, 1) - } - if (_url !== 'http://localhost:8545') { - rpcList.push(_url) - } - if (rpcList.length > 2) { - rpcList.shift() - } - return Promise.resolve(rpcList) - } - - getFrequentRpcList () { - return this.store.getState().frequentRpcList - } - - // - // PRIVATE METHODS - // - - - -} - -module.exports = PreferencesController diff --git a/app/scripts/lib/controllers/shapeshift.js b/app/scripts/lib/controllers/shapeshift.js deleted file mode 100644 index 3d955c01f..000000000 --- a/app/scripts/lib/controllers/shapeshift.js +++ /dev/null @@ -1,104 +0,0 @@ -const ObservableStore = require('obs-store') -const extend = require('xtend') - -// every three seconds when an incomplete tx is waiting -const POLLING_INTERVAL = 3000 - -class ShapeshiftController { - - constructor (opts = {}) { - const initState = extend({ - shapeShiftTxList: [], - }, opts.initState) - this.store = new ObservableStore(initState) - this.pollForUpdates() - } - - // - // PUBLIC METHODS - // - - getShapeShiftTxList () { - const shapeShiftTxList = this.store.getState().shapeShiftTxList - return shapeShiftTxList - } - - getPendingTxs () { - const txs = this.getShapeShiftTxList() - const pending = txs.filter(tx => tx.response && tx.response.status !== 'complete') - return pending - } - - pollForUpdates () { - const pendingTxs = this.getPendingTxs() - - if (pendingTxs.length === 0) { - return - } - - Promise.all(pendingTxs.map((tx) => { - return this.updateTx(tx) - })) - .then((results) => { - results.forEach(tx => this.saveTx(tx)) - this.timeout = setTimeout(this.pollForUpdates.bind(this), POLLING_INTERVAL) - }) - } - - updateTx (tx) { - const url = `https://shapeshift.io/txStat/${tx.depositAddress}` - return fetch(url) - .then((response) => { - return response.json() - }).then((json) => { - tx.response = json - if (tx.response.status === 'complete') { - tx.time = new Date().getTime() - } - return tx - }) - } - - saveTx (tx) { - const { shapeShiftTxList } = this.store.getState() - const index = shapeShiftTxList.indexOf(tx) - if (index !== -1) { - shapeShiftTxList[index] = tx - this.store.updateState({ shapeShiftTxList }) - } - } - - removeShapeShiftTx (tx) { - const { shapeShiftTxList } = this.store.getState() - const index = shapeShiftTxList.indexOf(index) - if (index !== -1) { - shapeShiftTxList.splice(index, 1) - } - this.updateState({ shapeShiftTxList }) - } - - createShapeShiftTx (depositAddress, depositType) { - const state = this.store.getState() - let { shapeShiftTxList } = state - - var shapeShiftTx = { - depositAddress, - depositType, - key: 'shapeshift', - time: new Date().getTime(), - response: {}, - } - - if (!shapeShiftTxList) { - shapeShiftTxList = [shapeShiftTx] - } else { - shapeShiftTxList.push(shapeShiftTx) - } - - this.store.updateState({ shapeShiftTxList }) - this.pollForUpdates() - } - -} - -module.exports = ShapeshiftController 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') -- cgit v1.2.3 From 9bd8c5f723abef25b8864457df7207eb361be8e3 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 6 Mar 2017 15:03:49 -0800 Subject: Render personal_sign messages as utf-8 text Calls to `personal_sign` are now: - When hex encoded, preserved as hex encoded, but displayed as utf-8 text. - When not hex encoded, decoded as utf-8 text as hex for signing. - The messages proposed for signing are displayed as UTF-8 text. - When the message cannot be rendered as UTF-8 text, it is displayed as hexadecimal. Fixes #1173 --- app/scripts/lib/personal-message-manager.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 3b8510767..04dba4a90 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -2,6 +2,7 @@ const EventEmitter = require('events') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const createId = require('./random-id') +const hexRe = /^[0-9A-Fa-f]+$/g module.exports = class PersonalMessageManager extends EventEmitter{ @@ -24,7 +25,8 @@ module.exports = class PersonalMessageManager extends EventEmitter{ } addUnapprovedMessage (msgParams) { - msgParams.data = normalizeMsgData(msgParams.data) + log.debug(`PersonalMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`) + msgParams.data = this.normalizeMsgData(msgParams.data) // create txData obj with parameters and meta data var time = (new Date()).getTime() var msgId = createId() @@ -106,14 +108,18 @@ module.exports = class PersonalMessageManager extends EventEmitter{ this.emit('updateBadge') } -} + normalizeMsgData(data) { + try { + const stripped = ethUtil.stripHexPrefix(data) + if (stripped.match(hexRe)) { + return stripped + } + } catch (e) { + log.debug(`Message was not hex encoded, interpreting as utf8.`) + } -function normalizeMsgData(data) { - if (data.slice(0, 2) === '0x') { - // data is already hex - return data - } else { - // data is unicode, convert to hex return ethUtil.bufferToHex(new Buffer(data, 'utf8')) } + } + -- cgit v1.2.3 From b84f1b053265fdabc0aaec4fa8aa3145b6fb7f51 Mon Sep 17 00:00:00 2001 From: Frankie Date: Mon, 6 Mar 2017 15:41:11 -0800 Subject: Fix issue where old txMeta object was being used to pass the txHash to the cb --- app/scripts/metamask-controller.js | 8 ++++---- app/scripts/transaction-manager.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index bd01a260d..3dddf7065 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -414,14 +414,14 @@ module.exports = class MetamaskController extends EventEmitter { self.sendUpdate() self.opts.showUnapprovedTx(txMeta) // listen for tx completion (success, fail) - self.txManager.once(`${txMeta.id}:finished`, (status) => { - switch (status) { + self.txManager.once(`${txMeta.id}:finished`, (completedTx) => { + switch (completedTx.status) { case 'submitted': - return cb(null, txMeta.hash) + return cb(null, completedTx.hash) case 'rejected': return cb(new Error('MetaMask Tx Signature: User denied transaction signature.')) default: - return cb(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(txMeta.txParams)}`)) + return cb(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(completedTx.txParams)}`)) } }) }) diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 07c90af7e..c6cfdf11d 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -353,7 +353,7 @@ module.exports = class TransactionManager extends EventEmitter { txMeta.status = status this.emit(`${txMeta.id}:${status}`, txId) if (status === 'submitted' || status === 'rejected') { - this.emit(`${txMeta.id}:finished`, status) + this.emit(`${txMeta.id}:finished`, txMeta) } this.updateTx(txMeta) this.emit('updateBadge') -- cgit v1.2.3 From e66e755766ef318c38277c184d2670cc2179d37a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 6 Mar 2017 16:33:33 -0800 Subject: Fix normalizeMsgData function to always return hex prefixed --- app/scripts/lib/personal-message-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 04dba4a90..bbc978446 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -112,7 +112,7 @@ module.exports = class PersonalMessageManager extends EventEmitter{ try { const stripped = ethUtil.stripHexPrefix(data) if (stripped.match(hexRe)) { - return stripped + return ethUtil.addHexPrefix(stripped) } } catch (e) { log.debug(`Message was not hex encoded, interpreting as utf8.`) -- cgit v1.2.3 From e7e024bcdd2c93b34a0baf8bc27e6c571c098476 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 7 Mar 2017 16:01:51 -0800 Subject: Refactor of code into separate reducers and actions. --- app/scripts/controllers/preferences.js | 2 +- app/scripts/metamask-controller.js | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'app/scripts') 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() -- cgit v1.2.3 From 4256e631a6174f04d338412f419ceb0c08d724f1 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 7 Mar 2017 19:57:57 -0500 Subject: remove constant buffer and add multiplier --- app/scripts/lib/tx-utils.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 19a2d430e..15cbb5b68 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -55,7 +55,7 @@ module.exports = class txProviderUtils { // try adding an additional gas buffer to our estimation for safety const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16) const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) - const estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn), 16) + const estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn, blockGasLimitHex), 16) // added gas buffer is too high if (estimationWithBuffer.gt(blockGasLimitBn)) { txParams.gas = txData.estimatedGas @@ -68,11 +68,14 @@ module.exports = class txProviderUtils { return } - addGasBuffer (gas) { - const gasBuffer = new BN('100000', 10) + addGasBuffer (gas, blockGasLimitHex) { + const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) - const correct = bnGas.add(gasBuffer) - return ethUtil.addHexPrefix(correct.toString(16)) + const bufferedGas = bnGas.mul(1.5) + + if (bnGas.gt(blockGasLimitBn)) return gas + if (bufferedGas.lt(blockGasLimitBn)) return ethUtil.addHexPrefix(bufferedGas.toString(16)) + return ethUtil.addHexPrefix(blockGasLimitBn.toString(16)) } fillInTxParams (txParams, cb) { -- cgit v1.2.3 From 3e8b584c9811b06526e69203a5e03f8eb82e8211 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 7 Mar 2017 17:59:03 -0800 Subject: fix issue where account import allows for duplicates --- app/scripts/keyring-controller.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index e1b1c4335..7669b9f8f 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -164,8 +164,11 @@ class KeyringController extends EventEmitter { return keyring.getAccounts() }) .then((accounts) => { + return this.checkForDuplicate(type, accounts) + }) + .then((checkedAccounts) => { this.keyrings.push(keyring) - return this.setupAccounts(accounts) + return this.setupAccounts(checkedAccounts) }) .then(() => this.persistAllKeyrings()) .then(() => this.fullUpdate()) @@ -175,6 +178,24 @@ class KeyringController extends EventEmitter { }) } + // For now just checks for simple key pairs + // but in the future + // should possibly add HD and other types + // + checkForDuplicate (type, newAccount) { + return this.getAccounts() + .then((accounts) => { + switch (type) { + case 'Simple Key Pair': + let isNotIncluded = !accounts.find((key) => key === newAccount[0] || key === ethUtil.stripHexPrefix(newAccount[0])) + return (isNotIncluded) ? Promise.resolve(newAccount) : Promise.reject(new Error('The account your are trying to import is a duplicate')) + default: + return Promise.resolve(newAccount) + } + }) + } + + // Add New Account // @number keyRingNum // -- cgit v1.2.3 From 2f7a95c25765ec040eddb8f3103bfe60d4760a26 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 7 Mar 2017 18:56:38 -0800 Subject: Fix grammar in erro message --- app/scripts/keyring-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 7669b9f8f..72f613641 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -188,7 +188,7 @@ class KeyringController extends EventEmitter { switch (type) { case 'Simple Key Pair': let isNotIncluded = !accounts.find((key) => key === newAccount[0] || key === ethUtil.stripHexPrefix(newAccount[0])) - return (isNotIncluded) ? Promise.resolve(newAccount) : Promise.reject(new Error('The account your are trying to import is a duplicate')) + return (isNotIncluded) ? Promise.resolve(newAccount) : Promise.reject(new Error('The account you\'re are trying to import is a duplicate')) default: return Promise.resolve(newAccount) } -- cgit v1.2.3 From 4916331c530896bbcef13a71a8f6dc0164b43c01 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 7 Mar 2017 22:42:16 -0500 Subject: change BN.mul to BN.muln --- app/scripts/lib/tx-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 15cbb5b68..f5051eb8f 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -71,7 +71,7 @@ module.exports = class txProviderUtils { addGasBuffer (gas, blockGasLimitHex) { const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) - const bufferedGas = bnGas.mul(1.5) + const bufferedGas = bnGas.muln(1.5) if (bnGas.gt(blockGasLimitBn)) return gas if (bufferedGas.lt(blockGasLimitBn)) return ethUtil.addHexPrefix(bufferedGas.toString(16)) -- cgit v1.2.3 From 17b805c76ea3ea160bcb2560d2043581b54c4834 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 7 Mar 2017 22:18:14 -0800 Subject: tx-utils - clean and comment --- app/scripts/lib/tx-utils.js | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index f5051eb8f..32a8a012a 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -55,26 +55,22 @@ module.exports = class txProviderUtils { // try adding an additional gas buffer to our estimation for safety const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16) const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) - const estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn, blockGasLimitHex), 16) - // added gas buffer is too high - if (estimationWithBuffer.gt(blockGasLimitBn)) { - txParams.gas = txData.estimatedGas - // added gas buffer is safe - } else { - const gasWithBufferHex = ethUtil.intToHex(estimationWithBuffer) - txParams.gas = gasWithBufferHex - } + const finalRecommendedGasBn = new BN(this.addGasBuffer(estimatedGasBn, blockGasLimitHex), 16) + txParams.gas = ethUtil.intToHex(finalRecommendedGasBn) cb() return } - addGasBuffer (gas, blockGasLimitHex) { + addGasBuffer (initialGasLimitHex, blockGasLimitHex) { const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) - const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16) - const bufferedGas = bnGas.muln(1.5) - - if (bnGas.gt(blockGasLimitBn)) return gas - if (bufferedGas.lt(blockGasLimitBn)) return ethUtil.addHexPrefix(bufferedGas.toString(16)) + const initialGasLimitBn = new BN(ethUtil.stripHexPrefix(initialGasLimitHex), 16) + const bufferedGasLimitBn = initialGasLimitBn.muln(1.5) + + // if initialGasLimit is above blockGasLimit, dont modify it + if (initialGasLimitBn.gt(blockGasLimitBn)) return initialGasLimitHex + // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit + if (bufferedGasLimitBn.lt(blockGasLimitBn)) return ethUtil.addHexPrefix(bufferedGasLimitBn.toString(16)) + // otherwise use blockGasLimit return ethUtil.addHexPrefix(blockGasLimitBn.toString(16)) } -- cgit v1.2.3 From c063fab9932c6b90414fd7db7849012d6594afb7 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 7 Mar 2017 22:47:35 -0800 Subject: tx-utils - stricter naming type-based convention --- app/scripts/lib/tx-utils.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 32a8a012a..f1171851c 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -53,25 +53,23 @@ module.exports = class txProviderUtils { } // if gasLimit not originally specified, // try adding an additional gas buffer to our estimation for safety - const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16) - const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) - const finalRecommendedGasBn = new BN(this.addGasBuffer(estimatedGasBn, blockGasLimitHex), 16) - txParams.gas = ethUtil.intToHex(finalRecommendedGasBn) + const recommendedGasHex = this.addGasBuffer(txData.estimatedGas, blockGasLimitHex) + txParams.gas = recommendedGasHex cb() return } addGasBuffer (initialGasLimitHex, blockGasLimitHex) { - const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16) - const initialGasLimitBn = new BN(ethUtil.stripHexPrefix(initialGasLimitHex), 16) + const initialGasLimitBn = hexToBn(initialGasLimitHex) + const blockGasLimitBn = hexToBn(blockGasLimitHex) const bufferedGasLimitBn = initialGasLimitBn.muln(1.5) // if initialGasLimit is above blockGasLimit, dont modify it - if (initialGasLimitBn.gt(blockGasLimitBn)) return initialGasLimitHex + if (initialGasLimitBn.gt(blockGasLimitBn)) return bnToHex(initialGasLimitBn) // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit - if (bufferedGasLimitBn.lt(blockGasLimitBn)) return ethUtil.addHexPrefix(bufferedGasLimitBn.toString(16)) + if (bufferedGasLimitBn.lt(blockGasLimitBn)) return bnToHex(bufferedGasLimitBn) // otherwise use blockGasLimit - return ethUtil.addHexPrefix(blockGasLimitBn.toString(16)) + return bnToHex(blockGasLimitBn) } fillInTxParams (txParams, cb) { @@ -129,3 +127,11 @@ module.exports = class txProviderUtils { function isUndef(value) { return value === undefined } + +function bnToHex(inputBn) { + return ethUtil.addHexPrefix(inputBn.toString(16)) +} + +function hexToBn(inputHex) { + return new BN(ethUtil.stripHexPrefix(inputHex), 16) +} \ No newline at end of file -- cgit v1.2.3 From 92b8443824bffca219b146028d5685e6aa1ffabf Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 7 Mar 2017 22:51:39 -0800 Subject: tx-utils - add encoding utils --- app/scripts/lib/tx-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index f1171851c..c6814c05f 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -91,7 +91,7 @@ module.exports = class txProviderUtils { // builds ethTx from txParams object buildEthTxFromParams (txParams) { // apply gas multiplyer - let gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16) + let gasPrice = hexToBn(txParams.gasPrice) // multiply and divide by 100 so as to add percision to integer mul txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) // normalize values -- cgit v1.2.3 From cf2268c3d29d97afa22cd11663bb6e3e74c09b5a Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 09:06:41 -0800 Subject: Nodeify and promisify calls to background. --- app/scripts/metamask-controller.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app/scripts') 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) }) } -- cgit v1.2.3 From 529eb25ced3337aadafd44bcf43e3ae6f192614a Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 10:13:45 -0800 Subject: Convert alert to a log.error --- app/scripts/popup-core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 0c97a5d19..ae8539a30 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -50,7 +50,7 @@ function setupControllerConnection (connectionStream, cb) { function setupApp (err, accountManager) { if (err) { - alert(err.stack) + log.error(err.stack) throw err } -- cgit v1.2.3 From 6f980cfe10d32ddc276b737df42005ef7cf4cd96 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 10:46:17 -0800 Subject: Add more informative message --- app/scripts/popup-core.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index ae8539a30..e093d06f4 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -49,12 +49,14 @@ function setupControllerConnection (connectionStream, cb) { } function setupApp (err, accountManager) { + var container = document.getElementById('app-content') if (err) { + container.innerHTML = '
The MetaMask app failed to load: please restart MetaMask
' + container.style.height = '80px' log.error(err.stack) throw err } - var container = document.getElementById('app-content') MetaMaskUi({ container: container, -- cgit v1.2.3 From acc9a2a9d05269511efe26bd790cbc256533c19e Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 8 Mar 2017 10:53:11 -0800 Subject: Modify message. --- app/scripts/popup-core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index e093d06f4..b1e521a7a 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -51,7 +51,7 @@ function setupControllerConnection (connectionStream, cb) { function setupApp (err, accountManager) { var container = document.getElementById('app-content') if (err) { - container.innerHTML = '
The MetaMask app failed to load: please restart MetaMask
' + container.innerHTML = '
The MetaMask app failed to load: please open and close MetaMask again to restart.
' container.style.height = '80px' log.error(err.stack) throw err -- cgit v1.2.3