From 0eae13f938b34f69ccb76d1869ad92f86ff97ad1 Mon Sep 17 00:00:00 2001 From: Daniel Ternyak Date: Sat, 22 Jul 2017 16:24:03 -0500 Subject: [PATCH] Swap Cleanup (#68) * add types for swap action creators (and separate out to separate module) * DRY up swapInformation and onGoingSwapInformation -> SwapInfoHeader. * stop bity rate loading when Swap will unmount * split out SimpleDropdown to separate module * various additional refactors --- common/actions/swap.js | 69 ++++--- common/actions/swapConstants.js | 4 +- common/actions/swapTypes.js | 66 ++++++ common/api/bity.js | 4 +- common/components/Footer/index.jsx | 4 +- common/components/ui/SimpleDropdown.js | 32 +++ common/config/data.js | 2 + .../Tabs/Swap/components/CurrencySwap.js | 151 ++++++++++++++ .../{currentRates.js => CurrentRates.js} | 50 ++--- ...eceivingAddress.js => ReceivingAddress.js} | 41 ++-- .../Tabs/Swap/components/SwapInfoHeader.js | 142 +++++++++++++ .../{swapProgress.js => SwapProgress.js} | 57 ++--- .../Tabs/Swap/components/currencySwap.js | 163 --------------- .../Swap/components/onGoingSwapInformation.js | 87 -------- .../Tabs/Swap/components/swapInformation.js | 79 ------- common/containers/Tabs/Swap/index.js | 194 +++++++++--------- common/reducers/swap.js | 33 +-- common/utils/formatters.js | 4 + 18 files changed, 646 insertions(+), 536 deletions(-) create mode 100644 common/actions/swapTypes.js create mode 100644 common/components/ui/SimpleDropdown.js create mode 100644 common/containers/Tabs/Swap/components/CurrencySwap.js rename common/containers/Tabs/Swap/components/{currentRates.js => CurrentRates.js} (69%) rename common/containers/Tabs/Swap/components/{receivingAddress.js => ReceivingAddress.js} (66%) create mode 100644 common/containers/Tabs/Swap/components/SwapInfoHeader.js rename common/containers/Tabs/Swap/components/{swapProgress.js => SwapProgress.js} (56%) delete mode 100644 common/containers/Tabs/Swap/components/currencySwap.js delete mode 100644 common/containers/Tabs/Swap/components/onGoingSwapInformation.js delete mode 100644 common/containers/Tabs/Swap/components/swapInformation.js diff --git a/common/actions/swap.js b/common/actions/swap.js index fa891b12..dc209571 100644 --- a/common/actions/swap.js +++ b/common/actions/swap.js @@ -1,86 +1,103 @@ +// @flow import { SWAP_DESTINATION_AMOUNT, SWAP_DESTINATION_KIND, SWAP_ORIGIN_AMOUNT, SWAP_ORIGIN_KIND, SWAP_UPDATE_BITY_RATES, - SWAP_PART_ONE_COMPLETE, - SWAP_PART_TWO_COMPLETE, SWAP_DESTINATION_ADDRESS, SWAP_RESTART, SWAP_LOAD_BITY_RATES, - SWAP_STOP_LOAD_BITY_RATES + SWAP_STOP_LOAD_BITY_RATES, + SWAP_STEP, + SWAP_REFERENCE_NUMBER } from './swapConstants'; -export const originKindSwap = value => { +import * as swapTypes from './swapTypes'; + +export function changeStepSwap(value: number): swapTypes.ChangeStepSwapAction { + return { + type: SWAP_STEP, + value + }; +} + +export function referenceNumberSwap( + value: string +): swapTypes.ReferenceNumberSwapAction { + return { + type: SWAP_REFERENCE_NUMBER, + value + }; +} + +export const originKindSwap = ( + value: string +): swapTypes.OriginKindSwapAction => { return { type: SWAP_ORIGIN_KIND, value }; }; -export const destinationKindSwap = value => { +export const destinationKindSwap = ( + value: string +): swapTypes.DestinationKindSwapAction => { return { type: SWAP_DESTINATION_KIND, value }; }; -export const originAmountSwap = value => { +export const originAmountSwap = ( + value: ?number +): swapTypes.OriginAmountSwapAction => { return { type: SWAP_ORIGIN_AMOUNT, value }; }; -export const destinationAmountSwap = value => { +export const destinationAmountSwap = ( + value: ?number +): swapTypes.DestinationAmountSwapAction => { return { type: SWAP_DESTINATION_AMOUNT, value }; }; -export const updateBityRatesSwap = value => { +export const updateBityRatesSwap = ( + value: swapTypes.Pairs +): swapTypes.BityRatesSwapAction => { return { type: SWAP_UPDATE_BITY_RATES, value }; }; -export const partOneCompleteSwap = (value: boolean) => { - return { - type: SWAP_PART_ONE_COMPLETE, - value - }; -}; - -export const partTwoCompleteSwap = (value: boolean) => { - return { - type: SWAP_PART_TWO_COMPLETE, - value - }; -}; - -export const destinationAddressSwap = value => { +export const destinationAddressSwap = ( + value: ?string +): swapTypes.DestinationAddressSwapAction => { return { type: SWAP_DESTINATION_ADDRESS, value }; }; -export const restartSwap = () => { +export const restartSwap = (): swapTypes.RestartSwapAction => { return { type: SWAP_RESTART }; }; -export const loadBityRates = () => { +export const loadBityRatesSwap = (): swapTypes.LoadBityRatesSwapAction => { return { type: SWAP_LOAD_BITY_RATES }; }; -export const stopLoadBityRates = () => { +export const stopLoadBityRatesSwap = (): swapTypes.StopLoadBityRatesSwapAction => { return { type: SWAP_STOP_LOAD_BITY_RATES }; diff --git a/common/actions/swapConstants.js b/common/actions/swapConstants.js index fda3a5d7..9360a14e 100644 --- a/common/actions/swapConstants.js +++ b/common/actions/swapConstants.js @@ -3,9 +3,9 @@ export const SWAP_DESTINATION_KIND = 'SWAP_DESTINATION_KIND'; export const SWAP_ORIGIN_AMOUNT = 'SWAP_ORIGIN_AMOUNT'; export const SWAP_DESTINATION_AMOUNT = 'SWAP_DESTINATION_AMOUNT'; export const SWAP_UPDATE_BITY_RATES = 'SWAP_UPDATE_BITY_RATES'; -export const SWAP_PART_ONE_COMPLETE = 'SWAP_PART_ONE_COMPLETE'; -export const SWAP_PART_TWO_COMPLETE = 'SWAP_PART_TWO_COMPLETE'; export const SWAP_DESTINATION_ADDRESS = 'SWAP_DESTINATION_ADDRESS'; export const SWAP_RESTART = 'SWAP_RESTART'; export const SWAP_LOAD_BITY_RATES = 'SWAP_LOAD_BITY_RATES'; export const SWAP_STOP_LOAD_BITY_RATES = 'SWAP_STOP_LOAD_BITY_RATES'; +export const SWAP_STEP = 'SWAP_STEP'; +export const SWAP_REFERENCE_NUMBER = 'SWAP_REFERENCE_NUMBER'; diff --git a/common/actions/swapTypes.js b/common/actions/swapTypes.js new file mode 100644 index 00000000..457289a2 --- /dev/null +++ b/common/actions/swapTypes.js @@ -0,0 +1,66 @@ +import { + SWAP_DESTINATION_AMOUNT, + SWAP_DESTINATION_KIND, + SWAP_ORIGIN_AMOUNT, + SWAP_ORIGIN_KIND, + SWAP_UPDATE_BITY_RATES, + SWAP_DESTINATION_ADDRESS, + SWAP_RESTART, + SWAP_LOAD_BITY_RATES, + SWAP_STOP_LOAD_BITY_RATES, + SWAP_STEP, + SWAP_REFERENCE_NUMBER +} from './swapConstants'; + +export type Pairs = { + ETHBTC: number, + ETHREP: number, + BTCETH: number, + BTCREP: number +}; + +export type ReferenceNumberSwapAction = { + type: SWAP_REFERENCE_NUMBER, + value: string +}; +export type OriginKindSwapAction = { + type: SWAP_ORIGIN_KIND, + value: string +}; +export type DestinationKindSwapAction = { + type: SWAP_DESTINATION_KIND, + value: string +}; +export type OriginAmountSwapAction = { + type: SWAP_ORIGIN_AMOUNT, + value: ?number +}; +export type DestinationAmountSwapAction = { + type: SWAP_DESTINATION_AMOUNT, + value: ?number +}; +export type BityRatesSwapAction = { + type: SWAP_UPDATE_BITY_RATES, + value: Pairs +}; +export type DestinationAddressSwapAction = { + type: SWAP_DESTINATION_ADDRESS, + value: ?number +}; + +export type RestartSwapAction = { + type: SWAP_RESTART +}; + +export type LoadBityRatesSwapAction = { + type: SWAP_LOAD_BITY_RATES +}; + +export type ChangeStepSwapAction = { + type: SWAP_STEP, + value: number +}; + +export type StopLoadBityRatesSwapAction = { + type: SWAP_STOP_LOAD_BITY_RATES +}; diff --git a/common/api/bity.js b/common/api/bity.js index 979cbd8a..90e73f83 100644 --- a/common/api/bity.js +++ b/common/api/bity.js @@ -1,9 +1,7 @@ // @flow import bityConfig from 'config/bity'; +import {combineAndUpper} from 'utils/formatters' -export function combineAndUpper(...args: string[]) { - return args.reduce((acc, item) => acc.concat(item.toUpperCase()), ''); -} function findRateFromBityRateList(rateObjects, pairName) { return rateObjects.find(x => x.pair === pairName); diff --git a/common/components/Footer/index.jsx b/common/components/Footer/index.jsx index e431210a..a8ad85c5 100644 --- a/common/components/Footer/index.jsx +++ b/common/components/Footer/index.jsx @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import translate, { getTranslators } from 'translations'; import { donationAddressMap } from 'config/data'; import logo from 'assets/images/logo-myetherwallet.svg'; - +import { bityReferralURL } from 'config/data'; import './index.scss'; export default class Footer extends Component { @@ -72,7 +72,7 @@ export default class Footer extends Component {
  • Swap ETH/BTC/EUR/CHF via Bity.com diff --git a/common/components/ui/SimpleDropdown.js b/common/components/ui/SimpleDropdown.js new file mode 100644 index 00000000..d2be05c4 --- /dev/null +++ b/common/components/ui/SimpleDropdown.js @@ -0,0 +1,32 @@ +// @flow +import React, { Component } from 'react'; + +type Props = { + value?: T, + options: Array, + onChange: (event: SyntheticInputEvent) => void +}; + +export default class SimpleDropDown extends Component { + props: Props; + + render() { + return ( + + + + ); + } +} diff --git a/common/config/data.js b/common/config/data.js index 4d0644f1..6731bbbe 100644 --- a/common/config/data.js +++ b/common/config/data.js @@ -14,6 +14,8 @@ export const gasPriceDefaults = { gasPriceMaxGwei: 60 }; +export const bityReferralURL = 'https://bity.com/af/jshkb37v'; + export const languages = [ { sign: 'en', diff --git a/common/containers/Tabs/Swap/components/CurrencySwap.js b/common/containers/Tabs/Swap/components/CurrencySwap.js new file mode 100644 index 00000000..65445f23 --- /dev/null +++ b/common/containers/Tabs/Swap/components/CurrencySwap.js @@ -0,0 +1,151 @@ +import React, { Component } from 'react'; +import translate from 'translations'; +import { combineAndUpper } from 'utils/formatters'; +import * as swapTypes from 'actions/swapTypes'; +import SimpleDropDown from 'components/ui/SimpleDropdown'; + +export type StateProps = { + bityRates: {}, + originAmount: ?number, + destinationAmount: ?number, + originKind: string, + destinationKind: string, + destinationKindOptions: String[], + originKindOptions: String[] +}; + +export type ActionProps = { + originKindSwap: (value: string) => swapTypes.OriginKindSwapAction, + destinationKindSwap: (value: string) => swapTypes.DestinationKindSwapAction, + originAmountSwap: (value: ?number) => swapTypes.OriginAmountSwapAction, + destinationAmountSwap: ( + value: ?number + ) => swapTypes.DestinationAmountSwapAction, + changeStepSwap: () => swapTypes.ChangeStepSwapAction +}; + +export default class CurrencySwap extends Component { + props: StateProps & ActionProps; + + state = { + disabled: false + }; + + onClickStartSwap = () => { + this.props.changeStepSwap(2); + }; + + setOriginAndDestinationToNull = () => { + this.props.originAmountSwap(null); + this.props.destinationAmountSwap(null); + }; + + onChangeOriginAmount = (event: SyntheticInputEvent) => { + const amount = event.target.value; + let originAmountAsNumber = parseFloat(amount); + if (originAmountAsNumber) { + let pairName = combineAndUpper( + this.props.originKind, + this.props.destinationKind + ); + let bityRate = this.props.bityRates[pairName]; + this.props.originAmountSwap(originAmountAsNumber); + this.props.destinationAmountSwap(originAmountAsNumber * bityRate); + } else { + this.setOriginAndDestinationToNull(); + } + }; + + onChangeDestinationAmount = (event: SyntheticInputEvent) => { + const amount = event.target.value; + let destinationAmountAsNumber = parseFloat(amount); + if (destinationAmountAsNumber) { + this.props.destinationAmountSwap(destinationAmountAsNumber); + let pairName = combineAndUpper( + this.props.destinationKind, + this.props.originKind + ); + let bityRate = this.props.bityRates[pairName]; + this.props.originAmountSwap(destinationAmountAsNumber * bityRate); + } else { + this.setOriginAndDestinationToNull(); + } + }; + + onChangeDestinationKind = (event: SyntheticInputEvent) => { + let newDestinationKind = event.target.value; + this.props.destinationKindSwap(newDestinationKind); + }; + + onChangeOriginKind = (event: SyntheticInputEvent) => { + let newOriginKind = event.target.value; + this.props.originKindSwap(newOriginKind); + }; + + render() { + const { + originAmount, + destinationAmount, + originKind, + destinationKind, + destinationKindOptions, + originKindOptions + } = this.props; + + return ( +
    +

    + {translate('SWAP_init_1')} +

    + 0 + ? 'is-valid' + : 'is-invalid'}`} + type="number" + placeholder="Amount" + value={originAmount || ''} + onChange={this.onChangeOriginAmount} + /> + + + +

    + {translate('SWAP_init_2')} +

    + + 0 + ? 'is-valid' + : 'is-invalid'}`} + type="number" + placeholder="Amount" + value={destinationAmount || ''} + onChange={this.onChangeDestinationAmount} + /> + + +
    + +
    +
    + ); + } +} diff --git a/common/containers/Tabs/Swap/components/currentRates.js b/common/containers/Tabs/Swap/components/CurrentRates.js similarity index 69% rename from common/containers/Tabs/Swap/components/currentRates.js rename to common/containers/Tabs/Swap/components/CurrentRates.js index 1016bec4..d524c789 100644 --- a/common/containers/Tabs/Swap/components/currentRates.js +++ b/common/containers/Tabs/Swap/components/CurrentRates.js @@ -1,27 +1,22 @@ +// @flow import React, { Component } from 'react'; import translate from 'translations'; -import PropTypes from 'prop-types'; import { toFixedIfLarger } from 'utils/formatters'; +import { Pairs } from 'actions/swapTypes'; +import { bityReferralURL } from 'config/data'; +import bityLogoWhite from 'assets/images/logo-bity-white.svg'; export default class CurrentRates extends Component { - constructor(props) { - super(props); - this.state = { - ETHBTCAmount: 1, - ETHREPAmount: 1, - BTCETHAmount: 1, - BTCREPAmount: 1 - }; - } + props: Pairs; - static propTypes = { - ETHBTC: PropTypes.number, - ETHREP: PropTypes.number, - BTCETH: PropTypes.number, - BTCREP: PropTypes.number + state = { + ETHBTCAmount: 1, + ETHREPAmount: 1, + BTCETHAmount: 1, + BTCREPAmount: 1 }; - onChange = event => { + onChange = (event: SyntheticInputEvent) => { const target = event.target; const value = target.value; const name = target.name; @@ -30,8 +25,9 @@ export default class CurrentRates extends Component { }); }; - // TODO - A little code duplication here, but simple enough to where it doesn't seem worth the time to fix. render() { + const { ETHBTC, ETHREP, BTCETH, BTCREP } = this.props; + return (
    @@ -50,7 +46,7 @@ export default class CurrentRates extends Component { /> {` ETH = ${toFixedIfLarger( - this.state.ETHBTCAmount * this.props.ETHBTC, + this.state.ETHBTCAmount * ETHBTC, 6 )} BTC`} @@ -64,7 +60,7 @@ export default class CurrentRates extends Component { /> {` ETH = ${toFixedIfLarger( - this.state.ETHREPAmount * this.props.ETHREP, + this.state.ETHREPAmount * ETHREP, 6 )} REP`} @@ -80,7 +76,7 @@ export default class CurrentRates extends Component { /> {` BTC = ${toFixedIfLarger( - this.state.BTCETHAmount * this.props.BTCETH, + this.state.BTCETHAmount * BTCETH, 6 )} ETH`} @@ -94,22 +90,14 @@ export default class CurrentRates extends Component { /> {` BTC = ${toFixedIfLarger( - this.state.BTCREPAmount * this.props.BTCREP, + this.state.BTCREPAmount * BTCREP, 6 )} REP`}

    -
    - + +
    diff --git a/common/containers/Tabs/Swap/components/receivingAddress.js b/common/containers/Tabs/Swap/components/ReceivingAddress.js similarity index 66% rename from common/containers/Tabs/Swap/components/receivingAddress.js rename to common/containers/Tabs/Swap/components/ReceivingAddress.js index c1599862..ea4d7005 100644 --- a/common/containers/Tabs/Swap/components/receivingAddress.js +++ b/common/containers/Tabs/Swap/components/ReceivingAddress.js @@ -1,18 +1,25 @@ // @flow import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import * as swapTypes from 'actions/swapTypes'; import { donationAddressMap } from 'config/data'; import { isValidBTCAddress, isValidETHAddress } from 'libs/validators'; import translate from 'translations'; +export type StateProps = { + destinationKind: string, + destinationAddress: string +}; + +export type ActionProps = { + destinationAddressSwap: ( + value: ?string + ) => swapTypes.DestinationAddressSwapAction, + changeStepSwap: (value: number) => swapTypes.ChangeStepSwapAction, + stopLoadBityRatesSwap: () => swapTypes.StopLoadBityRatesSwapAction +}; + export default class ReceivingAddress extends Component { - static propTypes = { - destinationKind: PropTypes.string.isRequired, - destinationAddressSwap: PropTypes.func.isRequired, - destinationAddress: PropTypes.string, - partTwoCompleteSwap: PropTypes.func, - stopLoadBityRates: PropTypes.func - }; + props: StateProps & ActionProps; onChangeDestinationAddress = (event: SyntheticInputEvent) => { const value = event.target.value; @@ -20,8 +27,10 @@ export default class ReceivingAddress extends Component { }; onClickPartTwoComplete = () => { - this.props.stopLoadBityRates(); - this.props.partTwoCompleteSwap(true); + this.props.stopLoadBityRatesSwap(); + // temporarily here for testing purposes. will live in saga + this.props.referenceNumberSwap(''); + this.props.changeStepSwap(3); }; render() { @@ -40,8 +49,12 @@ export default class ReceivingAddress extends Component {
    - {translate('SWAP_start_CTA')} + + {translate('SWAP_start_CTA')} +
    diff --git a/common/containers/Tabs/Swap/components/SwapInfoHeader.js b/common/containers/Tabs/Swap/components/SwapInfoHeader.js new file mode 100644 index 00000000..3d03620b --- /dev/null +++ b/common/containers/Tabs/Swap/components/SwapInfoHeader.js @@ -0,0 +1,142 @@ +// @flow +import React, { Component } from 'react'; +import { toFixedIfLarger } from 'utils/formatters'; +import translate from 'translations'; +import * as swapTypes from 'actions/swapTypes'; +import bityLogo from 'assets/images/logo-bity.svg'; +import { bityReferralURL } from 'config/data'; + +export type StateProps = { + timeRemaining: string, + originAmount: number, + originKind: string, + destinationKind: string, + destinationAmount: number, + referenceNumber: string +}; + +export type ActionProps = { + restartSwap: () => swapTypes.RestartSwapAction +}; + +export default class SwapInfoHeader extends Component { + props: StateProps & ActionProps; + + computedOriginDestinationRatio = () => { + return toFixedIfLarger( + this.props.destinationAmount / this.props.originAmount, + 6 + ); + }; + + isExpanded = () => { + const { referenceNumber, timeRemaining, restartSwap } = this.props; + return referenceNumber && timeRemaining && restartSwap; + }; + + computedClass = () => { + if (this.isExpanded()) { + return 'col-sm-3 order-info'; + } else { + return 'col-sm-4 order-info'; + } + }; + + render() { + const { + referenceNumber, + timeRemaining, + originAmount, + destinationAmount, + originKind, + destinationKind, + restartSwap + } = this.props; + return ( +
    +
    +
    + +
    +
    + {translate('SWAP_information')} +
    +
    + + + +
    +
    +
    + {/*Amount to send */} + {!this.isExpanded() && +
    +

    + {` ${toFixedIfLarger(originAmount, 6)} ${originKind}`} +

    +

    + {translate('SEND_amount')} +

    +
    } + + {/* Reference Number*/} + {this.isExpanded() && +
    +

    + {referenceNumber} +

    +

    + {translate('SWAP_ref_num')} +

    +
    } + + {/*Time remaining*/} + {this.isExpanded() && +
    +

    + {timeRemaining} +

    +

    + {translate('SWAP_time')} +

    +
    } + + {/*Amount to Receive*/} +
    +

    + {` ${toFixedIfLarger(destinationAmount, 6)} ${destinationKind}`} +

    +

    + {translate('SWAP_rec_amt')} +

    +
    + + {/*Your rate*/} +
    +

    + {` ${toFixedIfLarger( + this.computedOriginDestinationRatio(), + 6 + )} ${originKind}/${destinationKind} `} +

    +

    + {translate('SWAP_your_rate')} +

    +
    +
    +
    + ); + } +} diff --git a/common/containers/Tabs/Swap/components/swapProgress.js b/common/containers/Tabs/Swap/components/SwapProgress.js similarity index 56% rename from common/containers/Tabs/Swap/components/swapProgress.js rename to common/containers/Tabs/Swap/components/SwapProgress.js index dbcbed7e..283abd39 100644 --- a/common/containers/Tabs/Swap/components/swapProgress.js +++ b/common/containers/Tabs/Swap/components/SwapProgress.js @@ -1,29 +1,24 @@ //flow import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import translate from 'translations'; -export default class SwapProgress extends Component { - constructor(props) { - super(props); - } +export type StateProps = { + numberOfConfirmations: number, + destinationKind: string, + originKind: string, + orderStep: number +}; - static propTypes = { - numberOfConfirmations: PropTypes.number.isRequired, - destinationKind: PropTypes.string.isRequired, - originKind: PropTypes.string.isRequired, - activeStep: PropTypes.number.isRequired - }; +export default class SwapProgress extends Component { + props: StateProps; computedClass(i: number) { - const { activeStep } = this.props; + const { orderStep } = this.props; let cssClass = 'progress-item'; - if (activeStep > i) { + if (orderStep > i) { cssClass += ' progress-true'; - } else if (i === activeStep) { + } else if (i === orderStep) { cssClass += ' progress-active'; - } else { - cssClass += ''; } return cssClass; } @@ -35,25 +30,37 @@ export default class SwapProgress extends Component {
    -
    1
    -

    {translate('SWAP_progress_1')}

    +
    + 1 +
    +

    + {translate('SWAP_progress_1')} +

    -
    2
    +
    + 2 +

    - {translate('SWAP_progress_2')}{originKind}... + {translate('SWAP_progress_2')} + {originKind}...

    -
    3
    +
    + 3 +

    {originKind} {translate('SWAP_progress_3')}

    -
    4
    +
    + 4 +

    - Sending your {destinationKind} + Sending your + {destinationKind}
    Waiting for {numberOfConfirmations} confirmations... @@ -61,7 +68,9 @@ export default class SwapProgress extends Component {

    -
    5
    +
    + 5 +

    Order Complete

    diff --git a/common/containers/Tabs/Swap/components/currencySwap.js b/common/containers/Tabs/Swap/components/currencySwap.js deleted file mode 100644 index 2090c1b4..00000000 --- a/common/containers/Tabs/Swap/components/currencySwap.js +++ /dev/null @@ -1,163 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import translate from 'translations'; -import { combineAndUpper } from 'api/bity'; - -class CoinTypeDropDown extends Component { - constructor(props) { - super(props); - } - - static propTypes = { - kind: PropTypes.any, - onChange: PropTypes.any, - kindOptions: PropTypes.any - }; - - render() { - return ( - - - - ); - } -} - -export default class CurrencySwap extends Component { - constructor(props) { - super(props); - this.state = { - disabled: false - }; - } - - static propTypes = { - bityRates: PropTypes.any, - originAmount: PropTypes.any, - destinationAmount: PropTypes.any, - originKind: PropTypes.string, - destinationKind: PropTypes.string, - destinationKindOptions: PropTypes.array, - originKindOptions: PropTypes.array, - originKindSwap: PropTypes.func, - destinationKindSwap: PropTypes.func, - originAmountSwap: PropTypes.func, - destinationAmountSwap: PropTypes.func, - partOneCompleteSwap: PropTypes.func - }; - - onClickStartSwap = () => { - this.props.partOneCompleteSwap(true); - }; - - onChangeOriginAmount = amount => { - let originAmountAsNumber = parseFloat(amount); - if (originAmountAsNumber) { - let pairName = combineAndUpper( - this.props.originKind, - this.props.destinationKind - ); - let bityRate = this.props.bityRates[pairName]; - this.props.originAmountSwap(originAmountAsNumber); - this.props.destinationAmountSwap(originAmountAsNumber * bityRate); - } else { - this.props.originAmountSwap(''); - this.props.destinationAmountSwap(''); - } - }; - - onChangeDestinationAmount(amount) { - let destinationAmountAsNumber = parseFloat(amount); - if (destinationAmountAsNumber) { - this.props.destinationAmountSwap(destinationAmountAsNumber); - let pairName = combineAndUpper( - this.props.destinationKind, - this.props.originKind - ); - let bityRate = this.props.bityRates[pairName]; - this.props.originAmountSwap(destinationAmountAsNumber * bityRate); - } else { - this.props.originAmountSwap(''); - this.props.destinationAmountSwap(''); - } - } - - async onChangeDestinationKind(event) { - let newDestinationKind = event.target.value; - this.props.destinationKindSwap(newDestinationKind); - } - - async onChangeOriginKind(event) { - let newOriginKind = event.target.value; - this.props.originKindSwap(newOriginKind); - } - - render() { - const { - originAmount, - destinationAmount, - originKind, - destinationKind, - destinationKindOptions, - originKindOptions - } = this.props; - - return ( -
    -

    {translate('SWAP_init_1')}

    - 0 - ? 'is-valid' - : 'is-invalid'}`} - type="number" - placeholder="Amount" - onChange={e => this.onChangeOriginAmount(e.target.value)} - value={originAmount} - /> - - - -

    {translate('SWAP_init_2')}

    - - 0 - ? 'is-valid' - : 'is-invalid'}`} - type="number" - placeholder="Amount" - value={destinationAmount} - onChange={e => this.onChangeDestinationAmount(e.target.value)} - /> - - -
    - -
    -
    - ); - } -} diff --git a/common/containers/Tabs/Swap/components/onGoingSwapInformation.js b/common/containers/Tabs/Swap/components/onGoingSwapInformation.js deleted file mode 100644 index f23bd26b..00000000 --- a/common/containers/Tabs/Swap/components/onGoingSwapInformation.js +++ /dev/null @@ -1,87 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { toFixedIfLarger } from 'utils/formatters'; -import translate from 'translations'; - -export default class OnGoingSwapInformation extends Component { - constructor(props) { - super(props); - } - - static propTypes = { - referenceNumber: PropTypes.string.isRequired, - timeRemaining: PropTypes.any, // FIXME - originAmount: PropTypes.number.isRequired, - originKind: PropTypes.string.isRequired, - destinationKind: PropTypes.string.isRequired, - destinationAmount: PropTypes.number.isRequired, - restartSwap: PropTypes.func.isRequired - }; - - computedOriginDestinationRatio = () => { - return toFixedIfLarger( - this.props.destinationAmount / this.props.originAmount, - 6 - ); - }; - - render() { - const { - referenceNumber, - timeRemaining, - originAmount, - originKind, - destinationKind, - restartSwap - } = this.props; - return ( -
    -
    -
    - -
    -
    {translate('SWAP_information')}
    -
    - - - -
    -
    -
    -
    -

    {referenceNumber}

    -

    {translate('SWAP_ref_num')}

    -
    -
    -

    {timeRemaining}

    -

    - {translate('SWAP_time')} -

    -
    -
    -

    {originAmount} {originKind}

    -

    {translate('SWAP_rec_amt')}

    -
    -
    -

    - {`${this.computedOriginDestinationRatio()} ${destinationKind}/${originKind}`} -

    -

    {translate('SWAP_your_rate')}

    -
    -
    -
    - ); - } -} diff --git a/common/containers/Tabs/Swap/components/swapInformation.js b/common/containers/Tabs/Swap/components/swapInformation.js deleted file mode 100644 index def61d99..00000000 --- a/common/containers/Tabs/Swap/components/swapInformation.js +++ /dev/null @@ -1,79 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { toFixedIfLarger } from 'utils/formatters'; -import translate from 'translations'; - -export default class SwapInformation extends Component { - constructor(props) { - super(props); - } - - static propTypes = { - originAmount: PropTypes.number.isRequired, - destinationAmount: PropTypes.number.isRequired, - originKind: PropTypes.string.isRequired, - destinationKind: PropTypes.string.isRequired - }; - - computedOriginDestinationRatio = () => { - return this.props.destinationAmount / this.props.originAmount; - }; - - render() { - const { - originAmount, - originKind, - destinationAmount, - destinationKind - } = this.props; - - return ( -
    -
    -
    - {translate('SWAP_information')} -
    - -
    -
    -
    -

    - {` ${toFixedIfLarger(originAmount, 6)} ${originKind}`} -

    -

    {translate('SEND_amount')}

    -
    -
    -

    - {` ${toFixedIfLarger(destinationAmount, 6)} ${destinationKind}`} -

    -

    {translate('SWAP_rec_amt')}

    -
    -
    -

    - {` ${toFixedIfLarger( - this.computedOriginDestinationRatio(), - 6 - )} ${originKind}/${destinationKind} `} -

    -

    {translate('SWAP_your_rate')}

    -
    -
    -
    - ); - } -} diff --git a/common/containers/Tabs/Swap/index.js b/common/containers/Tabs/Swap/index.js index bea2c188..0799aaa1 100644 --- a/common/containers/Tabs/Swap/index.js +++ b/common/containers/Tabs/Swap/index.js @@ -1,48 +1,63 @@ import React, { Component } from 'react'; -import CurrencySwap from './components/currencySwap'; -import SwapInformation from './components/swapInformation'; -import CurrentRates from './components/currentRates'; -import ReceivingAddress from './components/receivingAddress'; -import SwapProgress from './components/swapProgress'; -import OnGoingSwapInformation from './components/onGoingSwapInformation'; import { connect } from 'react-redux'; import * as swapActions from 'actions/swap'; -import PropTypes from 'prop-types'; +import * as swapTypes from 'actions/swapTypes'; +import CurrencySwap from './components/CurrencySwap'; +import CurrentRates from './components/CurrentRates'; +import ReceivingAddress from './components/ReceivingAddress'; +import SwapInfoHeader from './components/SwapInfoHeader'; +import SwapProgress from './components/SwapProgress'; + +type ReduxStateProps = { + step: string, + destinationAddress: string, + destinationKind: string, + originKind: string, + destinationKindOptions: String[], + originKindOptions: String[], + bityRates: boolean, + originAmount: ?number, + destinationAmount: ?number, + // PART 3 + referenceNumber: string, + timeRemaining: string, + numberOfConfirmation: number, + orderStep: number, + orderStarted: boolean +}; + +type ReduxActionProps = { + changeStepSwap: (value: number) => swapTypes.ChangeStepSwapAction, + originKindSwap: (value: string) => swapTypes.OriginKindSwapAction, + destinationKindSwap: (value: string) => swapTypes.DestinationKindSwapAction, + originAmountSwap: (value: ?number) => swapTypes.OriginAmountSwapAction, + destinationAmountSwap: ( + value: ?number + ) => swapTypes.DestinationAmountSwapAction, + loadBityRatesSwap: () => swapTypes.LoadBityRatesSwapAction, + destinationAddressSwap: ( + value: ?string + ) => swapTypes.DestinationAddressSwapAction, + restartSwap: () => swapTypes.RestartSwapAction, + stopLoadBityRatesSwap: () => swapTypes.StopLoadBityRatesSwapAction, + // PART 3 (IGNORE FOR NOW) + referenceNumberSwap: typeof swapActions.referenceNumberSwap +}; class Swap extends Component { - constructor(props) { - super(props); - } - - static propTypes = { - bityRates: PropTypes.any, - originAmount: PropTypes.any, - destinationAmount: PropTypes.any, - originKind: PropTypes.string, - partOneComplete: PropTypes.bool, - destinationKind: PropTypes.string, - destinationKindOptions: PropTypes.array, - originKindOptions: PropTypes.array, - destinationAddress: PropTypes.string, - originKindSwap: PropTypes.func, - destinationKindSwap: PropTypes.func, - originAmountSwap: PropTypes.func, - destinationAmountSwap: PropTypes.func, - loadBityRates: PropTypes.func, - partOneCompleteSwap: PropTypes.func, - destinationAddressSwap: PropTypes.func, - restartSwap: PropTypes.func, - partTwoCompleteSwap: PropTypes.func, - partTwoComplete: PropTypes.bool, - stopLoadBityRates: PropTypes.func - }; + props: ReduxActionProps & ReduxStateProps; componentDidMount() { - this.props.loadBityRates(); + this.props.loadBityRatesSwap(); + } + + componentWillUnmount() { + this.props.stopLoadBityRatesSwap(); } render() { let { + // STATE bityRates, originAmount, destinationAmount, @@ -50,21 +65,50 @@ class Swap extends Component { destinationKind, destinationKindOptions, originKindOptions, + destinationAddress, + step, + referenceNumber, + timeRemaining, + numberOfConfirmations, + orderStep, + // ACTIONS + restartSwap, + stopLoadBityRatesSwap, + changeStepSwap, originKindSwap, destinationKindSwap, originAmountSwap, destinationAmountSwap, - partOneComplete, - partOneCompleteSwap, destinationAddressSwap, - destinationAddress, - restartSwap, - partTwoCompleteSwap, - partTwoComplete, - stopLoadBityRates + referenceNumberSwap } = this.props; - let wantToSwapMyProps = { + let ReceivingAddressProps = { + destinationKind, + destinationAddressSwap, + destinationAddress, + stopLoadBityRatesSwap, + changeStepSwap, + referenceNumberSwap + }; + + let SwapInfoHeaderProps = { + referenceNumber, + timeRemaining, + originAmount, + originKind, + destinationKind, + destinationAmount, + restartSwap, + numberOfConfirmations, + orderStep + }; + + const { ETHBTC, ETHREP, BTCETH, BTCREP } = bityRates; + + const CurrentRatesProps = { ETHBTC, ETHREP, BTCETH, BTCREP }; + + const CurrencySwapProps = { bityRates, originAmount, destinationAmount, @@ -76,62 +120,22 @@ class Swap extends Component { destinationKindSwap, originAmountSwap, destinationAmountSwap, - partOneCompleteSwap - }; - - let yourInformationProps = { - originAmount, - destinationAmount, - originKind, - destinationKind - }; - - let receivingAddressProps = { - destinationKind, - destinationAddressSwap, - destinationAddress, - partTwoCompleteSwap, - stopLoadBityRates - }; - - const referenceNumber = '2341asdfads'; - const timeRemaining = '2:30'; - - let onGoingSwapInformationProps = { - // from bity - referenceNumber: referenceNumber, - timeRemaining: timeRemaining, - originAmount, - originKind, - destinationKind, - destinationAmount, - restartSwap, - numberOfConfirmations: 3, - activeStep: 2 + changeStepSwap }; return (
    - {!partOneComplete && - !partTwoComplete && + {step === 1 &&
    - - -
    } - {partOneComplete && - !partTwoComplete && -
    - - -
    } - {partOneComplete && - partTwoComplete && -
    - - + +
    } + {(step === 2 || step === 3) && + } + {step === 2 && } + {step === 3 && }
    @@ -141,16 +145,20 @@ class Swap extends Component { function mapStateToProps(state) { return { - partTwoComplete: state.swap.partTwoComplete, + step: state.swap.step, destinationAddress: state.swap.destinationAddress, - partOneComplete: state.swap.partOneComplete, originAmount: state.swap.originAmount, destinationAmount: state.swap.destinationAmount, originKind: state.swap.originKind, destinationKind: state.swap.destinationKind, destinationKindOptions: state.swap.destinationKindOptions, originKindOptions: state.swap.originKindOptions, - bityRates: state.swap.bityRates + bityRates: state.swap.bityRates, + referenceNumber: state.swap.referenceNumber, + timeRemaining: state.swap.timeRemaining, + numberOfConfirmations: state.swap.numberOfConfirmations, + orderStep: state.swap.orderStep, + orderStarted: state.swap.orderStarted }; } diff --git a/common/reducers/swap.js b/common/reducers/swap.js index cc655e56..4aee6c93 100644 --- a/common/reducers/swap.js +++ b/common/reducers/swap.js @@ -4,12 +4,12 @@ import { SWAP_ORIGIN_AMOUNT, SWAP_ORIGIN_KIND, SWAP_UPDATE_BITY_RATES, - SWAP_PART_ONE_COMPLETE, SWAP_DESTINATION_ADDRESS, SWAP_RESTART, - SWAP_PART_TWO_COMPLETE + SWAP_STEP, + SWAP_REFERENCE_NUMBER } from 'actions/swapConstants'; -import { combineAndUpper } from 'api/bity'; +import { combineAndUpper } from 'utils/formatters'; export const ALL_CRYPTO_KIND_OPTIONS = ['BTC', 'ETH', 'REP']; @@ -24,10 +24,13 @@ const initialState = { originKindOptions: ALL_CRYPTO_KIND_OPTIONS.filter( element => element !== 'REP' ), - partOneComplete: false, - partTwoComplete: false, + step: 1, bityRates: {}, - destinationAddress: '' + destinationAddress: '', + referenceNumber: '', + timeRemaining: '', + numberOfConfirmations: null, + orderStep: null }; const buildDestinationAmount = ( @@ -101,16 +104,12 @@ export function swap(state = initialState, action) { ...action.value } }; - case SWAP_PART_ONE_COMPLETE: + case SWAP_STEP: { return { ...state, - partOneComplete: action.value - }; - case SWAP_PART_TWO_COMPLETE: - return { - ...state, - partTwoComplete: action.value + step: action.value }; + } case SWAP_DESTINATION_ADDRESS: return { ...state, @@ -122,6 +121,14 @@ export function swap(state = initialState, action) { ...initialState, bityRates: state.bityRates }; + case SWAP_REFERENCE_NUMBER: + return { + ...state, + referenceNumber: '2341asdfads', + timeRemaining: '2:30', + numberOfConfirmations: 3, + orderStep: 2 + }; default: return state; } diff --git a/common/utils/formatters.js b/common/utils/formatters.js index d0db12c3..d5d84e17 100644 --- a/common/utils/formatters.js +++ b/common/utils/formatters.js @@ -5,6 +5,10 @@ export function toFixedIfLarger(number: number, fixedSize: number = 6): string { return parseFloat(number.toFixed(fixedSize)).toString(); } +export function combineAndUpper(...args: string[]) { + return args.reduce((acc, item) => acc.concat(item.toUpperCase()), ''); +} + // Use in place of angular number filter export function formatNumber(number: Big, digits: number = 3): string { let parts = number.toFixed(digits).split('.');