mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-23 02:10:12 +01:00
Merge branch 'master' into ModularFiatBalance
This commit is contained in:
commit
58a8f02294
@ -2,8 +2,16 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
## 2.10.2 2016-09-02
|
||||
|
||||
- Fix bug where notification popup would not display.
|
||||
|
||||
## 2.10.1 2016-09-02
|
||||
|
||||
- Fix bug where provider menu did not allow switching to custom network from a custom network.
|
||||
- Sending a transaction from within MetaMask no longer triggers a popup.
|
||||
- The ability to build without livereload features (such as for production) can be enabled with the gulp --disableLiveReload flag.
|
||||
- Fix Ethereum JSON RPC Filters bug.
|
||||
|
||||
## 2.10.0 2016-08-29
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "MetaMask",
|
||||
"short_name": "Metamask",
|
||||
"version": "2.10.0",
|
||||
"version": "2.10.2",
|
||||
"manifest_version": 2,
|
||||
"author": "https://metamask.io",
|
||||
"description": "Ethereum Browser Extension",
|
||||
|
@ -80,7 +80,8 @@ MetamaskInpageProvider.prototype.send = function (payload) {
|
||||
|
||||
// throw not-supported Error
|
||||
default:
|
||||
var message = 'The MetaMask Web3 object does not support synchronous methods. See https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#all-async---think-of-metamask-as-a-light-client for details.'
|
||||
var message = 'The MetaMask Web3 object does not support synchronous methods like ' + payload.method +
|
||||
'. See https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#all-async---think-of-metamask-as-a-light-client for details.'
|
||||
throw new Error(message)
|
||||
|
||||
}
|
||||
@ -131,4 +132,4 @@ function eachJsonMessage(payload, transformFn){
|
||||
} else {
|
||||
return transformFn(payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,20 +9,26 @@ module.exports = notifications
|
||||
window.METAMASK_NOTIFIER = notifications
|
||||
|
||||
function show () {
|
||||
getWindows((windows) => {
|
||||
getPopup((err, popup) => {
|
||||
if (err) throw err
|
||||
|
||||
if (popup) {
|
||||
|
||||
// bring focus to existing popup
|
||||
extension.windows.update(popup.id, { focused: true })
|
||||
|
||||
} else {
|
||||
|
||||
// create new popup
|
||||
extension.windows.create({
|
||||
url: 'notification.html',
|
||||
type: 'popup',
|
||||
focused: true,
|
||||
width: 360,
|
||||
height: 500,
|
||||
})
|
||||
|
||||
if (windows.length > 0) {
|
||||
const win = windows[0]
|
||||
return extension.windows.update(win.id, { focused: true })
|
||||
}
|
||||
|
||||
extension.windows.create({
|
||||
url: 'notification.html',
|
||||
type: 'popup',
|
||||
focused: true,
|
||||
width: 360,
|
||||
height: 500,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -38,19 +44,19 @@ function getWindows(cb) {
|
||||
}
|
||||
|
||||
function getPopup(cb) {
|
||||
getWindows((windows) => {
|
||||
cb(getPopupIn(windows))
|
||||
getWindows((err, windows) => {
|
||||
if (err) throw err
|
||||
cb(null, getPopupIn(windows))
|
||||
})
|
||||
}
|
||||
|
||||
function getPopupIn(windows) {
|
||||
return windows ? windows.find((win) => {
|
||||
return win.type === 'popup'
|
||||
}) : null
|
||||
return windows ? windows.find((win) => win.type === 'popup') : null
|
||||
}
|
||||
|
||||
function closePopup() {
|
||||
getPopup((popup) => {
|
||||
getPopup((err, popup) => {
|
||||
if (err) throw err
|
||||
if (!popup) return
|
||||
extension.windows.remove(popup.id, console.error)
|
||||
})
|
||||
|
@ -199,6 +199,9 @@ module.exports = class MetamaskController {
|
||||
const idStore = this.idStore
|
||||
var state = idStore.getState()
|
||||
|
||||
let err = this.enforceTxValidations(txParams)
|
||||
if (err) return onTxDoneCb(err)
|
||||
|
||||
// It's locked
|
||||
if (!state.isUnlocked) {
|
||||
|
||||
@ -216,6 +219,13 @@ module.exports = class MetamaskController {
|
||||
}
|
||||
}
|
||||
|
||||
enforceTxValidations (txParams) {
|
||||
if (txParams.value.indexOf('-') === 0) {
|
||||
const msg = `Invalid transaction value of ${txParams.value} not a positive number.`
|
||||
return new Error(msg)
|
||||
}
|
||||
}
|
||||
|
||||
newUnsignedMessage (msgParams, cb) {
|
||||
var state = this.idStore.getState()
|
||||
if (!state.isUnlocked) {
|
||||
|
49
gulpfile.js
49
gulpfile.js
@ -16,6 +16,10 @@ var eslint = require('gulp-eslint')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var manifest = require('./app/manifest.json')
|
||||
var gulpif = require('gulp-if')
|
||||
var replace = require('gulp-replace')
|
||||
|
||||
var disableLiveReload = gutil.env.disableLiveReload
|
||||
|
||||
// browser reload
|
||||
|
||||
@ -72,8 +76,8 @@ gulp.task('copy:root', copyTask({
|
||||
pattern: '/*',
|
||||
}))
|
||||
|
||||
gulp.task('manifest:cleanup', function() {
|
||||
return gulp.src('./dist/firefox/manifest.json')
|
||||
gulp.task('manifest:chrome', function() {
|
||||
return gulp.src('./dist/chrome/manifest.json')
|
||||
.pipe(jsoneditor(function(json) {
|
||||
delete json.applications
|
||||
return json
|
||||
@ -81,7 +85,33 @@ gulp.task('manifest:cleanup', function() {
|
||||
.pipe(gulp.dest('./dist/chrome', { overwrite: true }))
|
||||
})
|
||||
|
||||
gulp.task('copy', gulp.series(gulp.parallel('copy:locales','copy:images','copy:fonts','copy:reload','copy:root'), 'manifest:cleanup'))
|
||||
gulp.task('manifest:production', function() {
|
||||
return gulp.src([
|
||||
'./dist/firefox/manifest.json',
|
||||
'./dist/chrome/manifest.json',
|
||||
'./dist/edge/manifest.json',
|
||||
],{base: './dist/'})
|
||||
.pipe(gulpif(disableLiveReload,jsoneditor(function(json) {
|
||||
json.background.scripts = ["scripts/background.js"]
|
||||
return json
|
||||
})))
|
||||
.pipe(gulp.dest('./dist/', { overwrite: true }))
|
||||
})
|
||||
|
||||
const staticFiles = [
|
||||
'locales',
|
||||
'images',
|
||||
'fonts',
|
||||
'root'
|
||||
]
|
||||
|
||||
var copyStrings = staticFiles.map(staticFile => `copy:${staticFile}`)
|
||||
|
||||
if (!disableLiveReload) {
|
||||
copyStrings.push('copy:reload')
|
||||
}
|
||||
|
||||
gulp.task('copy', gulp.series(gulp.parallel(...copyStrings), 'manifest:production', 'manifest:chrome'))
|
||||
gulp.task('copy:watch', function(){
|
||||
gulp.watch(['./app/{_locales,images}/*', './app/scripts/chromereload.js', './app/*.{html,json}'], gulp.series('copy'))
|
||||
})
|
||||
@ -115,14 +145,18 @@ const jsFiles = [
|
||||
'popup',
|
||||
]
|
||||
|
||||
var jsDevStrings = jsFiles.map(jsFile => `dev:js:${jsFile}`)
|
||||
var jsBuildStrings = jsFiles.map(jsFile => `build:js:${jsFile}`)
|
||||
|
||||
jsFiles.forEach((jsFile) => {
|
||||
gulp.task(`dev:js:${jsFile}`, bundleTask({ watch: true, filename: `${jsFile}.js` }))
|
||||
gulp.task(`build:js:${jsFile}`, bundleTask({ watch: false, filename: `${jsFile}.js` }))
|
||||
})
|
||||
|
||||
gulp.task('dev:js', gulp.parallel('dev:js:inpage','dev:js:contentscript','dev:js:background','dev:js:popup'))
|
||||
gulp.task('dev:js', gulp.parallel(...jsDevStrings))
|
||||
|
||||
gulp.task('build:js', gulp.parallel(...jsBuildStrings))
|
||||
|
||||
gulp.task('build:js', gulp.parallel('build:js:inpage','build:js:contentscript','build:js:background','build:js:popup'))
|
||||
|
||||
// clean dist
|
||||
|
||||
@ -152,6 +186,7 @@ gulp.task('zip', gulp.parallel('zip:chrome', 'zip:firefox', 'zip:edge'))
|
||||
// high level tasks
|
||||
|
||||
gulp.task('dev', gulp.series('dev:js', 'copy', gulp.parallel('copy:watch', 'dev:reload')))
|
||||
|
||||
gulp.task('build', gulp.series('clean', gulp.parallel('build:js', 'copy')))
|
||||
gulp.task('dist', gulp.series('build', 'zip'))
|
||||
|
||||
@ -170,7 +205,7 @@ function copyTask(opts){
|
||||
destinations.forEach(function(destination) {
|
||||
stream = stream.pipe(gulp.dest(destination))
|
||||
})
|
||||
stream.pipe(livereload())
|
||||
stream.pipe(gulpif(!disableLiveReload,livereload()))
|
||||
|
||||
return stream
|
||||
}
|
||||
@ -211,7 +246,7 @@ function bundleTask(opts) {
|
||||
.pipe(gulp.dest('./dist/firefox/scripts'))
|
||||
.pipe(gulp.dest('./dist/chrome/scripts'))
|
||||
.pipe(gulp.dest('./dist/edge/scripts'))
|
||||
.pipe(livereload())
|
||||
.pipe(gulpif(!disableLiveReload,livereload()))
|
||||
|
||||
)
|
||||
}
|
||||
|
@ -94,8 +94,10 @@
|
||||
"del": "^2.2.0",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp-brfs": "^0.1.0",
|
||||
"gulp-if": "^2.0.1",
|
||||
"gulp-json-editor": "^2.2.1",
|
||||
"gulp-livereload": "^3.8.1",
|
||||
"gulp-replace": "^0.5.4",
|
||||
"gulp-sourcemaps": "^1.6.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
"gulp-watch": "^4.3.5",
|
||||
|
97
test/unit/metamask-controller-test.js
Normal file
97
test/unit/metamask-controller-test.js
Normal file
@ -0,0 +1,97 @@
|
||||
var assert = require('assert')
|
||||
var MetaMaskController = require('../../app/scripts/metamask-controller')
|
||||
var sinon = require('sinon')
|
||||
var extend = require('xtend')
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
|
||||
describe('MetaMaskController', function() {
|
||||
const noop = () => {}
|
||||
let controller = new MetaMaskController({
|
||||
showUnconfirmedMessage: noop,
|
||||
unlockAccountMessage: noop,
|
||||
showUnconfirmedTx: noop,
|
||||
setData,
|
||||
loadData,
|
||||
})
|
||||
|
||||
beforeEach(function() {
|
||||
// sinon allows stubbing methods that are easily verified
|
||||
this.sinon = sinon.sandbox.create()
|
||||
window.localStorage = {} // Hacking localStorage support into JSDom
|
||||
})
|
||||
|
||||
afterEach(function() {
|
||||
// sinon requires cleanup otherwise it will overwrite context
|
||||
this.sinon.restore()
|
||||
})
|
||||
|
||||
describe('#enforceTxValidations', function () {
|
||||
it('returns null for positive values', function() {
|
||||
var sample = {
|
||||
value: '0x01'
|
||||
}
|
||||
var res = controller.enforceTxValidations(sample)
|
||||
assert.equal(res, null, 'no error')
|
||||
})
|
||||
|
||||
|
||||
it('returns error for negative values', function() {
|
||||
var sample = {
|
||||
value: '-0x01'
|
||||
}
|
||||
var res = controller.enforceTxValidations(sample)
|
||||
assert.ok(res, 'error')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
function loadData () {
|
||||
var oldData = getOldStyleData()
|
||||
var newData
|
||||
try {
|
||||
newData = JSON.parse(window.localStorage[STORAGE_KEY])
|
||||
} catch (e) {}
|
||||
|
||||
var data = extend({
|
||||
meta: {
|
||||
version: 0,
|
||||
},
|
||||
data: {
|
||||
config: {
|
||||
provider: {
|
||||
type: 'testnet',
|
||||
},
|
||||
},
|
||||
},
|
||||
}, oldData || null, newData || null)
|
||||
return data
|
||||
}
|
||||
|
||||
function getOldStyleData () {
|
||||
var config, wallet, seedWords
|
||||
|
||||
var result = {
|
||||
meta: { version: 0 },
|
||||
data: {},
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(window.localStorage['config'])
|
||||
result.data.config = config
|
||||
} catch (e) {}
|
||||
try {
|
||||
wallet = JSON.parse(window.localStorage['lightwallet'])
|
||||
result.data.wallet = wallet
|
||||
} catch (e) {}
|
||||
try {
|
||||
seedWords = window.localStorage['seedWords']
|
||||
result.data.seedWords = seedWords
|
||||
} catch (e) {}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function setData (data) {
|
||||
window.localStorage[STORAGE_KEY] = JSON.stringify(data)
|
||||
}
|
Loading…
Reference in New Issue
Block a user