aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan J Miller <danjm.com@gmail.com>2018-01-13 03:48:18 +0800
committerAlexander Tseung <alextsg@users.noreply.github.com>2018-01-13 03:48:18 +0800
commit5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f (patch)
treef354a007d35321ad7bc54564d2ae40e8f152176f
parentb72610fb534580e607c6934e938c50d58ba05350 (diff)
downloadtangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.tar
tangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.tar.gz
tangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.tar.bz2
tangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.tar.lz
tangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.tar.xz
tangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.tar.zst
tangerine-wallet-browser-5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f.zip
[NewUI-flat] New deposit ether modal UI. (#2642)
* New deposit ether modal. * New deposit modal full screen on mobile, and other style fixes. * Hide shapeshift option from deposit modal for now. * Add shapeshift form to new deposit modal. * Store recipient address for shapeshift tx in background. * Use Simpledropdown to achieve desired styling in coin selector. * Lint fix * Fix typos and remove dead code. * Remove storage of shapeshift receiving address from background. * Fix typos
-rw-r--r--app/images/coinbase logo.pngbin0 -> 9775 bytes
-rw-r--r--app/images/shapeshift logo.pngbin0 -> 17537 bytes
-rw-r--r--ui/app/actions.js5
-rw-r--r--ui/app/components/modals/buy-options-modal.js2
-rw-r--r--ui/app/components/modals/deposit-ether-modal.js182
-rw-r--r--ui/app/components/modals/modal.js32
-rw-r--r--ui/app/components/shapeshift-form.js468
-rw-r--r--ui/app/components/shift-list-item.js50
-rw-r--r--ui/app/components/tx-list.js10
-rw-r--r--ui/app/components/tx-view.js2
-rw-r--r--ui/app/css/itcss/components/modal.scss254
-rw-r--r--ui/app/css/itcss/settings/variables.scss2
-rw-r--r--ui/app/reducers/app.js5
-rw-r--r--yarn.lock23
14 files changed, 717 insertions, 318 deletions
diff --git a/app/images/coinbase logo.png b/app/images/coinbase logo.png
new file mode 100644
index 000000000..a23d7926d
--- /dev/null
+++ b/app/images/coinbase logo.png
Binary files differ
diff --git a/app/images/shapeshift logo.png b/app/images/shapeshift logo.png
new file mode 100644
index 000000000..ac8faba5b
--- /dev/null
+++ b/app/images/shapeshift logo.png
Binary files differ
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 55773b3b5..0d96d2b59 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -1438,7 +1438,6 @@ function pairUpdate (coin) {
function shapeShiftSubview (network) {
var pair = 'btc_eth'
-
return (dispatch) => {
dispatch(actions.showSubLoadingIndication())
shapeShiftRequest('marketinfo', {pair}, (mktResponse) => {
@@ -1464,7 +1463,7 @@ function coinShiftRquest (data, marketData) {
dispatch(actions.hideLoadingIndication())
if (response.error) return dispatch(actions.displayWarning(response.error))
var message = `
- Deposit your ${response.depositType} to the address bellow:`
+ Deposit your ${response.depositType} to the address below:`
log.debug(`background.createShapeShiftTx`)
background.createShapeShiftTx(response.deposit, response.depositType)
dispatch(actions.showQrView(response.deposit, [message].concat(marketData)))
@@ -1500,7 +1499,7 @@ function reshowQrCode (data, coin) {
if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error))
var message = [
- `Deposit your ${coin} to the address bellow:`,
+ `Deposit your ${coin} to the address below:`,
`Deposit Limit: ${mktResponse.limit}`,
`Deposit Minimum:${mktResponse.minimum}`,
]
diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js
index d735983f9..74a7a847e 100644
--- a/ui/app/components/modals/buy-options-modal.js
+++ b/ui/app/components/modals/buy-options-modal.js
@@ -69,7 +69,7 @@ BuyOptions.prototype.render = function () {
// h('div.buy-modal-content-option', {}, [
// h('div.buy-modal-content-option-title', {}, 'Shapeshift'),
// h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'),
- // ]),
+ // ]),,
this.renderModalContentOption(
'Direct Deposit',
diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js
new file mode 100644
index 000000000..3e6d3fde1
--- /dev/null
+++ b/ui/app/components/modals/deposit-ether-modal.js
@@ -0,0 +1,182 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const networkNames = require('../../../../app/scripts/config.js').networkNames
+const ShapeshiftForm = require('../shapeshift-form')
+
+const DIRECT_DEPOSIT_ROW_TITLE = 'Directly Deposit Ether'
+const DIRECT_DEPOSIT_ROW_TEXT = `If you already have some Ether, the quickest way to get Ether in
+your new wallet by direct deposit.`
+const COINBASE_ROW_TITLE = 'Buy on Coinbase'
+const COINBASE_ROW_TEXT = `Coinbase is the world’s most popular way to buy and sell bitcoin,
+ethereum, and litecoin.`
+const SHAPESHIFT_ROW_TITLE = 'Deposit with ShapeShift'
+const SHAPESHIFT_ROW_TEXT = `If you own other cryptocurrencies, you can trade and deposit Ether
+directly into your MetaMask wallet. No Account Needed.`
+const FAUCET_ROW_TITLE = 'Test Faucet'
+const facuetRowText = networkName => `Get Ether from a faucet for the ${networkName}`
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ address: state.metamask.selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ toCoinbase: (address) => {
+ dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
+ },
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ showAccountDetailModal: () => {
+ dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
+ },
+ toFaucet: network => dispatch(actions.buyEth({ network })),
+ }
+}
+
+inherits(DepositEtherModal, Component)
+function DepositEtherModal () {
+ Component.call(this)
+
+ this.state = {
+ buyingWithShapeshift: false,
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal)
+
+DepositEtherModal.prototype.renderRow = function ({
+ logo,
+ title,
+ text,
+ buttonLabel,
+ onButtonClick,
+ hide,
+ className,
+ hideButton,
+ hideTitle,
+ onBackClick,
+}) {
+ if (hide) {
+ return null
+ }
+
+ return h('div', {
+ className: className || 'deposit-ether-modal__buy-row',
+ }, [
+
+ h('div.deposit-ether-modal__buy-row__back', {
+ onClick: onBackClick,
+ }, [
+
+ h('i.fa.fa-arrow-left.cursor-pointer'),
+
+ ]),
+
+ h('div.deposit-ether-modal__buy-row__logo', [logo]),
+
+ h('div.deposit-ether-modal__buy-row__description', [
+
+ !hideTitle && h('div.deposit-ether-modal__buy-row__description__title', [title]),
+
+ h('div.deposit-ether-modal__buy-row__description__text', [text]),
+
+ ]),
+
+ !hideButton && h('div.deposit-ether-modal__buy-row__button', [
+ h('button.deposit-ether-modal__deposit-button', {
+ onClick: onButtonClick,
+ }, [buttonLabel]),
+ ]),
+
+ ])
+}
+
+DepositEtherModal.prototype.render = function () {
+ const { network, toCoinbase, address, toFaucet } = this.props
+ const { buyingWithShapeshift } = this.state
+
+ const isTestNetwork = ['3', '4', '42'].find(n => n === network)
+ const networkName = networkNames[network]
+
+ return h('div.deposit-ether-modal', {}, [
+
+ h('div.deposit-ether-modal__header', [
+
+ h('div.deposit-ether-modal__header__title', ['Deposit Ether']),
+
+ h('div.deposit-ether-modal__header__description', [
+ 'To interact with decentralized applications using MetaMask, you’ll need Ether in your wallet.',
+ ]),
+
+ h('div.deposit-ether-modal__header__close', {
+ onClick: () => {
+ this.setState({ buyingWithShapeshift: false })
+ this.props.hideModal()
+ },
+ }),
+
+ ]),
+
+ h('div.deposit-ether-modal__buy-rows', [
+
+ this.renderRow({
+ logo: h('img.deposit-ether-modal__buy-row__eth-logo', { src: '../../../images/eth_logo.svg' }),
+ title: DIRECT_DEPOSIT_ROW_TITLE,
+ text: DIRECT_DEPOSIT_ROW_TEXT,
+ buttonLabel: 'View Account',
+ onButtonClick: () => this.goToAccountDetailsModal(),
+ hide: buyingWithShapeshift,
+ }),
+
+ this.renderRow({
+ logo: h('i.fa.fa-tint.fa-2x'),
+ title: FAUCET_ROW_TITLE,
+ text: facuetRowText(networkName),
+ buttonLabel: 'Get Ether',
+ onButtonClick: () => toFaucet(network),
+ hide: !isTestNetwork || buyingWithShapeshift,
+ }),
+
+ this.renderRow({
+ logo: h('img.deposit-ether-modal__buy-row__coinbase-logo', {
+ src: '../../../images/coinbase logo.png',
+ }),
+ title: COINBASE_ROW_TITLE,
+ text: COINBASE_ROW_TEXT,
+ buttonLabel: 'Continue to Coinbase',
+ onButtonClick: () => toCoinbase(address),
+ hide: isTestNetwork || buyingWithShapeshift,
+ }),
+
+ this.renderRow({
+ logo: h('img.deposit-ether-modal__buy-row__shapeshift-logo', {
+ src: '../../../images/shapeshift logo.png',
+ }),
+ title: SHAPESHIFT_ROW_TITLE,
+ text: SHAPESHIFT_ROW_TEXT,
+ buttonLabel: 'Buy with Shapeshift',
+ onButtonClick: () => this.setState({ buyingWithShapeshift: true }),
+ hide: isTestNetwork,
+ hideButton: buyingWithShapeshift,
+ hideTitle: buyingWithShapeshift,
+ onBackClick: () => this.setState({ buyingWithShapeshift: false }),
+ className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy',
+ }),
+
+ buyingWithShapeshift && h(ShapeshiftForm),
+
+ ]),
+ ])
+}
+
+DepositEtherModal.prototype.goToAccountDetailsModal = function () {
+ this.props.hideModal()
+ this.props.showAccountDetailModal()
+}
diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js
index 2ff6accaa..afb2a2175 100644
--- a/ui/app/components/modals/modal.js
+++ b/ui/app/components/modals/modal.js
@@ -9,6 +9,7 @@ const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-n
// Modal Components
const BuyOptions = require('./buy-options-modal')
+const DepositEtherModal = require('./deposit-ether-modal')
const AccountDetailsModal = require('./account-details-modal')
const EditAccountNameModal = require('./edit-account-name-modal')
const ExportPrivateKeyModal = require('./export-private-key-modal')
@@ -73,6 +74,37 @@ const MODALS = {
},
},
+ DEPOSIT_ETHER: {
+ contents: [
+ h(DepositEtherModal, {}, []),
+ ],
+ mobileModalStyle: {
+ width: '100%',
+ height: '100%',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)',
+ top: '0',
+ display: 'flex',
+ },
+ laptopModalStyle: {
+ width: '900px',
+ maxWidth: '900px',
+ top: 'calc(10% + 10px)',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ boxShadow: '0 0 6px 0 rgba(0,0,0,0.3)',
+ borderRadius: '8px',
+ transform: 'none',
+ },
+ contentStyle: {
+ borderRadius: '8px',
+ },
+ },
+
EDIT_ACCOUNT_NAME: {
contents: [
h(EditAccountNameModal, {}, []),
diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js
index c5993e3d3..2270b8236 100644
--- a/ui/app/components/shapeshift-form.js
+++ b/ui/app/components/shapeshift-form.js
@@ -1,308 +1,242 @@
-const PersistentForm = require('../../lib/persistent-form')
const h = require('react-hyperscript')
const inherits = require('util').inherits
+const Component = require('react').Component
const connect = require('react-redux').connect
-const actions = require('../actions')
-const Qr = require('./qr-code')
-const isValidAddress = require('../util').isValidAddress
-module.exports = connect(mapStateToProps)(ShapeshiftForm)
+const classnames = require('classnames')
+const { qrcode } = require('qrcode-npm')
+const { shapeShiftSubview, pairUpdate, buyWithShapeShift } = require('../actions')
+const { isValidAddress } = require('../util')
+const SimpleDropdown = require('./dropdowns/simple-dropdown')
function mapStateToProps (state) {
+ const {
+ coinOptions,
+ tokenExchangeRates,
+ selectedAddress,
+ } = state.metamask
+
return {
- warning: state.appState.warning,
- isSubLoading: state.appState.isSubLoading,
- qrRequested: state.appState.qrRequested,
+ coinOptions,
+ tokenExchangeRates,
+ selectedAddress,
}
}
-inherits(ShapeshiftForm, PersistentForm)
+function mapDispatchToProps (dispatch) {
+ return {
+ shapeShiftSubview: () => dispatch(shapeShiftSubview()),
+ pairUpdate: coin => dispatch(pairUpdate(coin)),
+ buyWithShapeShift: data => dispatch(buyWithShapeShift(data)),
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftForm)
+inherits(ShapeshiftForm, Component)
function ShapeshiftForm () {
- PersistentForm.call(this)
- this.persistentFormParentId = 'shapeshift-buy-form'
+ Component.call(this)
+
+ this.state = {
+ depositCoin: 'btc',
+ refundAddress: '',
+ showQrCode: false,
+ depositAddress: '',
+ errorMessage: '',
+ isLoading: false,
+ bought: false,
+ }
}
-ShapeshiftForm.prototype.render = function () {
- return this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain()
+ShapeshiftForm.prototype.componentWillMount = function () {
+ this.props.shapeShiftSubview()
}
-ShapeshiftForm.prototype.renderMain = function () {
- const marketinfo = this.props.buyView.formView.marketinfo
- const coinOptions = this.props.buyView.formView.coinOptions
- var coin = marketinfo.pair.split('_')[0].toUpperCase()
-
- return h('.flex-column', {
- style: {
- position: 'relative',
- padding: '25px',
- paddingTop: '5px',
- width: '90%',
- minHeight: '215px',
- alignItems: 'center',
- overflowY: 'auto',
- },
- }, [
- h('.flex-row', {
- style: {
- justifyContent: 'center',
- alignItems: 'baseline',
- height: '42px',
- },
- }, [
- h('img', {
- src: coinOptions[coin].image,
- width: '25px',
- height: '25px',
- style: {
- marginRight: '5px',
- },
- }),
-
- h('.input-container', {
- position: 'relative',
- }, [
- h('input#fromCoin.buy-inputs.ex-coins', {
- type: 'text',
- list: 'coinList',
- autoFocus: true,
- dataset: {
- persistentFormId: 'input-coin',
- },
- style: {
- boxSizing: 'border-box',
- },
- onChange: this.handleLiveInput.bind(this),
- defaultValue: 'BTC',
- }),
+ShapeshiftForm.prototype.onCoinChange = function (e) {
+ const coin = e.target.value
+ this.setState({
+ depositCoin: coin,
+ errorMessage: '',
+ })
+ this.props.pairUpdate(coin)
+}
- this.renderCoinList(),
+ShapeshiftForm.prototype.onBuyWithShapeShift = function () {
+ this.setState({
+ isLoading: true,
+ showQrCode: true,
+ })
- h('i.fa.fa-pencil-square-o.edit-text', {
- style: {
- fontSize: '12px',
- color: '#F7861C',
- position: 'absolute',
- },
- }),
- ]),
+ const {
+ buyWithShapeShift,
+ selectedAddress: withdrawal,
+ } = this.props
+ const {
+ refundAddress: returnAddress,
+ depositCoin,
+ } = this.state
+ const pair = `${depositCoin}_eth`
+ const data = {
+ withdrawal,
+ pair,
+ returnAddress,
+ // Public api key
+ 'apiKey': '803d1f5df2ed1b1476e4b9e6bcd089e34d8874595dda6a23b67d93c56ea9cc2445e98a6748b219b2b6ad654d9f075f1f1db139abfa93158c04e825db122c14b6',
+ }
- h('.icon-control', {
- style: {
- position: 'relative',
- },
- }, [
- // Not visible on the screen, can't see it on master.
-
- // h('i.fa.fa-refresh.fa-4.orange', {
- // style: {
- // bottom: '5px',
- // left: '5px',
- // color: '#F7861C',
- // },
- // onClick: this.updateCoin.bind(this),
- // }),
- h('i.fa.fa-chevron-right.fa-4.orange', {
- style: {
- position: 'absolute',
- bottom: '35%',
- left: '0%',
- color: '#F7861C',
- },
- onClick: this.updateCoin.bind(this),
- }),
- ]),
+ if (isValidAddress(withdrawal)) {
+ buyWithShapeShift(data)
+ .then(d => this.setState({
+ showQrCode: true,
+ depositAddress: d.deposit,
+ isLoading: false,
+ }))
+ .catch(() => this.setState({
+ showQrCode: false,
+ errorMessage: 'Invalid Request',
+ isLoading: false,
+ }))
+ }
+}
- h('#toCoin.ex-coins', marketinfo.pair.split('_')[1].toUpperCase()),
+ShapeshiftForm.prototype.renderMetadata = function (label, value) {
+ return h('div', {className: 'shapeshift-form__metadata-wrapper'}, [
- h('img', {
- src: coinOptions[marketinfo.pair.split('_')[1].toUpperCase()].image,
- width: '25px',
- height: '25px',
- style: {
- marginLeft: '5px',
- },
- }),
+ h('div.shapeshift-form__metadata-label', {}, [
+ h('span', `${label}:`),
]),
- h('.flex-column', {
- style: {
- marginTop: '1%',
- alignItems: 'flex-start',
- },
- }, [
- this.props.warning ?
- this.props.warning &&
- h('span.error.flex-center', {
- style: {
- textAlign: 'center',
- width: '229px',
- height: '82px',
- },
- }, this.props.warning)
- : this.renderInfo(),
-
- this.renderRefundAddressForCoin(coin),
+ h('div.shapeshift-form__metadata-value', {}, [
+ h('span', value),
]),
])
}
-ShapeshiftForm.prototype.renderRefundAddressForCoin = function (coin) {
- return h(this.activeToggle('.input-container'), {
- style: {
- marginTop: '1%',
- },
- }, [
-
- h('div', `${coin} Address:`),
-
- h('input#fromCoinAddress.buy-inputs', {
- type: 'text',
- placeholder: `Your ${coin} Refund Address`,
- dataset: {
- persistentFormId: 'refund-address',
-
- },
- style: {
- boxSizing: 'border-box',
- width: '227px',
- height: '30px',
- padding: ' 5px ',
- },
- }),
-
- h('i.fa.fa-pencil-square-o.edit-text', {
- style: {
- fontSize: '12px',
- color: '#F7861C',
- position: 'absolute',
- },
- }),
- h('div.flex-row', {
- style: {
- justifyContent: 'flex-start',
- },
- }, [
- h('button', {
- onClick: this.shift.bind(this),
- style: {
- marginTop: '1%',
- },
- },
- 'Submit'),
- ]),
+ShapeshiftForm.prototype.renderMarketInfo = function () {
+ const { depositCoin } = this.state
+ const coinPair = `${depositCoin}_eth`
+ const { tokenExchangeRates } = this.props
+ const {
+ limit,
+ rate,
+ minimum,
+ } = tokenExchangeRates[coinPair] || {}
+
+ return h('div.shapeshift-form__metadata', {}, [
+
+ this.renderMetadata('Status', limit ? 'Available' : 'Unavailable'),
+ this.renderMetadata('Limit', limit),
+ this.renderMetadata('Exchange Rate', rate),
+ this.renderMetadata('Minimum', minimum),
+
])
}
-ShapeshiftForm.prototype.shift = function () {
- var props = this.props
- var withdrawal = this.props.buyView.buyAddress
- var returnAddress = document.getElementById('fromCoinAddress').value
- var pair = this.props.buyView.formView.marketinfo.pair
- var data = {
- 'withdrawal': withdrawal,
- 'pair': pair,
- 'returnAddress': returnAddress,
- // Public api key
- 'apiKey': '803d1f5df2ed1b1476e4b9e6bcd089e34d8874595dda6a23b67d93c56ea9cc2445e98a6748b219b2b6ad654d9f075f1f1db139abfa93158c04e825db122c14b6',
- }
- var message = [
- `Deposit Limit: ${props.buyView.formView.marketinfo.limit}`,
- `Deposit Minimum:${props.buyView.formView.marketinfo.minimum}`,
- ]
- if (isValidAddress(withdrawal)) {
- this.props.dispatch(actions.coinShiftRquest(data, message))
- }
-}
+ShapeshiftForm.prototype.renderQrCode = function () {
+ const { depositAddress, isLoading } = this.state
+ const qrImage = qrcode(4, 'M')
+ qrImage.addData(depositAddress)
+ qrImage.make()
-ShapeshiftForm.prototype.renderCoinList = function () {
- var list = Object.keys(this.props.buyView.formView.coinOptions).map((item) => {
- return h('option', {
- value: item,
- }, item)
- })
+ return h('div.shapeshift-form', {}, [
- return h('datalist#coinList', {
- onClick: (event) => {
- event.preventDefault()
- },
- }, list)
-}
+ h('div.shapeshift-form__deposit-instruction', [
+ 'Deposit your BTC to the address below:',
+ ]),
-ShapeshiftForm.prototype.updateCoin = function (event) {
- event.preventDefault()
- const props = this.props
- var coinOptions = this.props.buyView.formView.coinOptions
- var coin = document.getElementById('fromCoin').value
-
- if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') {
- var message = 'Not a valid coin'
- return props.dispatch(actions.displayWarning(message))
- } else {
- return props.dispatch(actions.pairUpdate(coin))
- }
-}
+ h('div', depositAddress),
-ShapeshiftForm.prototype.handleLiveInput = function () {
- const props = this.props
- var coinOptions = this.props.buyView.formView.coinOptions
- var coin = document.getElementById('fromCoin').value
+ h('div.shapeshift-form__qr-code', [
+ isLoading
+ ? h('img', {
+ src: 'images/loading.svg',
+ style: { width: '60px'},
+ })
+ : h('div', {
+ dangerouslySetInnerHTML: { __html: qrImage.createTableTag(4) },
+ }),
+ ]),
- if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') {
- return null
- } else {
- return props.dispatch(actions.pairUpdate(coin))
- }
-}
+ this.renderMarketInfo(),
-ShapeshiftForm.prototype.renderInfo = function () {
- const marketinfo = this.props.buyView.formView.marketinfo
- const coinOptions = this.props.buyView.formView.coinOptions
- var coin = marketinfo.pair.split('_')[0].toUpperCase()
-
- return h('span', {
- style: {
- },
- }, [
- h('h3.flex-row.text-transform-uppercase', {
- style: {
- color: '#868686',
- paddingTop: '4px',
- justifyContent: 'space-around',
- textAlign: 'center',
- fontSize: '17px',
- },
- }, `Market Info for ${marketinfo.pair.replace('_', ' to ').toUpperCase()}:`),
- h('.marketinfo', ['Status : ', `${coinOptions[coin].status}`]),
- h('.marketinfo', ['Exchange Rate: ', `${marketinfo.rate}`]),
- h('.marketinfo', ['Limit: ', `${marketinfo.limit}`]),
- h('.marketinfo', ['Minimum : ', `${marketinfo.minimum}`]),
])
}
-ShapeshiftForm.prototype.activeToggle = function (elementType) {
- if (!this.props.buyView.formView.response || this.props.warning) return elementType
- return `${elementType}.inactive`
-}
-ShapeshiftForm.prototype.renderLoading = function () {
- return h('span', {
- style: {
- position: 'absolute',
- left: '70px',
- bottom: '194px',
- background: 'transparent',
- width: '229px',
- height: '82px',
- display: 'flex',
- justifyContent: 'center',
- },
- }, [
- h('img', {
- style: {
- width: '60px',
- },
- src: 'images/loading.svg',
- }),
- ])
+ShapeshiftForm.prototype.render = function () {
+ const { coinOptions, btnClass } = this.props
+ const { depositCoin, errorMessage, showQrCode, depositAddress } = this.state
+ const coinPair = `${depositCoin}_eth`
+ const { tokenExchangeRates } = this.props
+ const token = tokenExchangeRates[coinPair]
+
+ return h('div.shapeshift-form-wrapper', [
+ showQrCode
+ ? this.renderQrCode()
+ : h('div.shapeshift-form', [
+ h('div.shapeshift-form__selectors', [
+
+ h('div.shapeshift-form__selector', [
+
+ h('div.shapeshift-form__selector-label', 'Deposit'),
+
+ h(SimpleDropdown, {
+ selectedOption: this.state.depositCoin,
+ onSelect: this.onCoinChange,
+ options: Object.entries(coinOptions).map(([coin]) => ({
+ value: coin.toLowerCase(),
+ displayValue: coin,
+ })),
+ }),
+
+ ]),
+
+ h('div.icon.shapeshift-form__caret', {
+ style: { backgroundImage: 'url(images/caret-right.svg)'},
+ }),
+
+ h('div.shapeshift-form__selector', [
+
+ h('div.shapeshift-form__selector-label', [
+ 'Receive',
+ ]),
+
+ h('div.shapeshift-form__selector-input', ['ETH']),
+
+ ]),
+
+ ]),
+
+ h('div', {
+ className: classnames('shapeshift-form__address-input-wrapper', {
+ 'shapeshift-form__address-input-wrapper--error': errorMessage,
+ }),
+ }, [
+
+ h('div.shapeshift-form__address-input-label', [
+ 'Your Refund Address',
+ ]),
+
+ h('input.shapeshift-form__address-input', {
+ type: 'text',
+ onChange: e => this.setState({
+ refundAddress: e.target.value,
+ errorMessage: '',
+ }),
+ }),
+
+ h('divshapeshift-form__address-input-error-message', [errorMessage]),
+ ]),
+
+ this.renderMarketInfo(),
+
+ ]),
+
+ !depositAddress && h('button.shapeshift-form__shapeshift-buy-btn', {
+ className: btnClass,
+ disabled: !token,
+ onClick: () => this.onBuyWithShapeShift(),
+ }, ['Buy']),
+
+ ])
}
diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js
index 43973de63..111a77df4 100644
--- a/ui/app/components/shift-list-item.js
+++ b/ui/app/components/shift-list-item.js
@@ -16,6 +16,7 @@ module.exports = connect(mapStateToProps)(ShiftListItem)
function mapStateToProps (state) {
return {
+ selectedAddress: state.metamask.selectedAddress,
conversionRate: state.metamask.conversionRate,
currentCurrency: state.metamask.currentCurrency,
}
@@ -28,36 +29,39 @@ function ShiftListItem () {
}
ShiftListItem.prototype.render = function () {
+ const { selectedAddress, receivingAddress } = this.props
return (
- h('div.tx-list-item.tx-list-clickable', {
- style: {
- paddingTop: '20px',
- paddingBottom: '20px',
- justifyContent: 'space-around',
- alignItems: 'center',
- },
- }, [
- h('div', {
+ selectedAddress === receivingAddress
+ ? h('div.tx-list-item.tx-list-clickable', {
style: {
- width: '0px',
- position: 'relative',
- bottom: '19px',
+ paddingTop: '20px',
+ paddingBottom: '20px',
+ justifyContent: 'space-around',
+ alignItems: 'center',
},
}, [
- h('img', {
- src: 'https://info.shapeshift.io/sites/default/files/logo.png',
+ h('div', {
style: {
- height: '35px',
- width: '132px',
- position: 'absolute',
- clip: 'rect(0px,23px,34px,0px)',
+ width: '0px',
+ position: 'relative',
+ bottom: '19px',
},
- }),
- ]),
+ }, [
+ h('img', {
+ src: 'https://info.shapeshift.io/sites/default/files/logo.png',
+ style: {
+ height: '35px',
+ width: '132px',
+ position: 'absolute',
+ clip: 'rect(0px,23px,34px,0px)',
+ },
+ }),
+ ]),
- this.renderInfo(),
- this.renderUtilComponents(),
- ])
+ this.renderInfo(),
+ this.renderUtilComponents(),
+ ])
+ : null
)
}
diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js
index 70722f43e..50e328dac 100644
--- a/ui/app/components/tx-list.js
+++ b/ui/app/components/tx-list.js
@@ -52,7 +52,7 @@ TxList.prototype.render = function () {
TxList.prototype.renderTransaction = function () {
const { txsToRender, conversionRate } = this.props
return txsToRender.length
- ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate))
+ ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate, i))
: [h(
'div.tx-list-item.tx-list-item--empty',
{ key: 'tx-list-none' },
@@ -61,12 +61,16 @@ TxList.prototype.renderTransaction = function () {
}
// TODO: Consider moving TxListItem into a separate component
-TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) {
+TxList.prototype.renderTransactionListItem = function (transaction, conversionRate, index) {
// console.log({transaction})
// refer to transaction-list.js:line 58
if (transaction.key === 'shapeshift') {
- return h(ShiftListItem, transaction)
+ return h('div', {
+ key: `shapeshift${index}`,
+ }, [
+ h(ShiftListItem, transaction),
+ ])
}
const props = {
diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js
index e42a20c85..949d91f6f 100644
--- a/ui/app/components/tx-view.js
+++ b/ui/app/components/tx-view.js
@@ -73,7 +73,7 @@ TxView.prototype.renderButtons = function () {
textAlign: 'center',
},
onClick: () => showModal({
- name: 'BUY',
+ name: 'DEPOSIT_ETHER',
}),
}, 'DEPOSIT'),
diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss
index 9b64564d6..2431e2f63 100644
--- a/ui/app/css/itcss/components/modal.scss
+++ b/ui/app/css/itcss/components/modal.scss
@@ -598,4 +598,256 @@
justify-content: center;
font-size: 17px;
color: $nile-blue;
-} \ No newline at end of file
+}
+
+// Deposit Ether Modal
+.deposit-ether-modal {
+ border-radius: 8px;
+ font-family: Roboto;
+ display: flex;
+ flex-flow: column;
+ height: 100%;
+
+ &__header {
+ width: 100%;
+ border-radius: 8px 8px 0 0;
+ background-color: $mid-gray;
+ display: flex;
+ position: relative;
+ padding: 25px;
+ flex-flow: column;
+ align-items: flex-start;
+
+ &__title {
+ color: $white;
+ font-size: 24px;
+ line-height: 32px;
+ }
+
+ &__description {
+ color: $white;
+ font-size: 16px;
+ line-height: 22px;
+ margin-top: 10px;
+ }
+
+ &__close::after {
+ content: '\00D7';
+ font-size: 2em;
+ color: $white;
+ position: absolute;
+ top: 20.8px;
+ right: 28px;
+ cursor: pointer;
+ }
+ }
+
+ &__buy-rows {
+ width: 100%;
+ padding: 33px;
+ padding-top: 0px;
+ display: flex;
+ flex-flow: column nowrap;
+ flex: 1;
+ overflow-y: auto;
+
+ @media screen and (max-width: 575px) {
+ height: 0;
+ }
+ }
+
+ &__buy-row {
+ border-bottom: 1px solid $alto;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex: 1;
+ padding-bottom: 25px;
+ padding-top: 25px;
+
+ @media screen and (max-width: 575px) {
+ min-height: 360px;
+ flex-flow: column;
+ justify-content: center;
+ padding-top: 45px;
+ }
+
+ &__back {
+ position: absolute;
+ top: 10px;
+ left: 0px;
+ }
+
+ &__shapeshift-buy {
+ padding-top: 25px;
+ position: relative;
+ @media screen and (max-width: 575px) {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex: 1;
+ padding-bottom: 25px;
+ flex-flow: column;
+ justify-content: center;
+ padding-top: 20px;
+ min-height: 240px;
+ border: none;
+ }
+ }
+
+ &__logo {
+ display: flex;
+ justify-content: center;
+ flex: 0.3 1 auto;
+
+ @media screen and (min-width: 575px) {
+ min-width: 215px;
+ }
+ }
+
+ &__coinbase-logo {
+ height: 40px;
+ width: 180px;
+ }
+
+ &__shapeshift-logo {
+ height: 60px;
+ width: 174px;
+ }
+
+ &__eth-logo {
+ border-radius: 50%;
+ width: 68px;
+ height: 68px;
+ border: 3px solid $tundora;
+ z-index: 25;
+ padding: 4px;
+ background-color: #fff;
+ }
+
+ &__right {
+ display: flex;
+ }
+
+ &__description {
+ color: $cape-cod;
+ flex: 0.5 1 auto;
+
+ @media screen and (min-width: 575px) {
+ min-width: 315px;
+ }
+
+ &__title {
+ font-size: 20px;
+ line-height: 30px;
+ }
+
+ &__text {
+ font-size: 14px;
+ line-height: 22px;
+ margin-top: 7px;
+ }
+ }
+
+ &__button {
+ display: flex;
+ justify-content: flex-end;
+
+ @media screen and (min-width: 575px) {
+ min-width: 300px;
+ }
+ }
+ }
+
+ &__buy-row:last-of-type {
+ border-bottom: 0px;
+ }
+
+ &__deposit-button, .shapeshift-form__shapeshift-buy-btn {
+ height: 54px;
+ width: 257px;
+ border: 1px solid $curious-blue;
+ border-radius: 4px;
+ display: flex;
+ justify-content: center;
+ font-size: 16px;
+ color: $curious-blue;
+ background-color: $white;
+ }
+
+ .shapeshift-form-wrapper {
+ display: flex;
+ flex-flow: column;
+ justify-content: center;
+ align-items: center;
+ margin-top: 28px;
+ flex: 1 0 auto;
+
+ .shapeshift-form {
+ width: auto;
+
+ &__caret {
+ width: auto;
+ flex: 1;
+ }
+ }
+ }
+
+ .shapeshift-form__shapeshift-buy-btn {
+ margin-top: 10px;
+ }
+
+ .simple-dropdown {
+ color: #5B5D67;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 21px;
+ border: 1px solid #D8D8D8;
+ background-color: #FFFFFF;
+ text-align: center;
+ width: 100%;
+ height: 45px;
+ line-height: 44px;
+ font-family: Montserrat Light;
+ }
+
+ .simple-dropdown__selected {
+ text-align: center;
+ }
+}
+
+//Notification Modal
+
+.notification-modal-wrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ position: relative;
+ border: 1px solid $alto;
+ box-shadow: 0 0 2px 2px $alto;
+ font-family: Roboto;
+}
+
+.notification-modal-header {
+ background: $wild-sand;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ padding: 30px;
+ font-size: 22px;
+ color: $nile-blue;
+ height: 79px;
+}
+
+.notification-modal-message {
+ padding: 20px;
+}
+
+.notification-modal-message {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ font-size: 17px;
+ color: $nile-blue;
+}
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
index 387d14b5f..edc376c17 100644
--- a/ui/app/css/itcss/settings/variables.scss
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -42,6 +42,8 @@ $malibu-blue: #7ac9fd;
$athens-grey: #e9edf0;
$jaffa: #f28930;
$geyser: #d2d8dd;
+$mid-gray: #5b5d67;
+$cape-cod: #38393a;
/*
Z-Indicies
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 3a4fb536d..e96dea0be 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -58,6 +58,7 @@ function reduceApp (state, action) {
isLoading: false,
// Used to display error text
warning: null,
+ buyView: {},
}, state.appState)
switch (action.type) {
@@ -591,8 +592,8 @@ function reduceApp (state, action) {
marketinfo: action.value.marketinfo,
coinOptions: action.value.coinOptions,
},
- buyAddress: appState.buyView.buyAddress,
- amount: appState.buyView.amount,
+ buyAddress: action.value.buyAddress || appState.buyView.buyAddress,
+ amount: appState.buyView.amount || 0,
},
})
diff --git a/yarn.lock b/yarn.lock
index 3a22dcf98..f9c705843 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -508,7 +508,7 @@ async-eventemitter@^0.2.2:
dependencies:
async "^2.4.0"
-"async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c":
+async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c:
version "0.2.3"
resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c"
dependencies:
@@ -2210,10 +2210,6 @@ clone-stats@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680"
-clone@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f"
-
clone@^1.0.0, clone@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f"
@@ -11141,12 +11137,12 @@ vinyl-fs@^3.0.0:
vinyl "^2.0.0"
vinyl-sourcemap "^1.1.0"
-vinyl-source-stream@^1.1.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780"
+vinyl-source-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-2.0.0.tgz#f38a5afb9dd1e93b65d550469ac6182ac4f54b8e"
dependencies:
through2 "^2.0.3"
- vinyl "^0.4.3"
+ vinyl "^2.1.0"
vinyl-sourcemap@^1.1.0:
version "1.1.0"
@@ -11166,13 +11162,6 @@ vinyl-sourcemaps-apply@^0.2.0:
dependencies:
source-map "^0.5.1"
-vinyl@^0.4.3:
- version "0.4.6"
- resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
- dependencies:
- clone "^0.2.0"
- clone-stats "^0.0.1"
-
vinyl@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde"
@@ -11189,7 +11178,7 @@ vinyl@^1.1.0, vinyl@^1.2.0:
clone-stats "^0.0.1"
replace-ext "0.0.1"
-vinyl@^2.0.0:
+vinyl@^2.0.0, vinyl@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c"
dependencies: