aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChi Kei Chan <chikeichan@gmail.com>2017-08-30 02:50:12 +0800
committerGitHub <noreply@github.com>2017-08-30 02:50:12 +0800
commite23ae5371b410b9fe94ac83be08f4de71c184eb0 (patch)
tree0ef0cebe952b2587fff55010bb15573ab0e60c88
parent4076496c8ea8c5a771db421b6c6a037c6ad48df1 (diff)
parentc605c9897d40f8fc2568b63d33cfc018635bcf25 (diff)
downloadtangerine-wallet-browser-e23ae5371b410b9fe94ac83be08f4de71c184eb0.tar.gz
tangerine-wallet-browser-e23ae5371b410b9fe94ac83be08f4de71c184eb0.tar.zst
tangerine-wallet-browser-e23ae5371b410b9fe94ac83be08f4de71c184eb0.zip
Merge pull request #1982 from danjm/send-gas-tooltip
Send Gas Tooltip
-rwxr-xr-xapp/fonts/Lato/Lato-Black.ttfbin0 -> 114588 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-BlackItalic.ttfbin0 -> 111616 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-Bold.ttfbin0 -> 121788 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-BoldItalic.ttfbin0 -> 120312 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-Hairline.ttfbin0 -> 115316 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-HairlineItalic.ttfbin0 -> 91460 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-Italic.ttfbin0 -> 118352 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-Light.ttfbin0 -> 122524 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-LightItalic.ttfbin0 -> 91600 bytes
-rwxr-xr-xapp/fonts/Lato/Lato-Regular.ttfbin0 -> 120196 bytes
-rwxr-xr-xapp/fonts/Lato/OFL.txt93
-rw-r--r--ui/app/components/eth-balance.js69
-rw-r--r--ui/app/components/fiat-value.js20
-rw-r--r--ui/app/components/gas-tooltip.js102
-rw-r--r--ui/app/components/input-number.js57
-rw-r--r--ui/app/components/tooltip.js2
-rw-r--r--ui/app/css/itcss/components/send.scss139
-rw-r--r--ui/app/css/itcss/settings/typography.scss7
-rw-r--r--ui/app/css/itcss/settings/variables.scss1
-rw-r--r--ui/app/send.js106
-rw-r--r--ui/app/util.js22
21 files changed, 568 insertions, 50 deletions
diff --git a/app/fonts/Lato/Lato-Black.ttf b/app/fonts/Lato/Lato-Black.ttf
new file mode 100755
index 000000000..6848db0d1
--- /dev/null
+++ b/app/fonts/Lato/Lato-Black.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-BlackItalic.ttf b/app/fonts/Lato/Lato-BlackItalic.ttf
new file mode 100755
index 000000000..5decf1297
--- /dev/null
+++ b/app/fonts/Lato/Lato-BlackItalic.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-Bold.ttf b/app/fonts/Lato/Lato-Bold.ttf
new file mode 100755
index 000000000..74343694e
--- /dev/null
+++ b/app/fonts/Lato/Lato-Bold.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-BoldItalic.ttf b/app/fonts/Lato/Lato-BoldItalic.ttf
new file mode 100755
index 000000000..684aacf5b
--- /dev/null
+++ b/app/fonts/Lato/Lato-BoldItalic.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-Hairline.ttf b/app/fonts/Lato/Lato-Hairline.ttf
new file mode 100755
index 000000000..288be2955
--- /dev/null
+++ b/app/fonts/Lato/Lato-Hairline.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-HairlineItalic.ttf b/app/fonts/Lato/Lato-HairlineItalic.ttf
new file mode 100755
index 000000000..c2bfd3353
--- /dev/null
+++ b/app/fonts/Lato/Lato-HairlineItalic.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-Italic.ttf b/app/fonts/Lato/Lato-Italic.ttf
new file mode 100755
index 000000000..3d3b7a298
--- /dev/null
+++ b/app/fonts/Lato/Lato-Italic.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-Light.ttf b/app/fonts/Lato/Lato-Light.ttf
new file mode 100755
index 000000000..a958067a8
--- /dev/null
+++ b/app/fonts/Lato/Lato-Light.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-LightItalic.ttf b/app/fonts/Lato/Lato-LightItalic.ttf
new file mode 100755
index 000000000..5e45ad9a6
--- /dev/null
+++ b/app/fonts/Lato/Lato-LightItalic.ttf
Binary files differ
diff --git a/app/fonts/Lato/Lato-Regular.ttf b/app/fonts/Lato/Lato-Regular.ttf
new file mode 100755
index 000000000..04ea8efb1
--- /dev/null
+++ b/app/fonts/Lato/Lato-Regular.ttf
Binary files differ
diff --git a/app/fonts/Lato/OFL.txt b/app/fonts/Lato/OFL.txt
new file mode 100755
index 000000000..dfca0da4b
--- /dev/null
+++ b/app/fonts/Lato/OFL.txt
@@ -0,0 +1,93 @@
+Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato"
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js
index 4f538fd31..32ff4efdf 100644
--- a/ui/app/components/eth-balance.js
+++ b/ui/app/components/eth-balance.js
@@ -37,7 +37,17 @@ EthBalanceComponent.prototype.render = function () {
}
EthBalanceComponent.prototype.renderBalance = function (value) {
var props = this.props
- const { conversionRate, shorten, incoming, currentCurrency } = props
+ const {
+ conversionRate,
+ shorten,
+ incoming,
+ currentCurrency,
+ hideTooltip,
+ styleOveride,
+ } = props
+
+ const { fontSize, color, fontFamily, lineHeight } = styleOveride
+
if (value === 'None') return value
if (value === '...') return value
var balanceObj = generateBalanceObject(value, shorten ? 1 : 3)
@@ -54,36 +64,41 @@ EthBalanceComponent.prototype.renderBalance = function (value) {
}
var label = balanceObj.label
+ const tooltipProps = hideTooltip ? {} : {
+ position: 'bottom',
+ title: `${ethNumber} ${ethSuffix}`,
+ };
return (
- h(Tooltip, {
- position: 'bottom',
- title: `${ethNumber} ${ethSuffix}`,
- }, h('div.flex-column', [
- h('.flex-row', {
- style: {
- alignItems: 'flex-end',
- lineHeight: '13px',
- fontFamily: 'Montserrat Light',
- textRendering: 'geometricPrecision',
- },
- }, [
- h('div', {
- style: {
- width: '100%',
- textAlign: 'right',
- },
- }, incoming ? `+${balance}` : balance),
- h('div', {
+ h(hideTooltip ? 'div' : Tooltip,
+ tooltipProps,
+ h('div.flex-column', [
+ h('.flex-row', {
style: {
- color: ' #AEAEAE',
- fontSize: '12px',
- marginLeft: '5px',
+ alignItems: 'flex-end',
+ lineHeight: lineHeight || '13px',
+ fontFamily: fontFamily || 'Montserrat Light',
+ textRendering: 'geometricPrecision',
},
- }, label),
- ]),
+ }, [
+ h('div', {
+ style: {
+ width: '100%',
+ textAlign: 'right',
+ fontSize: fontSize || 'inherit',
+ color: color || 'inherit',
+ },
+ }, incoming ? `+${balance}` : balance),
+ h('div', {
+ style: {
+ color: color || '#AEAEAE',
+ fontSize: fontSize || '12px',
+ marginLeft: '5px',
+ },
+ }, label),
+ ]),
- showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null,
- ]))
+ showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null,
+ ]))
)
}
diff --git a/ui/app/components/fiat-value.js b/ui/app/components/fiat-value.js
index 8a64a1cfc..665789353 100644
--- a/ui/app/components/fiat-value.js
+++ b/ui/app/components/fiat-value.js
@@ -12,7 +12,7 @@ function FiatValue () {
FiatValue.prototype.render = function () {
const props = this.props
- const { conversionRate, currentCurrency } = props
+ const { conversionRate, currentCurrency, style } = props
const value = formatBalance(props.value, 6)
@@ -28,16 +28,18 @@ FiatValue.prototype.render = function () {
fiatTooltipNumber = 'Unknown'
}
- return fiatDisplay(fiatDisplayNumber, currentCurrency)
+ return fiatDisplay(fiatDisplayNumber, currentCurrency, style)
}
-function fiatDisplay (fiatDisplayNumber, fiatSuffix) {
+function fiatDisplay (fiatDisplayNumber, fiatSuffix, styleOveride = {}) {
+ const { fontSize, color, fontFamily, lineHeight } = styleOveride
+
if (fiatDisplayNumber !== 'N/A') {
return h('.flex-row', {
style: {
alignItems: 'flex-end',
- lineHeight: '13px',
- fontFamily: 'Montserrat Light',
+ lineHeight: lineHeight || '13px',
+ fontFamily: fontFamily || 'Montserrat Light',
textRendering: 'geometricPrecision',
},
}, [
@@ -45,15 +47,15 @@ function fiatDisplay (fiatDisplayNumber, fiatSuffix) {
style: {
width: '100%',
textAlign: 'right',
- fontSize: '12px',
- color: '#333333',
+ fontSize: fontSize || '12px',
+ color: color || '#333333',
},
}, fiatDisplayNumber),
h('div', {
style: {
- color: '#AEAEAE',
+ color: color || '#AEAEAE',
marginLeft: '5px',
- fontSize: '12px',
+ fontSize: fontSize || '12px',
},
}, fiatSuffix),
])
diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js
new file mode 100644
index 000000000..68b7aea61
--- /dev/null
+++ b/ui/app/components/gas-tooltip.js
@@ -0,0 +1,102 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const InputNumber = require('./input-number.js')
+const findDOMNode = require('react-dom').findDOMNode
+
+module.exports = GasTooltip
+
+inherits(GasTooltip, Component)
+function GasTooltip () {
+ Component.call(this)
+ this.state = {
+ gasLimit: 0,
+ gasPrice: 0,
+ }
+
+ this.updateGasPrice = this.updateGasPrice.bind(this);
+ this.updateGasLimit = this.updateGasLimit.bind(this);
+ this.onClose = this.onClose.bind(this);
+}
+
+GasTooltip.prototype.componentWillMount = function () {
+ const { gasPrice = 0, gasLimit = 0} = this.props
+
+ this.setState({
+ gasPrice: parseInt(gasPrice, 16) / 1000000000,
+ gasLimit: parseInt(gasLimit, 16),
+ })
+}
+
+GasTooltip.prototype.updateGasPrice = function (newPrice) {
+ const { onFeeChange } = this.props
+ const { gasLimit } = this.state
+
+ this.setState({ gasPrice: newPrice })
+ onFeeChange({
+ gasLimit: gasLimit.toString(16),
+ gasPrice: (newPrice * 1000000000).toString(16)
+ })
+}
+
+GasTooltip.prototype.updateGasLimit = function (newLimit) {
+ const { onFeeChange } = this.props
+ const { gasPrice } = this.state
+
+ this.setState({ gasLimit: newLimit })
+ onFeeChange({
+ gasLimit: newLimit.toString(16),
+ gasPrice: (gasPrice * 1000000000).toString(16)
+ })
+}
+
+GasTooltip.prototype.onClose = function (e) {
+ e.stopPropagation();
+ this.props.onClose();
+}
+
+GasTooltip.prototype.render = function () {
+ const { position, title, children, className } = this.props
+ const { gasPrice, gasLimit } = this.state
+
+ return h('div.gas-tooltip', {}, [
+ h('div.gas-tooltip-close-area', {
+ onClick: this.onClose
+ }),
+ h('div.customize-gas-tooltip-container', {}, [
+ h('div.customize-gas-tooltip', {}, [
+ h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']),
+ h('div.gas-tooltip-input-label', {}, [
+ h('span.gas-tooltip-label', {}, ['Gas Price']),
+ h('i.fa.fa-info-circle')
+ ]),
+ h(InputNumber, {
+ unitLabel: 'GWEI',
+ step: 1,
+ min: 0,
+ placeholder: '0',
+ initValue: gasPrice,
+ onChange: (newPrice) => this.updateGasPrice(newPrice),
+ }),
+ h('div.gas-tooltip-input-label', {
+ style: {
+ 'marginTop': '81px',
+ },
+ }, [
+ h('span.gas-tooltip-label', {}, ['Gas Limit']),
+ h('i.fa.fa-info-circle')
+ ]),
+ h(InputNumber, {
+ unitLabel: 'UNITS',
+ step: 1,
+ min: 0,
+ placeholder: '0',
+ initValue: gasLimit,
+ onChange: (newLimit) => this.updateGasLimit(newLimit),
+ }),
+ ]),
+ h('div.gas-tooltip-arrow', {}),
+ ])
+ ])
+}
+
diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js
new file mode 100644
index 000000000..c8bdd5ec5
--- /dev/null
+++ b/ui/app/components/input-number.js
@@ -0,0 +1,57 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const findDOMNode = require('react-dom').findDOMNode
+
+module.exports = InputNumber
+
+inherits(InputNumber, Component)
+function InputNumber () {
+ Component.call(this)
+
+ this.state = {
+ value: 0,
+ }
+
+ this.setValue = this.setValue.bind(this);
+}
+
+InputNumber.prototype.componentWillMount = function () {
+ const { initValue = 0 } = this.props
+
+ this.setState({ value: initValue });
+}
+
+InputNumber.prototype.setValue = function (newValue) {
+ const { fixed, min, onChange } = this.props
+
+ if (fixed) newValue = Number(newValue.toFixed(4))
+
+ if (newValue >= min) {
+ this.setState({ value: newValue })
+ onChange(newValue)
+ }
+}
+
+InputNumber.prototype.render = function () {
+ const { unitLabel, step = 1, min, placeholder } = this.props
+ const { value } = this.state
+
+ return h('div.customize-gas-input-wrapper', {}, [
+ h('input.customize-gas-input', {
+ placeholder,
+ type: 'number',
+ value,
+ onChange: (e) => this.setValue(Number(e.target.value))
+ }),
+ h('span.gas-tooltip-input-detail', {}, [unitLabel]),
+ h('div.gas-tooltip-input-arrows', {}, [
+ h('i.fa.fa-angle-up', {
+ onClick: () => this.setValue(value + step)
+ }),
+ h('i.fa.fa-angle-down', {
+ onClick: () => this.setValue(value - step)
+ }),
+ ]),
+ ])
+}
diff --git a/ui/app/components/tooltip.js b/ui/app/components/tooltip.js
index edbc074bb..74cf1ae43 100644
--- a/ui/app/components/tooltip.js
+++ b/ui/app/components/tooltip.js
@@ -12,7 +12,7 @@ function Tooltip () {
Tooltip.prototype.render = function () {
const props = this.props
- const { position, title, children } = props
+ const { position, title, children, show = true } = props
return h(ReactTooltip, {
position: position || 'left',
diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss
index 7c84d3b9f..507351cd1 100644
--- a/ui/app/css/itcss/components/send.scss
+++ b/ui/app/css/itcss/components/send.scss
@@ -6,6 +6,7 @@
z-index: $send-card-z-index;
position: absolute;
top: 5%;
+ font-family: 'DIN OT';
@media screen and (max-width: $break-small) {
top: 33px;
@@ -45,6 +46,7 @@
.send-screen-input-wrapper {
width: 95%;
+ position: relative;
}
.send-screen-input {
@@ -53,9 +55,18 @@
.send-screen-gas-input {
width: 100%;
- background-color: $concrete;
+ height: 41px;
+ border-radius: 3px;
+ background-color: #f3f3f3;
border-width: 0px;
border-style: none;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding-left: 10px;
+ padding-right: 12px;
+ font-size: 16px;
+ color: $scorpion;
}
.send-screen-amount-labels {
@@ -70,4 +81,128 @@
justify-content: space-between;
}
-.send-screen-bolt-icon {} \ No newline at end of file
+.selected-currency {
+ color: $curious-blue;
+}
+
+.unselected-currency {
+ cursor: pointer;
+}
+
+.send-screen-gas-input-customize {
+ color: $curious-blue;
+ font-size: 12px;
+ cursor: pointer;
+}
+
+.gas-tooltip-close-area {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1000;
+ width: 100%;
+ height: 100%;
+}
+
+.customize-gas-tooltip-container {
+ position: absolute;
+ bottom: 50px;
+ width: 237px;
+ height: 307px;
+ background-color: white;
+ opacity: 1;
+ box-shadow: grey 0px 0px 5px;
+ z-index: 1050;
+ padding: 13px 19px;
+ font-size: 16px;
+ border-radius: 4px;
+ font-family: 'Lato';
+ font-weigth: 500;
+}
+
+.gas-tooltip-arrow {
+ height: 25px;
+ width: 25px;
+ z-index: 1200;
+ background: white;
+ position: absolute;
+ -webkit-transform: rotate(45deg);
+ transform: rotate(45deg);
+ left: 107px;
+ top: 294px;
+ -webkit-box-shadow: 0 0 5px grey;
+ box-shadow: 2px 2px 2px $alto;
+}
+
+.customize-gas-tooltip-container input[type=number]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ display:none;
+}
+
+.customize-gas-tooltip-container input[type=number]:hover::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ display:none;
+}
+
+.customize-gas-tooltip {
+ position: relative;
+}
+
+.gas-tooltip {
+ display: flex;
+ justify-content: center;
+}
+
+.gas-tooltip-label {
+ font-size: 16px;
+ color: $tundora;
+}
+
+.gas-tooltip-header {
+ padding-bottom: 12px;
+}
+
+.gas-tooltip-input-label {
+ margin-bottom: 5px;
+}
+
+.gas-tooltip-input-label i {
+ color: $silver-chalice;
+ margin-left: 6px;
+}
+
+.customize-gas-input {
+ width: 178px;
+ height: 28px;
+ border: 1px solid $alto;
+ font-size: 16px;
+ color: $nile-blue;
+ padding-left: 8px;
+}
+
+.customize-gas-input-wrapper {
+ position: relative;
+}
+
+.gas-tooltip-input-detail {
+ position: absolute;
+ top: 4px;
+ right: 26px;
+ font-size: 12px;
+ color: $silver-chalice;
+}
+
+.gas-tooltip-input-arrows {
+ position: absolute;
+ top: 0px;
+ left: 178px;
+ width: 17px;
+ height: 28px;
+ border: 1px solid #dadada;
+ border-left: 0px;
+ display: flex;
+ flex-direction: column;
+ color: #9b9b9b;
+ font-size: 0.8em;
+ padding: 1px 4px;
+} \ No newline at end of file
diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss
index e18a1979d..8051b5fe3 100644
--- a/ui/app/css/itcss/settings/typography.scss
+++ b/ui/app/css/itcss/settings/typography.scss
@@ -41,3 +41,10 @@
font-weight: 400;
font-style: normal;
}
+
+@font-face {
+ font-family: 'Lato';
+ src: url('/fonts/Lato/Lato-Regular.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+}
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
index 2f5f17f17..ac719e50b 100644
--- a/ui/app/css/itcss/settings/variables.scss
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -29,6 +29,7 @@ $curious-blue: #2f9ae0;
$concrete: #f3f3f3;
$tundora: #4d4d4d;
$nile-blue: #1b344d;
+$scorpion: #5d5d5d;
/*
Z-Indicies
diff --git a/ui/app/send.js b/ui/app/send.js
index ef4e92e26..848f53f7c 100644
--- a/ui/app/send.js
+++ b/ui/app/send.js
@@ -5,13 +5,19 @@ const connect = require('react-redux').connect
const Identicon = require('./components/identicon')
const actions = require('./actions')
const util = require('./util')
+const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
+const hexToBn = require('../../app/scripts/lib/hex-to-bn')
const numericBalance = require('./util').numericBalance
const addressSummary = require('./util').addressSummary
+const bnMultiplyByFraction = require('./util').bnMultiplyByFraction
const isHex = require('./util').isHex
const EthBalance = require('./components/eth-balance')
const EnsInput = require('./components/ens-input')
-const ethUtil = require('ethereumjs-util')
+const FiatValue = require('./components/fiat-value.js')
+const GasTooltip = require('./components/gas-tooltip.js')
const { getSelectedIdentity } = require('./selectors')
+const getTxFeeBn = require('./util').getTxFeeBn
const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0'
@@ -28,6 +34,7 @@ function mapStateToProps (state) {
addressBook: state.metamask.addressBook,
conversionRate: state.metamask.conversionRate,
currentCurrency: state.metamask.currentCurrency,
+ blockGasLimit: state.metamask.currentBlockGasLimit,
}
result.error = result.warning && result.warning.split('.')[0]
@@ -51,12 +58,20 @@ function SendTransactionScreen () {
to: '',
// these values are hardcoded, so "Next" can be clicked
amount: '0.0001', // see L544
- gasPrice: '4a817c800',
+ gasPrice: '0x5d21dba00',
gas: '0x7b0d',
txData: null,
memo: '',
},
+ tooltipIsOpen: false,
}
+
+ this.back = this.back.bind(this)
+ this.closeTooltip = this.closeTooltip.bind(this)
+ this.onSubmit = this.onSubmit.bind(this)
+ this.recipientDidChange = this.recipientDidChange.bind(this)
+ this.setCurrentCurrency = this.setCurrentCurrency.bind(this)
+ this.toggleTooltip = this.toggleTooltip.bind(this)
}
SendTransactionScreen.prototype.render = function () {
@@ -74,6 +89,8 @@ SendTransactionScreen.prototype.render = function () {
conversionRate,
currentCurrency,
} = props
+ const { blockGasLimit, newTx } = this.state
+ const { gas, gasPrice } = newTx
console.log({ selectedIdentity, identities })
console.log("SendTransactionScreen state:", this.state)
@@ -174,7 +191,17 @@ SendTransactionScreen.prototype.render = function () {
h('div.send-screen-amount-labels', {}, [
h('span', {}, ['Amount']),
- h('span', {}, ['ETH <> USD']), //holding on icon from design
+ h('span', {}, [
+ h('span', {
+ className: currentCurrency === 'ETH' ? 'selected-currency' : 'unselected-currency',
+ onClick: () => this.setCurrentCurrency('ETH')
+ }, ['ETH']),
+ '<>',
+ h('span', {
+ className: currentCurrency === 'USD' ? 'selected-currency' : 'unselected-currency',
+ onClick: () => this.setCurrentCurrency('USD'),
+ }, ['USD']),
+ ]), //holding on icon from design
]),
h('input.large-input.send-screen-input', {
@@ -195,6 +222,21 @@ SendTransactionScreen.prototype.render = function () {
]),
h('div.send-screen-input-wrapper', {}, [
+ this.state.tooltipIsOpen && h(GasTooltip, {
+ className: 'send-tooltip',
+ gasPrice,
+ gasLimit: gas,
+ onClose: this.closeTooltip,
+ onFeeChange: ({gasLimit, gasPrice}) => {
+ this.setState({
+ newTx: {
+ ...this.state.newTx,
+ gas: gasLimit,
+ gasPrice,
+ },
+ })
+ }
+ }),
h('div.send-screen-gas-labels', {}, [
h('span', {}, [
@@ -212,9 +254,39 @@ SendTransactionScreen.prototype.render = function () {
h('span', {}, ['What\'s this?']),
]),
- h('input.large-input.send-screen-gas-input', {
- placeholder: '0',
- }, []),
+ // TODO: handle loading time when switching to USD
+ h('div.large-input.send-screen-gas-input', {}, [
+ currentCurrency === 'USD'
+ ? h(FiatValue, {
+ value: getTxFeeBn(gas, gasPrice, blockGasLimit),
+ conversionRate,
+ currentCurrency,
+ style: {
+ color: '#5d5d5d',
+ fontSize: '16px',
+ fontFamily: 'DIN OT',
+ lineHeight: '22.4px'
+ }
+ })
+ : h(EthBalance, {
+ value: getTxFeeBn(gas, gasPrice, blockGasLimit),
+ currentCurrency,
+ conversionRate,
+ showFiat: false,
+ hideTooltip: true,
+ styleOveride: {
+ color: '#5d5d5d',
+ fontSize: '16px',
+ fontFamily: 'DIN OT',
+ lineHeight: '22.4px'
+ }
+ }),
+ h('div.send-screen-gas-input-customize', {
+ onClick: this.toggleTooltip,
+ }, [
+ 'Customize'
+ ]),
+ ]),
]),
@@ -264,7 +336,7 @@ SendTransactionScreen.prototype.render = function () {
h('section.flex-column.flex-center', [
h('button.btn-light', {
- onClick: this.onSubmit.bind(this),
+ onClick: this.onSubmit,
style: {
marginTop: '8px',
width: '8em',
@@ -273,7 +345,7 @@ SendTransactionScreen.prototype.render = function () {
}, 'Next'),
h('button.btn-light', {
- onClick: this.back.bind(this),
+ onClick: this.back,
style: {
background: '#F7F7F7', // $alabaster
border: 'none',
@@ -392,7 +464,7 @@ SendTransactionScreen.prototype.renderSendToken = function () {
h(EnsInput, {
name: 'address',
placeholder: 'Recipient Address',
- onChange: this.recipientDidChange.bind(this),
+ onChange: this.recipientDidChange,
network,
identities,
addressBook,
@@ -484,7 +556,7 @@ SendTransactionScreen.prototype.renderSendToken = function () {
h('section.flex-column.flex-center', [
h('button.btn-light', {
- onClick: this.onSubmit.bind(this),
+ onClick: this.onSubmit,
style: {
marginTop: '8px',
width: '8em',
@@ -493,7 +565,7 @@ SendTransactionScreen.prototype.renderSendToken = function () {
}, 'Next'),
h('button.btn-light', {
- onClick: this.back.bind(this),
+ onClick: this.back,
style: {
background: '#F7F7F7', // $alabaster
border: 'none',
@@ -507,6 +579,18 @@ SendTransactionScreen.prototype.renderSendToken = function () {
)
}
+SendTransactionScreen.prototype.toggleTooltip = function () {
+ this.setState({ tooltipIsOpen: !this.state.tooltipIsOpen })
+}
+
+SendTransactionScreen.prototype.closeTooltip = function () {
+ this.setState({ tooltipIsOpen: false })
+}
+
+SendTransactionScreen.prototype.setCurrentCurrency = function (newCurrency) {
+ this.props.dispatch(actions.setCurrentCurrency(newCurrency))
+}
+
SendTransactionScreen.prototype.navigateToAccounts = function (event) {
event.stopPropagation()
this.props.dispatch(actions.showAccountsPage())
diff --git a/ui/app/util.js b/ui/app/util.js
index 4dd0e30f3..a624726e2 100644
--- a/ui/app/util.js
+++ b/ui/app/util.js
@@ -1,4 +1,5 @@
const ethUtil = require('ethereumjs-util')
+const hexToBn = require('../../app/scripts/lib/hex-to-bn')
const vreme = new (require('vreme'))()
// formatData :: ( date: <Unix Timestamp> ) -> String
@@ -43,6 +44,8 @@ module.exports = {
bnTable: bnTable,
isHex: isHex,
formatDate,
+ bnMultiplyByFraction,
+ getTxFeeBn,
}
function valuesFor (obj) {
@@ -222,3 +225,22 @@ function readableDate (ms) {
function isHex (str) {
return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/))
}
+
+function bnMultiplyByFraction (targetBN, numerator, denominator) {
+ const numBN = new ethUtil.BN(numerator)
+ const denomBN = new ethUtil.BN(denominator)
+ return targetBN.mul(numBN).div(denomBN)
+}
+
+function getTxFeeBn (gas, gasPrice = MIN_GAS_PRICE_BN.toString(16), blockGasLimit) {
+ // Gas Limit
+ const gasBn = hexToBn(gas)
+ const gasLimit = new ethUtil.BN(parseInt(blockGasLimit))
+ const safeGasLimit = bnMultiplyByFraction(gasLimit, 19, 20).toString(10)
+
+ // Gas Price
+ const gasPriceBn = hexToBn(gasPrice)
+ const txFeeBn = gasBn.mul(gasPriceBn)
+
+ return txFeeBn.toString(16);
+}