aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Miller <danjm.com@gmail.com>2018-08-03 00:02:22 +0800
committerDan Miller <danjm.com@gmail.com>2018-12-04 11:36:04 +0800
commit342dc95410b10f042b3f8ee4135f5fef1fd6fe93 (patch)
tree83f6e8a0500e91fef1fdc9f460c03dc638e33f99
parent5e7409482b6fc55eafc330e4bc119f7485f068bb (diff)
downloadtangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.tar
tangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.tar.gz
tangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.tar.bz2
tangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.tar.lz
tangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.tar.xz
tangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.tar.zst
tangerine-wallet-browser-342dc95410b10f042b3f8ee4135f5fef1fd6fe93.zip
Adds the content of the advanced tab - w/o chart or dynamic content - to gas customize modal.
-rw-r--r--app/_locales/en/messages.json6
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js105
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.js1
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss109
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.js1
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.scss13
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.component.js33
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.utils.js11
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js40
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js19
-rw-r--r--ui/app/components/gas-customization/gas-modal-page-container/index.scss8
-rw-r--r--ui/app/components/gas-customization/gas-slider/gas-slider.component.js48
-rw-r--r--ui/app/components/gas-customization/gas-slider/index.js1
-rw-r--r--ui/app/components/gas-customization/gas-slider/index.scss54
-rw-r--r--ui/app/components/gas-customization/index.scss3
-rw-r--r--ui/app/components/index.scss8
-rw-r--r--ui/app/css/itcss/components/gas-slider.scss51
-rw-r--r--ui/app/css/itcss/settings/variables.scss1
-rw-r--r--ui/app/ducks/custom-gas.js67
-rw-r--r--ui/app/reducers.js3
-rw-r--r--ui/app/selectors/custom-gas.js19
21 files changed, 538 insertions, 63 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 6e7df3aa8..103d8534f 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -701,6 +701,9 @@
"missingYourTokens": {
"message": "Don't see your tokens?"
},
+ "minutesShorthand": {
+ "message": "Min"
+ },
"myAccounts": {
"message": "My Accounts"
},
@@ -1036,6 +1039,9 @@
"secretPhrase": {
"message": "Enter your secret twelve word phrase here to restore your vault."
},
+ "secondsShorthand": {
+ "message": "Sec"
+ },
"seedPhraseReq": {
"message": "Seed phrases are 12 words long"
},
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js
new file mode 100644
index 000000000..7ddf13e51
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js
@@ -0,0 +1,105 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import {
+ MIN_GAS_PRICE_DEC,
+ MIN_GAS_LIMIT_DEC,
+} from '../../../send/send.constants'
+import GasSlider from '../../gas-slider'
+import TimeRemaining from './time-remaining'
+
+export default class AdvancedTabContent extends Component {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ static propTypes = {
+ updateCustomGasPrice: PropTypes.func,
+ updateCustomGasLimit: PropTypes.func,
+ customGasPrice: PropTypes.number,
+ customGasLimit: PropTypes.number,
+ millisecondsRemaining: PropTypes.number,
+ }
+
+ gasInput (value, onChange, min, precision, showGWEI) {
+ return (
+ <div className="advanced-tab__gas-edit-row__input-wrapper">
+ <input
+ className="advanced-tab__gas-edit-row__input"
+ type="number"
+ value={value}
+ onChange={event => onChange(Number(event.target.value))}
+ />
+ {showGWEI
+ ? <span className="advanced-tab__gas-edit-row__gwei-symbol">GWEI</span>
+ : null}
+ </div>
+ )
+ }
+
+ infoButton (onClick) {
+ return <i className="fa info-circle" onClick={onClick} />
+ }
+
+ render () {
+ const {
+ updateCustomGasPrice,
+ updateCustomGasLimit,
+ millisecondsRemaining,
+ customGasPrice,
+ customGasLimit,
+ } = this.props
+
+ return (
+ <div className="advanced-tab">
+ <div className="advanced-tab__transaction-data-summary">
+ <div className="advanced-tab__transaction-data-summary__titles">
+ <span>New Transaction Fee</span>
+ <span>~Transaction Time</span>
+ </div>
+ <div className="advanced-tab__transaction-data-summary__container">
+ <div className="advanced-tab__transaction-data-summary__fee">
+ $0.30
+ </div>
+ <TimeRemaining
+ milliseconds={millisecondsRemaining}
+ />
+ </div>
+ </div>
+ <div className="advanced-tab__fee-chart-title">
+ Live Transaction Fee Predictions
+ </div>
+ <div className="advanced-tab__fee-chart" />
+ <div className="advanced-tab__slider-container">
+ <GasSlider
+ onChange={value => {
+ updateCustomGasPrice(Number(value))
+ }}
+ lowLabel={'Cheaper'}
+ highLabel={'Faster'}
+ value={customGasPrice}
+ step={0.1}
+ max={200}
+ min={0}
+ coloredStart={{}}
+ />
+ </div>
+ <div className="advanced-tab__gas-edit-rows">
+ <div className="advanced-tab__gas-edit-row">
+ <div className="advanced-tab__gas-edit-row__label">
+ Gas Price
+ { this.infoButton(() => {}) }
+ </div>
+ { this.gasInput(customGasPrice, updateCustomGasPrice, MIN_GAS_PRICE_DEC, 9, true) }
+ </div>
+ <div className="advanced-tab__gas-edit-row">
+ <div className="advanced-tab__gas-edit-row__label">
+ Gas Limit
+ { this.infoButton(() => {}) }
+ </div>
+ { this.gasInput(customGasLimit, updateCustomGasLimit, MIN_GAS_LIMIT_DEC, 0) }
+ </div>
+ </div>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.js
new file mode 100644
index 000000000..492037f25
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.js
@@ -0,0 +1 @@
+export { default } from './advanced-tab-content.component'
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss
new file mode 100644
index 000000000..5dc30e061
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss
@@ -0,0 +1,109 @@
+@import './time-remaining/index';
+
+.advanced-tab {
+ display: flex;
+ flex-flow: column;
+ border-bottom: 1px solid $alto;
+
+ &__transaction-data-summary,
+ &__fee-chart-title,
+ &__gas-edit-row {
+ padding-left: 24px;
+ padding-right: 24px;
+ }
+
+ &__transaction-data-summary {
+ display: flex;
+ flex-flow: column;
+ color: $mid-gray;
+ margin-top: 12px;
+
+ &__titles,
+ &__container {
+ display: flex;
+ flex-flow: row;
+ justify-content: space-between;
+ font-size: 12px;
+ }
+
+ &__container {
+ font-size: 26px;
+ margin-top: 6px;
+ }
+ }
+
+ &__fee-chart-title {
+ font-size: 14px;
+ color: $scorpion;
+ margin-top: 22px;
+ }
+
+ &__fee-chart {
+ padding-left: 10px;
+ margin-top: 24px;
+ height: 134px;
+ }
+
+ &__slider-container {
+ padding-left: 27px;
+ padding-right: 27px;
+ }
+
+ &__gas-edit-rows {
+ margin-top: 44px;
+ height: 87px;
+ display: flex;
+ flex-flow: column;
+ justify-content: space-between;
+ }
+
+ &__gas-edit-row {
+ display: flex;
+ flex-flow: row;
+ justify-content: space-between;
+
+ &__label {
+ color: $mid-gray;
+ font-size: 16px;
+
+ .info-circle {
+ color: $silver;
+ margin-left: 10px;
+ }
+ }
+
+
+ &__input-wrapper {
+ position: relative;
+ }
+
+ &__input {
+ border: 1px solid $dusty-gray;
+ border-radius: 4px;
+ color: $mid-gray;
+ font-size: 16px;
+ height: 37px;
+ width: 163px;
+ padding: 8px 10px 10px 10px;
+ }
+
+ input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: none;
+ }
+
+ input[type="number"]:hover::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: none;
+ }
+
+ &__gwei-symbol {
+ position: absolute;
+ top: 8px;
+ right: 10px;
+ color: $dusty-gray;
+ }
+ }
+} \ No newline at end of file
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.js
new file mode 100644
index 000000000..61b681e1a
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.js
@@ -0,0 +1 @@
+export { default } from './time-remaining.component'
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.scss b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.scss
new file mode 100644
index 000000000..01bb06268
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/index.scss
@@ -0,0 +1,13 @@
+.time-remaining {
+ .minutes-num, .seconds-num {
+ font-size: 26px;
+ }
+
+ .seconds-num {
+ margin-left: 7px;
+ }
+
+ .minutes-label, .seconds-label {
+ font-size: 14px;
+ }
+} \ No newline at end of file
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.component.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.component.js
new file mode 100644
index 000000000..826d41f9c
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.component.js
@@ -0,0 +1,33 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { getTimeBreakdown } from './time-remaining.utils'
+
+export default class TimeRemaining extends Component {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ static propTypes = {
+ milliseconds: PropTypes.number,
+ }
+
+ render () {
+ const {
+ milliseconds,
+ } = this.props
+
+ const {
+ minutes,
+ seconds,
+ } = getTimeBreakdown(milliseconds)
+
+ return (
+ <div className="time-remaining">
+ <span className="minutes-num">{minutes}</span>
+ <span className="minutes-label">{this.context.t('minutesShorthand')}</span>
+ <span className="seconds-num">{seconds}</span>
+ <span className="seconds-label">{this.context.t('secondsShorthand')}</span>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.utils.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.utils.js
new file mode 100644
index 000000000..cf43e0acb
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/time-remaining/time-remaining.utils.js
@@ -0,0 +1,11 @@
+function getTimeBreakdown (milliseconds) {
+ return {
+ hours: Math.floor(milliseconds / 3600000),
+ minutes: Math.floor((milliseconds % 3600000) / 60000),
+ seconds: Math.floor((milliseconds % 60000) / 1000),
+ }
+}
+
+module.exports = {
+ getTimeBreakdown,
+}
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js
index 697594ec9..1d7a9d986 100644
--- a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js
+++ b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import PageContainer from '../../page-container'
import { Tabs, Tab } from '../../tabs'
+import AdvancedTabContent from './advanced-tab-content'
export default class GasModalPageContainer extends Component {
static contextTypes = {
@@ -10,6 +11,10 @@ export default class GasModalPageContainer extends Component {
static propTypes = {
hideModal: PropTypes.func,
+ updateCustomGasPrice: PropTypes.func,
+ updateCustomGasLimit: PropTypes.func,
+ customGasPrice: PropTypes.number,
+ customGasLimit: PropTypes.number,
}
state = {}
@@ -20,9 +25,22 @@ export default class GasModalPageContainer extends Component {
)
}
- renderAdvancedTabContent () {
+ renderAdvancedTabContent = () => {
+ const {
+ updateCustomGasPrice,
+ updateCustomGasLimit,
+ customGasPrice,
+ customGasLimit,
+ } = this.props
+
return (
- <div className="gas-modal-content__advanced-tab"/>
+ <AdvancedTabContent
+ updateCustomGasPrice={updateCustomGasPrice}
+ updateCustomGasLimit={updateCustomGasLimit}
+ customGasPrice={customGasPrice}
+ customGasLimit={customGasLimit}
+ millisecondsRemaining={91000}
+ />
)
}
@@ -68,14 +86,16 @@ export default class GasModalPageContainer extends Component {
const { hideModal } = this.props
return (
- <PageContainer
- title={this.context.t('customGas')}
- subtitle={this.context.t('customGasSubTitle')}
- tabsComponent={this.renderTabs()}
- disabled={false}
- onCancel={() => hideModal()}
- onClose={() => hideModal()}
- />
+ <div className="gas-modal-page-container">
+ <PageContainer
+ title={this.context.t('customGas')}
+ subtitle={this.context.t('customGasSubTitle')}
+ tabsComponent={this.renderTabs()}
+ disabled={false}
+ onCancel={() => hideModal()}
+ onClose={() => hideModal()}
+ />
+ </div>
)
}
}
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
index 71c700507..f7ac91a38 100644
--- a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
+++ b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
@@ -1,11 +1,28 @@
import { connect } from 'react-redux'
import GasModalPageContainer from './gas-modal-page-container.component'
import { hideModal } from '../../../actions'
+import {
+ setCustomGasPrice,
+ setCustomGasLimit,
+} from '../../../ducks/custom-gas'
+import {
+ getCustomGasPrice,
+ getCustomGasLimit,
+} from '../../../selectors/custom-gas'
+
+const mapStateToProps = state => {
+ return {
+ customGasPrice: getCustomGasPrice(state),
+ customGasLimit: getCustomGasLimit(state),
+ }
+}
const mapDispatchToProps = dispatch => {
return {
hideModal: () => dispatch(hideModal()),
+ updateCustomGasPrice: (newPrice) => dispatch(setCustomGasPrice(newPrice)),
+ updateCustomGasLimit: (newLimit) => dispatch(setCustomGasLimit(newLimit)),
}
}
-export default connect(null, mapDispatchToProps)(GasModalPageContainer)
+export default connect(mapStateToProps, mapDispatchToProps)(GasModalPageContainer)
diff --git a/ui/app/components/gas-customization/gas-modal-page-container/index.scss b/ui/app/components/gas-customization/gas-modal-page-container/index.scss
index a6609a385..027165b48 100644
--- a/ui/app/components/gas-customization/gas-modal-page-container/index.scss
+++ b/ui/app/components/gas-customization/gas-modal-page-container/index.scss
@@ -1,3 +1,11 @@
+@import './advanced-tab-content/index';
+
+.gas-modal-page-container {
+ .page-container {
+ width: 391px;
+ }
+}
+
.gas-modal-content {
&__basic-tab {
height: 219px;
diff --git a/ui/app/components/gas-customization/gas-slider/gas-slider.component.js b/ui/app/components/gas-customization/gas-slider/gas-slider.component.js
new file mode 100644
index 000000000..5836e7dfc
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-slider/gas-slider.component.js
@@ -0,0 +1,48 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+export default class AdvancedTabContent extends Component {
+ static propTypes = {
+ onChange: PropTypes.func,
+ lowLabel: PropTypes.string,
+ highLabel: PropTypes.string,
+ value: PropTypes.number,
+ step: PropTypes.number,
+ max: PropTypes.number,
+ min: PropTypes.number,
+ }
+
+ render () {
+ const {
+ onChange,
+ lowLabel,
+ highLabel,
+ value,
+ step,
+ max,
+ min,
+ } = this.props
+
+ return (
+ <div className="gas-slider">
+ <input
+ className="gas-slider__input"
+ type="range"
+ step={step}
+ max={max}
+ min={min}
+ value={value}
+ id="gasSlider"
+ onChange={event => onChange(event.target.value)}
+ />
+ <div className="gas-slider__bar">
+ <div className="gas-slider__colored"/>
+ </div>
+ <div className="gas-slider__labels">
+ <span>{lowLabel}</span>
+ <span>{highLabel}</span>
+ </div>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/gas-customization/gas-slider/index.js b/ui/app/components/gas-customization/gas-slider/index.js
new file mode 100644
index 000000000..f1752c93f
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-slider/index.js
@@ -0,0 +1 @@
+export { default } from './gas-slider.component'
diff --git a/ui/app/components/gas-customization/gas-slider/index.scss b/ui/app/components/gas-customization/gas-slider/index.scss
new file mode 100644
index 000000000..e6c734367
--- /dev/null
+++ b/ui/app/components/gas-customization/gas-slider/index.scss
@@ -0,0 +1,54 @@
+.gas-slider {
+ position: relative;
+ width: 322px;
+
+ &__input {
+ width: 322px;
+ margin-left: -2px;
+ z-index: 2;
+ }
+
+ input[type=range] {
+ -webkit-appearance: none !important;
+ }
+
+ input[type=range]::-webkit-slider-thumb {
+ -webkit-appearance: none !important;
+ height: 34px;
+ width: 34px;
+ background-color: $curious-blue;
+ box-shadow: 0 2px 4px 0 rgba(0,0,0,0.08);
+ border-radius: 50%;
+ position: relative;
+ z-index: 10;
+ }
+
+ &__bar {
+ height: 6px;
+ width: 322px;
+ background: $alto;
+ display: flex;
+ justify-content: space-between;
+ position: absolute;
+ top: 16px;
+ z-index: 0;
+ border-radius: 4px;
+ }
+
+ &__colored {
+ height: 6px;
+ border-radius: 4px;
+ margin-left: 102px;
+ width: 322px;
+ z-index: 1;
+ background-color: $blizzard-blue;
+ }
+
+ &__labels {
+ display: flex;
+ justify-content: space-between;
+ font-size: 12px;
+ margin-top: -6px;
+ color: $mid-gray;
+ }
+} \ No newline at end of file
diff --git a/ui/app/components/gas-customization/index.scss b/ui/app/components/gas-customization/index.scss
new file mode 100644
index 000000000..91ca5004e
--- /dev/null
+++ b/ui/app/components/gas-customization/index.scss
@@ -0,0 +1,3 @@
+@import './gas-slider/index';
+
+@import './gas-modal-page-container/index';
diff --git a/ui/app/components/index.scss b/ui/app/components/index.scss
index 48c6496d9..156b1b9f6 100644
--- a/ui/app/components/index.scss
+++ b/ui/app/components/index.scss
@@ -64,4 +64,10 @@
@import './unit-input/index';
-@import './gas-customization/gas-modal-page-container/index'
+@import './gas-customization/gas-modal-page-container/index';
+
+@import './gas-customization/gas-modal-page-container/index';
+
+@import './gas-customization/gas-modal-page-container/index';
+
+@import './gas-customization/index';
diff --git a/ui/app/css/itcss/components/gas-slider.scss b/ui/app/css/itcss/components/gas-slider.scss
index c27a560bd..e69de29bb 100644
--- a/ui/app/css/itcss/components/gas-slider.scss
+++ b/ui/app/css/itcss/components/gas-slider.scss
@@ -1,51 +0,0 @@
-.gas-slider {
- position: relative;
- width: 313px;
-
- &__input {
- width: 317px;
- margin-left: -2px;
- z-index: 2;
- }
-
- input[type=range] {
- -webkit-appearance: none !important;
- }
-
- input[type=range]::-webkit-slider-thumb {
- -webkit-appearance: none !important;
- height: 26px;
- width: 26px;
- border: 2px solid #B8B8B8;
- background-color: #FFFFFF;
- box-shadow: 0 2px 4px 0 rgba(0,0,0,0.08);
- border-radius: 50%;
- position: relative;
- z-index: 10;
- }
-
- &__bar {
- height: 6px;
- width: 313px;
- background: $alto;
- display: flex;
- justify-content: space-between;
- position: absolute;
- top: 11px;
- z-index: 0;
- }
-
- &__low, &__high {
- height: 6px;
- width: 49px;
- z-index: 1;
- }
-
- &__low {
- background-color: $crimson;
- }
-
- &__high {
- background-color: $caribbean-green;
- }
-} \ No newline at end of file
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
index 6c2b82f39..1c95f06a0 100644
--- a/ui/app/css/itcss/settings/variables.scss
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -57,6 +57,7 @@ $ecstasy: #f7861c;
$linen: #fdf4f4;
$oslo-gray: #8C8E94;
$polar: #fafcfe;
+$blizzard-blue: #bfdef3;
/*
Z-Indicies
diff --git a/ui/app/ducks/custom-gas.js b/ui/app/ducks/custom-gas.js
new file mode 100644
index 000000000..f1f483e93
--- /dev/null
+++ b/ui/app/ducks/custom-gas.js
@@ -0,0 +1,67 @@
+import extend from 'xtend'
+
+// Actions
+const SET_CUSTOM_GAS_PRICE = 'metamask/custom-gas/SET_CUSTOM_GAS_PRICE'
+const SET_CUSTOM_GAS_LIMIT = 'metamask/custom-gas/SET_CUSTOM_GAS_LIMIT'
+const SET_CUSTOM_GAS_ERRORS = 'metamask/custom-gas/SET_CUSTOM_GAS_ERRORS'
+const RESET_CUSTOM_GAS_STATE = 'metamask/custom-gas/RESET_CUSTOM_GAS_STATE'
+
+// TODO: determine if this approach to initState is consistent with conventional ducks pattern
+const initState = {
+ price: 0,
+ limit: 21000,
+ errors: {},
+}
+
+// Reducer
+export default function reducer ({ customGas: customGasState = initState }, action = {}) {
+ const newState = extend({}, customGasState)
+
+ switch (action.type) {
+ case SET_CUSTOM_GAS_PRICE:
+ return extend(newState, {
+ price: action.value,
+ })
+ case SET_CUSTOM_GAS_LIMIT:
+ return extend(newState, {
+ limit: action.value,
+ })
+ case SET_CUSTOM_GAS_ERRORS:
+ return extend(newState, {
+ errors: {
+ ...newState.errors,
+ ...action.value,
+ },
+ })
+ case RESET_CUSTOM_GAS_STATE:
+ return extend({}, initState)
+ default:
+ return newState
+ }
+}
+
+// Action Creators
+export function setCustomGasPrice (newPrice) {
+ return {
+ type: SET_CUSTOM_GAS_PRICE,
+ value: newPrice,
+ }
+}
+
+export function setCustomGasLimit (newLimit) {
+ return {
+ type: SET_CUSTOM_GAS_LIMIT,
+ value: newLimit,
+ }
+}
+
+export function setCustomGasErrors (newErrors) {
+ return {
+ type: SET_CUSTOM_GAS_ERRORS,
+ value: newErrors,
+ }
+}
+
+export function resetCustomGasState () {
+ return { type: RESET_CUSTOM_GAS_STATE }
+}
diff --git a/ui/app/reducers.js b/ui/app/reducers.js
index e1a982f93..7234c3c02 100644
--- a/ui/app/reducers.js
+++ b/ui/app/reducers.js
@@ -10,6 +10,7 @@ const reduceApp = require('./reducers/app')
const reduceLocale = require('./reducers/locale')
const reduceSend = require('./ducks/send.duck').default
import reduceConfirmTransaction from './ducks/confirm-transaction.duck'
+import reduceCustomGas from './ducks/custom-gas'
window.METAMASK_CACHED_LOG_STATE = null
@@ -49,6 +50,8 @@ function rootReducer (state, action) {
state.confirmTransaction = reduceConfirmTransaction(state, action)
+ state.customGas = reduceCustomGas(state, action)
+
window.METAMASK_CACHED_LOG_STATE = state
return state
}
diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js
new file mode 100644
index 000000000..97280190f
--- /dev/null
+++ b/ui/app/selectors/custom-gas.js
@@ -0,0 +1,19 @@
+const selectors = {
+ getCustomGasPrice,
+ getCustomGasLimit,
+ getCustomGasErrors,
+}
+
+module.exports = selectors
+
+function getCustomGasPrice (state) {
+ return state.customGas.price
+}
+
+function getCustomGasLimit (state) {
+ return state.customGas.limit
+}
+
+function getCustomGasErrors (state) {
+ return state.customGas.errors
+}