diff options
Diffstat (limited to 'mascara/src/app/shapeshift-form/index.js')
-rw-r--r-- | mascara/src/app/shapeshift-form/index.js | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/mascara/src/app/shapeshift-form/index.js b/mascara/src/app/shapeshift-form/index.js new file mode 100644 index 000000000..15c7e95e1 --- /dev/null +++ b/mascara/src/app/shapeshift-form/index.js @@ -0,0 +1,217 @@ +import React, {Component, PropTypes} from 'react' +import classnames from 'classnames' +import {qrcode} from 'qrcode-npm' +import {connect} from 'react-redux' +import {shapeShiftSubview, pairUpdate, buyWithShapeShift} from '../../../../ui/app/actions' +import {isValidAddress} from '../../../../ui/app/util' + +export class ShapeShiftForm extends Component { + static propTypes = { + selectedAddress: PropTypes.string.isRequired, + btnClass: PropTypes.string.isRequired, + tokenExchangeRates: PropTypes.object.isRequired, + coinOptions: PropTypes.object.isRequired, + shapeShiftSubview: PropTypes.func.isRequired, + pairUpdate: PropTypes.func.isRequired, + buyWithShapeShift: PropTypes.func.isRequired, + }; + + state = { + depositCoin: 'btc', + refundAddress: '', + showQrCode: false, + depositAddress: '', + errorMessage: '', + isLoading: false, + }; + + componentWillMount () { + this.props.shapeShiftSubview() + } + + onCoinChange = e => { + const coin = e.target.value + this.setState({ + depositCoin: coin, + errorMessage: '', + }) + this.props.pairUpdate(coin) + } + + onBuyWithShapeShift = () => { + this.setState({ + isLoading: true, + showQrCode: true, + }) + + 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', + } + + 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, + })) + } + } + + renderMetadata (label, value) { + return ( + <div className='shapeshift-form__metadata-wrapper'> + <div className='shapeshift-form__metadata-label'> + {label}: + </div> + <div className='shapeshift-form__metadata-value'> + {value} + </div> + </div> + ) + } + + renderMarketInfo () { + const { depositCoin } = this.state + const coinPair = `${depositCoin}_eth` + const { tokenExchangeRates } = this.props + const { + limit, + rate, + minimum, + } = tokenExchangeRates[coinPair] || {} + + return ( + <div className='shapeshift-form__metadata'> + {this.renderMetadata('Status', limit ? 'Available' : 'Unavailable')} + {this.renderMetadata('Limit', limit)} + {this.renderMetadata('Exchange Rate', rate)} + {this.renderMetadata('Minimum', minimum)} + </div> + ) + } + + renderQrCode () { + const { depositAddress, isLoading } = this.state + const qrImage = qrcode(4, 'M') + qrImage.addData(depositAddress) + qrImage.make() + + return ( + <div className='shapeshift-form'> + <div className='shapeshift-form__deposit-instruction'> + Deposit your BTC to the address bellow: + </div> + <div className='shapeshift-form__qr-code'> + {isLoading + ? <img src='images/loading.svg' style={{ width: '60px' }} /> + : <div dangerouslySetInnerHTML={{ __html: qrImage.createTableTag(4) }} /> + } + </div> + {this.renderMarketInfo()} + </div> + ) + } + + render () { + const { coinOptions, btnClass } = this.props + const { depositCoin, errorMessage, showQrCode } = this.state + const coinPair = `${depositCoin}_eth` + const { tokenExchangeRates } = this.props + const token = tokenExchangeRates[coinPair] + + return showQrCode ? this.renderQrCode() : ( + <div> + <div className='shapeshift-form'> + <div className='shapeshift-form__selectors'> + <div className='shapeshift-form__selector'> + <div className='shapeshift-form__selector-label'> + Deposit + </div> + <select + className='shapeshift-form__selector-input' + value={this.state.depositCoin} + onChange={this.onCoinChange} + > + {Object.entries(coinOptions).map(([coin]) => ( + <option key={coin} value={coin.toLowerCase()}> + {coin} + </option> + ))} + </select> + </div> + <div + className='icon shapeshift-form__caret' + style={{ backgroundImage: 'url(images/caret-right.svg)'}} + /> + <div className='shapeshift-form__selector'> + <div className='shapeshift-form__selector-label'> + Receive + </div> + <div className='shapeshift-form__selector-input'> + ETH + </div> + </div> + </div> + <div + className={classnames('shapeshift-form__address-input-wrapper', { + 'shapeshift-form__address-input-wrapper--error': errorMessage, + })} + > + <div className='shapeshift-form__address-input-label'> + Your Refund Address + </div> + <input + type='text' + className='shapeshift-form__address-input' + onChange={e => this.setState({ + refundAddress: e.target.value, + errorMessage: '', + })} + /> + <div className='shapeshift-form__address-input-error-message'> + {errorMessage} + </div> + </div> + {this.renderMarketInfo()} + </div> + <button + className={btnClass} + disabled={!token} + onClick={this.onBuyWithShapeShift} + > + Buy + </button> + </div> + ) + } +} + +export default connect( + ({ metamask: { coinOptions, tokenExchangeRates, selectedAddress } }) => ({ + coinOptions, tokenExchangeRates, selectedAddress, + }), + dispatch => ({ + shapeShiftSubview: () => dispatch(shapeShiftSubview()), + pairUpdate: coin => dispatch(pairUpdate(coin)), + buyWithShapeShift: data => dispatch(buyWithShapeShift(data)), + }) +)(ShapeShiftForm) |