import React, { PureComponent } from 'react'; import { connect } from 'react-redux'; import sample from 'lodash/sample'; import times from 'lodash/times'; import { NormalizedBityRates, NormalizedShapeshiftRates, NormalizedShapeshiftRate } from 'reducers/swap/types'; import bityLogoWhite from 'assets/images/logo-bity-white.svg'; import shapeshiftLogoWhite from 'assets/images/logo-shapeshift.svg'; import Spinner from 'components/ui/Spinner'; import { bityReferralURL, shapeshiftReferralURL } from 'config'; import translate from 'translations'; import { SHAPESHIFT_WHITELIST } from 'api/shapeshift'; import { loadShapeshiftRatesRequestedSwap, TLoadShapeshiftRatesRequestedSwap, stopLoadShapeshiftRatesSwap, TStopLoadShapeshiftRatesSwap, ProviderName } from 'actions/swap'; import { getOffline } from 'selectors/config'; import Rates from './Rates'; import { AppState } from 'reducers'; import './CurrentRates.scss'; import { Optional } from 'utils/types'; interface StateProps { isOffline: boolean; provider: ProviderName; bityRates: NormalizedBityRates; shapeshiftRates: NormalizedShapeshiftRates; } interface ActionProps { loadShapeshiftRatesRequestedSwap: TLoadShapeshiftRatesRequestedSwap; stopLoadShapeshiftRatesSwap: TStopLoadShapeshiftRatesSwap; } type Props = StateProps & ActionProps; class CurrentRates extends PureComponent { private shapeShiftRateCache: any = null; public componentDidMount() { if (!this.props.isOffline) { this.loadRates(); } } public componentWillReceiveProps(nextProps: Props) { if (this.props.isOffline && !nextProps.isOffline) { this.loadRates(); } } public componentWillUnmount() { this.props.stopLoadShapeshiftRatesSwap(); } public loadRates() { this.props.loadShapeshiftRatesRequestedSwap(); } public getRandomSSPairData = ( shapeshiftRates: NormalizedShapeshiftRates ): NormalizedShapeshiftRate => { const coinOne = sample(SHAPESHIFT_WHITELIST) as string; const coinTwo = sample(SHAPESHIFT_WHITELIST) as string; const pair = coinOne + coinTwo; const pairData = shapeshiftRates.byId[pair]; if (pairData) { return pairData; } else { // if random pairing is unavailable / missing in state return this.getRandomSSPairData(shapeshiftRates); } }; public buildSSPairs = (shapeshiftRates: NormalizedShapeshiftRates, n: number = 4) => { const pairCollection = times(n, () => this.getRandomSSPairData(shapeshiftRates)); const byId = pairCollection.reduce<{ [id: string]: NormalizedShapeshiftRate }>((acc, cur) => { acc[cur.id] = cur; return acc; }, {}); const allIds = pairCollection.map(SSData => SSData.id); return { byId, allIds }; }; public isValidRates = (rates: Optional) => { return rates && rates.allIds && rates.allIds.length > 0; }; public setupRates = () => { const { shapeshiftRates, bityRates, provider } = this.props; let fixedRates; if (provider === 'bity') { fixedRates = bityRates; } else if (provider === 'shapeshift') { // if ShapeShift rates are valid, filter to 4 random pairs if (this.isValidRates(shapeshiftRates)) { if (!this.shapeShiftRateCache) { fixedRates = this.buildSSPairs(shapeshiftRates); this.shapeShiftRateCache = fixedRates; } else { fixedRates = this.shapeShiftRateCache; } } else { // else, pass along invalid rates. Child component will handle showing spinner until they become valid fixedRates = shapeshiftRates; } } return fixedRates; }; public swapEl = (providerURL: string, providerLogo: string, children: any) => { return (

{translate('SWAP_RATES')}

{children} Shapeshift Logo
); }; public render() { const { provider } = this.props; const rates = this.setupRates(); const providerLogo = provider === 'shapeshift' ? shapeshiftLogoWhite : bityLogoWhite; const providerURL = provider === 'shapeshift' ? shapeshiftReferralURL : bityReferralURL; let children; if (this.isValidRates(rates)) { children = ; } else { // TODO - de-dup children = ( <>
); } return this.swapEl(providerURL, providerLogo, children); } } function mapStateToProps(state: AppState): StateProps { return { isOffline: getOffline(state), provider: state.swap.provider, bityRates: state.swap.bityRates, shapeshiftRates: state.swap.shapeshiftRates }; } export default connect(mapStateToProps, { loadShapeshiftRatesRequestedSwap, stopLoadShapeshiftRatesSwap })(CurrentRates);