diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e27f5c04..0a54cf886 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Current Master +- Popup new transactions in Firefox. + ## 3.5.2 2017-3-28 - Fix bug where gas estimate totals were sometimes wrong. diff --git a/app/manifest.json b/app/manifest.json index 75e72c295..a3242149b 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -57,7 +57,8 @@ "permissions": [ "storage", "clipboardWrite", - "http://localhost:8545/" + "http://localhost:8545/", + "https://www.cryptonator.com/" ], "web_accessible_resources": [ "scripts/inpage.js" diff --git a/app/scripts/lib/extension.js b/app/scripts/lib/extension.js index 4b670490f..6f8b5d800 100644 --- a/app/scripts/lib/extension.js +++ b/app/scripts/lib/extension.js @@ -11,4 +11,7 @@ */ const Extension = require('./extension-instance') -module.exports = new Extension() +const instance = new Extension() +window.METAMASK_EXTENSION = instance +module.exports = instance + diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 3db1ac6b5..0ec01f3a7 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -22,10 +22,12 @@ function show () { extension.windows.create({ url: 'notification.html', type: 'popup', - focused: true, width, height, }) + .catch((reason) => { + log.error('failed to create poupup', reason) + }) } }) } diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 72df53631..e8e23f8b5 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -63,14 +63,15 @@ module.exports = class txProviderUtils { addGasBuffer (initialGasLimitHex, blockGasLimitHex) { const initialGasLimitBn = hexToBn(initialGasLimitHex) const blockGasLimitBn = hexToBn(blockGasLimitHex) + const upperGasLimitBn = blockGasLimitBn.muln(0.9) const bufferedGasLimitBn = initialGasLimitBn.muln(1.5) // if initialGasLimit is above blockGasLimit, dont modify it - if (initialGasLimitBn.gt(blockGasLimitBn)) return bnToHex(initialGasLimitBn) + if (initialGasLimitBn.gt(upperGasLimitBn)) return bnToHex(initialGasLimitBn) // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit - if (bufferedGasLimitBn.lt(blockGasLimitBn)) return bnToHex(bufferedGasLimitBn) + if (bufferedGasLimitBn.lt(upperGasLimitBn)) return bnToHex(bufferedGasLimitBn) // otherwise use blockGasLimit - return bnToHex(blockGasLimitBn) + return bnToHex(upperGasLimitBn) } fillInTxParams (txParams, cb) { diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index a3dd48c17..019b4d13d 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -22,4 +22,5 @@ module.exports = [ require('./009'), require('./010'), require('./011'), + require('./012'), ] diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index a70159680..d7051b2cb 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -205,11 +205,23 @@ module.exports = class TransactionManager extends EventEmitter { }) } + getChainId() { + const networkState = this.networkStore.getState() + const getChainId = parseInt(networkState.network) + if (Number.isNaN(getChainId)) { + return 0 + } else { + return getChainId + } + } + signTransaction (txId, cb) { - let txMeta = this.getTx(txId) - let txParams = txMeta.txParams - let fromAddress = txParams.from - let ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) + const txMeta = this.getTx(txId) + const txParams = txMeta.txParams + const fromAddress = txParams.from + // add network/chain id + txParams.chainId = this.getChainId() + const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) this.signEthTx(ethTx, fromAddress).then(() => { this.setTxStatusSigned(txMeta.id) cb(null, ethUtil.bufferToHex(ethTx.serialize())) diff --git a/package.json b/package.json index d69dcbb91..b96197915 100644 --- a/package.json +++ b/package.json @@ -5,20 +5,20 @@ "private": true, "scripts": { "start": "npm run dev", - "lint": "gulp lint", - "buildCiUnits": "node test/integration/index.js", "dev": "gulp dev --debug", "disc": "gulp disc --debug", "dist": "gulp dist --disableLiveReload", - "test": "npm run lint && npm run fastTest && npm run ci", - "fastTest": "METAMASK_ENV=test mocha --require test/helper.js --recursive \"test/unit/**/*.js\"", + "test": "npm run lint && npm run test-unit && npm run test-integration", + "test-unit": "METAMASK_ENV=test mocha --require test/helper.js --recursive \"test/unit/**/*.js\"", + "test-integration": "npm run buildMock && npm run buildCiUnits && testem ci -P 2", + "lint": "gulp lint", + "buildCiUnits": "node test/integration/index.js", "watch": "mocha watch --recursive \"test/unit/**/*.js\"", "genStates": "node development/genStates.js", "ui": "npm run genStates && beefy ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", "mock": "beefy mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", "buildMock": "npm run genStates && browserify ./mock-dev.js -o ./development/bundle.js", "testem": "npm run buildMock && testem", - "ci": "npm run buildMock && npm run buildCiUnits && testem ci -P 2", "announce": "node development/announcer.js", "generateNotice": "node notices/notice-generator.js", "deleteNotice": "node notices/notice-delete.js" @@ -40,6 +40,7 @@ "async": "^1.5.2", "async-q": "^0.3.1", "bip39": "^2.2.0", + "bluebird": "^3.5.0", "browser-passworder": "^2.0.3", "browserify-derequire": "^0.9.4", "client-sw-ready-event": "^1.0.2", @@ -57,7 +58,7 @@ "eth-query": "^1.0.3", "eth-sig-util": "^1.1.1", "eth-simple-keyring": "^1.1.1", - "ethereumjs-tx": "^1.0.0", + "ethereumjs-tx": "^1.2.5", "ethereumjs-util": "ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", "ethereumjs-wallet": "^0.6.0", "ethjs-ens": "^1.0.2", @@ -111,7 +112,7 @@ "valid-url": "^1.0.9", "vreme": "^3.0.2", "web3": "0.18.2", - "web3-provider-engine": "^11.0.1", + "web3-provider-engine": "^11.0.2", "web3-stream-provider": "^2.0.6", "xtend": "^4.0.1" }, diff --git a/test/helper.js b/test/helper.js index a01ea1e53..aaac7580e 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,11 +1,54 @@ +// disallow promises from swallowing errors +enableFailureOnUnhandledPromiseRejection() + +// logging util var log = require('loglevel') log.setDefaultLevel(5) +global.log = log +// +// polyfills +// + +// dom require('jsdom-global')() + +// localStorage window.localStorage = {} -if (!('crypto' in window)) { window.crypto = {} } -window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues') +// crypto.getRandomValues +if (!window.crypto) window.crypto = {} +if (!window.crypto.getRandomValues) window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues') -window.log = log -global.log = log + + +function enableFailureOnUnhandledPromiseRejection() { + // overwrite node's promise with the stricter Bluebird promise + global.Promise = require('bluebird') + + // modified from https://github.com/mochajs/mocha/issues/1926#issuecomment-180842722 + + // rethrow unhandledRejections + if (typeof process !== 'undefined') { + process.on('unhandledRejection', function (reason) { + throw reason + }) + } else if (typeof window !== 'undefined') { + // 2016-02-01: No browsers support this natively, however bluebird, when.js, + // and probably other libraries do. + if (typeof window.addEventListener === 'function') { + window.addEventListener('unhandledrejection', function (evt) { + throw evt.detail.reason + }) + } else { + var oldOHR = window.onunhandledrejection + window.onunhandledrejection = function (evt) { + if (typeof oldOHR === 'function') oldOHR.apply(this, arguments) + throw evt.detail.reason + } + } + } else if (typeof console !== 'undefined' && + typeof (console.error || console.log) === 'function') { + (console.error || console.log)('Unhandled rejections will be ignored!') + } +} \ No newline at end of file diff --git a/test/unit/keyring-controller-test.js b/test/unit/keyring-controller-test.js index aae4cdfd6..efd0a3546 100644 --- a/test/unit/keyring-controller-test.js +++ b/test/unit/keyring-controller-test.js @@ -135,7 +135,7 @@ describe('KeyringController', function() { }) describe('#getAccounts', function() { - it('returns the result of getAccounts for each keyring', function() { + it('returns the result of getAccounts for each keyring', function(done) { keyringController.keyrings = [ { getAccounts() { return Promise.resolve([1,2,3]) } }, { getAccounts() { return Promise.resolve([4,5,6]) } }, diff --git a/test/unit/notice-controller-test.js b/test/unit/notice-controller-test.js index 73fdb2f2e..ea37108bb 100644 --- a/test/unit/notice-controller-test.js +++ b/test/unit/notice-controller-test.js @@ -11,8 +11,6 @@ describe('notice-controller', function() { beforeEach(function() { // simple localStorage polyfill - window.localStorage = {} - if (window.localStorage.clear) window.localStorage.clear() let configManager = configManagerGen() noticeController = new NoticeController({ configManager: configManager, @@ -21,7 +19,7 @@ describe('notice-controller', function() { describe('notices', function() { describe('#getNoticesList', function() { - it('should return an empty array when new', function() { + it('should return an empty array when new', function(done) { var testList = [{ id:0, read:false, @@ -29,11 +27,12 @@ describe('notice-controller', function() { }] var result = noticeController.getNoticesList() assert.equal(result.length, 0) + done() }) }) describe('#setNoticesList', function() { - it('should set data appropriately', function () { + it('should set data appropriately', function (done) { var testList = [{ id:0, read:false, @@ -42,11 +41,12 @@ describe('notice-controller', function() { noticeController.setNoticesList(testList) var testListId = noticeController.getNoticesList()[0].id assert.equal(testListId, 0) + done() }) }) describe('#updateNoticeslist', function() { - it('should integrate the latest changes from the source', function() { + it('should integrate the latest changes from the source', function(done) { var testList = [{ id:55, read:false, @@ -57,26 +57,26 @@ describe('notice-controller', function() { var newList = noticeController.getNoticesList() assert.ok(newList[0].id === 55) assert.ok(newList[1]) + done() }) }) - it('should not overwrite any existing fields', function () { + it('should not overwrite any existing fields', function (done) { var testList = [{ id:0, read:false, title:"Futuristic Notice" }] noticeController.setNoticesList(testList) - noticeController.updateNoticesList().then(() => { - var newList = noticeController.getNoticesList() - assert.equal(newList[0].id, 0) - assert.equal(newList[0].title, "Futuristic Notice") - assert.equal(newList.length, 1) - }) + var newList = noticeController.getNoticesList() + assert.equal(newList[0].id, 0) + assert.equal(newList[0].title, "Futuristic Notice") + assert.equal(newList.length, 1) + done() }) }) describe('#markNoticeRead', function () { - it('should mark a notice as read', function () { + it('should mark a notice as read', function (done) { var testList = [{ id:0, read:false, @@ -86,11 +86,12 @@ describe('notice-controller', function() { noticeController.markNoticeRead(testList[0]) var newList = noticeController.getNoticesList() assert.ok(newList[0].read) + done() }) }) describe('#getLatestUnreadNotice', function () { - it('should retrieve the latest unread notice', function () { + it('should retrieve the latest unread notice', function (done) { var testList = [ {id:0,read:true,title:"Past Notice"}, {id:1,read:false,title:"Current Notice"}, @@ -99,8 +100,9 @@ describe('notice-controller', function() { noticeController.setNoticesList(testList) var latestUnread = noticeController.getLatestUnreadNotice() assert.equal(latestUnread.id, 2) + done() }) - it('should return undefined if no unread notices exist.', function () { + it('should return undefined if no unread notices exist.', function (done) { var testList = [ {id:0,read:true,title:"Past Notice"}, {id:1,read:true,title:"Current Notice"}, @@ -109,6 +111,7 @@ describe('notice-controller', function() { noticeController.setNoticesList(testList) var latestUnread = noticeController.getLatestUnreadNotice() assert.ok(!latestUnread) + done() }) }) }) diff --git a/test/unit/tx-manager-test.js b/test/unit/tx-manager-test.js index d4bffdd9b..21e94357b 100644 --- a/test/unit/tx-manager-test.js +++ b/test/unit/tx-manager-test.js @@ -1,19 +1,28 @@ const assert = require('assert') const extend = require('xtend') const EventEmitter = require('events') +const ethUtil = require('ethereumjs-util') +const EthTx = require('ethereumjs-tx') const ObservableStore = require('obs-store') const STORAGE_KEY = 'metamask-persistance-key' const TransactionManager = require('../../app/scripts/transaction-manager') const noop = () => true +const currentNetworkId = 42 +const otherNetworkId = 36 +const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex') describe('Transaction Manager', function() { let txManager beforeEach(function() { txManager = new TransactionManager({ - networkStore: new ObservableStore({ network: 'unit test' }), + networkStore: new ObservableStore({ network: currentNetworkId }), txHistoryLimit: 10, blockTracker: new EventEmitter(), + signTransaction: (ethTx) => new Promise((resolve) => { + ethTx.sign(privKey) + resolve() + }) }) }) @@ -27,7 +36,6 @@ describe('Transaction Manager', function() { }) }) - it('returns error for negative values', function() { var sample = { value: '-0x01' @@ -51,7 +59,7 @@ describe('Transaction Manager', function() { describe('#addTx', function() { it('adds a tx returned in getTxList', function() { - var tx = { id: 1, status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} } + var tx = { id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx, noop) var result = txManager.getTxList() assert.ok(Array.isArray(result)) @@ -60,8 +68,8 @@ describe('Transaction Manager', function() { }) it('does not override txs from other networks', function() { - var tx = { id: 1, status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} } - var tx2 = { id: 2, status: 'confirmed', metamaskNetworkId: 'another net', txParams: {} } + var tx = { id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} } + var tx2 = { id: 2, status: 'confirmed', metamaskNetworkId: otherNetworkId, txParams: {} } txManager.addTx(tx, noop) txManager.addTx(tx2, noop) var result = txManager.getFullTxList() @@ -73,7 +81,7 @@ describe('Transaction Manager', function() { it('cuts off early txs beyond a limit', function() { const limit = txManager.txHistoryLimit for (let i = 0; i < limit + 1; i++) { - let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} } + let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx, noop) } var result = txManager.getTxList() @@ -84,7 +92,7 @@ describe('Transaction Manager', function() { it('cuts off early txs beyond a limit whether or not it is confirmed or rejected', function() { const limit = txManager.txHistoryLimit for (let i = 0; i < limit + 1; i++) { - let tx = { id: i, time: new Date(), status: 'rejected', metamaskNetworkId: 'unit test', txParams: {} } + let tx = { id: i, time: new Date(), status: 'rejected', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx, noop) } var result = txManager.getTxList() @@ -93,11 +101,11 @@ describe('Transaction Manager', function() { }) it('cuts off early txs beyond a limit but does not cut unapproved txs', function() { - var unconfirmedTx = { id: 0, time: new Date(), status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} } + var unconfirmedTx = { id: 0, time: new Date(), status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(unconfirmedTx, noop) const limit = txManager.txHistoryLimit for (let i = 1; i < limit + 1; i++) { - let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} } + let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx, noop) } var result = txManager.getTxList() @@ -110,7 +118,7 @@ describe('Transaction Manager', function() { describe('#setTxStatusSigned', function() { it('sets the tx status to signed', function() { - var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} } + var tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx, noop) txManager.setTxStatusSigned(1) var result = txManager.getTxList() @@ -121,7 +129,7 @@ describe('Transaction Manager', function() { it('should emit a signed event to signal the exciton of callback', (done) => { this.timeout(10000) - var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} } + var tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } let noop = function () { assert(true, 'event listener has been triggered and noop executed') done() @@ -134,7 +142,7 @@ describe('Transaction Manager', function() { describe('#setTxStatusRejected', function() { it('sets the tx status to rejected', function() { - var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} } + var tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx) txManager.setTxStatusRejected(1) var result = txManager.getTxList() @@ -145,7 +153,7 @@ describe('Transaction Manager', function() { it('should emit a rejected event to signal the exciton of callback', (done) => { this.timeout(10000) - var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} } + var tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txManager.addTx(tx) let noop = function (err, txId) { assert(true, 'event listener has been triggered and noop executed') @@ -159,9 +167,9 @@ describe('Transaction Manager', function() { describe('#updateTx', function() { it('replaces the tx with the same id', function() { - txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }, noop) - txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }, noop) - txManager.updateTx({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test', txParams: {} }) + txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) + txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) + txManager.updateTx({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: currentNetworkId, txParams: {} }) var result = txManager.getTx('1') assert.equal(result.hash, 'foo') }) @@ -169,8 +177,8 @@ describe('Transaction Manager', function() { describe('#getUnapprovedTxList', function() { it('returns unapproved txs in a hash', function() { - txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }, noop) - txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }, noop) + txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) + txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) let result = txManager.getUnapprovedTxList() assert.equal(typeof result, 'object') assert.equal(result['1'].status, 'unapproved') @@ -180,8 +188,8 @@ describe('Transaction Manager', function() { describe('#getTx', function() { it('returns a tx with the requested id', function() { - txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }, noop) - txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }, noop) + txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) + txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) assert.equal(txManager.getTx('1').status, 'unapproved') assert.equal(txManager.getTx('2').status, 'confirmed') }) @@ -190,16 +198,16 @@ describe('Transaction Manager', function() { describe('#getFilteredTxList', function() { it('returns a tx with the requested data', function() { let txMetas = [ - { id: 0, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' }, - { id: 1, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' }, - { id: 2, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' }, - { id: 3, status: 'unapproved', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' }, - { id: 4, status: 'unapproved', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' }, - { id: 5, status: 'confirmed', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' }, - { id: 6, status: 'confirmed', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' }, - { id: 7, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' }, - { id: 8, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' }, - { id: 9, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' }, + { id: 0, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: currentNetworkId }, + { id: 1, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: currentNetworkId }, + { id: 2, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: currentNetworkId }, + { id: 3, status: 'unapproved', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: currentNetworkId }, + { id: 4, status: 'unapproved', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: currentNetworkId }, + { id: 5, status: 'confirmed', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: currentNetworkId }, + { id: 6, status: 'confirmed', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: currentNetworkId }, + { id: 7, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: currentNetworkId }, + { id: 8, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: currentNetworkId }, + { id: 9, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: currentNetworkId }, ] txMetas.forEach((txMeta) => txManager.addTx(txMeta, noop)) let filterParams @@ -219,4 +227,15 @@ describe('Transaction Manager', function() { }) }) + describe('#sign replay-protected tx', function() { + it('prepares a tx with the chainId set', function() { + txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) + txManager.signTransaction('1', (err, rawTx) => { + if (err) return assert.fail('it should not fail') + const ethTx = new EthTx(ethUtil.toBuffer(rawTx)) + assert.equal(ethTx.getChainId(), currentNetworkId) + }) + }) + }) + }) diff --git a/test/unit/tx-utils-test.js b/test/unit/tx-utils-test.js index e57b25e83..93e9e4134 100644 --- a/test/unit/tx-utils-test.js +++ b/test/unit/tx-utils-test.js @@ -12,10 +12,27 @@ describe('txUtils', function() { txUtils = new TxUtils() }) + describe('chain Id', function() { + it('prepares a transaction with the provided chainId', function() { + const txParams = { + to: '0x70ad465e0bab6504002ad58c744ed89c7da38524', + from: '0x69ad465e0bab6504002ad58c744ed89c7da38525', + value: '0x0', + gas: '0x7b0c', + gasPrice: '0x199c82cc00', + data: '0x', + nonce: '0x3', + chainId: 42, + } + const ethTx = txUtils.buildEthTxFromParams(txParams) + assert.equal(ethTx.getChainId(), 42, 'chainId is set from tx params') + }) + }) + describe('addGasBuffer', function() { it('multiplies by 1.5, when within block gas limit', function() { - // naive estimatedGas: 0x123fad (~1.2 mil) - const inputHex = '0x123fad' + // naive estimatedGas: 0x16e360 (1.5 mil) + const inputHex = '0x16e360' // dummy gas limit: 0x3d4c52 (4 mil) const blockGasLimitHex = '0x3d4c52' const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex) @@ -26,8 +43,8 @@ describe('txUtils', function() { }) it('uses original estimatedGas, when above block gas limit', function() { - // naive estimatedGas: 0x123fad (~1.2 mil) - const inputHex = '0x123fad' + // naive estimatedGas: 0x16e360 (1.5 mil) + const inputHex = '0x16e360' // dummy gas limit: 0x0f4240 (1 mil) const blockGasLimitHex = '0x0f4240' const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex) @@ -37,16 +54,18 @@ describe('txUtils', function() { assert(outputBn.eq(expectedBn), 'returns the original estimatedGas value') }) - it('buffers up to block gas limit', function() { - // naive estimatedGas: 0x123fad (~1.2 mil) - const inputHex = '0x1e8480' + it('buffers up to reccomend gas limit reccomended ceiling', function() { + // naive estimatedGas: 0x16e360 (1.5 mil) + const inputHex = '0x16e360' // dummy gas limit: 0x1e8480 (2 mil) const blockGasLimitHex = '0x1e8480' + const blockGasLimitBn = hexToBn(blockGasLimitHex) + const ceilGasLimitBn = blockGasLimitBn.muln(0.9) const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex) - const inputBn = hexToBn(inputHex) - const outputBn = hexToBn(output) - const expectedBn = hexToBn(blockGasLimitHex) - assert(outputBn.eq(expectedBn), 'returns the block gas limit value') + // const inputBn = hexToBn(inputHex) + // const outputBn = hexToBn(output) + const expectedHex = bnToHex(ceilGasLimitBn) + assert.equal(output, expectedHex, 'returns the gas limit reccomended ceiling value') }) }) }) @@ -55,4 +74,8 @@ describe('txUtils', function() { function hexToBn(inputHex) { return new BN(ethUtil.stripHexPrefix(inputHex), 16) +} + +function bnToHex(inputBn) { + return ethUtil.addHexPrefix(inputBn.toString(16)) } \ No newline at end of file diff --git a/ui/app/css/index.css b/ui/app/css/index.css index de8ae0e92..033502f5a 100644 --- a/ui/app/css/index.css +++ b/ui/app/css/index.css @@ -148,7 +148,6 @@ h2.page-subtitle { } textarea.twelve-word-phrase { - margin-top: 20px; padding: 12px; width: 300px; height: 140px; diff --git a/ui/app/keychains/hd/create-vault-complete.js b/ui/app/keychains/hd/create-vault-complete.js index 7272ebdbd..5230797ad 100644 --- a/ui/app/keychains/hd/create-vault-complete.js +++ b/ui/app/keychains/hd/create-vault-complete.js @@ -45,12 +45,17 @@ CreateVaultCompleteScreen.prototype.render = function () { 'Vault Created', ]), - h('span.error', { // Error for the right red + h('div', { style: { - padding: '12px 20px 0px 20px', + width: '360px', + height: '78px', + fontSize: '1em', + marginTop: '10px', textAlign: 'center', }, - }, 'These 12 words can restore all of your MetaMask accounts for this vault.\nSave them somewhere safe and secret.'), + }, [ + h('span.error', 'These 12 words can restore all of your MetaMask accounts for this vault.\nSave them somewhere safe and secret.'), + ]), h('textarea.twelve-word-phrase', { readOnly: true,