mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
commit
3180b69b97
@ -2,6 +2,14 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
## 4.6.1 Mon Apr 30 2018
|
||||
|
||||
- Fix bug where sending a transaction resulted in an infinite spinner
|
||||
- Allow transactions with a 0 gwei gas price
|
||||
- Handle encoding errors in ERC20 symbol + digits
|
||||
- Fix ShapeShift forms (new + old ui)
|
||||
- Fix sourcemaps
|
||||
|
||||
## 4.6.0 Thu Apr 26 2018
|
||||
|
||||
- Correctly format currency conversion for locally selected preferred currency.
|
||||
|
@ -98,6 +98,9 @@
|
||||
"clickCopy": {
|
||||
"message": "Click to Copy"
|
||||
},
|
||||
"close": {
|
||||
"message": "Close"
|
||||
},
|
||||
"confirm": {
|
||||
"message": "Confirm"
|
||||
},
|
||||
@ -259,6 +262,9 @@
|
||||
"enterPasswordConfirm": {
|
||||
"message": "Enter your password to confirm"
|
||||
},
|
||||
"enterPasswordContinue": {
|
||||
"message": "Enter password to continue"
|
||||
},
|
||||
"passwordNotLongEnough": {
|
||||
"message": "Password not long enough"
|
||||
},
|
||||
@ -331,6 +337,9 @@
|
||||
"gasPriceRequired": {
|
||||
"message": "Gas Price Required"
|
||||
},
|
||||
"generatingTransaction": {
|
||||
"message": "Generating transaction"
|
||||
},
|
||||
"getEther": {
|
||||
"message": "Get Ether"
|
||||
},
|
||||
@ -476,6 +485,9 @@
|
||||
"metamaskDescription": {
|
||||
"message": "MetaMask is a secure identity vault for Ethereum."
|
||||
},
|
||||
"metamaskSeedWords": {
|
||||
"message": "MetaMask Seed Words"
|
||||
},
|
||||
"min": {
|
||||
"message": "Minimum"
|
||||
},
|
||||
@ -549,6 +561,9 @@
|
||||
"message": "or",
|
||||
"description": "choice between creating or importing a new account"
|
||||
},
|
||||
"password": {
|
||||
"message": "Password"
|
||||
},
|
||||
"passwordCorrect": {
|
||||
"message": "Please make sure your password is correct."
|
||||
},
|
||||
@ -634,8 +649,17 @@
|
||||
"revealSeedWords": {
|
||||
"message": "Reveal Seed Words"
|
||||
},
|
||||
"revealSeedWordsTitle": {
|
||||
"message": "Seed Phrase"
|
||||
},
|
||||
"revealSeedWordsDescription": {
|
||||
"message": "If you ever change browsers or move computers, you will need this seed phrase to access your accounts. Save them somewhere safe and secret."
|
||||
},
|
||||
"revealSeedWordsWarningTitle": {
|
||||
"message": "DO NOT share this phrase with anyone!"
|
||||
},
|
||||
"revealSeedWordsWarning": {
|
||||
"message": "Do not recover your seed words in a public place! These words can be used to steal all your accounts."
|
||||
"message": "These words can be used to steal all your accounts."
|
||||
},
|
||||
"revert": {
|
||||
"message": "Revert"
|
||||
@ -677,6 +701,9 @@
|
||||
"reprice_subtitle": {
|
||||
"message": "Increase your gas price to attempt to overwrite and speed up your transaction"
|
||||
},
|
||||
"saveAsCsvFile": {
|
||||
"message": "Save as CSV File"
|
||||
},
|
||||
"saveAsFile": {
|
||||
"message": "Save as File",
|
||||
"description": "Account export process"
|
||||
@ -909,7 +936,7 @@
|
||||
"youSign": {
|
||||
"message": "You are signing"
|
||||
},
|
||||
"generatingTransaction": {
|
||||
"message": "Generating transaction"
|
||||
"yourPrivateSeedPhrase": {
|
||||
"message": "Your private seed phrase"
|
||||
}
|
||||
}
|
||||
|
24
app/images/copy-to-clipboard.svg
Normal file
24
app/images/copy-to-clipboard.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="17px" viewBox="0 0 18 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>374E58A5-C29E-4921-83E7-889FA06D6408</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="Reveal-Seedphrase" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Seed-phrase-2" transform="translate(-39.000000, -379.000000)">
|
||||
<g id="Group-2">
|
||||
<g id="Group-8" transform="translate(16.000000, 248.000000)">
|
||||
<g id="Group-6" transform="translate(23.336478, 120.000000)">
|
||||
<g id="Group-5" transform="translate(0.408805, 11.000000)">
|
||||
<g id="copy-to-clipboard">
|
||||
<rect id="Rectangle-18" stroke="#3098DC" stroke-width="2" x="1" y="1" width="12.0220126" height="12"></rect>
|
||||
<rect id="Rectangle-18-Copy-2" fill="#FFFFFF" x="2.1572327" y="2" width="14.0220126" height="14"></rect>
|
||||
<rect id="Rectangle-18-Copy" stroke="#3098DC" stroke-width="2" x="4.23584906" y="4" width="12.0220126" height="12"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -1,15 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="24.088px" height="24px" viewBox="138.01 0 24.088 24" enable-background="new 138.01 0 24.088 24" xml:space="preserve" fill="#F7861C">
|
||||
<g>
|
||||
<polygon fill="#F7861C" points="157.551,17.075 156.55,17.075 156.55,19.149 142.569,19.149 142.569,17.075 141.568,17.075
|
||||
141.568,20.145 141.955,20.145 141.955,20.15 157.006,20.15 157.006,20.145 157.551,20.145 "/>
|
||||
<polygon fill="#F7861C" points="152.555,10.275 152.555,11.26 152.555,11.268 151.562,11.268 151.562,12.252 150.565,12.252
|
||||
150.565,4.171 149.564,4.171 149.564,12.236 148.564,12.236 148.564,11.252 147.564,11.252 147.564,11.236 147.564,11.221
|
||||
147.564,10.236 146.563,10.236 146.563,11.221 146.563,11.236 146.563,12.221 147.563,12.221 147.563,12.236 147.563,12.252
|
||||
147.563,13.236 148.563,13.236 148.563,14.221 149.564,14.221 149.564,15.725 150.565,15.725 150.565,14.236 151.563,14.236
|
||||
151.563,13.252 152.563,13.252 152.563,12.268 152.563,12.26 153.556,12.26 153.556,11.275 153.556,11.26 153.556,10.275 "/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="18px" viewBox="0 0 20 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>50559280-0739-419A-8E87-3CDD16A6996A</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="Reveal-Seedphrase" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Seed-phrase-2" transform="translate(-212.000000, -379.000000)" stroke="#259DE5" stroke-width="2">
|
||||
<g id="Group-2">
|
||||
<g id="Group-8" transform="translate(16.000000, 248.000000)">
|
||||
<g id="Group-6" transform="translate(23.336478, 120.000000)">
|
||||
<g id="Group-3" transform="translate(174.000000, 11.000000)">
|
||||
<g id="Group-4">
|
||||
<g id="download">
|
||||
<polyline id="Path-5" points="0 11 0 17 17 17 17 11"></polyline>
|
||||
<path d="M8.5,0 L8.5,11" id="Path-6"></path>
|
||||
<polyline id="Path-7" points="3.1875 7 8.5 11 13.8125 7"></polyline>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
22
app/images/warning.svg
Normal file
22
app/images/warning.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="33px" height="32px" viewBox="0 0 33 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Group 7</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Reveal-Seedphrase" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Seed-phrase-2" transform="translate(-29.000000, -155.000000)">
|
||||
<g id="Group-2" transform="translate(0.000000, 132.000000)">
|
||||
<g id="Group" transform="translate(28.000000, 19.000000)">
|
||||
<g id="Group-19-Copy-2" transform="translate(0.000000, 3.000000)">
|
||||
<g id="Group-7">
|
||||
<path d="M20.1321134,3.85444772 L32.5721829,26.6020033 C33.367162,28.0556794 32.8331826,29.8785746 31.3795065,30.6735537 C30.9381289,30.9149321 30.4431378,31.0414403 29.9400695,31.0414403 L5.05993054,31.0414403 C3.40307629,31.0414403 2.05993054,29.6982946 2.05993054,28.0414403 C2.05993054,27.538372 2.18643873,27.0433809 2.42781712,26.6020033 L14.8678866,3.85444772 C15.6628657,2.40077162 17.4857609,1.86679221 18.939437,2.66177133 C19.442875,2.93708896 19.8567958,3.35100977 20.1321134,3.85444772 Z" id="Triangle-2-Copy" stroke="#FF001F" stroke-width="2"></path>
|
||||
<rect id="Rectangle-5" fill="#FF001F" x="16" y="9" width="3" height="13"></rect>
|
||||
<rect id="Rectangle-5-Copy" fill="#FF001F" x="16" y="24" width="3" height="3"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "__MSG_appName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "4.6.0",
|
||||
"version": "4.6.1",
|
||||
"manifest_version": 2,
|
||||
"author": "https://metamask.io",
|
||||
"description": "__MSG_appDescription__",
|
||||
|
@ -1,4 +1,5 @@
|
||||
const ObservableStore = require('obs-store')
|
||||
const { warn } = require('loglevel')
|
||||
|
||||
// By default, poll every 3 minutes
|
||||
const DEFAULT_INTERVAL = 180 * 1000
|
||||
@ -42,7 +43,10 @@ class TokenRatesController {
|
||||
const response = await fetch(`https://metamask.balanc3.net/prices?from=${address}&to=ETH&autoConversion=false&summaryOnly=true`)
|
||||
const json = await response.json()
|
||||
return json && json.length ? json[0].averagePrice : 0
|
||||
} catch (error) { }
|
||||
} catch (error) {
|
||||
warn(`MetaMask - TokenRatesController exchange rate fetch failed for ${address}.`, error)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,6 +101,7 @@ ConfigManager.prototype.setShowSeedWords = function (should) {
|
||||
this.setData(data)
|
||||
}
|
||||
|
||||
|
||||
ConfigManager.prototype.getShouldShowSeedWords = function () {
|
||||
var data = this.getData()
|
||||
return data.showSeedWords
|
||||
@ -116,27 +117,6 @@ ConfigManager.prototype.getSeedWords = function () {
|
||||
var data = this.getData()
|
||||
return data.seedWords
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set the isRevealingSeedWords flag. This happens only when the user chooses to reveal
|
||||
* the seed words and not during the first time flow.
|
||||
* @param {boolean} reveal - Value to set the isRevealingSeedWords flag.
|
||||
*/
|
||||
ConfigManager.prototype.setIsRevealingSeedWords = function (reveal = false) {
|
||||
const data = this.getData()
|
||||
data.isRevealingSeedWords = reveal
|
||||
this.setData(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the isRevealingSeedWords flag.
|
||||
* @returns {boolean|undefined}
|
||||
*/
|
||||
ConfigManager.prototype.getIsRevealingSeedWords = function () {
|
||||
const data = this.getData()
|
||||
return data.isRevealingSeedWords
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setRpcTarget = function (rpcUrl) {
|
||||
var config = this.getConfig()
|
||||
config.provider = {
|
||||
|
@ -23,23 +23,16 @@ function setupRaven(opts) {
|
||||
release,
|
||||
transport: function(opts) {
|
||||
const report = opts.data
|
||||
// simplify certain complex error messages
|
||||
if (report.exception && report.exception.values) {
|
||||
report.exception.values.forEach(item => {
|
||||
let errorMessage = item.value
|
||||
// simplify ethjs error messages
|
||||
errorMessage = extractEthjsErrorMessage(errorMessage)
|
||||
// simplify 'Transaction Failed: known transaction'
|
||||
if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) {
|
||||
// cut the hash from the error message
|
||||
errorMessage = 'Transaction Failed: known transaction'
|
||||
}
|
||||
// finalize
|
||||
item.value = errorMessage
|
||||
})
|
||||
try {
|
||||
// handle error-like non-error exceptions
|
||||
nonErrorException(report)
|
||||
// simplify certain complex error messages (e.g. Ethjs)
|
||||
simplifyErrorMessages(report)
|
||||
// modify report urls
|
||||
rewriteReportUrls(report)
|
||||
} catch (err) {
|
||||
console.warn(err)
|
||||
}
|
||||
// modify report urls
|
||||
rewriteReportUrls(report)
|
||||
// make request normally
|
||||
client._makeRequest(opts)
|
||||
},
|
||||
@ -49,6 +42,31 @@ function setupRaven(opts) {
|
||||
return Raven
|
||||
}
|
||||
|
||||
function nonErrorException(report) {
|
||||
// handle errors that lost their error-ness in serialization
|
||||
if (report.message.includes('Non-Error exception captured with keys: message')) {
|
||||
if (!(report.extra && report.extra.__serialized__)) return
|
||||
report.message = `Non-Error Exception: ${report.extra.__serialized__.message}`
|
||||
}
|
||||
}
|
||||
|
||||
function simplifyErrorMessages(report) {
|
||||
if (report.exception && report.exception.values) {
|
||||
report.exception.values.forEach(item => {
|
||||
let errorMessage = item.value
|
||||
// simplify ethjs error messages
|
||||
errorMessage = extractEthjsErrorMessage(errorMessage)
|
||||
// simplify 'Transaction Failed: known transaction'
|
||||
if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) {
|
||||
// cut the hash from the error message
|
||||
errorMessage = 'Transaction Failed: known transaction'
|
||||
}
|
||||
// finalize
|
||||
item.value = errorMessage
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function rewriteReportUrls(report) {
|
||||
// update request url
|
||||
report.request.url = toMetamaskUrl(report.request.url)
|
||||
|
@ -309,7 +309,6 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
lostAccounts: this.configManager.getLostAccounts(),
|
||||
seedWords: this.configManager.getSeedWords(),
|
||||
forgottenPassword: this.configManager.getPasswordForgotten(),
|
||||
isRevealingSeedWords: Boolean(this.configManager.getIsRevealingSeedWords()),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -351,7 +350,6 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
clearSeedWordCache: this.clearSeedWordCache.bind(this),
|
||||
resetAccount: nodeify(this.resetAccount, this),
|
||||
importAccountWithStrategy: this.importAccountWithStrategy.bind(this),
|
||||
setIsRevealingSeedWords: this.configManager.setIsRevealingSeedWords.bind(this.configManager),
|
||||
|
||||
// vault management
|
||||
submitPassword: nodeify(keyringController.submitPassword, keyringController),
|
||||
|
49
development/sourcemap-validator.js
Normal file
49
development/sourcemap-validator.js
Normal file
@ -0,0 +1,49 @@
|
||||
const fs = require('fs')
|
||||
const { SourceMapConsumer } = require('source-map')
|
||||
|
||||
//
|
||||
// Utility to help check if sourcemaps are working
|
||||
//
|
||||
// searches `dist/chrome/inpage.js` for "new Error" statements
|
||||
// and prints their source lines using the sourcemaps.
|
||||
// if not working it may error or print minified garbage
|
||||
//
|
||||
|
||||
start()
|
||||
|
||||
async function start() {
|
||||
const rawBuild = fs.readFileSync(__dirname + '/../dist/chrome/inpage.js', 'utf8')
|
||||
const rawSourceMap = fs.readFileSync(__dirname + '/../dist/sourcemaps/inpage.js.map', 'utf8')
|
||||
const consumer = await new SourceMapConsumer(rawSourceMap)
|
||||
|
||||
console.log('hasContentsOfAllSources:', consumer.hasContentsOfAllSources(), '\n')
|
||||
console.log('sources:')
|
||||
consumer.sources.map((sourcePath) => console.log(sourcePath))
|
||||
|
||||
console.log('\nexamining "new Error" statements:\n')
|
||||
const sourceLines = rawBuild.split('\n')
|
||||
sourceLines.map(line => indicesOf('new Error', line))
|
||||
.forEach((errorIndices, lineIndex) => {
|
||||
// if (errorIndex === null) return console.log('line does not contain "new Error"')
|
||||
errorIndices.forEach((errorIndex) => {
|
||||
const position = { line: lineIndex + 1, column: errorIndex }
|
||||
const result = consumer.originalPositionFor(position)
|
||||
if (!result.source) return console.warn(`!! missing source for position: ${position}`)
|
||||
// filter out deps distributed minified without sourcemaps
|
||||
if (result.source === 'node_modules/browserify/node_modules/browser-pack/_prelude.js') return // minified mess
|
||||
if (result.source === 'node_modules/web3/dist/web3.min.js') return // minified mess
|
||||
const sourceContent = consumer.sourceContentFor(result.source)
|
||||
const sourceLines = sourceContent.split('\n')
|
||||
const line = sourceLines[result.line-1]
|
||||
console.log(`\n========================== ${result.source} ====================================\n`)
|
||||
console.log(line)
|
||||
console.log(`\n==============================================================================\n`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function indicesOf(substring, string) {
|
||||
var a=[],i=-1;
|
||||
while((i=string.indexOf(substring,i+1)) >= 0) a.push(i);
|
||||
return a;
|
||||
}
|
22
gulpfile.js
22
gulpfile.js
@ -247,7 +247,7 @@ gulp.task('dev:scss', createScssBuildTask({
|
||||
src: 'ui/app/css/index.scss',
|
||||
dest: 'ui/app/css/output',
|
||||
devMode: true,
|
||||
pattern: 'ui/app/css/**/*.scss',
|
||||
pattern: 'ui/app/**/*.scss',
|
||||
}))
|
||||
|
||||
function createScssBuildTask({ src, dest, devMode, pattern }) {
|
||||
@ -484,16 +484,6 @@ function generateBundler(opts, performBundle) {
|
||||
NODE_ENV: opts.devMode ? 'development' : 'production',
|
||||
}))
|
||||
|
||||
// Minification
|
||||
if (opts.minifyBuild) {
|
||||
bundler.transform('uglifyify', {
|
||||
global: true,
|
||||
mangle: {
|
||||
reserved: [ 'MetamaskInpageProvider' ]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (opts.watch) {
|
||||
bundler = watchify(bundler)
|
||||
// on any file update, re-runs the bundler
|
||||
@ -567,6 +557,16 @@ function bundleTask(opts) {
|
||||
.pipe(sourcemaps.init({ loadMaps: true }))
|
||||
}
|
||||
|
||||
// Minification
|
||||
if (opts.minifyBuild) {
|
||||
buildStream = buildStream
|
||||
.pipe(uglify({
|
||||
mangle: {
|
||||
reserved: [ 'MetamaskInpageProvider' ]
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
// Finalize Source Maps (writes .map file)
|
||||
if (opts.buildSourceMaps) {
|
||||
buildStream = buildStream
|
||||
|
@ -8,7 +8,6 @@ import Identicon from '../../../../ui/app/components/identicon'
|
||||
import Breadcrumbs from './breadcrumbs'
|
||||
import LoadingScreen from './loading-screen'
|
||||
import { DEFAULT_ROUTE, INITIALIZE_CONFIRM_SEED_ROUTE } from '../../../../ui/app/routes'
|
||||
import { confirmSeedWords } from '../../../../ui/app/actions'
|
||||
|
||||
const LockIcon = props => (
|
||||
<svg
|
||||
@ -45,8 +44,6 @@ class BackupPhraseScreen extends Component {
|
||||
address: PropTypes.string.isRequired,
|
||||
seedWords: PropTypes.string,
|
||||
history: PropTypes.object,
|
||||
isRevealingSeedWords: PropTypes.bool,
|
||||
clearSeedWords: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@ -61,14 +58,6 @@ class BackupPhraseScreen extends Component {
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.checkSeedWords()
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this.checkSeedWords()
|
||||
}
|
||||
|
||||
checkSeedWords () {
|
||||
const { seedWords, history } = this.props
|
||||
|
||||
if (!seedWords) {
|
||||
@ -103,29 +92,9 @@ class BackupPhraseScreen extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderSubmitButton () {
|
||||
const { isRevealingSeedWords, clearSeedWords, history } = this.props
|
||||
const { isShowingSecret } = this.state
|
||||
|
||||
return isRevealingSeedWords
|
||||
? <button
|
||||
className="first-time-flow__button"
|
||||
onClick={() => clearSeedWords().then(() => history.push(DEFAULT_ROUTE))}
|
||||
disabled={!isShowingSecret}
|
||||
>
|
||||
Done
|
||||
</button>
|
||||
: <button
|
||||
className="first-time-flow__button"
|
||||
onClick={() => isShowingSecret && history.push(INITIALIZE_CONFIRM_SEED_ROUTE)}
|
||||
disabled={!isShowingSecret}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
}
|
||||
|
||||
renderSecretScreen () {
|
||||
const { isRevealingSeedWords } = this.props
|
||||
const { isShowingSecret } = this.state
|
||||
const { history } = this.props
|
||||
|
||||
return (
|
||||
<div className="backup-phrase__content-wrapper">
|
||||
@ -152,8 +121,14 @@ class BackupPhraseScreen extends Component {
|
||||
</div>
|
||||
</div>
|
||||
<div className="backup-phrase__next-button">
|
||||
{ this.renderSubmitButton() }
|
||||
{ !isRevealingSeedWords && <Breadcrumbs total={3} currentIndex={1} />}
|
||||
<button
|
||||
className="first-time-flow__button"
|
||||
onClick={() => isShowingSecret && history.push(INITIALIZE_CONFIRM_SEED_ROUTE)}
|
||||
disabled={!isShowingSecret}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
<Breadcrumbs total={3} currentIndex={1} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -175,25 +150,13 @@ class BackupPhraseScreen extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({ metamask, appState }) => {
|
||||
const { selectedAddress, seedWords, isRevealingSeedWords } = metamask
|
||||
const { isLoading } = appState
|
||||
|
||||
return {
|
||||
seedWords,
|
||||
isRevealingSeedWords,
|
||||
isLoading,
|
||||
address: selectedAddress,
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
clearSeedWords: () => dispatch(confirmSeedWords()),
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
connect(
|
||||
({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({
|
||||
seedWords,
|
||||
isLoading,
|
||||
address: selectedAddress,
|
||||
})
|
||||
)
|
||||
)(BackupPhraseScreen)
|
||||
|
@ -16,8 +16,7 @@ const addressSummary = util.addressSummary
|
||||
const nameForAddress = require('../../lib/contract-namer')
|
||||
const BNInput = require('./bn-as-decimal-input')
|
||||
|
||||
// corresponds with 0.1 GWEI
|
||||
const MIN_GAS_PRICE_BN = new BN('100000000')
|
||||
const MIN_GAS_PRICE_BN = new BN('0')
|
||||
const MIN_GAS_LIMIT_BN = new BN('21000')
|
||||
|
||||
module.exports = PendingTx
|
||||
|
@ -138,7 +138,7 @@ ShapeshiftForm.prototype.renderMain = function () {
|
||||
width: '229px',
|
||||
height: '82px',
|
||||
},
|
||||
}, this.props.warning)
|
||||
}, this.props.warning + '')
|
||||
: this.renderInfo(),
|
||||
|
||||
this.renderRefundAddressForCoin(coin),
|
||||
|
238
package-lock.json
generated
238
package-lock.json
generated
@ -2821,6 +2821,20 @@
|
||||
"ieee754": "1.1.8"
|
||||
}
|
||||
},
|
||||
"buffer-alloc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz",
|
||||
"integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=",
|
||||
"requires": {
|
||||
"buffer-alloc-unsafe": "0.1.1",
|
||||
"buffer-fill": "0.1.1"
|
||||
}
|
||||
},
|
||||
"buffer-alloc-unsafe": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz",
|
||||
"integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo="
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
@ -2831,6 +2845,11 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
|
||||
"integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74="
|
||||
},
|
||||
"buffer-fill": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.1.tgz",
|
||||
"integrity": "sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q=="
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
|
||||
@ -3603,6 +3622,14 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
|
||||
"integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"requires": {
|
||||
"amdefine": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4350,7 +4377,7 @@
|
||||
"requires": {
|
||||
"file-type": "5.2.0",
|
||||
"is-stream": "1.1.0",
|
||||
"tar-stream": "1.5.5"
|
||||
"tar-stream": "1.6.0"
|
||||
}
|
||||
},
|
||||
"decompress-tarbz2": {
|
||||
@ -4833,6 +4860,15 @@
|
||||
"string_decoder": "0.10.31"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"amdefine": "1.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
@ -5870,25 +5906,26 @@
|
||||
"resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.0.0.tgz",
|
||||
"integrity": "sha512-Ab6170AxlF4DK+HDImh52+AetwHPHstgg8uWtX4im26rqK7u4ziSfvUIUK2+/LK0pi0wbIFb8hZm5jPKAXDmBA==",
|
||||
"requires": {
|
||||
"eth-json-rpc-middleware": "1.5.0",
|
||||
"eth-json-rpc-middleware": "1.6.0",
|
||||
"json-rpc-engine": "3.6.1",
|
||||
"json-rpc-error": "2.0.0",
|
||||
"tape": "4.8.0"
|
||||
}
|
||||
},
|
||||
"eth-json-rpc-middleware": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.5.0.tgz",
|
||||
"integrity": "sha1-FrEFM4aqOAOxJXMqpt4H6t8Ghyk=",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz",
|
||||
"integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==",
|
||||
"requires": {
|
||||
"async": "2.6.0",
|
||||
"eth-query": "2.1.2",
|
||||
"eth-tx-summary": "3.1.2",
|
||||
"eth-tx-summary": "3.2.1",
|
||||
"ethereumjs-block": "1.7.0",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"ethereumjs-vm": "2.3.2",
|
||||
"fetch-ponyfill": "4.1.0",
|
||||
"json-rpc-engine": "3.6.1",
|
||||
"json-rpc-error": "2.0.0",
|
||||
"json-stable-stringify": "1.0.1",
|
||||
"promise-to-callback": "1.0.0",
|
||||
@ -5896,9 +5933,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz",
|
||||
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"create-hash": "1.1.3",
|
||||
@ -6226,11 +6263,12 @@
|
||||
}
|
||||
},
|
||||
"eth-tx-summary": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.1.2.tgz",
|
||||
"integrity": "sha1-44g2/J+LVvFNdZUvD15XD4j7IiA=",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.1.tgz",
|
||||
"integrity": "sha512-mu8g5tDkQxlFah58ggFhTzolE4OnYTj6j8SVsnGsiWT7WxN722RwnEsk/bco2foy+PLSEF2Mnoiw+wCqKoY72A==",
|
||||
"requires": {
|
||||
"async": "2.6.0",
|
||||
"bn.js": "4.11.8",
|
||||
"clone": "2.1.1",
|
||||
"concat-stream": "1.6.0",
|
||||
"end-of-stream": "1.4.0",
|
||||
@ -6238,12 +6276,46 @@
|
||||
"ethereumjs-block": "1.7.0",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
||||
"ethereumjs-vm": "2.3.2",
|
||||
"ethereumjs-vm": "2.3.5",
|
||||
"through2": "2.0.3",
|
||||
"treeify": "1.1.0",
|
||||
"web3-provider-engine": "13.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-vm": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.5.tgz",
|
||||
"integrity": "sha512-AJ7x44+xqyE5+UO3Nns19WkTdZfyqFZ+sEjIEpvme7Ipbe3iBU1uwCcHEdiu/yY9bdhr3IfSa/NfIKNeXPaRVQ==",
|
||||
"requires": {
|
||||
"async": "2.6.0",
|
||||
"async-eventemitter": "0.2.4",
|
||||
"ethereum-common": "0.2.0",
|
||||
"ethereumjs-account": "2.0.4",
|
||||
"ethereumjs-block": "1.7.0",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"fake-merkle-patricia-tree": "1.0.1",
|
||||
"functional-red-black-tree": "1.0.1",
|
||||
"merkle-patricia-tree": "2.3.0",
|
||||
"rustbn.js": "0.1.1",
|
||||
"safe-buffer": "5.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"create-hash": "1.1.3",
|
||||
"ethjs-util": "0.1.4",
|
||||
"keccak": "1.4.0",
|
||||
"rlp": "2.0.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"secp256k1": "3.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"web3-provider-engine": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz",
|
||||
@ -6255,8 +6327,8 @@
|
||||
"eth-sig-util": "1.4.2",
|
||||
"ethereumjs-block": "1.7.0",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-vm": "2.3.2",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"ethereumjs-vm": "2.3.5",
|
||||
"fetch-ponyfill": "4.1.0",
|
||||
"json-rpc-error": "2.0.0",
|
||||
"json-stable-stringify": "1.0.1",
|
||||
@ -6271,9 +6343,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz",
|
||||
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"create-hash": "1.1.3",
|
||||
@ -7790,6 +7862,11 @@
|
||||
"null-check": "1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||
},
|
||||
"fs-exists-sync": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
|
||||
@ -8871,7 +8948,7 @@
|
||||
"ethereumjs-account": "2.0.4",
|
||||
"ethereumjs-block": "1.2.2",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"ethereumjs-vm": "2.3.3",
|
||||
"ethereumjs-wallet": "0.6.0",
|
||||
"fake-merkle-patricia-tree": "1.0.1",
|
||||
@ -8892,7 +8969,7 @@
|
||||
"tmp": "0.0.31",
|
||||
"web3": "1.0.0-beta.34",
|
||||
"web3-provider-engine": "13.8.0",
|
||||
"websocket": "1.0.25",
|
||||
"websocket": "1.0.26",
|
||||
"yargs": "7.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -8992,9 +9069,9 @@
|
||||
}
|
||||
},
|
||||
"ethereumjs-util": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz",
|
||||
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.6",
|
||||
"create-hash": "1.1.3",
|
||||
@ -9015,7 +9092,7 @@
|
||||
"ethereum-common": "0.2.0",
|
||||
"ethereumjs-account": "2.0.4",
|
||||
"ethereumjs-block": "1.7.1",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"fake-merkle-patricia-tree": "1.0.1",
|
||||
"functional-red-black-tree": "1.0.1",
|
||||
"merkle-patricia-tree": "2.3.0",
|
||||
@ -9036,7 +9113,7 @@
|
||||
"async": "2.6.0",
|
||||
"ethereum-common": "0.2.0",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"merkle-patricia-tree": "2.3.0"
|
||||
}
|
||||
}
|
||||
@ -9174,7 +9251,7 @@
|
||||
"eth-sig-util": "1.4.2",
|
||||
"ethereumjs-block": "1.2.2",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"ethereumjs-vm": "2.3.3",
|
||||
"fetch-ponyfill": "4.1.0",
|
||||
"json-rpc-error": "2.0.0",
|
||||
@ -10422,7 +10499,7 @@
|
||||
"debug-fabulous": "1.0.0",
|
||||
"detect-newline": "2.1.0",
|
||||
"graceful-fs": "4.1.11",
|
||||
"source-map": "0.4.4",
|
||||
"source-map": "0.7.2",
|
||||
"strip-bom-string": "1.0.0",
|
||||
"through2": "2.0.3"
|
||||
},
|
||||
@ -11933,6 +12010,16 @@
|
||||
"integrity": "sha1-Skxd2OT7Xps82mDIIt+tyu5m4K8=",
|
||||
"requires": {
|
||||
"source-map": "0.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"requires": {
|
||||
"amdefine": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"inquirer": {
|
||||
@ -21856,6 +21943,16 @@
|
||||
"requires": {
|
||||
"js-base64": "2.4.3",
|
||||
"source-map": "0.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"requires": {
|
||||
"amdefine": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"secp256k1": {
|
||||
@ -22718,12 +22815,10 @@
|
||||
"integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A=="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"requires": {
|
||||
"amdefine": "1.0.1"
|
||||
}
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.2.tgz",
|
||||
"integrity": "sha512-NDJB/R2BS7YJG0tP9SbE4DKwKj1idLT5RJqfVYZ7dreFX7wulZT3xxVhbYKrQo9n0JkRptl51TrX/5VK3HodMA==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-resolve": {
|
||||
"version": "0.5.1",
|
||||
@ -22920,7 +23015,7 @@
|
||||
"requires": {
|
||||
"esprima": "1.0.4",
|
||||
"estraverse": "1.3.2",
|
||||
"source-map": "0.4.4"
|
||||
"source-map": "0.7.2"
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
@ -24245,13 +24340,16 @@
|
||||
}
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz",
|
||||
"integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.0.tgz",
|
||||
"integrity": "sha512-lh2iAPG/BHNmN6WB9Ybdynk9rEJ5GD/dy4zscHmVlwa1dq2tpE+BH78i5vjYwYVWEaOXGBjzxr89aVACF17Cpw==",
|
||||
"requires": {
|
||||
"bl": "1.2.1",
|
||||
"buffer-alloc": "1.1.0",
|
||||
"end-of-stream": "1.4.0",
|
||||
"fs-constants": "1.0.0",
|
||||
"readable-stream": "2.3.3",
|
||||
"to-buffer": "1.1.1",
|
||||
"xtend": "4.0.1"
|
||||
}
|
||||
},
|
||||
@ -24639,6 +24737,11 @@
|
||||
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
||||
"integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
|
||||
},
|
||||
"to-buffer": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
|
||||
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
|
||||
@ -24972,55 +25075,12 @@
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
|
||||
"integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
|
||||
},
|
||||
"uglify-es": {
|
||||
"version": "3.3.9",
|
||||
"resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
|
||||
"integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.13.0",
|
||||
"source-map": "0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
|
||||
"integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-to-browserify": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
|
||||
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
|
||||
"optional": true
|
||||
},
|
||||
"uglifyify": {
|
||||
"version": "github:MetaMask/uglifyify#8662585e39125a96a5379d71cb4a606829790f87",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"convert-source-map": "1.1.3",
|
||||
"extend": "1.3.0",
|
||||
"minimatch": "3.0.4",
|
||||
"through": "2.3.8",
|
||||
"uglify-es": "3.3.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz",
|
||||
"integrity": "sha1-0VFvsP9WJNLr+RI+odrFoZlABPg=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
|
||||
@ -26284,7 +26344,7 @@
|
||||
"ethereumjs-block": "1.7.0",
|
||||
"ethereumjs-tx": "1.3.3",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-vm": "2.3.4",
|
||||
"ethereumjs-vm": "2.3.5",
|
||||
"json-rpc-error": "2.0.0",
|
||||
"json-stable-stringify": "1.0.1",
|
||||
"promise-to-callback": "1.0.0",
|
||||
@ -26317,7 +26377,7 @@
|
||||
"integrity": "sha512-uMYkEP6fga8CyNo8TMoA/7cxi6bL3V8pTvjKQikOi9iYl6/AO5xlfgniyAMElSiq2mmXz3lYa/9VYDMzt/J5aA==",
|
||||
"requires": {
|
||||
"cross-fetch": "2.1.0",
|
||||
"eth-json-rpc-middleware": "1.5.0",
|
||||
"eth-json-rpc-middleware": "1.6.0",
|
||||
"json-rpc-engine": "3.6.1",
|
||||
"json-rpc-error": "2.0.0",
|
||||
"tape": "4.8.0"
|
||||
@ -26338,9 +26398,9 @@
|
||||
}
|
||||
},
|
||||
"ethereumjs-vm": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz",
|
||||
"integrity": "sha512-Y4SlzNDqxrCO58jhp98HdnZVdjOqB+HC0hoU+N/DEp1aU+hFkRX/nru5F7/HkQRPIlA6aJlQp/xIA6xZs1kspw==",
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.5.tgz",
|
||||
"integrity": "sha512-AJ7x44+xqyE5+UO3Nns19WkTdZfyqFZ+sEjIEpvme7Ipbe3iBU1uwCcHEdiu/yY9bdhr3IfSa/NfIKNeXPaRVQ==",
|
||||
"requires": {
|
||||
"async": "2.6.0",
|
||||
"async-eventemitter": "0.2.4",
|
||||
@ -27017,9 +27077,9 @@
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"version": "1.0.25",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.25.tgz",
|
||||
"integrity": "sha512-M58njvi6ZxVb5k7kpnHh2BvNKuBWiwIYvsToErBzWhvBZYwlEiLcyLrG41T1jRcrY9ettqPYEqduLI7ul54CVQ==",
|
||||
"version": "1.0.26",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.26.tgz",
|
||||
"integrity": "sha512-fjcrYDPIQxpTnqFQ9JjxUQcdvR89MFAOjPBlF+vjOt49w/XW4fJknUoMz/mDIn2eK1AdslVojcaOxOqyZZV8rw==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"nan": "2.8.0",
|
||||
|
@ -217,9 +217,10 @@
|
||||
"eslint-plugin-json": "^1.2.0",
|
||||
"eslint-plugin-mocha": "^5.0.0",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"eth-json-rpc-middleware": "^1.2.7",
|
||||
"eth-json-rpc-middleware": "^1.6.0",
|
||||
"fs-promise": "^2.0.3",
|
||||
"ganache-cli": "^6.1.0",
|
||||
"ganache-core": "^2.1.0",
|
||||
"gifencoder": "^1.1.0",
|
||||
"gulp": "github:gulpjs/gulp#6d71a658c61edb3090221579d8f97dbe086ba2ed",
|
||||
"gulp-babel": "^7.0.0",
|
||||
@ -269,10 +270,10 @@
|
||||
"selenium-webdriver": "^3.5.0",
|
||||
"shell-parallel": "^1.0.3",
|
||||
"sinon": "^5.0.0",
|
||||
"source-map": "^0.7.2",
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"tape": "^4.5.1",
|
||||
"testem": "^2.0.0",
|
||||
"uglifyify": "github:MetaMask/uglifyify#keep-flags",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vinyl-source-stream": "^2.0.0",
|
||||
"watchify": "^3.9.0"
|
||||
|
@ -23,6 +23,37 @@ global.ethQuery = {
|
||||
|
||||
global.ethereumProvider = {}
|
||||
|
||||
async function customizeGas (assert, price, limit, ethFee, usdFee) {
|
||||
const sendGasOpenCustomizeModalButton = await queryAsync($, '.sliders-icon-container')
|
||||
sendGasOpenCustomizeModalButton[0].click()
|
||||
|
||||
const customizeGasModal = await queryAsync($, '.send-v2__customize-gas')
|
||||
assert.ok(customizeGasModal[0], 'should render the customize gas modal')
|
||||
|
||||
const customizeGasPriceInput = (await queryAsync($, '.send-v2__gas-modal-card')).first().find('input')
|
||||
customizeGasPriceInput.val(price)
|
||||
reactTriggerChange(customizeGasPriceInput[0])
|
||||
const customizeGasLimitInput = (await queryAsync($, '.send-v2__gas-modal-card')).last().find('input')
|
||||
customizeGasLimitInput.val(limit)
|
||||
reactTriggerChange(customizeGasLimitInput[0])
|
||||
|
||||
const customizeGasSaveButton = await queryAsync($, '.send-v2__customize-gas__save')
|
||||
customizeGasSaveButton[0].click()
|
||||
const sendGasField = await queryAsync($, '.send-v2__gas-fee-display')
|
||||
|
||||
assert.equal(
|
||||
(await findAsync(sendGasField, '.currency-display__input-wrapper > input')).val(),
|
||||
ethFee,
|
||||
'send gas field should show customized gas total'
|
||||
)
|
||||
|
||||
assert.equal(
|
||||
(await findAsync(sendGasField, '.currency-display__converted-value'))[0].textContent,
|
||||
usdFee,
|
||||
'send gas field should show customized gas total converted to USD'
|
||||
)
|
||||
}
|
||||
|
||||
async function runSendFlowTest(assert, done) {
|
||||
console.log('*** start runSendFlowTest')
|
||||
const selectState = await queryAsync($, 'select')
|
||||
@ -95,32 +126,8 @@ async function runSendFlowTest(assert, done) {
|
||||
'send gas field should show estimated gas total converted to USD'
|
||||
)
|
||||
|
||||
const sendGasOpenCustomizeModalButton = await queryAsync($, '.sliders-icon-container')
|
||||
sendGasOpenCustomizeModalButton[0].click()
|
||||
|
||||
const customizeGasModal = await queryAsync($, '.send-v2__customize-gas')
|
||||
assert.ok(customizeGasModal[0], 'should render the customize gas modal')
|
||||
|
||||
const customizeGasPriceInput = (await queryAsync($, '.send-v2__gas-modal-card')).first().find('input')
|
||||
customizeGasPriceInput.val(50)
|
||||
reactTriggerChange(customizeGasPriceInput[0])
|
||||
const customizeGasLimitInput = (await queryAsync($, '.send-v2__gas-modal-card')).last().find('input')
|
||||
customizeGasLimitInput.val(60000)
|
||||
reactTriggerChange(customizeGasLimitInput[0])
|
||||
|
||||
const customizeGasSaveButton = await queryAsync($, '.send-v2__customize-gas__save')
|
||||
customizeGasSaveButton[0].click()
|
||||
|
||||
assert.equal(
|
||||
(await findAsync(sendGasField, '.currency-display__input-wrapper > input')).val(),
|
||||
'0.003',
|
||||
'send gas field should show customized gas total'
|
||||
)
|
||||
assert.equal(
|
||||
(await findAsync(sendGasField, '.currency-display__converted-value'))[0].textContent,
|
||||
'$3.60 USD',
|
||||
'send gas field should show customized gas total converted to USD'
|
||||
)
|
||||
await customizeGas(assert, 0, 21000, '0', '$0.00 USD')
|
||||
await customizeGas(assert, 500, 60000, '0.003', '$3.60 USD')
|
||||
|
||||
const sendButton = await queryAsync($, 'button.btn-primary--lg.page-container__footer-button')
|
||||
assert.equal(sendButton[0].textContent, 'Next', 'next button rendered')
|
||||
|
@ -1,14 +1,28 @@
|
||||
const JsonRpcEngine = require('json-rpc-engine')
|
||||
const scaffoldMiddleware = require('eth-json-rpc-middleware/scaffold')
|
||||
const TestBlockchain = require('eth-block-tracker/test/util/testBlockMiddleware')
|
||||
const providerAsMiddleware = require('eth-json-rpc-middleware/providerAsMiddleware')
|
||||
const GanacheCore = require('ganache-core')
|
||||
|
||||
module.exports = {
|
||||
createEngineForTestData,
|
||||
providerFromEngine,
|
||||
scaffoldMiddleware,
|
||||
createTestProviderTools,
|
||||
getTestSeed,
|
||||
getTestAccounts,
|
||||
}
|
||||
|
||||
function getTestSeed () {
|
||||
return 'people carpet cluster attract ankle motor ozone mass dove original primary mask'
|
||||
}
|
||||
|
||||
function getTestAccounts () {
|
||||
return [
|
||||
{ address: '0x88bb7F89eB5e5b30D3e15a57C68DBe03C6aCCB21', key: Buffer.from('254A8D551474F35CCC816388B4ED4D20B945C96B7EB857A68064CB9E9FB2C092', 'hex') },
|
||||
{ address: '0x1fe9aAB565Be19629fF4e8541ca2102fb42D7724', key: Buffer.from('6BAB5A4F2A6911AF8EE2BD32C6C05F6643AC48EF6C939CDEAAAE6B1620805A9B', 'hex') },
|
||||
{ address: '0xbda5c89aa6bA1b352194291AD6822C92AbC87c7B', key: Buffer.from('9B11D7F833648F26CE94D544855558D7053ECD396E4F4563968C232C012879B0', 'hex') },
|
||||
]
|
||||
}
|
||||
|
||||
function createEngineForTestData () {
|
||||
return new JsonRpcEngine()
|
||||
@ -21,11 +35,13 @@ function providerFromEngine (engine) {
|
||||
|
||||
function createTestProviderTools (opts = {}) {
|
||||
const engine = createEngineForTestData()
|
||||
const testBlockchain = new TestBlockchain()
|
||||
// handle provided hooks
|
||||
engine.push(scaffoldMiddleware(opts.scaffold || {}))
|
||||
// handle block tracker methods
|
||||
engine.push(testBlockchain.createMiddleware())
|
||||
engine.push(providerAsMiddleware(GanacheCore.provider({
|
||||
mnemonic: getTestSeed(),
|
||||
})))
|
||||
// wrap in standard provider interface
|
||||
const provider = providerFromEngine(engine)
|
||||
return { provider, engine, testBlockchain }
|
||||
return { provider, engine }
|
||||
}
|
||||
|
@ -6,6 +6,12 @@ const MetaMaskController = require('../../app/scripts/metamask-controller')
|
||||
const blacklistJSON = require('../stub/blacklist')
|
||||
const firstTimeState = require('../../app/scripts/first-time-state')
|
||||
|
||||
const DEFAULT_LABEL = 'Account 1'
|
||||
const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
|
||||
const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
|
||||
const TEST_SEED_ALT = 'setup olympic issue mobile velvet surge alcohol burger horse view reopen gentle'
|
||||
const TEST_ADDRESS_ALT = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'
|
||||
|
||||
describe('MetaMaskController', function () {
|
||||
let metamaskController
|
||||
const sandbox = sinon.sandbox.create()
|
||||
@ -87,17 +93,28 @@ describe('MetaMaskController', function () {
|
||||
|
||||
describe('#createNewVaultAndRestore', function () {
|
||||
it('should be able to call newVaultAndRestore despite a mistake.', async function () {
|
||||
|
||||
const password = 'what-what-what'
|
||||
const wrongSeed = 'debris dizzy just program just float decrease vacant alarm reduce speak stadiu'
|
||||
const rightSeed = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
|
||||
await metamaskController.createNewVaultAndRestore(password, wrongSeed)
|
||||
.catch((e) => {
|
||||
return
|
||||
})
|
||||
await metamaskController.createNewVaultAndRestore(password, rightSeed)
|
||||
await metamaskController.createNewVaultAndRestore(password, TEST_SEED.slice(0, -1)).catch((e) => null)
|
||||
await metamaskController.createNewVaultAndRestore(password, TEST_SEED)
|
||||
|
||||
assert(metamaskController.keyringController.createNewVaultAndRestore.calledTwice)
|
||||
})
|
||||
|
||||
it('should clear previous identities after vault restoration', async () => {
|
||||
await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED)
|
||||
assert.deepEqual(metamaskController.getState().identities, {
|
||||
[TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL },
|
||||
})
|
||||
|
||||
await metamaskController.keyringController.saveAccountLabel(TEST_ADDRESS, 'Account Foo')
|
||||
assert.deepEqual(metamaskController.getState().identities, {
|
||||
[TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' },
|
||||
})
|
||||
|
||||
await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT)
|
||||
assert.deepEqual(metamaskController.getState().identities, {
|
||||
[TEST_ADDRESS_ALT]: { address: TEST_ADDRESS_ALT, name: DEFAULT_LABEL },
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -6,16 +6,15 @@ const ObservableStore = require('obs-store')
|
||||
const sinon = require('sinon')
|
||||
const TransactionController = require('../../app/scripts/controllers/transactions')
|
||||
const TxGasUtils = require('../../app/scripts/controllers/transactions/tx-gas-utils')
|
||||
const { createTestProviderTools } = require('../stub/provider')
|
||||
const { createTestProviderTools, getTestAccounts } = require('../stub/provider')
|
||||
|
||||
const noop = () => true
|
||||
const currentNetworkId = 42
|
||||
const otherNetworkId = 36
|
||||
const privKey = new Buffer('8718b9618a37d1fc78c436511fc6df3c8258d3250635bba617f33003270ec03e', 'hex')
|
||||
|
||||
|
||||
describe('Transaction Controller', function () {
|
||||
let txController, provider, providerResultStub, testBlockchain
|
||||
let txController, provider, providerResultStub, query, fromAccount
|
||||
|
||||
beforeEach(function () {
|
||||
providerResultStub = {
|
||||
@ -24,9 +23,9 @@ describe('Transaction Controller', function () {
|
||||
// by default, all accounts are external accounts (not contracts)
|
||||
eth_getCode: '0x',
|
||||
}
|
||||
const providerTools = createTestProviderTools({ scaffold: providerResultStub })
|
||||
provider = providerTools.provider
|
||||
testBlockchain = providerTools.testBlockchain
|
||||
provider = createTestProviderTools({ scaffold: providerResultStub }).provider
|
||||
query = new EthjsQuery(provider)
|
||||
fromAccount = getTestAccounts()[0]
|
||||
|
||||
txController = new TransactionController({
|
||||
provider,
|
||||
@ -34,7 +33,7 @@ describe('Transaction Controller', function () {
|
||||
txHistoryLimit: 10,
|
||||
blockTracker: { getCurrentBlock: noop, on: noop, once: noop },
|
||||
signTransaction: (ethTx) => new Promise((resolve) => {
|
||||
ethTx.sign(privKey)
|
||||
ethTx.sign(fromAccount.key)
|
||||
resolve()
|
||||
}),
|
||||
})
|
||||
@ -298,12 +297,12 @@ describe('Transaction Controller', function () {
|
||||
|
||||
describe('#updateAndApproveTransaction', function () {
|
||||
let txMeta
|
||||
beforeEach(function () {
|
||||
beforeEach(() => {
|
||||
txMeta = {
|
||||
id: 1,
|
||||
status: 'unapproved',
|
||||
txParams: {
|
||||
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
|
||||
from: fromAccount.address,
|
||||
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
gasPrice: '0x77359400',
|
||||
gas: '0x7b0d',
|
||||
@ -312,11 +311,12 @@ describe('Transaction Controller', function () {
|
||||
metamaskNetworkId: currentNetworkId,
|
||||
}
|
||||
})
|
||||
it('should update and approve transactions', function () {
|
||||
it('should update and approve transactions', async () => {
|
||||
txController.txStateManager.addTx(txMeta)
|
||||
txController.updateAndApproveTransaction(txMeta)
|
||||
const approvalPromise = txController.updateAndApproveTransaction(txMeta)
|
||||
const tx = txController.txStateManager.getTx(1)
|
||||
assert.equal(tx.status, 'approved')
|
||||
await approvalPromise
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -95,4 +95,4 @@ describe('txUtils', function () {
|
||||
txUtils.validateFrom(txParams)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -83,7 +83,7 @@ var actions = {
|
||||
REVEAL_SEED_CONFIRMATION: 'REVEAL_SEED_CONFIRMATION',
|
||||
revealSeedConfirmation: revealSeedConfirmation,
|
||||
requestRevealSeed: requestRevealSeed,
|
||||
|
||||
requestRevealSeedWords,
|
||||
// unlock screen
|
||||
UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS',
|
||||
UNLOCK_FAILED: 'UNLOCK_FAILED',
|
||||
@ -345,11 +345,13 @@ function transitionBackward () {
|
||||
}
|
||||
}
|
||||
|
||||
function clearSeedWordCache () {
|
||||
log.debug(`background.clearSeedWordCache`)
|
||||
function confirmSeedWords () {
|
||||
return dispatch => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
log.debug(`background.clearSeedWordCache`)
|
||||
return new Promise((resolve, reject) => {
|
||||
background.clearSeedWordCache((err, account) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
dispatch(actions.displayWarning(err.message))
|
||||
return reject(err)
|
||||
@ -363,22 +365,6 @@ function clearSeedWordCache () {
|
||||
}
|
||||
}
|
||||
|
||||
function confirmSeedWords () {
|
||||
return async dispatch => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
const account = await dispatch(clearSeedWordCache())
|
||||
return dispatch(setIsRevealingSeedWords(false))
|
||||
.then(() => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
return account
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
return account
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function createNewVaultAndRestore (password, seed) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
@ -441,6 +427,30 @@ function revealSeedConfirmation () {
|
||||
}
|
||||
}
|
||||
|
||||
function verifyPassword (password) {
|
||||
return new Promise((resolve, reject) => {
|
||||
background.submitPassword(password, error => {
|
||||
if (error) {
|
||||
return reject(error)
|
||||
}
|
||||
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function verifySeedPhrase () {
|
||||
return new Promise((resolve, reject) => {
|
||||
background.verifySeedPhrase((error, seedWords) => {
|
||||
if (error) {
|
||||
return reject(error)
|
||||
}
|
||||
|
||||
resolve(seedWords)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function requestRevealSeed (password) {
|
||||
return dispatch => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
@ -460,13 +470,29 @@ function requestRevealSeed (password) {
|
||||
}
|
||||
|
||||
dispatch(actions.showNewVaultSeed(result))
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
.then(() => dispatch(setIsRevealingSeedWords(true)))
|
||||
.then(() => dispatch(actions.hideLoadingIndication()))
|
||||
.catch(() => dispatch(actions.hideLoadingIndication()))
|
||||
}
|
||||
}
|
||||
|
||||
function requestRevealSeedWords (password) {
|
||||
return async dispatch => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
log.debug(`background.submitPassword`)
|
||||
|
||||
try {
|
||||
await verifyPassword(password)
|
||||
const seedWords = await verifySeedPhrase()
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
return seedWords
|
||||
} catch (error) {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
dispatch(actions.displayWarning(error.message))
|
||||
throw new Error(error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1923,11 +1949,3 @@ function updateNetworkEndpointType (networkEndpointType) {
|
||||
value: networkEndpointType,
|
||||
}
|
||||
}
|
||||
|
||||
function setIsRevealingSeedWords (reveal) {
|
||||
return dispatch => {
|
||||
log.debug(`background.setIsRevealingSeedWords`)
|
||||
background.setIsRevealingSeedWords(reveal)
|
||||
return forceUpdateMetamaskState(dispatch)
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ const Initialized = require('./components/pages/initialized')
|
||||
const Settings = require('./components/pages/settings')
|
||||
const UnlockPage = require('./components/pages/unlock')
|
||||
const RestoreVaultPage = require('./components/pages/keychains/restore-vault')
|
||||
const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation')
|
||||
const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed')
|
||||
const AddTokenPage = require('./components/pages/add-token')
|
||||
const CreateAccountPage = require('./components/pages/create-account')
|
||||
const NoticeScreen = require('./components/pages/notice')
|
||||
@ -56,20 +56,11 @@ const {
|
||||
|
||||
class App extends Component {
|
||||
componentWillMount () {
|
||||
const {
|
||||
currentCurrency,
|
||||
setCurrentCurrencyToUSD,
|
||||
isRevealingSeedWords,
|
||||
clearSeedWords,
|
||||
} = this.props
|
||||
const { currentCurrency, setCurrentCurrencyToUSD } = this.props
|
||||
|
||||
if (!currentCurrency) {
|
||||
setCurrentCurrencyToUSD()
|
||||
}
|
||||
|
||||
if (isRevealingSeedWords) {
|
||||
clearSeedWords()
|
||||
}
|
||||
}
|
||||
|
||||
renderRoutes () {
|
||||
@ -402,8 +393,6 @@ App.propTypes = {
|
||||
isMouseUser: PropTypes.bool,
|
||||
setMouseUserState: PropTypes.func,
|
||||
t: PropTypes.func,
|
||||
isRevealingSeedWords: PropTypes.bool,
|
||||
clearSeedWords: PropTypes.func,
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
@ -484,7 +473,6 @@ function mapDispatchToProps (dispatch, ownProps) {
|
||||
setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
|
||||
toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
|
||||
setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)),
|
||||
clearSeedWords: () => dispatch(actions.confirmSeedWords()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,8 +280,7 @@ CustomizeGasModal.prototype.render = function () {
|
||||
h(GasModalCard, {
|
||||
value: convertedGasPrice,
|
||||
min: forceGasMin || MIN_GAS_PRICE_GWEI,
|
||||
// max: 1000,
|
||||
step: multiplyCurrencies(MIN_GAS_PRICE_GWEI, 10),
|
||||
step: 1,
|
||||
onChange: value => this.convertAndSetGasPrice(value),
|
||||
title: this.context.t('gasPrice'),
|
||||
copy: this.context.t('gasPriceCalculation'),
|
||||
@ -290,7 +289,6 @@ CustomizeGasModal.prototype.render = function () {
|
||||
h(GasModalCard, {
|
||||
value: convertedGasLimit,
|
||||
min: 1,
|
||||
// max: 100000,
|
||||
step: 1,
|
||||
onChange: value => this.convertAndSetGasLimit(value),
|
||||
title: this.context.t('gasLimit'),
|
||||
|
@ -0,0 +1,45 @@
|
||||
const { Component } = require('react')
|
||||
const PropTypes = require('prop-types')
|
||||
const h = require('react-hyperscript')
|
||||
const copyToClipboard = require('copy-to-clipboard')
|
||||
const { exportAsFile } = require('../../util')
|
||||
|
||||
class ExportTextContainer extends Component {
|
||||
render () {
|
||||
const { text = '', filename = '' } = this.props
|
||||
const { t } = this.context
|
||||
|
||||
return (
|
||||
h('.export-text-container', [
|
||||
h('.export-text-container__text-container', [
|
||||
h('.export-text-container__text', text),
|
||||
]),
|
||||
h('.export-text-container__buttons-container', [
|
||||
h('.export-text-container__button.export-text-container__button--copy', {
|
||||
onClick: () => copyToClipboard(text),
|
||||
}, [
|
||||
h('img', { src: 'images/copy-to-clipboard.svg' }),
|
||||
h('.export-text-container__button-text', t('copyToClipboard')),
|
||||
]),
|
||||
h('.export-text-container__button', {
|
||||
onClick: () => exportAsFile(filename, text),
|
||||
}, [
|
||||
h('img', { src: 'images/download.svg' }),
|
||||
h('.export-text-container__button-text', t('saveAsCsvFile')),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ExportTextContainer.propTypes = {
|
||||
text: PropTypes.string,
|
||||
filename: PropTypes.string,
|
||||
}
|
||||
|
||||
ExportTextContainer.contextTypes = {
|
||||
t: PropTypes.func,
|
||||
}
|
||||
|
||||
module.exports = ExportTextContainer
|
@ -0,0 +1,52 @@
|
||||
.export-text-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border: 1px solid $alto;
|
||||
border-radius: 4px;
|
||||
font-weight: 400;
|
||||
|
||||
&__text-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
background: $alabaster;
|
||||
}
|
||||
|
||||
&__text {
|
||||
resize: none;
|
||||
border: none;
|
||||
background: $alabaster;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__buttons-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-top: 1px solid $alto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__button {
|
||||
padding: 10px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: $curious-blue;
|
||||
|
||||
&--copy {
|
||||
border-right: 1px solid $alto;
|
||||
}
|
||||
}
|
||||
|
||||
&__button-text {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
2
ui/app/components/export-text-container/index.js
Normal file
2
ui/app/components/export-text-container/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
const ExportTextContainer = require('./export-text-container.component')
|
||||
module.exports = ExportTextContainer
|
@ -192,7 +192,7 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address)
|
||||
if (symbol && decimals) {
|
||||
this.setState({
|
||||
customSymbol: symbol,
|
||||
customDecimals: decimals.toString(),
|
||||
customDecimals: decimals,
|
||||
autoFilled: true,
|
||||
})
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ const QrView = require('../../components/qr-code')
|
||||
|
||||
// Routes
|
||||
const {
|
||||
REVEAL_SEED_ROUTE,
|
||||
INITIALIZE_BACKUP_PHRASE_ROUTE,
|
||||
RESTORE_VAULT_ROUTE,
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
NOTICE_ROUTE,
|
||||
@ -69,7 +69,7 @@ class Home extends Component {
|
||||
log.debug('rendering seed words')
|
||||
return h(Redirect, {
|
||||
to: {
|
||||
pathname: REVEAL_SEED_ROUTE,
|
||||
pathname: INITIALIZE_BACKUP_PHRASE_ROUTE,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -2,11 +2,27 @@ const { Component } = require('react')
|
||||
const { connect } = require('react-redux')
|
||||
const PropTypes = require('prop-types')
|
||||
const h = require('react-hyperscript')
|
||||
const { exportAsFile } = require('../../../util')
|
||||
const { requestRevealSeed, confirmSeedWords } = require('../../../actions')
|
||||
const classnames = require('classnames')
|
||||
|
||||
const { requestRevealSeedWords } = require('../../../actions')
|
||||
const { DEFAULT_ROUTE } = require('../../../routes')
|
||||
const ExportTextContainer = require('../../export-text-container')
|
||||
|
||||
const PASSWORD_PROMPT_SCREEN = 'PASSWORD_PROMPT_SCREEN'
|
||||
const REVEAL_SEED_SCREEN = 'REVEAL_SEED_SCREEN'
|
||||
|
||||
class RevealSeedPage extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
screen: PASSWORD_PROMPT_SCREEN,
|
||||
password: '',
|
||||
seedWords: null,
|
||||
error: null,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const passwordBox = document.getElementById('password-box')
|
||||
if (passwordBox) {
|
||||
@ -14,182 +30,135 @@ class RevealSeedPage extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
checkConfirmation (event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
this.revealSeedWords()
|
||||
}
|
||||
handleSubmit (event) {
|
||||
event.preventDefault()
|
||||
this.setState({ seedWords: null, error: null })
|
||||
this.props.requestRevealSeedWords(this.state.password)
|
||||
.then(seedWords => this.setState({ seedWords, screen: REVEAL_SEED_SCREEN }))
|
||||
.catch(error => this.setState({ error: error.message }))
|
||||
}
|
||||
|
||||
revealSeedWords () {
|
||||
const password = document.getElementById('password-box').value
|
||||
this.props.requestRevealSeed(password)
|
||||
}
|
||||
|
||||
renderSeed () {
|
||||
const { seedWords, confirmSeedWords, history } = this.props
|
||||
|
||||
renderWarning () {
|
||||
return (
|
||||
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||
|
||||
h('h3.flex-center.text-transform-uppercase', {
|
||||
style: {
|
||||
background: '#EBEBEB',
|
||||
color: '#AEAEAE',
|
||||
marginTop: 36,
|
||||
marginBottom: 8,
|
||||
width: '100%',
|
||||
fontSize: '20px',
|
||||
padding: 6,
|
||||
},
|
||||
}, [
|
||||
'Vault Created',
|
||||
]),
|
||||
|
||||
h('div', {
|
||||
style: {
|
||||
fontSize: '1em',
|
||||
marginTop: '10px',
|
||||
textAlign: 'center',
|
||||
},
|
||||
}, [
|
||||
h('span.error', 'These 12 words are the only way to restore your MetaMask accounts.\nSave them somewhere safe and secret.'),
|
||||
]),
|
||||
|
||||
h('textarea.twelve-word-phrase', {
|
||||
readOnly: true,
|
||||
value: seedWords,
|
||||
h('.page-container__warning-container', [
|
||||
h('img.page-container__warning-icon', {
|
||||
src: 'images/warning.svg',
|
||||
}),
|
||||
|
||||
h('button.primary', {
|
||||
onClick: () => confirmSeedWords().then(() => history.push(DEFAULT_ROUTE)),
|
||||
style: {
|
||||
margin: '24px',
|
||||
fontSize: '0.9em',
|
||||
marginBottom: '10px',
|
||||
},
|
||||
}, 'I\'ve copied it somewhere safe'),
|
||||
|
||||
h('button.primary', {
|
||||
onClick: () => exportAsFile(`MetaMask Seed Words`, seedWords),
|
||||
style: {
|
||||
margin: '10px',
|
||||
fontSize: '0.9em',
|
||||
},
|
||||
}, 'Save Seed Words As File'),
|
||||
h('.page-container__warning-message', [
|
||||
h('.page-container__warning-title', [this.context.t('revealSeedWordsWarningTitle')]),
|
||||
h('div', [this.context.t('revealSeedWordsWarning')]),
|
||||
]),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
renderConfirmation () {
|
||||
const { history, warning, inProgress } = this.props
|
||||
renderContent () {
|
||||
return this.state.screen === PASSWORD_PROMPT_SCREEN
|
||||
? this.renderPasswordPromptContent()
|
||||
: this.renderRevealSeedContent()
|
||||
}
|
||||
|
||||
renderPasswordPromptContent () {
|
||||
const { t } = this.context
|
||||
|
||||
return (
|
||||
h('.initialize-screen.flex-column.flex-center.flex-grow', {
|
||||
style: { maxWidth: '420px' },
|
||||
h('form', {
|
||||
onSubmit: event => this.handleSubmit(event),
|
||||
}, [
|
||||
|
||||
h('h3.flex-center.text-transform-uppercase', {
|
||||
style: {
|
||||
background: '#EBEBEB',
|
||||
color: '#AEAEAE',
|
||||
marginBottom: 24,
|
||||
width: '100%',
|
||||
fontSize: '20px',
|
||||
padding: 6,
|
||||
},
|
||||
}, [
|
||||
'Reveal Seed Words',
|
||||
]),
|
||||
|
||||
h('.div', {
|
||||
style: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '20px',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
}, [
|
||||
|
||||
h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'),
|
||||
|
||||
// confirmation
|
||||
h('input.large-input.letter-spacey', {
|
||||
h('label.input-label', {
|
||||
htmlFor: 'password-box',
|
||||
}, t('enterPasswordContinue')),
|
||||
h('.input-group', [
|
||||
h('input.form-control', {
|
||||
type: 'password',
|
||||
placeholder: t('password'),
|
||||
id: 'password-box',
|
||||
placeholder: 'Enter your password to confirm',
|
||||
onKeyPress: this.checkConfirmation.bind(this),
|
||||
style: {
|
||||
width: 260,
|
||||
marginTop: '12px',
|
||||
},
|
||||
value: this.state.password,
|
||||
onChange: event => this.setState({ password: event.target.value }),
|
||||
className: classnames({ 'form-control--error': this.state.error }),
|
||||
}),
|
||||
|
||||
h('.flex-row.flex-start', {
|
||||
style: {
|
||||
marginTop: 30,
|
||||
width: '50%',
|
||||
},
|
||||
}, [
|
||||
// cancel
|
||||
h('button.primary', {
|
||||
onClick: () => history.push(DEFAULT_ROUTE),
|
||||
}, 'CANCEL'),
|
||||
|
||||
// submit
|
||||
h('button.primary', {
|
||||
style: { marginLeft: '10px' },
|
||||
onClick: this.revealSeedWords.bind(this),
|
||||
}, 'OK'),
|
||||
|
||||
]),
|
||||
|
||||
warning && (
|
||||
h('span.error', {
|
||||
style: {
|
||||
margin: '20px',
|
||||
},
|
||||
}, warning.split('-'))
|
||||
),
|
||||
|
||||
inProgress && (
|
||||
h('span.in-progress-notification', 'Generating Seed...')
|
||||
),
|
||||
]),
|
||||
this.state.error && h('.reveal-seed__error', this.state.error),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
renderRevealSeedContent () {
|
||||
const { t } = this.context
|
||||
|
||||
return (
|
||||
h('div', [
|
||||
h('label.reveal-seed__label', t('yourPrivateSeedPhrase')),
|
||||
h(ExportTextContainer, {
|
||||
text: this.state.seedWords,
|
||||
filename: t('metamaskSeedWords'),
|
||||
}),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
renderFooter () {
|
||||
return this.state.screen === PASSWORD_PROMPT_SCREEN
|
||||
? this.renderPasswordPromptFooter()
|
||||
: this.renderRevealSeedFooter()
|
||||
}
|
||||
|
||||
renderPasswordPromptFooter () {
|
||||
return (
|
||||
h('.page-container__footer', [
|
||||
h('button.btn-secondary--lg.page-container__footer-button', {
|
||||
onClick: () => this.props.history.push(DEFAULT_ROUTE),
|
||||
}, this.context.t('cancel')),
|
||||
h('button.btn-primary--lg.page-container__footer-button', {
|
||||
onClick: event => this.handleSubmit(event),
|
||||
disabled: this.state.password === '',
|
||||
}, this.context.t('next')),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
renderRevealSeedFooter () {
|
||||
return (
|
||||
h('.page-container__footer', [
|
||||
h('button.btn-secondary--lg.page-container__footer-button', {
|
||||
onClick: () => this.props.history.push(DEFAULT_ROUTE),
|
||||
}, this.context.t('close')),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
return this.props.seedWords
|
||||
? this.renderSeed()
|
||||
: this.renderConfirmation()
|
||||
return (
|
||||
h('.page-container', [
|
||||
h('.page-container__header', [
|
||||
h('.page-container__title', this.context.t('revealSeedWordsTitle')),
|
||||
h('.page-container__subtitle', this.context.t('revealSeedWordsDescription')),
|
||||
]),
|
||||
h('.page-container__content', [
|
||||
this.renderWarning(),
|
||||
h('.reveal-seed__content', [
|
||||
this.renderContent(),
|
||||
]),
|
||||
]),
|
||||
this.renderFooter(),
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
RevealSeedPage.propTypes = {
|
||||
requestRevealSeed: PropTypes.func,
|
||||
confirmSeedWords: PropTypes.func,
|
||||
seedWords: PropTypes.string,
|
||||
inProgress: PropTypes.bool,
|
||||
requestRevealSeedWords: PropTypes.func,
|
||||
history: PropTypes.object,
|
||||
warning: PropTypes.string,
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const { appState: { warning }, metamask: { seedWords } } = state
|
||||
|
||||
return {
|
||||
warning,
|
||||
seedWords,
|
||||
}
|
||||
RevealSeedPage.contextTypes = {
|
||||
t: PropTypes.func,
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
requestRevealSeed: password => dispatch(requestRevealSeed(password)),
|
||||
confirmSeedWords: () => dispatch(confirmSeedWords()),
|
||||
requestRevealSeedWords: password => dispatch(requestRevealSeedWords(password)),
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(RevealSeedPage)
|
||||
module.exports = connect(null, mapDispatchToProps)(RevealSeedPage)
|
||||
|
@ -8,7 +8,7 @@ const abiDecoder = require('abi-decoder')
|
||||
abiDecoder.addABI(abi)
|
||||
const inherits = require('util').inherits
|
||||
const actions = require('../../actions')
|
||||
const util = require('../../util')
|
||||
const { getSymbolAndDecimals } = require('../../token-util')
|
||||
const ConfirmSendEther = require('./confirm-send-ether')
|
||||
const ConfirmSendToken = require('./confirm-send-token')
|
||||
const ConfirmDeployContract = require('./confirm-deploy-contract')
|
||||
@ -26,6 +26,7 @@ function mapStateToProps (state) {
|
||||
const {
|
||||
conversionRate,
|
||||
identities,
|
||||
tokens: existingTokens,
|
||||
} = state.metamask
|
||||
const accounts = state.metamask.accounts
|
||||
const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
|
||||
@ -33,6 +34,7 @@ function mapStateToProps (state) {
|
||||
conversionRate,
|
||||
identities,
|
||||
selectedAddress,
|
||||
existingTokens,
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +68,7 @@ PendingTx.prototype.componentDidUpdate = function (prevProps, prevState) {
|
||||
}
|
||||
|
||||
PendingTx.prototype.setTokenData = async function () {
|
||||
const { existingTokens } = this.props
|
||||
const txMeta = this.gatherTxMeta()
|
||||
const txParams = txMeta.txParams || {}
|
||||
|
||||
@ -89,30 +92,15 @@ PendingTx.prototype.setTokenData = async function () {
|
||||
}
|
||||
|
||||
if (isTokenTransaction) {
|
||||
const token = util.getContractAtAddress(txParams.to)
|
||||
const results = await Promise.all([
|
||||
token.symbol(),
|
||||
token.decimals(),
|
||||
])
|
||||
const [ symbol, decimals ] = results
|
||||
const { symbol, decimals } = await getSymbolAndDecimals(txParams.to, existingTokens)
|
||||
|
||||
if (symbol[0] && decimals[0]) {
|
||||
this.setState({
|
||||
transactionType: TX_TYPES.SEND_TOKEN,
|
||||
tokenAddress: txParams.to,
|
||||
tokenSymbol: symbol[0],
|
||||
tokenDecimals: decimals[0],
|
||||
isFetching: false,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
transactionType: TX_TYPES.SEND_TOKEN,
|
||||
tokenAddress: txParams.to,
|
||||
tokenSymbol: null,
|
||||
tokenDecimals: null,
|
||||
isFetching: false,
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
transactionType: TX_TYPES.SEND_TOKEN,
|
||||
tokenAddress: txParams.to,
|
||||
tokenSymbol: symbol,
|
||||
tokenDecimals: decimals,
|
||||
isFetching: false,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
transactionType: TX_TYPES.SEND_ETHER,
|
||||
|
@ -89,7 +89,6 @@ CurrencyDisplay.prototype.render = function () {
|
||||
} = this.props
|
||||
|
||||
const valueToRender = this.getValueToRender()
|
||||
|
||||
const convertedValueToRender = this.getConvertedValueToRender(valueToRender)
|
||||
|
||||
return h('div', {
|
||||
@ -97,22 +96,24 @@ CurrencyDisplay.prototype.render = function () {
|
||||
style: {
|
||||
borderColor: inError ? 'red' : null,
|
||||
},
|
||||
onClick: () => this.currencyInput.focus(),
|
||||
onClick: () => this.currencyInput && this.currencyInput.focus(),
|
||||
}, [
|
||||
|
||||
h('div.currency-display__primary-row', [
|
||||
|
||||
h('div.currency-display__input-wrapper', [
|
||||
|
||||
h(CurrencyInput, {
|
||||
h(readOnly ? 'input' : CurrencyInput, {
|
||||
className: primaryBalanceClassName,
|
||||
value: `${valueToRender}`,
|
||||
placeholder: '0',
|
||||
readOnly,
|
||||
onInputChange: newValue => {
|
||||
handleChange(this.getAmount(newValue))
|
||||
},
|
||||
inputRef: input => { this.currencyInput = input },
|
||||
...(!readOnly ? {
|
||||
onInputChange: newValue => {
|
||||
handleChange(this.getAmount(newValue))
|
||||
},
|
||||
inputRef: input => { this.currencyInput = input },
|
||||
} : {}),
|
||||
}),
|
||||
|
||||
h('span.currency-display__currency-symbol', primaryCurrency),
|
||||
|
@ -1,8 +1,8 @@
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
|
||||
|
||||
const MIN_GAS_PRICE_HEX = (100000000).toString(16)
|
||||
const MIN_GAS_PRICE_DEC = '100000000'
|
||||
const MIN_GAS_PRICE_DEC = '0'
|
||||
const MIN_GAS_PRICE_HEX = (parseInt(MIN_GAS_PRICE_DEC)).toString(16)
|
||||
const MIN_GAS_LIMIT_DEC = '21000'
|
||||
const MIN_GAS_LIMIT_HEX = (parseInt(MIN_GAS_LIMIT_DEC)).toString(16)
|
||||
|
||||
|
@ -55,6 +55,10 @@ function ShapeshiftForm () {
|
||||
}
|
||||
}
|
||||
|
||||
ShapeshiftForm.prototype.getCoinPair = function () {
|
||||
return `${this.state.depositCoin.toUpperCase()}_ETH`
|
||||
}
|
||||
|
||||
ShapeshiftForm.prototype.componentWillMount = function () {
|
||||
this.props.shapeShiftSubview()
|
||||
}
|
||||
@ -120,14 +124,12 @@ ShapeshiftForm.prototype.renderMetadata = function (label, value) {
|
||||
}
|
||||
|
||||
ShapeshiftForm.prototype.renderMarketInfo = function () {
|
||||
const { depositCoin } = this.state
|
||||
const coinPair = `${depositCoin}_eth`
|
||||
const { tokenExchangeRates } = this.props
|
||||
const {
|
||||
limit,
|
||||
rate,
|
||||
minimum,
|
||||
} = tokenExchangeRates[coinPair] || {}
|
||||
} = tokenExchangeRates[this.getCoinPair()] || {}
|
||||
|
||||
return h('div.shapeshift-form__metadata', {}, [
|
||||
|
||||
@ -172,10 +174,9 @@ ShapeshiftForm.prototype.renderQrCode = function () {
|
||||
|
||||
ShapeshiftForm.prototype.render = function () {
|
||||
const { coinOptions, btnClass, warning } = this.props
|
||||
const { depositCoin, errorMessage, showQrCode, depositAddress } = this.state
|
||||
const coinPair = `${depositCoin}_eth`
|
||||
const { errorMessage, showQrCode, depositAddress } = this.state
|
||||
const { tokenExchangeRates } = this.props
|
||||
const token = tokenExchangeRates[coinPair]
|
||||
const token = tokenExchangeRates[this.getCoinPair()]
|
||||
|
||||
return h('div.shapeshift-form-wrapper', [
|
||||
showQrCode
|
||||
|
@ -61,3 +61,5 @@
|
||||
@import './welcome-screen.scss';
|
||||
|
||||
@import './sender-to-recipient.scss';
|
||||
|
||||
@import '../../../components/export-text-container/export-text-container.scss';
|
||||
|
@ -1 +1,3 @@
|
||||
@import './unlock.scss';
|
||||
|
||||
@import './reveal-seed.scss';
|
||||
|
17
ui/app/css/itcss/components/pages/reveal-seed.scss
Normal file
17
ui/app/css/itcss/components/pages/reveal-seed.scss
Normal file
@ -0,0 +1,17 @@
|
||||
.reveal-seed {
|
||||
&__content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
padding-bottom: 10px;
|
||||
font-weight: 400;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&__error {
|
||||
color: $crimson;
|
||||
font-size: 14px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
}
|
@ -207,6 +207,27 @@ input.large-input {
|
||||
&__content {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
min-height: 250px;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
&__warning-container {
|
||||
background: $linen;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
&__warning-message {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
&__warning-title {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&__warning-icon {
|
||||
padding-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,3 +258,49 @@ input.large-input {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 576px) {
|
||||
.page-container {
|
||||
height: 600px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.input-label {
|
||||
padding-bottom: 10px;
|
||||
font-weight: 400;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
padding-left: 10px;
|
||||
font-size: 14px;
|
||||
height: 40px;
|
||||
border: 1px solid $alto;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
font-weight: 100;
|
||||
color: $dusty-gray;
|
||||
}
|
||||
|
||||
&::-moz-placeholder {
|
||||
font-weight: 100;
|
||||
color: $dusty-gray;
|
||||
}
|
||||
|
||||
&:-ms-input-placeholder {
|
||||
font-weight: 100;
|
||||
color: $dusty-gray;
|
||||
}
|
||||
|
||||
&:-moz-placeholder {
|
||||
font-weight: 100;
|
||||
color: $dusty-gray;
|
||||
}
|
||||
|
||||
&--error {
|
||||
border: 1px solid $monzo;
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ $saffron: #f6c343;
|
||||
$dodger-blue: #3099f2;
|
||||
$zumthor: #edf7ff;
|
||||
$ecstasy: #f7861c;
|
||||
$linen: #fdf4f4;
|
||||
|
||||
/*
|
||||
Z-Indicies
|
||||
|
@ -1,138 +0,0 @@
|
||||
const inherits = require('util').inherits
|
||||
const Component = require('react').Component
|
||||
const PropTypes = require('prop-types')
|
||||
const connect = require('react-redux').connect
|
||||
const h = require('react-hyperscript')
|
||||
const actions = require('../../../actions')
|
||||
const { withRouter } = require('react-router-dom')
|
||||
const { compose } = require('recompose')
|
||||
const {
|
||||
DEFAULT_ROUTE,
|
||||
INITIALIZE_BACKUP_PHRASE_ROUTE,
|
||||
} = require('../../../routes')
|
||||
|
||||
RevealSeedConfirmation.contextTypes = {
|
||||
t: PropTypes.func,
|
||||
}
|
||||
|
||||
module.exports = compose(
|
||||
withRouter,
|
||||
connect(mapStateToProps)
|
||||
)(RevealSeedConfirmation)
|
||||
|
||||
|
||||
inherits(RevealSeedConfirmation, Component)
|
||||
function RevealSeedConfirmation () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
warning: state.appState.warning,
|
||||
}
|
||||
}
|
||||
|
||||
RevealSeedConfirmation.prototype.render = function () {
|
||||
const props = this.props
|
||||
|
||||
return (
|
||||
|
||||
h('.initialize-screen.flex-column.flex-center.flex-grow', {
|
||||
style: { maxWidth: '420px' },
|
||||
}, [
|
||||
|
||||
h('h3.flex-center.text-transform-uppercase', {
|
||||
style: {
|
||||
background: '#EBEBEB',
|
||||
color: '#AEAEAE',
|
||||
marginBottom: 24,
|
||||
width: '100%',
|
||||
fontSize: '20px',
|
||||
padding: 6,
|
||||
},
|
||||
}, [
|
||||
'Reveal Seed Words',
|
||||
]),
|
||||
|
||||
h('.div', {
|
||||
style: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '20px',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
}, [
|
||||
|
||||
h('h4', this.context.t('revealSeedWordsWarning')),
|
||||
|
||||
// confirmation
|
||||
h('input.large-input.letter-spacey', {
|
||||
type: 'password',
|
||||
id: 'password-box',
|
||||
placeholder: this.context.t('enterPasswordConfirm'),
|
||||
onKeyPress: this.checkConfirmation.bind(this),
|
||||
style: {
|
||||
width: 260,
|
||||
marginTop: '12px',
|
||||
},
|
||||
}),
|
||||
|
||||
h('.flex-row.flex-start', {
|
||||
style: {
|
||||
marginTop: 30,
|
||||
width: '50%',
|
||||
},
|
||||
}, [
|
||||
// cancel
|
||||
h('button.primary', {
|
||||
onClick: this.goHome.bind(this),
|
||||
}, 'CANCEL'),
|
||||
|
||||
// submit
|
||||
h('button.primary', {
|
||||
style: { marginLeft: '10px' },
|
||||
onClick: this.revealSeedWords.bind(this),
|
||||
}, 'OK'),
|
||||
|
||||
]),
|
||||
|
||||
(props.warning) && (
|
||||
h('span.error', {
|
||||
style: {
|
||||
margin: '20px',
|
||||
},
|
||||
}, props.warning.split('-'))
|
||||
),
|
||||
|
||||
props.inProgress && (
|
||||
h('span.in-progress-notification', this.context.t('generatingSeed'))
|
||||
),
|
||||
]),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
RevealSeedConfirmation.prototype.componentDidMount = function () {
|
||||
document.getElementById('password-box').focus()
|
||||
}
|
||||
|
||||
RevealSeedConfirmation.prototype.goHome = function () {
|
||||
this.props.dispatch(actions.showConfigPage(false))
|
||||
this.props.dispatch(actions.confirmSeedWords())
|
||||
.then(() => this.props.history.push(DEFAULT_ROUTE))
|
||||
}
|
||||
|
||||
// create vault
|
||||
|
||||
RevealSeedConfirmation.prototype.checkConfirmation = function (event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
this.revealSeedWords()
|
||||
}
|
||||
}
|
||||
|
||||
RevealSeedConfirmation.prototype.revealSeedWords = function () {
|
||||
var password = document.getElementById('password-box').value
|
||||
this.props.dispatch(actions.requestRevealSeed(password))
|
||||
.then(() => this.props.history.push(INITIALIZE_BACKUP_PHRASE_ROUTE))
|
||||
}
|
@ -493,7 +493,7 @@ SendTransactionScreen.prototype.renderFooter = function () {
|
||||
history,
|
||||
} = this.props
|
||||
|
||||
const missingTokenBalance = selectedToken && !tokenBalance
|
||||
const missingTokenBalance = selectedToken && (tokenBalance === null || tokenBalance === undefined)
|
||||
const noErrors = !amountError && toError === null
|
||||
|
||||
return h('div.page-container__footer', [
|
||||
|
@ -1,14 +1,6 @@
|
||||
const abi = require('human-standard-token-abi')
|
||||
const Eth = require('ethjs-query')
|
||||
const EthContract = require('ethjs-contract')
|
||||
|
||||
const tokenInfoGetter = function () {
|
||||
if (typeof global.ethereumProvider === 'undefined') return
|
||||
|
||||
const eth = new Eth(global.ethereumProvider)
|
||||
const contract = new EthContract(eth)
|
||||
const TokenContract = contract(abi)
|
||||
const util = require('./util')
|
||||
|
||||
function tokenInfoGetter () {
|
||||
const tokens = {}
|
||||
|
||||
return async (address) => {
|
||||
@ -16,21 +8,38 @@ const tokenInfoGetter = function () {
|
||||
return tokens[address]
|
||||
}
|
||||
|
||||
const contract = TokenContract.at(address)
|
||||
|
||||
const result = await Promise.all([
|
||||
contract.symbol(),
|
||||
contract.decimals(),
|
||||
])
|
||||
|
||||
const [ symbol = [], decimals = [] ] = result
|
||||
|
||||
tokens[address] = { symbol: symbol[0], decimals: decimals[0] }
|
||||
tokens[address] = await getSymbolAndDecimals(address)
|
||||
|
||||
return tokens[address]
|
||||
}
|
||||
}
|
||||
|
||||
async function getSymbolAndDecimals (tokenAddress, existingTokens = []) {
|
||||
const existingToken = existingTokens.find(({ address }) => tokenAddress === address)
|
||||
if (existingToken) {
|
||||
return existingToken
|
||||
}
|
||||
|
||||
let result = []
|
||||
try {
|
||||
const token = util.getContractAtAddress(tokenAddress)
|
||||
|
||||
result = await Promise.all([
|
||||
token.symbol(),
|
||||
token.decimals(),
|
||||
])
|
||||
} catch (err) {
|
||||
console.log(`symbol() and decimal() calls for token at address ${tokenAddress} resulted in error:`, err)
|
||||
}
|
||||
|
||||
const [ symbol = [], decimals = [] ] = result
|
||||
|
||||
return {
|
||||
symbol: symbol[0] || null,
|
||||
decimals: decimals[0] && decimals[0].toString() || null,
|
||||
}
|
||||
}
|
||||
|
||||
function calcTokenAmount (value, decimals) {
|
||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||
const amount = Number(value / multiplier)
|
||||
@ -42,4 +51,5 @@ function calcTokenAmount (value, decimals) {
|
||||
module.exports = {
|
||||
tokenInfoGetter,
|
||||
calcTokenAmount,
|
||||
getSymbolAndDecimals,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user