aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts')
-rw-r--r--app/scripts/controllers/currency.js (renamed from app/scripts/lib/controllers/currency.js)0
-rw-r--r--app/scripts/controllers/preferences.js63
-rw-r--r--app/scripts/controllers/shapeshift.js (renamed from app/scripts/lib/controllers/shapeshift.js)0
-rw-r--r--app/scripts/keyring-controller.js23
-rw-r--r--app/scripts/lib/controllers/preferences.js33
-rw-r--r--app/scripts/lib/personal-message-manager.js22
-rw-r--r--app/scripts/lib/tx-utils.js39
-rw-r--r--app/scripts/metamask-controller.js32
-rw-r--r--app/scripts/popup-core.js6
-rw-r--r--app/scripts/transaction-manager.js2
10 files changed, 148 insertions, 72 deletions
diff --git a/app/scripts/lib/controllers/currency.js b/app/scripts/controllers/currency.js
index c4904f8ac..c4904f8ac 100644
--- a/app/scripts/lib/controllers/currency.js
+++ b/app/scripts/controllers/currency.js
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
new file mode 100644
index 000000000..18fccf11b
--- /dev/null
+++ b/app/scripts/controllers/preferences.js
@@ -0,0 +1,63 @@
+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 Promise.resolve()
+ })
+ }
+
+ 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/controllers/shapeshift.js
index 3d955c01f..3d955c01f 100644
--- a/app/scripts/lib/controllers/shapeshift.js
+++ b/app/scripts/controllers/shapeshift.js
diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js
index e1b1c4335..72f613641 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 you\'re are trying to import is a duplicate'))
+ default:
+ return Promise.resolve(newAccount)
+ }
+ })
+ }
+
+
// Add New Account
// @number keyRingNum
//
diff --git a/app/scripts/lib/controllers/preferences.js b/app/scripts/lib/controllers/preferences.js
deleted file mode 100644
index c5e93a5b9..000000000
--- a/app/scripts/lib/controllers/preferences.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const ObservableStore = require('obs-store')
-const normalizeAddress = require('eth-sig-util').normalize
-
-class PreferencesController {
-
- constructor (opts = {}) {
- const initState = 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
- }
-
- //
- // PRIVATE METHODS
- //
-
-}
-
-module.exports = PreferencesController
diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js
index 3b8510767..bbc978446 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 ethUtil.addHexPrefix(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'))
}
+
}
+
diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js
index 19a2d430e..c6814c05f 100644
--- a/app/scripts/lib/tx-utils.js
+++ b/app/scripts/lib/tx-utils.js
@@ -53,26 +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 estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn), 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 recommendedGasHex = this.addGasBuffer(txData.estimatedGas, blockGasLimitHex)
+ txParams.gas = recommendedGasHex
cb()
return
}
- addGasBuffer (gas) {
- const gasBuffer = new BN('100000', 10)
- const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16)
- const correct = bnGas.add(gasBuffer)
- return ethUtil.addHexPrefix(correct.toString(16))
+ addGasBuffer (initialGasLimitHex, blockGasLimitHex) {
+ 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 bnToHex(initialGasLimitBn)
+ // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit
+ if (bufferedGasLimitBn.lt(blockGasLimitBn)) return bnToHex(bufferedGasLimitBn)
+ // otherwise use blockGasLimit
+ return bnToHex(blockGasLimitBn)
}
fillInTxParams (txParams, cb) {
@@ -94,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
@@ -130,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
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index bd01a260d..536891dc6 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')
@@ -244,7 +244,6 @@ module.exports = class MetamaskController extends EventEmitter {
return {
// etc
getState: (cb) => cb(null, this.getState()),
- setRpcTarget: this.setRpcTarget.bind(this),
setProviderType: this.setProviderType.bind(this),
useEtherscanProvider: this.useEtherscanProvider.bind(this),
setCurrentCurrency: this.setCurrentCurrency.bind(this),
@@ -265,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),
@@ -414,14 +415,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)}`))
}
})
})
@@ -661,10 +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()
+ return Promise.resolve('http://localhost:8545')
+ }
+
+ setCustomRpc (rpcTarget, rpcList) {
+ this.configManager.setRpcTarget(rpcTarget)
+ return this.preferencesController.updateFrequentRpcList(rpcTarget)
+ .then(() => {
+ extension.runtime.reload()
+ this.lookupNetwork()
+ return Promise.resolve(rpcTarget)
+ })
}
setProviderType (type) {
diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js
index 0c97a5d19..b1e521a7a 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) {
- alert(err.stack)
+ container.innerHTML = '<div class="critical-error">The MetaMask app failed to load: please open and close MetaMask again to restart.</div>'
+ container.style.height = '80px'
+ log.error(err.stack)
throw err
}
- var container = document.getElementById('app-content')
MetaMaskUi({
container: container,
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')