feature/default_network_editable
Alexander Tseung 7 years ago
commit 34e608e9dc
  1. 38
      .circleci/config.yml
  2. 5
      CHANGELOG.md
  3. 2
      app/_locales/en/messages.json
  4. 2
      app/manifest.json
  5. 4
      app/scripts/background.js
  6. 2
      app/scripts/config.js
  7. 5
      app/scripts/controllers/blacklist.js
  8. 23
      app/scripts/controllers/currency.js
  9. 18
      app/scripts/controllers/infura.js
  10. 15
      app/scripts/controllers/shapeshift.js
  11. 2
      app/scripts/first-time-state.js
  12. 2
      app/scripts/inpage.js
  13. 2
      app/scripts/lib/setupRaven.js
  14. 12
      app/scripts/lib/tx-state-manager.js
  15. 109
      development/metamaskbot-build-announce.js
  16. 55
      development/sentry-publish.js
  17. 16
      gulpfile.js
  18. 8
      package-lock.json
  19. 11
      package.json
  20. 2
      test/integration/lib/add-token.js
  21. 21
      ui/app/components/pages/add-token.js
  22. 29
      ui/app/css/itcss/components/add-token.scss
  23. 2
      ui/app/store.js
  24. 21
      ui/i18n-helper.js

@ -23,7 +23,7 @@ workflows:
requires:
- prep-deps-npm
- prep-build
- job-announce:
- job-publish:
requires:
- prep-deps-npm
- prep-build
@ -67,7 +67,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Install deps via npm
command: npm install
@ -75,6 +75,10 @@ jobs:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- node_modules
- save_cache:
key: dependency-cache-{{ .Revision }}
paths:
- node_modules
prep-deps-firefox:
docker:
@ -97,7 +101,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: build:dist
command: npm run dist
@ -116,7 +120,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Get Scss Cache key
# this allows us to checksum against a whole directory
@ -135,7 +139,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Test
command: npm run lint
@ -146,7 +150,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- restore_cache:
key: build-cache-{{ .Revision }}
- run:
@ -162,7 +166,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- restore_cache:
key: build-cache-{{ .Revision }}
- run:
@ -173,13 +177,13 @@ jobs:
paths:
- test-artifacts
job-announce:
job-publish:
docker:
- image: circleci/node:8-browsers
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- restore_cache:
key: build-cache-{{ .Revision }}
- restore_cache:
@ -187,6 +191,9 @@ jobs:
- store_artifacts:
path: dist/mascara
destination: builds/mascara
- store_artifacts:
path: dist/sourcemaps
destination: builds/sourcemaps
- store_artifacts:
path: builds
destination: builds
@ -196,6 +203,9 @@ jobs:
- run:
name: build:announce
command: ./development/metamaskbot-build-announce.js
- run:
name: sentry sourcemaps upload
command: npm run sentry:publish
test-unit:
docker:
@ -203,7 +213,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: test:coverage
command: npm run test:coverage
@ -225,7 +235,7 @@ jobs:
&& sudo mv /usr/bin/firefox /usr/bin/firefox-old
&& sudo ln -s /opt/firefox58/firefox /usr/bin/firefox
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Get Scss Cache key
# this allows us to checksum against a whole directory
@ -244,7 +254,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Get Scss Cache key
# this allows us to checksum against a whole directory
@ -272,7 +282,7 @@ jobs:
&& sudo mv /usr/bin/firefox /usr/bin/firefox-old
&& sudo ln -s /opt/firefox58/firefox /usr/bin/firefox
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Get Scss Cache key
# this allows us to checksum against a whole directory
@ -291,7 +301,7 @@ jobs:
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
key: dependency-cache-{{ .Revision }}
- run:
name: Get Scss Cache key
# this allows us to checksum against a whole directory

@ -2,6 +2,11 @@
## Current Master
## 4.5.1 Tue Apr 03 2018
- Fix default network (should be mainnet not Rinkeby)
- Fix Sentry automated error reporting endpoint
## 4.5.0 Mon Apr 02 2018
- (beta ui) Internationalization: Select your preferred language in the settings screen

@ -56,7 +56,7 @@
"message": "Balance:"
},
"balances": {
"message": "Your balances"
"message": "Token balance(s)"
},
"balanceIsInsufficientGas": {
"message": "Insufficient balance for current gas total"

@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "__MSG_appName__",
"version": "4.5.0",
"version": "4.5.1",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "__MSG_appDescription__",

@ -22,7 +22,7 @@ const EdgeEncryptor = require('./edge-encryptor')
const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code')
const STORAGE_KEY = 'metamask-config'
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
window.log = log
log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn')
@ -94,7 +94,7 @@ function setupController (initState, initLangCode) {
//
// MetaMask Controller
//
const controller = new MetamaskController({
// User confirmation callbacks:
showUnconfirmedMessage: triggerUi,

@ -13,7 +13,7 @@ const DEFAULT_RPC = 'rinkeby'
const OLD_UI_NETWORK_TYPE = 'network'
const BETA_UI_NETWORK_TYPE = 'networkBeta'
global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
global.METAMASK_DEBUG = process.env.METAMASK_DEBUG
module.exports = {
network: {

@ -41,9 +41,9 @@ class BlacklistController {
scheduleUpdates () {
if (this._phishingUpdateIntervalRef) return
this.updatePhishingList()
this.updatePhishingList().catch(log.warn)
this._phishingUpdateIntervalRef = setInterval(() => {
this.updatePhishingList()
this.updatePhishingList().catch(log.warn)
}, POLLING_INTERVAL)
}
@ -57,4 +57,3 @@ class BlacklistController {
}
module.exports = BlacklistController

@ -43,20 +43,19 @@ class CurrencyController {
this.store.updateState({ conversionDate })
}
updateConversionRate () {
const currentCurrency = this.getCurrentCurrency()
return fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`)
.then(response => response.json())
.then((parsedResponse) => {
async updateConversionRate () {
let currentCurrency
try {
currentCurrency = this.getCurrentCurrency()
const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`)
const parsedResponse = await response.json()
this.setConversionRate(Number(parsedResponse.bid))
this.setConversionDate(Number(parsedResponse.timestamp))
}).catch((err) => {
if (err) {
console.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err)
this.setConversionRate(0)
this.setConversionDate('N/A')
}
})
} catch (err) {
log.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err)
this.setConversionRate(0)
this.setConversionDate('N/A')
}
}
scheduleConversionInterval () {

@ -19,15 +19,13 @@ class InfuraController {
// Responsible for retrieving the status of Infura's nodes. Can return either
// ok, degraded, or down.
checkInfuraNetworkStatus () {
return fetch('https://api.infura.io/v1/status/metamask')
.then(response => response.json())
.then((parsedResponse) => {
this.store.updateState({
infuraNetworkStatus: parsedResponse,
})
return parsedResponse
})
async checkInfuraNetworkStatus () {
const response = await fetch('https://api.infura.io/v1/status/metamask')
const parsedResponse = await response.json()
this.store.updateState({
infuraNetworkStatus: parsedResponse,
})
return parsedResponse
}
scheduleInfuraNetworkCheck () {
@ -35,7 +33,7 @@ class InfuraController {
clearInterval(this.conversionInterval)
}
this.conversionInterval = setInterval(() => {
this.checkInfuraNetworkStatus()
this.checkInfuraNetworkStatus().catch(log.warn)
}, POLLING_INTERVAL)
}
}

@ -45,18 +45,19 @@ class ShapeshiftController {
})
}
updateTx (tx) {
const url = `https://shapeshift.io/txStat/${tx.depositAddress}`
return fetch(url)
.then((response) => {
return response.json()
}).then((json) => {
async updateTx (tx) {
try {
const url = `https://shapeshift.io/txStat/${tx.depositAddress}`
const response = await fetch(url)
const json = await response.json()
tx.response = json
if (tx.response.status === 'complete') {
tx.time = new Date().getTime()
}
return tx
})
} catch (err) {
log.warn(err)
}
}
saveTx (tx) {

@ -1,6 +1,6 @@
// test and development environment variables
const env = process.env.METAMASK_ENV
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
//
// The default state of MetaMask

@ -9,7 +9,7 @@ const setupDappAutoReload = require('./lib/auto-reload.js')
const MetamaskInpageProvider = require('./lib/inpage-provider.js')
restoreContextAfterImports()
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
window.log = log
log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn')

@ -1,5 +1,5 @@
const Raven = require('raven-js')
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
const extractEthjsErrorMessage = require('./extractEthjsErrorMessage')
const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505'
const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'

@ -140,8 +140,16 @@ module.exports = class TransactionStateManager extends EventEmitter {
validateTxParams(txParams) {
Object.keys(txParams).forEach((key) => {
const value = txParams[key]
if (typeof value !== 'string') throw new Error(`${key}: ${value} in txParams is not a string`)
if (!ethUtil.isHexPrefixed(value)) throw new Error('is not hex prefixed, everything on txParams must be hex prefixed')
// validate types
switch (key) {
case 'chainId':
if (typeof value !== 'number') throw new Error(`${key} in txParams is not a Number. got: (${value})`)
break
default:
if (typeof value !== 'string') throw new Error(`${key} in txParams is not a string. got: (${value})`)
if (!ethUtil.isHexPrefixed(value)) throw new Error(`${key} in txParams is not hex prefixed. got: (${value})`)
break
}
})
}

@ -1,51 +1,62 @@
#!/usr/bin/env node
const request = require('request-promise')
const { version } = require('../dist/chrome/manifest.json')
const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN
const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST
console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST)
const CIRCLE_SHA1 = process.env.CIRCLE_SHA1
console.log('CIRCLE_SHA1', CIRCLE_SHA1)
const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM
console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM)
const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop()
const SHORT_SHA1 = CIRCLE_SHA1.slice(0,7)
const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0`
const MASCARA = `${BUILD_LINK_BASE}/builds/mascara/home.html`
const CHROME = `${BUILD_LINK_BASE}/builds/metamask-chrome-${version}.zip`
const FIREFOX = `${BUILD_LINK_BASE}/builds/metamask-firefox-${version}.zip`
const EDGE = `${BUILD_LINK_BASE}/builds/metamask-edge-${version}.zip`
const OPERA = `${BUILD_LINK_BASE}/builds/metamask-opera-${version}.zip`
const WALKTHROUGH = `${BUILD_LINK_BASE}/test-artifacts/screens/walkthrough%20%28en%29.gif`
const commentBody = `
<details>
<summary>
Builds ready [${SHORT_SHA1}]:
<a href="${MASCARA}">mascara</a>,
<a href="${CHROME}">chrome</a>,
<a href="${FIREFOX}">firefox</a>,
<a href="${EDGE}">edge</a>,
<a href="${OPERA}">opera</a>
</summary>
<image src="${WALKTHROUGH}">
</details>
`
const JSON_PAYLOAD = JSON.stringify({ body: commentBody })
const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments`
console.log(`Announcement:\n${commentBody}`)
console.log(`Posting to: ${POST_COMMENT_URI}`)
request({
method: 'POST',
uri: POST_COMMENT_URI,
body: JSON_PAYLOAD,
headers: {
'User-Agent': 'metamaskbot',
'Authorization': `token ${GITHUB_COMMENT_TOKEN}`,
},
})
const VERSION = require('../dist/chrome/manifest.json').version
start().catch(console.error)
async function start() {
const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN
const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST
console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST)
const CIRCLE_SHA1 = process.env.CIRCLE_SHA1
console.log('CIRCLE_SHA1', CIRCLE_SHA1)
const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM
console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM)
if (!CIRCLE_PULL_REQUEST) {
console.warn(`No pull request detected for commit "${CIRCLE_SHA1}"`)
return
}
const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop()
const SHORT_SHA1 = CIRCLE_SHA1.slice(0,7)
const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0`
const MASCARA = `${BUILD_LINK_BASE}/builds/mascara/home.html`
const CHROME = `${BUILD_LINK_BASE}/builds/metamask-chrome-${VERSION}.zip`
const FIREFOX = `${BUILD_LINK_BASE}/builds/metamask-firefox-${VERSION}.zip`
const EDGE = `${BUILD_LINK_BASE}/builds/metamask-edge-${VERSION}.zip`
const OPERA = `${BUILD_LINK_BASE}/builds/metamask-opera-${VERSION}.zip`
const WALKTHROUGH = `${BUILD_LINK_BASE}/test-artifacts/screens/walkthrough%20%28en%29.gif`
const commentBody = `
<details>
<summary>
Builds ready [${SHORT_SHA1}]:
<a href="${MASCARA}">mascara</a>,
<a href="${CHROME}">chrome</a>,
<a href="${FIREFOX}">firefox</a>,
<a href="${EDGE}">edge</a>,
<a href="${OPERA}">opera</a>
</summary>
<image src="${WALKTHROUGH}">
</details>
`
const JSON_PAYLOAD = JSON.stringify({ body: commentBody })
const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments`
console.log(`Announcement:\n${commentBody}`)
console.log(`Posting to: ${POST_COMMENT_URI}`)
await request({
method: 'POST',
uri: POST_COMMENT_URI,
body: JSON_PAYLOAD,
headers: {
'User-Agent': 'metamaskbot',
'Authorization': `token ${GITHUB_COMMENT_TOKEN}`,
},
})
}

@ -0,0 +1,55 @@
#!/usr/bin/env node
const pify = require('pify')
const exec = pify(require('child_process').exec, { multiArgs: true })
const VERSION = require('../dist/chrome/manifest.json').version
start().catch(console.error)
async function start(){
const authWorked = await checkIfAuthWorks()
if (!authWorked) {
console.log(`Sentry auth failed...`)
}
// check if version exists or not
const versionAlreadyExists = await checkIfVersionExists()
// abort if versions exists
if (versionAlreadyExists) {
console.log(`Version "${VERSION}" already exists on Sentry, aborting sourcemap upload.`)
return
}
// create sentry release
console.log(`creating Sentry release for "${VERSION}"...`)
await exec(`sentry-cli releases --org 'metamask' --project 'metamask' new ${VERSION}`)
console.log(`removing any existing files from Sentry release "${VERSION}"...`)
await exec(`sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} delete --all`)
// upload sentry source and sourcemaps
console.log(`uploading source files Sentry release "${VERSION}"...`)
await exec(`for FILEPATH in ./dist/chrome/*.js; do [ -e $FILEPATH ] || continue; export FILE=\`basename $FILEPATH\` && echo uploading $FILE && sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} upload $FILEPATH metamask/$FILE; done;`)
console.log(`uploading sourcemaps Sentry release "${VERSION}"...`)
await exec(`sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} upload-sourcemaps ./dist/sourcemaps/ --url-prefix 'sourcemaps'`)
console.log('all done!')
}
async function checkIfAuthWorks() {
const itWorked = await doesNotFail(async () => {
await exec(`sentry-cli releases --org 'metamask' --project 'metamask' list`)
})
return itWorked
}
async function checkIfVersionExists() {
const versionAlreadyExists = await doesNotFail(async () => {
await exec(`sentry-cli releases --org 'metamask' --project 'metamask' info ${VERSION}`)
})
return versionAlreadyExists
}
async function doesNotFail(asyncFn) {
try {
await asyncFn()
return true
} catch (err) {
return false
}
}

@ -1,5 +1,6 @@
const watchify = require('watchify')
const browserify = require('browserify')
const envify = require('envify/custom')
const disc = require('disc')
const gulp = require('gulp')
const source = require('vinyl-source-stream')
@ -377,12 +378,6 @@ gulp.task('zip:edge', zipTask('edge'))
gulp.task('zip:opera', zipTask('opera'))
gulp.task('zip', gulp.parallel('zip:chrome', 'zip:firefox', 'zip:edge', 'zip:opera'))
// set env for production
gulp.task('apply-prod-environment', function(done) {
process.env.NODE_ENV = 'production'
done()
});
// high level tasks
gulp.task('dev',
@ -458,7 +453,6 @@ gulp.task('build:mascara',
gulp.task('dist',
gulp.series(
'apply-prod-environment',
'build',
'zip'
)
@ -484,6 +478,12 @@ function generateBundler(opts, performBundle) {
let bundler = browserify(browserifyOpts)
// inject variables into bundle
bundler.transform(envify({
METAMASK_DEBUG: opts.devMode,
NODE_ENV: opts.devMode ? 'development' : 'production',
}))
// Minification
if (opts.minifyBuild) {
bundler.transform('uglifyify', {
@ -557,8 +557,6 @@ function bundleTask(opts) {
buildStream = buildStream
// convert bundle stream to gulp vinyl stream
.pipe(source(opts.filename))
// inject variables into bundle
.pipe(replace('\'GULP_METAMASK_DEBUG\'', opts.devMode))
// buffer file contents (?)
.pipe(buffer())

8
package-lock.json generated

@ -188,7 +188,7 @@
"integrity": "sha1-AtD3eBwe5eG+WkMSoyX76LGzcjE=",
"dev": true,
"requires": {
"https-proxy-agent": "2.2.0",
"https-proxy-agent": "2.2.1",
"node-fetch": "1.7.3",
"progress": "2.0.0",
"proxy-from-env": "1.0.0"
@ -213,9 +213,9 @@
}
},
"https-proxy-agent": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz",
"integrity": "sha512-uUWcfXHvy/dwfM9bqa6AozvAjS32dZSTUYd/4SEpYKRg6LEcPLshksnQYRudM9AyNvUARMfAg5TLjUDyX/K4vA==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
"integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
"dev": true,
"requires": {
"agent-base": "4.2.0",

@ -5,7 +5,7 @@
"private": true,
"scripts": {
"start": "gulp dev:extension",
"mascara": "gulp dev:mascara & cross-env METAMASK_DEBUG=true node ./mascara/example/server",
"mascara": "gulp dev:mascara & node ./mascara/example/server",
"dist": "gulp dist",
"test": "npm run test:unit && npm run test:integration && npm run lint",
"test:unit": "cross-env METAMASK_ENV=test mocha --exit --require babel-core/register --require test/helper.js --recursive \"test/unit/**/*.js\"",
@ -31,13 +31,7 @@
"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",
"ganache:start": "ganache-cli -m 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'",
"sentry": "export RELEASE=`cat app/manifest.json| jq -r .version` && npm run sentry:release && npm run sentry:upload",
"sentry:release": "npm run sentry:release:new && npm run sentry:release:clean",
"sentry:release:new": "sentry-cli releases --org 'metamask' --project 'metamask' new $RELEASE",
"sentry:release:clean": "sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE delete --all",
"sentry:upload": "npm run sentry:upload:source && npm run sentry:upload:maps",
"sentry:upload:source": "for FILEPATH in ./dist/chrome/scripts/*.js; do [ -e $FILEPATH ] || continue; export FILE=`basename $FILEPATH` && echo uploading $FILE && sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE upload $FILEPATH metamask/scripts/$FILE; done;",
"sentry:upload:maps": "sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE upload-sourcemaps ./dist/sourcemaps/ --url-prefix 'sourcemaps' --rewrite",
"sentry:publish": "node ./development/sentry-publish.js",
"lint": "gulp lint",
"lint:fix": "gulp lint:fix",
"ui": "npm run test:flat:build:states && beefy development/ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./",
@ -61,7 +55,6 @@
}
],
"reactify",
"envify",
"brfs"
]
},

@ -75,7 +75,7 @@ async function runAddTokenFlowTest (assert, done) {
// Confirm Add token
assert.equal(
$('.add-token__description')[0].textContent,
'Would you like to add these tokens?',
'Token balance(s)',
'confirm add token rendered'
)
assert.ok($('button.btn-primary--lg')[0], 'confirm add token button found')

@ -56,6 +56,7 @@ inherits(AddTokenScreen, Component)
function AddTokenScreen () {
this.state = {
isShowingConfirmation: false,
isShowingInfoBox: true,
customAddress: '',
customSymbol: '',
customDecimals: '',
@ -310,9 +311,6 @@ AddTokenScreen.prototype.renderConfirmation = function () {
return (
h('div.add-token', [
h('div.add-token__wrapper', [
h('div.add-token__title-container.add-token__confirmation-title', [
h('div.add-token__description', this.context.t('likeToAddTokens')),
]),
h('div.add-token__content-container.add-token__confirmation-content', [
h('div.add-token__description.add-token__confirmation-description', this.context.t('balances')),
h('div.add-token__confirmation-token-list',
@ -347,18 +345,22 @@ AddTokenScreen.prototype.displayTab = function (selectedTab) {
}
AddTokenScreen.prototype.renderTabs = function () {
const { displayedTab, errors } = this.state
const { isShowingInfoBox, displayedTab, errors } = this.state
return displayedTab === 'CUSTOM_TOKEN'
? this.renderCustomForm()
: h('div', [
h('div.add-token__wrapper', [
h('div.add-token__content-container', [
h('div.add-token__info-box', [
h('div.add-token__info-box__close'),
isShowingInfoBox && h('div.add-token__info-box', [
h('div.add-token__info-box__close', {
onClick: () => this.setState({ isShowingInfoBox: false }),
}),
h('div.add-token__info-box__title', this.context.t('whatsThis')),
h('div.add-token__info-box__copy', this.context.t('keepTrackTokens')),
h('div.add-token__info-box__copy--blue', this.context.t('learnMore')),
h('a.add-token__info-box__copy--blue', {
href: 'http://metamask.helpscoutdocs.com/article/16-managing-erc20-tokens',
}, this.context.t('learnMore')),
]),
h('div.add-token__input-container', [
h('input.add-token__input', {
@ -390,12 +392,13 @@ AddTokenScreen.prototype.render = function () {
h('span', this.context.t('cancel')),
]),
h('div.add-token__header__title', this.context.t('addTokens')),
isShowingConfirmation && h('div.add-token__header__subtitle', this.context.t('likeToAddTokens')),
!isShowingConfirmation && h('div.add-token__header__tabs', [
h('div.add-token__header__tabs__tab', {
className: classnames('add-token__header__tabs__tab', {
'add-token__header__tabs__selected': displayedTab === 'SEARCH',
'add-token__header__tabs__unselected cursor-pointer': displayedTab !== 'SEARCH',
'add-token__header__tabs__unselected': displayedTab !== 'SEARCH',
}),
onClick: () => this.displayTab('SEARCH'),
}, this.context.t('search')),
@ -403,7 +406,7 @@ AddTokenScreen.prototype.render = function () {
h('div.add-token__header__tabs__tab', {
className: classnames('add-token__header__tabs__tab', {
'add-token__header__tabs__selected': displayedTab === 'CUSTOM_TOKEN',
'add-token__header__tabs__unselected cursor-pointer': displayedTab !== 'CUSTOM_TOKEN',
'add-token__header__tabs__unselected': displayedTab !== 'CUSTOM_TOKEN',
}),
onClick: () => this.displayTab('CUSTOM_TOKEN'),
}, this.context.t('customToken')),

@ -8,6 +8,7 @@
font-family: 'Roboto';
background: white;
border-radius: 8px;
box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08);
&__wrapper {
background-color: $white;
@ -20,7 +21,7 @@
&__header {
display: flex;
flex-flow: column nowrap;
padding: 16px 16px 0px;
padding: 20px 20px 0px;
border-bottom: 1px solid $geyser;
flex: 0 0 auto;
@ -31,7 +32,8 @@
span {
font-family: Roboto;
font-size: 16px;
font-size: 16px;
font-weight: 400;
line-height: 21px;
margin-left: 8px;
}
@ -44,8 +46,13 @@
margin-top: 4px;
}
&__subtitle {
font-weight: 400;
margin-top: 15px;
margin-bottom: 21px;
}
&__tabs {
margin-left: 22px;
display: flex;
&__tab {
@ -54,6 +61,7 @@
color: $dusty-gray;
font-family: Roboto;
font-size: 18px;
font-weight: 400;
line-height: 24px;
text-align: center;
}
@ -65,6 +73,7 @@
&__unselected:hover {
color: $black;
border-bottom: none;
cursor: pointer;
}
&__selected {
@ -76,7 +85,7 @@
&__info-box {
height: 96px;
margin: 20px 24px 0px;
margin: 20px 20px 0px;
border-radius: 4px;
background-color: $alabaster;
position: relative;
@ -98,6 +107,7 @@
color: $mid-gray;
font-family: Roboto;
font-size: 14px;
font-weight: 400;
margin-top: 15px;
margin-bottom: 9px;
}
@ -107,6 +117,7 @@
color: $mid-gray;
font-family: Roboto;
font-size: 12px;
font-weight: 400;
line-height: 18px;
}
@ -124,7 +135,8 @@
}
&__confirmation-description {
margin: 12px 0;
font-weight: 400;
margin: 20px 0 40px 0;
}
&__content-container {
@ -151,7 +163,7 @@
&__input,
&__add-custom-input {
height: 54px;
padding: 21px 6px;
padding: 0px 20px;
border: 1px solid $geyser;
border-radius: 4px;
margin: 22px 24px;
@ -232,6 +244,7 @@
&__add-custom-label {
font-size: 16px;
font-weight: 400;
line-height: 21px;
margin-left: 22px;
color: $scorpion;
@ -274,9 +287,11 @@
color: #5B5D67;
font-family: Roboto;
font-size: 18px;
font-weight: 400;
line-height: 24px;
margin-left: 24px;
margin-top: 8px;
margin-bottom: 20px;
}
&__token-icons-container {
@ -317,6 +332,7 @@
}
&__token-name {
font-weight: 400;
font-size: 14px;
line-height: 19px;
}
@ -368,6 +384,7 @@
&__symbol {
color: $scorpion;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}

@ -4,7 +4,7 @@ const thunkMiddleware = require('redux-thunk').default
const rootReducer = require('./reducers')
const createLogger = require('redux-logger').createLogger
global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
global.METAMASK_DEBUG = process.env.METAMASK_DEBUG
module.exports = configureStore

@ -25,18 +25,15 @@ const getMessage = (locale, key, substitutions) => {
return phrase
}
function fetchLocale (localeName) {
return new Promise((resolve, reject) => {
return fetch(`./_locales/${localeName}/messages.json`)
.then(response => response.json())
.then(
locale => resolve(locale),
error => {
log.error(`failed to fetch ${localeName} locale because of ${error}`)
resolve({})
}
)
})
async function fetchLocale (localeName) {
try {
const response = await fetch(`./_locales/${localeName}/messages.json`)
const locale = await response.json()
return locale
} catch (error) {
log.error(`failed to fetch ${localeName} locale because of ${error}`)
return {}
}
}
module.exports = {

Loading…
Cancel
Save