aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorkumavis <aaron@kumavis.me>2018-07-03 04:54:05 +0800
committerkumavis <aaron@kumavis.me>2018-07-03 04:54:05 +0800
commita89902c1701f2dcc41effc06d2315e515946b2ca (patch)
tree922408cf99bcca97c956d5860ac80c2c0c472ecc /app
parent055346843bc90a5168151ba2adc9deacedf8afd4 (diff)
parent4c86f25f5bc4fa18847ca1b77e005afc3f37eddc (diff)
downloadtangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.tar
tangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.tar.gz
tangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.tar.bz2
tangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.tar.lz
tangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.tar.xz
tangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.tar.zst
tangerine-wallet-browser-a89902c1701f2dcc41effc06d2315e515946b2ca.zip
Merge branch 'develop' of github.com:MetaMask/metamask-extension into network-remove-provider-engine
Diffstat (limited to 'app')
-rw-r--r--app/_locales/en/messages.json9
-rw-r--r--app/manifest.json2
-rw-r--r--app/scripts/account-import-strategies/index.js13
-rw-r--r--app/scripts/background.js14
-rw-r--r--app/scripts/controllers/network/network.js11
-rw-r--r--app/scripts/controllers/transactions/index.js9
-rw-r--r--app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js2
-rw-r--r--app/scripts/controllers/transactions/lib/recipient-blacklist-config.json14
-rw-r--r--app/scripts/controllers/transactions/lib/recipient-blacklist.js17
-rw-r--r--app/scripts/controllers/transactions/nonce-tracker.js4
-rw-r--r--app/scripts/inpage.js23
-rw-r--r--app/scripts/lib/createStreamSink.js24
-rw-r--r--app/scripts/lib/get-first-preferred-lang-code.js20
-rw-r--r--app/scripts/lib/notification-manager.js6
-rw-r--r--app/scripts/metamask-controller.js36
-rw-r--r--app/scripts/notice-controller.js33
16 files changed, 154 insertions, 83 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 457c3c3b1..46fbdc1a7 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -146,6 +146,9 @@
"copy": {
"message": "Copy"
},
+ "copyContractAddress": {
+ "message": "Copy Contract Address"
+ },
"copyToClipboard": {
"message": "Copy to clipboard"
},
@@ -262,6 +265,9 @@
"encryptNewDen": {
"message": "Encrypt your new DEN"
},
+ "ensNameNotFound": {
+ "message": "ENS name not found"
+ },
"enterPassword": {
"message": "Enter password"
},
@@ -955,6 +961,9 @@
"viewAccount": {
"message": "View Account"
},
+ "viewOnEtherscan": {
+ "message": "View on Etherscan"
+ },
"visitWebSite": {
"message": "Visit our web site"
},
diff --git a/app/manifest.json b/app/manifest.json
index e3a7fd963..50b7e3c53 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "__MSG_appName__",
- "version": "4.7.4",
+ "version": "4.8.0",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "__MSG_appDescription__",
diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js
index 96e2b5912..16ae224ea 100644
--- a/app/scripts/account-import-strategies/index.js
+++ b/app/scripts/account-import-strategies/index.js
@@ -16,7 +16,18 @@ const accountImporter = {
strategies: {
'Private Key': (privateKey) => {
- const stripped = ethUtil.stripHexPrefix(privateKey)
+ if (!privateKey) {
+ throw new Error('Cannot import an empty key.')
+ }
+
+ const prefixed = ethUtil.addHexPrefix(privateKey)
+ const buffer = ethUtil.toBuffer(prefixed)
+
+ if (!ethUtil.isValidPrivate(buffer)) {
+ throw new Error('Cannot import invalid private key.')
+ }
+
+ const stripped = ethUtil.stripHexPrefix(prefixed)
return stripped
},
'JSON File': (input, password) => {
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 9866ff0b0..45d1adcf5 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -16,6 +16,7 @@ const ExtensionPlatform = require('./platforms/extension')
const Migrator = require('./lib/migrator/')
const migrations = require('./migrations/')
const PortStream = require('./lib/port-stream.js')
+const createStreamSink = require('./lib/createStreamSink')
const NotificationManager = require('./lib/notification-manager.js')
const MetamaskController = require('./metamask-controller')
const rawFirstTimeState = require('./first-time-state')
@@ -276,7 +277,7 @@ function setupController (initState, initLangCode) {
asStream(controller.store),
debounce(1000),
storeTransform(versionifyData),
- storeTransform(persistData),
+ createStreamSink(persistData),
(error) => {
log.error('MetaMask - Persistence pipeline failed', error)
}
@@ -292,7 +293,7 @@ function setupController (initState, initLangCode) {
return versionedData
}
- function persistData (state) {
+ async function persistData (state) {
if (!state) {
throw new Error('MetaMask - updated state is missing', state)
}
@@ -300,12 +301,13 @@ function setupController (initState, initLangCode) {
throw new Error('MetaMask - updated state does not have data', state)
}
if (localStore.isSupported) {
- localStore.set(state)
- .catch((err) => {
+ try {
+ await localStore.set(state)
+ } catch (err) {
+ // log error so we dont break the pipeline
log.error('error setting state in local store:', err)
- })
+ }
}
- return state
}
//
diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js
index 9e622981b..628e32fa4 100644
--- a/app/scripts/controllers/network/network.js
+++ b/app/scripts/controllers/network/network.js
@@ -98,14 +98,21 @@ module.exports = class NetworkController extends EventEmitter {
type: 'rpc',
rpcTarget,
}
- this.providerStore.updateState(providerConfig)
- this._switchNetwork(providerConfig)
+ this.providerConfig = providerConfig
}
async setProviderType (type) {
assert.notEqual(type, 'rpc', `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`)
assert(INFURA_PROVIDER_TYPES.includes(type) || type === LOCALHOST, `NetworkController - Unknown rpc type "${type}"`)
const providerConfig = { type }
+ this.providerConfig = providerConfig
+ }
+
+ resetConnection () {
+ this.providerConfig = this.getProviderConfig()
+ }
+
+ set providerConfig (providerConfig) {
this.providerStore.updateState(providerConfig)
this._switchNetwork(providerConfig)
}
diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js
index c270be294..6884bbc49 100644
--- a/app/scripts/controllers/transactions/index.js
+++ b/app/scripts/controllers/transactions/index.js
@@ -170,7 +170,7 @@ class TransactionController extends EventEmitter {
// add default tx params
txMeta = await this.addTxGasDefaults(txMeta)
} catch (error) {
- console.log(error)
+ log.warn(error)
this.txStateManager.setTxStatusFailed(txMeta.id, error)
throw error
}
@@ -269,7 +269,12 @@ class TransactionController extends EventEmitter {
// must set transaction to submitted/failed before releasing lock
nonceLock.releaseLock()
} catch (err) {
- this.txStateManager.setTxStatusFailed(txId, err)
+ // this is try-catch wrapped so that we can guarantee that the nonceLock is released
+ try {
+ this.txStateManager.setTxStatusFailed(txId, err)
+ } catch (err) {
+ log.error(err)
+ }
// must set transaction to submitted/failed before releasing lock
if (nonceLock) nonceLock.releaseLock()
// continue with error chain
diff --git a/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js b/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js
index 84c6df1f0..e4df2367e 100644
--- a/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js
+++ b/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js
@@ -1,4 +1,4 @@
-const Config = require('./recipient-blacklist-config.json')
+const Config = require('./recipient-blacklist.js')
/** @module*/
module.exports = {
diff --git a/app/scripts/controllers/transactions/lib/recipient-blacklist-config.json b/app/scripts/controllers/transactions/lib/recipient-blacklist-config.json
deleted file mode 100644
index b348eb72e..000000000
--- a/app/scripts/controllers/transactions/lib/recipient-blacklist-config.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "blacklist": [
- "0x627306090abab3a6e1400e9345bc60c78a8bef57",
- "0xf17f52151ebef6c7334fad080c5704d77216b732",
- "0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef",
- "0x821aea9a577a9b44299b9c15c88cf3087f3b5544",
- "0x0d1d4e623d10f9fba5db95830f7d3839406c6af2",
- "0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e",
- "0x2191ef87e392377ec08e7c08eb105ef5448eced5",
- "0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5",
- "0x6330a553fc93768f612722bb8c2ec78ac90b3bbc",
- "0x5aeda56215b167893e80b4fe645ba6d5bab767de"
- ]
-}
diff --git a/app/scripts/controllers/transactions/lib/recipient-blacklist.js b/app/scripts/controllers/transactions/lib/recipient-blacklist.js
new file mode 100644
index 000000000..08e1a2ccd
--- /dev/null
+++ b/app/scripts/controllers/transactions/lib/recipient-blacklist.js
@@ -0,0 +1,17 @@
+module.exports = {
+ 'blacklist': [
+ // IDEX phisher
+ '0x9bcb0A9d99d815Bb87ee3191b1399b1Bcc46dc77',
+ // Ganache default seed phrases
+ '0x627306090abab3a6e1400e9345bc60c78a8bef57',
+ '0xf17f52151ebef6c7334fad080c5704d77216b732',
+ '0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef',
+ '0x821aea9a577a9b44299b9c15c88cf3087f3b5544',
+ '0x0d1d4e623d10f9fba5db95830f7d3839406c6af2',
+ '0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e',
+ '0x2191ef87e392377ec08e7c08eb105ef5448eced5',
+ '0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5',
+ '0x6330a553fc93768f612722bb8c2ec78ac90b3bbc',
+ '0x5aeda56215b167893e80b4fe645ba6d5bab767de',
+ ],
+}
diff --git a/app/scripts/controllers/transactions/nonce-tracker.js b/app/scripts/controllers/transactions/nonce-tracker.js
index 14581c998..a27568843 100644
--- a/app/scripts/controllers/transactions/nonce-tracker.js
+++ b/app/scripts/controllers/transactions/nonce-tracker.js
@@ -83,8 +83,8 @@ class NonceTracker {
async _globalMutexFree () {
const globalMutex = this._lookupMutex('global')
- const release = await globalMutex.acquire()
- release()
+ const releaseLock = await globalMutex.acquire()
+ releaseLock()
}
async _takeMutex (lockId) {
diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js
index 6d16eebd4..7dd7fda02 100644
--- a/app/scripts/inpage.js
+++ b/app/scripts/inpage.js
@@ -38,9 +38,30 @@ web3.setProvider = function () {
log.debug('MetaMask - overrode web3.setProvider')
}
log.debug('MetaMask - injected web3')
-// export global web3, with usage-detection
+
setupDappAutoReload(web3, inpageProvider.publicConfigStore)
+// export global web3, with usage-detection and deprecation warning
+
+/* TODO: Uncomment this area once auto-reload.js has been deprecated:
+let hasBeenWarned = false
+global.web3 = new Proxy(web3, {
+ get: (_web3, key) => {
+ // show warning once on web3 access
+ if (!hasBeenWarned && key !== 'currentProvider') {
+ console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation')
+ hasBeenWarned = true
+ }
+ // return value normally
+ return _web3[key]
+ },
+ set: (_web3, key, value) => {
+ // set value normally
+ _web3[key] = value
+ },
+})
+*/
+
// set web3 defaultAccount
inpageProvider.publicConfigStore.subscribe(function (state) {
web3.eth.defaultAccount = state.selectedAddress
diff --git a/app/scripts/lib/createStreamSink.js b/app/scripts/lib/createStreamSink.js
new file mode 100644
index 000000000..cf9416fea
--- /dev/null
+++ b/app/scripts/lib/createStreamSink.js
@@ -0,0 +1,24 @@
+const WritableStream = require('readable-stream').Writable
+const promiseToCallback = require('promise-to-callback')
+
+module.exports = createStreamSink
+
+
+function createStreamSink(asyncWriteFn, _opts) {
+ return new AsyncWritableStream(asyncWriteFn, _opts)
+}
+
+class AsyncWritableStream extends WritableStream {
+
+ constructor (asyncWriteFn, _opts) {
+ const opts = Object.assign({ objectMode: true }, _opts)
+ super(opts)
+ this._asyncWriteFn = asyncWriteFn
+ }
+
+ // write from incomming stream to state
+ _write (chunk, encoding, callback) {
+ promiseToCallback(this._asyncWriteFn(chunk, encoding))(callback)
+ }
+
+}
diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js
index 1e6a83ba6..41a886d74 100644
--- a/app/scripts/lib/get-first-preferred-lang-code.js
+++ b/app/scripts/lib/get-first-preferred-lang-code.js
@@ -2,8 +2,7 @@ const extension = require('extensionizer')
const promisify = require('pify')
const allLocales = require('../../_locales/index.json')
-const isSupported = extension.i18n && extension.i18n.getAcceptLanguages
-const getPreferredLocales = isSupported ? promisify(
+const getPreferredLocales = extension.i18n ? promisify(
extension.i18n.getAcceptLanguages,
{ errorFirst: false }
) : async () => []
@@ -18,7 +17,21 @@ const existingLocaleCodes = allLocales.map(locale => locale.code.toLowerCase().r
*
*/
async function getFirstPreferredLangCode () {
- const userPreferredLocaleCodes = await getPreferredLocales()
+ let userPreferredLocaleCodes
+
+ try {
+ userPreferredLocaleCodes = await getPreferredLocales()
+ } catch (e) {
+ // Brave currently throws when calling getAcceptLanguages, so this handles that.
+ userPreferredLocaleCodes = []
+ }
+
+ // safeguard for Brave Browser until they implement chrome.i18n.getAcceptLanguages
+ // https://github.com/MetaMask/metamask-extension/issues/4270
+ if (!userPreferredLocaleCodes){
+ userPreferredLocaleCodes = []
+ }
+
const firstPreferredLangCode = userPreferredLocaleCodes
.map(code => code.toLowerCase())
.find(code => existingLocaleCodes.includes(code))
@@ -26,3 +39,4 @@ async function getFirstPreferredLangCode () {
}
module.exports = getFirstPreferredLangCode
+
diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js
index 5dfb42078..6b88a7a99 100644
--- a/app/scripts/lib/notification-manager.js
+++ b/app/scripts/lib/notification-manager.js
@@ -32,6 +32,8 @@ class NotificationManager {
type: 'popup',
width,
height,
+ }).then((currentPopup) => {
+ this._popupId = currentPopup.id
})
}
})
@@ -84,7 +86,7 @@ class NotificationManager {
}
/**
- * Given an array of windows, returns the first that has a 'popup' type, or null if no such window exists.
+ * Given an array of windows, returns the 'popup' that has been opened by MetaMask, or null if no such window exists.
*
* @private
* @param {array} windows An array of objects containing data about the open MetaMask extension windows.
@@ -93,7 +95,7 @@ class NotificationManager {
_getPopupIn (windows) {
return windows ? windows.find((win) => {
// Returns notification popup
- return (win && win.type === 'popup')
+ return (win && win.type === 'popup' && win.id === this._popupId)
}) : null
}
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index c00d31949..9abb64900 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -45,7 +45,6 @@ const BN = require('ethereumjs-util').BN
const GWEI_BN = new BN('1000000000')
const percentile = require('percentile')
const seedPhraseVerifier = require('./lib/seed-phrase-verifier')
-const DiagnosticsReporter = require('./lib/diagnostics-reporter')
const log = require('loglevel')
module.exports = class MetamaskController extends EventEmitter {
@@ -64,12 +63,6 @@ module.exports = class MetamaskController extends EventEmitter {
const initState = opts.initState || {}
this.recordFirstTimeInfo(initState)
- // metamask diagnostics reporter
- this.diagnostics = opts.diagnostics || new DiagnosticsReporter({
- firstTimeInfo: initState.firstTimeInfo,
- version,
- })
-
// platform-specific api
this.platform = opts.platform
@@ -91,7 +84,6 @@ module.exports = class MetamaskController extends EventEmitter {
this.preferencesController = new PreferencesController({
initState: initState.PreferencesController,
initLangCode: opts.initLangCode,
- diagnostics: this.diagnostics,
})
// currency controller
@@ -189,9 +181,6 @@ module.exports = class MetamaskController extends EventEmitter {
version,
firstVersion: initState.firstTimeInfo.version,
})
- this.noticeController.updateNoticesList()
- // to be uncommented when retrieving notices from a remote server.
- // this.noticeController.startPolling()
this.shapeshiftController = new ShapeShiftController({
initState: initState.ShapeShiftController,
@@ -430,28 +419,24 @@ module.exports = class MetamaskController extends EventEmitter {
* @returns {Object} vault
*/
async createNewVaultAndKeychain (password) {
- const release = await this.createVaultMutex.acquire()
- let vault
-
+ const releaseLock = await this.createVaultMutex.acquire()
try {
+ let vault
const accounts = await this.keyringController.getAccounts()
-
if (accounts.length > 0) {
vault = await this.keyringController.fullUpdate()
-
} else {
vault = await this.keyringController.createNewVaultAndKeychain(password)
const accounts = await this.keyringController.getAccounts()
this.preferencesController.setAddresses(accounts)
this.selectFirstIdentity()
}
- release()
+ releaseLock()
+ return vault
} catch (err) {
- release()
+ releaseLock()
throw err
}
-
- return vault
}
/**
@@ -460,7 +445,7 @@ module.exports = class MetamaskController extends EventEmitter {
* @param {} seed
*/
async createNewVaultAndRestore (password, seed) {
- const release = await this.createVaultMutex.acquire()
+ const releaseLock = await this.createVaultMutex.acquire()
try {
// clear known identities
this.preferencesController.setAddresses([])
@@ -470,10 +455,10 @@ module.exports = class MetamaskController extends EventEmitter {
const accounts = await this.keyringController.getAccounts()
this.preferencesController.setAddresses(accounts)
this.selectFirstIdentity()
- release()
+ releaseLock()
return vault
} catch (err) {
- release()
+ releaseLock()
throw err
}
}
@@ -624,10 +609,7 @@ module.exports = class MetamaskController extends EventEmitter {
async resetAccount () {
const selectedAddress = this.preferencesController.getSelectedAddress()
this.txController.wipeTransactions(selectedAddress)
-
- const networkController = this.networkController
- const oldType = networkController.getProviderConfig().type
- await networkController.setProviderType(oldType, true)
+ this.networkController.resetConnection()
return selectedAddress
}
diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js
index 14a63eae7..2def4371e 100644
--- a/app/scripts/notice-controller.js
+++ b/app/scripts/notice-controller.js
@@ -2,7 +2,7 @@ const EventEmitter = require('events').EventEmitter
const semver = require('semver')
const extend = require('xtend')
const ObservableStore = require('obs-store')
-const hardCodedNotices = require('../../notices/notices.json')
+const hardCodedNotices = require('../../notices/notices.js')
const uniqBy = require('lodash.uniqby')
module.exports = class NoticeController extends EventEmitter {
@@ -16,8 +16,12 @@ module.exports = class NoticeController extends EventEmitter {
noticesList: [],
}, opts.initState)
this.store = new ObservableStore(initState)
+ // setup memStore
this.memStore = new ObservableStore({})
this.store.subscribe(() => this._updateMemstore())
+ this._updateMemstore()
+ // pull in latest notices
+ this.updateNoticesList()
}
getNoticesList () {
@@ -29,9 +33,9 @@ module.exports = class NoticeController extends EventEmitter {
return notices.filter((notice) => notice.read === false)
}
- getLatestUnreadNotice () {
+ getNextUnreadNotice () {
const unreadNotices = this.getUnreadNotices()
- return unreadNotices[unreadNotices.length - 1]
+ return unreadNotices[0]
}
async setNoticesList (noticesList) {
@@ -47,7 +51,7 @@ module.exports = class NoticeController extends EventEmitter {
notices[index].read = true
notices[index].body = ''
this.setNoticesList(notices)
- const latestNotice = this.getLatestUnreadNotice()
+ const latestNotice = this.getNextUnreadNotice()
cb(null, latestNotice)
} catch (err) {
cb(err)
@@ -64,15 +68,6 @@ module.exports = class NoticeController extends EventEmitter {
return result
}
- startPolling () {
- if (this.noticePoller) {
- clearInterval(this.noticePoller)
- }
- this.noticePoller = setInterval(() => {
- this.noticeController.updateNoticesList()
- }, 300000)
- }
-
_mergeNotices (oldNotices, newNotices) {
return uniqBy(oldNotices.concat(newNotices), 'id')
}
@@ -91,19 +86,15 @@ module.exports = class NoticeController extends EventEmitter {
})
}
- _mapNoticeIds (notices) {
- return notices.map((notice) => notice.id)
- }
-
async _retrieveNoticeData () {
- // Placeholder for the API.
+ // Placeholder for remote notice API.
return hardCodedNotices
}
_updateMemstore () {
- const lastUnreadNotice = this.getLatestUnreadNotice()
- const noActiveNotices = !lastUnreadNotice
- this.memStore.updateState({ lastUnreadNotice, noActiveNotices })
+ const nextUnreadNotice = this.getNextUnreadNotice()
+ const noActiveNotices = !nextUnreadNotice
+ this.memStore.updateState({ nextUnreadNotice, noActiveNotices })
}
}