mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 12:29:06 +01:00
Merge branch 'master' into NewUI-flat
This commit is contained in:
commit
a67d3ecd46
@ -2,11 +2,17 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
- Fix bug that would sometimes display transactions as failed that could be successfully mined.
|
||||
|
||||
## 3.10.1 2017-9-18
|
||||
|
||||
- Add ability to export private keys as a file.
|
||||
- Add ability to export seed words as a file.
|
||||
- Changed state logs to a file download than a clipboard copy.
|
||||
- Add specific error for failed recipient address checksum.
|
||||
- Fixed a long standing memory leak associated with filters installed by dapps
|
||||
- Fix link to support center.
|
||||
- Fixed tooltip icon locations to avoid overflow.
|
||||
- Warn users when a dapp proposes a high gas limit (90% of blockGasLimit or higher)
|
||||
|
||||
## 3.10.0 2017-9-11
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "MetaMask",
|
||||
"short_name": "Metamask",
|
||||
"version": "3.10.0",
|
||||
"version": "3.10.1",
|
||||
"manifest_version": 2,
|
||||
"author": "https://metamask.io",
|
||||
"description": "Ethereum Browser Extension",
|
||||
|
@ -76,6 +76,9 @@ module.exports = class PendingTransactionTracker extends EventEmitter {
|
||||
Dont marked as failed if the error is a "known" transaction warning
|
||||
"there is already a transaction with the same sender-nonce
|
||||
but higher/same gas price"
|
||||
|
||||
Also don't mark as failed if it has ever been broadcast successfully.
|
||||
A successful broadcast means it may still be mined.
|
||||
*/
|
||||
const errorMessage = err.message.toLowerCase()
|
||||
const isKnownTx = (
|
||||
@ -88,6 +91,7 @@ module.exports = class PendingTransactionTracker extends EventEmitter {
|
||||
// other
|
||||
|| errorMessage.includes('gateway timeout')
|
||||
|| errorMessage.includes('nonce too low')
|
||||
|| txMeta.retryCount > 1
|
||||
)
|
||||
// ignore resubmit warnings, return early
|
||||
if (isKnownTx) return
|
||||
@ -117,10 +121,12 @@ module.exports = class PendingTransactionTracker extends EventEmitter {
|
||||
// Only auto-submit already-signed txs:
|
||||
if (!('rawTx' in txMeta)) return
|
||||
|
||||
// Increment a try counter.
|
||||
txMeta.retryCount++
|
||||
const rawTx = txMeta.rawTx
|
||||
return await this.publishTransaction(rawTx)
|
||||
const txHash = await this.publishTransaction(rawTx)
|
||||
|
||||
// Increment successful tries:
|
||||
txMeta.retryCount++
|
||||
return txHash
|
||||
}
|
||||
|
||||
async _checkPendingTx (txMeta) {
|
||||
|
@ -3,7 +3,7 @@ machine:
|
||||
version: 8.1.4
|
||||
test:
|
||||
override:
|
||||
- "npm run ci"
|
||||
- "npm test"
|
||||
dependencies:
|
||||
pre:
|
||||
- sudo apt-get update
|
||||
|
@ -14,13 +14,13 @@
|
||||
</body>
|
||||
|
||||
<style>
|
||||
html, body, #app-content, .super-dev-container {
|
||||
html, body, #test-container, .super-dev-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: white;
|
||||
}
|
||||
.mock-app-root {
|
||||
#app-content {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
</style>
|
||||
|
@ -18,13 +18,14 @@
|
||||
</body>
|
||||
|
||||
<style>
|
||||
html, body, #app-content, .super-dev-container {
|
||||
html, body, #test-container, .super-dev-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: white;
|
||||
}
|
||||
.mock-app-root {
|
||||
|
||||
#app-content {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,7 +1,6 @@
|
||||
const createParentStream = require('iframe-stream').ParentStream
|
||||
const SWcontroller = require('client-sw-ready-event/lib/sw-client.js')
|
||||
const SwStream = require('sw-stream/lib/sw-stream.js')
|
||||
const SetupUntrustedComunication = ('./lib/setup-untrusted-connection.js')
|
||||
|
||||
let intervalDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000
|
||||
const background = new SWcontroller({
|
||||
@ -12,7 +11,7 @@ const background = new SWcontroller({
|
||||
})
|
||||
|
||||
const pageStream = createParentStream()
|
||||
background.on('ready', (_) => {
|
||||
background.on('ready', () => {
|
||||
let swStream = SwStream({
|
||||
serviceWorker: background.controller,
|
||||
context: 'dapp',
|
||||
|
@ -2,8 +2,6 @@ const injectCss = require('inject-css')
|
||||
const SWcontroller = require('client-sw-ready-event/lib/sw-client.js')
|
||||
const SwStream = require('sw-stream/lib/sw-stream.js')
|
||||
const MetaMaskUiCss = require('../../ui/css')
|
||||
const setupIframe = require('./lib/setup-iframe.js')
|
||||
const MetamaskInpageProvider = require('../../app/scripts/lib/inpage-provider.js')
|
||||
const MetamascaraPlatform = require('../../app/scripts/platforms/window')
|
||||
const startPopup = require('../../app/scripts/popup-core')
|
||||
|
||||
@ -17,6 +15,7 @@ const container = document.getElementById('app-content')
|
||||
|
||||
var name = 'popup'
|
||||
window.METAMASK_UI_TYPE = name
|
||||
window.METAMASK_PLATFORM_TYPE = 'mascara'
|
||||
|
||||
let intervalDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000
|
||||
|
||||
@ -32,25 +31,39 @@ const connectApp = function (readSw) {
|
||||
serviceWorker: background.controller,
|
||||
context: name,
|
||||
})
|
||||
return new Promise((resolve, reject) => {
|
||||
startPopup({ container, connectionStream }, (err, store) => {
|
||||
if (err) return displayCriticalError(err)
|
||||
console.log('hello from MetaMascara ui!')
|
||||
if (err) reject(err)
|
||||
store.subscribe(() => {
|
||||
const state = store.getState()
|
||||
if (state.appState.shouldClose) window.close()
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
background.on('ready', (sw) => {
|
||||
background.on('ready', async (sw) => {
|
||||
try {
|
||||
background.removeListener('updatefound', connectApp)
|
||||
connectApp(sw)
|
||||
await timeout(1000)
|
||||
await connectApp(sw)
|
||||
console.log('hello from cb ready event!')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
background.on('updatefound', () => window.location.reload())
|
||||
background.on('updatefound', windowReload)
|
||||
|
||||
background.startWorker()
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
const appContent = document.getElementById(`app-content`)
|
||||
if (!appContent.children.length) window.location.reload()
|
||||
}, 2000)
|
||||
|
||||
function windowReload() {
|
||||
if (window.METAMASK_SKIP_RELOAD) return
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
function timeout (time) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, time || 1500)
|
||||
})
|
||||
console.log('hello from MetaMascara ui!')
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>QUnit Example</title>
|
||||
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.0.0.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
<script src="https://code.jquery.com/qunit/qunit-2.0.0.js"></script>
|
||||
<script src="./jquery-3.1.0.min.js"></script>
|
||||
<script src="./helpers.js"></script>
|
||||
<script src="./test-bundle.js"></script>
|
||||
<script src="/testem.js"></script>
|
||||
|
||||
<div id="app-content"></div>
|
||||
<script src="./bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,119 +0,0 @@
|
||||
const PASSWORD = 'password123'
|
||||
|
||||
QUnit.module('first time usage')
|
||||
|
||||
QUnit.test('render init screen', function (assert) {
|
||||
var done = assert.async()
|
||||
let app
|
||||
|
||||
wait(1000).then(function() {
|
||||
app = $('#app-content').contents()
|
||||
const recurseNotices = function () {
|
||||
let button = app.find('button')
|
||||
if (button.html() === 'Accept') {
|
||||
let termsPage = app.find('.markdown')[0]
|
||||
termsPage.scrollTop = termsPage.scrollHeight
|
||||
return wait().then(() => {
|
||||
button.click()
|
||||
return wait()
|
||||
}).then(() => {
|
||||
return recurseNotices()
|
||||
})
|
||||
} else {
|
||||
return wait()
|
||||
}
|
||||
}
|
||||
return recurseNotices()
|
||||
}).then(function() {
|
||||
// Scroll through terms
|
||||
var title = app.find('h1').text()
|
||||
assert.equal(title, 'MetaMask', 'title screen')
|
||||
|
||||
// enter password
|
||||
var pwBox = app.find('#password-box')[0]
|
||||
var confBox = app.find('#password-box-confirm')[0]
|
||||
pwBox.value = PASSWORD
|
||||
confBox.value = PASSWORD
|
||||
|
||||
return wait()
|
||||
}).then(function() {
|
||||
|
||||
// create vault
|
||||
var createButton = app.find('button.primary')[0]
|
||||
createButton.click()
|
||||
|
||||
return wait(1500)
|
||||
}).then(function() {
|
||||
|
||||
var created = app.find('h3')[0]
|
||||
assert.equal(created.textContent, 'Vault Created', 'Vault created screen')
|
||||
|
||||
// Agree button
|
||||
var button = app.find('button')[0]
|
||||
assert.ok(button, 'button present')
|
||||
button.click()
|
||||
|
||||
return wait(1000)
|
||||
}).then(function() {
|
||||
|
||||
var detail = app.find('.account-detail-section')[0]
|
||||
assert.ok(detail, 'Account detail section loaded.')
|
||||
|
||||
var sandwich = app.find('.sandwich-expando')[0]
|
||||
sandwich.click()
|
||||
|
||||
return wait()
|
||||
}).then(function() {
|
||||
|
||||
var sandwich = app.find('.menu-droppo')[0]
|
||||
var children = sandwich.children
|
||||
var lock = children[children.length - 2]
|
||||
assert.ok(lock, 'Lock menu item found')
|
||||
lock.click()
|
||||
|
||||
return wait(1000)
|
||||
}).then(function() {
|
||||
|
||||
var pwBox = app.find('#password-box')[0]
|
||||
pwBox.value = PASSWORD
|
||||
|
||||
var createButton = app.find('button.primary')[0]
|
||||
createButton.click()
|
||||
|
||||
return wait(1000)
|
||||
}).then(function() {
|
||||
|
||||
var detail = app.find('.account-detail-section')[0]
|
||||
assert.ok(detail, 'Account detail section loaded again.')
|
||||
|
||||
return wait()
|
||||
}).then(function (){
|
||||
|
||||
var qrButton = app.find('.fa.fa-qrcode')[0]
|
||||
qrButton.click()
|
||||
|
||||
return wait(1000)
|
||||
}).then(function (){
|
||||
|
||||
var qrHeader = app.find('.qr-header')[0]
|
||||
var qrContainer = app.find('#qr-container')[0]
|
||||
assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.')
|
||||
assert.ok(qrContainer, 'QR Container found')
|
||||
|
||||
return wait()
|
||||
}).then(function (){
|
||||
|
||||
var networkMenu = app.find('.network-indicator')[0]
|
||||
networkMenu.click()
|
||||
|
||||
return wait()
|
||||
}).then(function (){
|
||||
|
||||
var networkMenu = app.find('.network-indicator')[0]
|
||||
var children = networkMenu.children
|
||||
children.length[3]
|
||||
assert.ok(children, 'All network options present')
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
12
mascara/test/test-ui.js
Normal file
12
mascara/test/test-ui.js
Normal file
@ -0,0 +1,12 @@
|
||||
const Helper = require('./util/mascara-test-helper.js')
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
window.METAMASK_SKIP_RELOAD = true
|
||||
// inject app container
|
||||
const body = document.body
|
||||
const container = document.createElement('div')
|
||||
container.id = 'app-content'
|
||||
body.appendChild(container)
|
||||
// start ui
|
||||
require('../src/ui.js')
|
||||
})
|
@ -1,13 +0,0 @@
|
||||
launch_in_dev:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Opera
|
||||
launch_in_ci:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Opera
|
||||
framework:
|
||||
- qunit
|
||||
before_tests: "npm run mascaraCi"
|
||||
after_tests: "rm ./background.js ./test-bundle.js ./bundle.js"
|
||||
test_page: "./index.html"
|
@ -1,5 +0,0 @@
|
||||
const Helper = require('./util/mascara-test-helper.js')
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
require('../src/ui.js')
|
||||
})
|
@ -94,9 +94,8 @@ startApp()
|
||||
function startApp(){
|
||||
const body = document.body
|
||||
const container = document.createElement('div')
|
||||
container.id = 'app-content'
|
||||
container.id = 'test-container'
|
||||
body.appendChild(container)
|
||||
console.log('container', container)
|
||||
|
||||
render(
|
||||
h('.super-dev-container', [
|
||||
@ -113,7 +112,7 @@ function startApp(){
|
||||
|
||||
h(Selector, { actions, selectedKey: selectedView, states, store }),
|
||||
|
||||
h('.mock-app-root', {
|
||||
h('#app-content', {
|
||||
style: {
|
||||
height: '500px',
|
||||
width: '360px',
|
||||
|
45
package.json
45
package.json
@ -6,30 +6,33 @@
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "gulp dev --debug",
|
||||
"disc": "gulp disc --debug",
|
||||
"clear": "rm -rf node_modules/eth-contract-metadata && rm -rf node_modules/eth-phishing-detect",
|
||||
"dist": "npm run clear && npm install && gulp dist",
|
||||
"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\"",
|
||||
"single-test": "METAMASK_ENV=test mocha --require test/helper.js",
|
||||
"test-integration": "npm run buildMock && npm run buildCiUnits && karma start",
|
||||
"test-coverage": "nyc npm run test-unit && if [ $COVERALLS_REPO_TOKEN ]; then nyc report --reporter=text-lcov | coveralls; fi",
|
||||
"ci": "npm run lint && npm run test-coverage && npm run test-integration",
|
||||
"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 ./",
|
||||
"ui": "npm run test:flat:build:states && 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",
|
||||
"watch": "mocha watch --recursive \"test/unit/**/*.js\"",
|
||||
"mascara": "node ./mascara/example/server",
|
||||
"dist": "npm run dist:clear && npm install && gulp dist",
|
||||
"dist:clear": "rm -rf node_modules/eth-contract-metadata && rm -rf node_modules/eth-phishing-detect",
|
||||
"test": "npm run lint && npm run test:coverage && npm run test:integration",
|
||||
"test:unit": "METAMASK_ENV=test mocha --require test/helper.js --recursive \"test/unit/**/*.js\"",
|
||||
"test:single": "METAMASK_ENV=test mocha --require test/helper.js",
|
||||
"test:integration": "npm run test:flat && npm run test:mascara",
|
||||
"test:coverage": "nyc npm run test:unit && npm run test:coveralls-upload",
|
||||
"test:coveralls-upload": "if [ $COVERALLS_REPO_TOKEN ]; then nyc report --reporter=text-lcov | coveralls; fi",
|
||||
"test:flat": "npm run test:flat:build && karma start test/flat.conf.js",
|
||||
"test:flat:build": "npm run test:flat:build:ui && npm run test:flat:build:tests",
|
||||
"test:flat:build:tests": "node test/integration/index.js",
|
||||
"test:flat:build:states": "node development/genStates.js",
|
||||
"test:flat:build:ui": "npm run test:flat:build:states && browserify ./mock-dev.js -o ./development/bundle.js",
|
||||
"test:mascara": "npm run test:mascara:build && karma start test/mascara.conf.js",
|
||||
"test:mascara:build": "mkdir -p dist/mascara && npm run test:mascara:build:ui && npm run test:mascara:build:background && npm run test:mascara:build:tests",
|
||||
"test:mascara:build:ui": "browserify mascara/test/test-ui.js -o dist/mascara/ui.js",
|
||||
"test:mascara:build:background": "browserify mascara/src/background.js -o dist/mascara/background.js",
|
||||
"test:mascara:build:tests": "browserify test/integration/lib/first-time.js -o dist/mascara/tests.js",
|
||||
"lint": "gulp lint",
|
||||
"disc": "gulp disc --debug",
|
||||
"announce": "node development/announcer.js",
|
||||
"generateNotice": "node notices/notice-generator.js",
|
||||
"deleteNotice": "node notices/notice-delete.js",
|
||||
"mascara": "node ./mascara/example/server",
|
||||
"buildMascaraCi": "browserify mascara/test/window-load.js -o mascara/test/bundle.js",
|
||||
"buildMascaraSWCi": "browserify mascara/src/background.js -o mascara/test/background.js",
|
||||
"mascaraCi": "npm run buildMascaraCi && npm run buildMascaraSWCi && node mascara/test/index.js",
|
||||
"testMascara": "cd mascara/test && npm run mascaraCi && testem ci -P 3"
|
||||
"deleteNotice": "node notices/notice-delete.js"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Generated on Mon Sep 11 2017 18:45:48 GMT-0700 (PDT)
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
return {
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: process.cwd(),
|
||||
|
||||
@ -16,9 +16,7 @@ module.exports = function(config) {
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'development/bundle.js',
|
||||
'test/integration/jquery-3.1.0.min.js',
|
||||
'test/integration/bundle.js',
|
||||
{ pattern: 'dist/chrome/images/**/*.*', watched: false, included: false, served: true },
|
||||
{ pattern: 'dist/chrome/fonts/**/*.*', watched: false, included: false, served: true },
|
||||
],
|
||||
@ -57,5 +55,5 @@ module.exports = function(config) {
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity
|
||||
})
|
||||
}
|
||||
}
|
8
test/flat.conf.js
Normal file
8
test/flat.conf.js
Normal file
@ -0,0 +1,8 @@
|
||||
const getBaseConfig = require('./base.conf.js')
|
||||
|
||||
module.exports = function(config) {
|
||||
const settings = getBaseConfig(config)
|
||||
settings.files.push('development/bundle.js')
|
||||
settings.files.push('test/integration/bundle.js')
|
||||
config.set(settings)
|
||||
}
|
@ -10,19 +10,12 @@ QUnit.test('render init screen', (assert) => {
|
||||
})
|
||||
})
|
||||
|
||||
// QUnit.testDone(({ module, name, total, passed, failed, skipped, todo, runtime }) => {
|
||||
// if (failed > 0) {
|
||||
// const app = $('iframe').contents()[0].documentElement
|
||||
// console.warn('Test failures - dumping DOM:')
|
||||
// console.log(app.innerHTML)
|
||||
// }
|
||||
// })
|
||||
|
||||
async function runFirstTimeUsageTest(assert, done) {
|
||||
let waitTime = 0
|
||||
if (window.METAMASK_PLATFORM_TYPE === 'mascara') waitTime = 4000
|
||||
await timeout(waitTime)
|
||||
|
||||
await timeout()
|
||||
|
||||
const app = $('#app-content .mock-app-root')
|
||||
const app = $('#app-content')
|
||||
|
||||
// recurse notices
|
||||
while (true) {
|
||||
@ -32,10 +25,12 @@ async function runFirstTimeUsageTest(assert, done) {
|
||||
const termsPage = app.find('.markdown')[0]
|
||||
termsPage.scrollTop = termsPage.scrollHeight
|
||||
await timeout()
|
||||
console.log('Clearing notice')
|
||||
button.click()
|
||||
await timeout()
|
||||
} else {
|
||||
// exit loop
|
||||
console.log('No more notices...')
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -58,7 +53,7 @@ async function runFirstTimeUsageTest(assert, done) {
|
||||
const createButton = app.find('button.primary')[0]
|
||||
createButton.click()
|
||||
|
||||
await timeout(1500)
|
||||
await timeout(3000)
|
||||
|
||||
const created = app.find('h3')[0]
|
||||
assert.equal(created.textContent, 'Vault Created', 'Vault created screen')
|
||||
@ -130,9 +125,7 @@ async function runFirstTimeUsageTest(assert, done) {
|
||||
}
|
||||
|
||||
function timeout (time) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
resolve()
|
||||
}, time * 3 || 1500)
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(resolve, time || 1500)
|
||||
})
|
||||
}
|
17
test/mascara.conf.js
Normal file
17
test/mascara.conf.js
Normal file
@ -0,0 +1,17 @@
|
||||
const getBaseConfig = require('./base.conf.js')
|
||||
|
||||
module.exports = function(config) {
|
||||
const settings = getBaseConfig(config)
|
||||
|
||||
// ui and tests
|
||||
settings.files.push('dist/mascara/ui.js')
|
||||
settings.files.push('dist/mascara/tests.js')
|
||||
// service worker background
|
||||
settings.files.push({ pattern: 'dist/mascara/background.js', watched: false, included: false, served: true }),
|
||||
settings.proxies['/background.js'] = '/base/dist/mascara/background.js'
|
||||
|
||||
// use this to keep the browser open for debugging
|
||||
settings.browserNoActivityTimeout = 10000000
|
||||
|
||||
config.set(settings)
|
||||
}
|
@ -61,7 +61,7 @@ const actions = {
|
||||
var css = MetaMaskUiCss()
|
||||
injectCss(css)
|
||||
|
||||
const container = document.querySelector('#app-content')
|
||||
const container = document.querySelector('#test-container')
|
||||
|
||||
// parse opts
|
||||
var store = configureStore(states[selectedView])
|
||||
@ -72,7 +72,7 @@ render(
|
||||
|
||||
h(Selector, { actions, selectedKey: selectedView, states, store }),
|
||||
|
||||
h('.mock-app-root', {
|
||||
h('#app-content', {
|
||||
style: {
|
||||
height: '500px',
|
||||
width: '360px',
|
||||
|
@ -17,6 +17,6 @@ Tooltip.prototype.render = function () {
|
||||
return h(ReactTooltip, {
|
||||
position: position || 'left',
|
||||
title,
|
||||
fixed: false,
|
||||
fixed: true,
|
||||
}, children)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ TransactionIcon.prototype.render = function () {
|
||||
case 'submitted':
|
||||
return h(Tooltip, {
|
||||
title: 'Pending',
|
||||
position: 'bottom',
|
||||
position: 'right',
|
||||
}, [
|
||||
h('i.fa.fa-ellipsis-h', {
|
||||
style: {
|
||||
|
@ -65,7 +65,7 @@ TransactionListItem.prototype.render = function () {
|
||||
|
||||
h(Tooltip, {
|
||||
title: 'Transaction Number',
|
||||
position: 'bottom',
|
||||
position: 'right',
|
||||
}, [
|
||||
h('span', {
|
||||
style: {
|
||||
|
@ -385,10 +385,15 @@ SendTransactionScreen.prototype.onSubmit = function (event) {
|
||||
// return this.props.dispatch(actions.displayWarning(message))
|
||||
// }
|
||||
|
||||
// if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) {
|
||||
// message = 'Recipient address is invalid.'
|
||||
// return this.props.dispatch(actions.displayWarning(message))
|
||||
// }
|
||||
if ((util.isInvalidChecksumAddress(recipient))) {
|
||||
message = 'Recipient address checksum is invalid.'
|
||||
return this.props.dispatch(actions.displayWarning(message))
|
||||
}
|
||||
|
||||
if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) {
|
||||
message = 'Recipient address is invalid.'
|
||||
return this.props.dispatch(actions.displayWarning(message))
|
||||
}
|
||||
|
||||
if (txData && !isHex(stripHexPrefix(txData))) {
|
||||
message = 'Transaction data must be hex string.'
|
||||
|
@ -54,6 +54,7 @@ module.exports = {
|
||||
shortenBalance,
|
||||
getContractAtAddress,
|
||||
exportAsFile: exportAsFile,
|
||||
isInvalidChecksumAddress,
|
||||
}
|
||||
|
||||
function valuesFor (obj) {
|
||||
@ -83,6 +84,12 @@ function isValidAddress (address) {
|
||||
return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed)
|
||||
}
|
||||
|
||||
function isInvalidChecksumAddress (address) {
|
||||
var prefixed = ethUtil.addHexPrefix(address)
|
||||
if (address === '0x0000000000000000000000000000000000000000') return false
|
||||
return !isAllOneCase(prefixed) && !ethUtil.isValidChecksumAddress(prefixed) && ethUtil.isValidAddress(prefixed)
|
||||
}
|
||||
|
||||
function isAllOneCase (address) {
|
||||
if (!address) return true
|
||||
var lower = address.toLowerCase()
|
||||
|
Loading…
Reference in New Issue
Block a user