Skip to content

Commit

Permalink
feat(trading currency): implemented new way of setting trading curren…
Browse files Browse the repository at this point in the history
…cy on the fly
  • Loading branch information
milan-bc committed Nov 26, 2021
1 parent 66920c4 commit 148ac1c
Show file tree
Hide file tree
Showing 20 changed files with 303 additions and 147 deletions.
2 changes: 2 additions & 0 deletions packages/blockchain-info-components/src/Images/Images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import failedKyc3 from './img/failed-kyc@3x.png'
import fileDelete from './img/file-delete.svg'
import fileDownload from './img/file-download.svg'
import fintecture from './img/fintecture.svg'
import globe from './img/globe.svg'
import goldApproved from './img/gold-approved.svg'
import goldNotice from './img/gold-notice.png'
import goldVerified from './img/gold-verified.svg'
Expand Down Expand Up @@ -253,6 +254,7 @@ const Images = {
'firmware-connect': firmwareConnect,
'firmware-connect2': firmwareConnect2,
'firmware-connect3': firmwareConnect3,
globe,
'gold-approved': goldApproved,
'gold-notice': goldNotice,
'gold-verified': goldVerified,
Expand Down
10 changes: 10 additions & 0 deletions packages/blockchain-info-components/src/Images/img/globe.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -1256,23 +1256,18 @@ type MessagesType = {
'modals.recoveryphrase.success': 'Success!'
'modals.recoveryphrase.success.body': 'Your Wallet is now backed up.'
'modals.recoveryphrase.success.close': 'Close'

'modals.recurringbuys.notification.title': 'Recurring buys'
'modals.recurringbuys.notification.button': 'Setup recurring buy'
'modals.recurringbuys.disabled.paymentmethod': 'Recurring buys are not available for this payment method yet.'
'modals.recurringbuys.delete_confirmation_title': 'Are you sure you want to remove this Recurring Buy?'
'modals.recurringbuys.notification.page_1.title': 'Instead of timing the market, many smart investors use'
'modals.recurringbuys.notification.page_1.description': 'Dollar cost averaging'

'modals.recurringbuys.notification.page_2.title': 'The strategy is pretty simple'
'modals.recurringbuys.notification.page_2.description': 'Invest the same amount every week'

'modals.recurringbuys.notification.page_3.title': 'When the price goes down'
'modals.recurringbuys.notification.page_3.description': 'You’ll buy more crypto'

'modals.recurringbuys.notification.page_4.title': 'When the price goes up'
'modals.recurringbuys.notification.page_4.description': 'You’ll buy less'

'modals.recurringbuys.notification.page_5.title': 'But does it work?'
'modals.recurringbuys.notification.page_5.description': 'Over the past 5 years, buying Bitcoin every week performed better than timing the market'
'modals.recurringbuys.notification.page_5.disclaimer': '82% of the time.'
Expand All @@ -1281,27 +1276,21 @@ type MessagesType = {
'modals.recurringbuys.timeframe.every_week': 'Every week'
'modals.recurringbuys.timeframe.2_weeks': 'Every 2 weeks'
'modals.recurringbuys.timeframe.every_month': 'Every month'

'modals.recurringbuys.period_fetch_error': 'There was an error fetching recurring buy frequency options. Please try again.'
'modals.recurringbuys.time_options.one_time': 'One Time'
'modals.recurringbuys.time_options.daily': 'Daily'
'modals.recurringbuys.time_options.weekly': 'Weekly'
'modals.recurringbuys.time_options.bi_weekly': 'Twice a Month'
'modals.recurringbuys.time_options.monthly': 'Monthly'

'modals.recurringbuys.frequency_disabled': '{period} recurring buys are unavailable for your payment method at this time.'

'modals.recurringbuys.get_started.title': 'Set Up a Recurring Buy'
'modals.recurringbuys.get_started.description': 'Buy {amount} of {outputCurrency} every day, week or month with a Recurring Buy. No need to ever time the market.'
'modals.recurringbuys.get_started.buy_amount_of_currency': 'Buy {amount} of {currency}'
'modals.recurringbuys.get_started.get_started': 'Get Started'
'modals.recurringbuys.get_started.maybe_later': 'Maybe Later'

'modals.recurringbuys.get_started.get_started': 'Get Started'
'modals.recurringbuys.get_started.maybe_later': 'Maybe Later'

'modals.recurringbuys.available_methods_tool_tip': 'Recurring Buys are only available for these methods at this time: {methods}'

'modals.recurringbuys.recurring_buy_started': 'Recurring Buy Started!'
'modals.recurringbuys.select_a_frequency': 'Select a Frequency'
'modals.recurringbuys.we_will_buy': 'We will buy {fiatAmount} of {coin} {period} at that moment’s market price. Cancel this recurring buy at anytime.'
Expand Down Expand Up @@ -1645,6 +1634,11 @@ type MessagesType = {
'modals.simplebuy.linkbank.description': 'Link your bank and instantly buy crypto at anytime.'
'modals.simplebuy.card_limit': '{card} Limit'
'modals.simplebuy.card_ending_in': 'Card Ending in {lastFour}'

'modals.simplebuy.select_trading_currency.title': 'Select a Trading Currency.'
'modals.simplebuy.select_trading_currency.description': 'Right now, {currency} is not supported for buying crypto.You can add a bank account or card from the list of available currencies below.'
'modals.simplebuy.select_trading_currency.disclaimer': 'Additional bank fees may apply. Your bank may add fee and Exchange Rates to each transaction.'

'modals.simplebuy.card_expire': 'Exp: {month}/{year}'
'modals.simplebuy.goldupgrade.title1': 'Upgrade Your Profile.'
'modals.simplebuy.goldupgrade.title2': 'Buy & Sell More Crypto.'
Expand Down Expand Up @@ -1819,7 +1813,6 @@ type MessagesType = {
'modals.tradinglimits.upgrade.tier.silver.title': 'Upgrade to Gold Limits'
'modals.tradinglimits.upgrade.tier.silver.description': 'Verify your ID and link your bank to Buy & Sell Crypto straight from your wallet.'
'modals.tradinglimits.upgrade.silver_limits': 'Silver Limits'
'modals.tradinglimits.upgrade.include_silver_limits': 'Includes Silver Features'
'modals.tradinglimits.upgrade.gold_limits': 'Gold Limits'
'modals.tradinglimits.upgrade.unlock_tier_zero': 'Unlock new trading features in your Blockchain.com Wallet by verifying your ID and link a bank or card.'
'modals.tradinglimits.receive_crypto': 'Receive Crypto'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {
BSPairsType,
BSPaymentTypes,
CoinType,
FiatType,
Limits,
SwapOrderType,
WalletFiatEnum,
WalletFiatType
} from '@core/types'

Expand Down Expand Up @@ -154,3 +156,5 @@ export const getValidPaymentMethod = (method: BSPaymentTypes) => {

return method
}

export const isFiatCurrencySupported = (currency: FiatType) => currency in WalletFiatEnum
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default ({ api, coreSagas, networks }) => {
yield takeLatest(actions.pollOrder.type, buySellSagas.pollBSOrder)
yield takeLatest(actions.showModal.type, buySellSagas.showModal)
yield takeLatest(actions.switchFix.type, buySellSagas.switchFix)
yield takeLatest(actions.setFiatTradingCurrency.type, buySellSagas.setFiatTradingCurrency)
yield takeLatest(actions.fetchCrossBorderLimits.type, buySellSagas.fetchCrossBorderLimits)

// Fetch balances when profile/user is fetched
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
ProductTypes,
ProviderDetailsType,
SwapOrderType,
WalletFiatType,
WalletOptionsType
} from '@core/types'
import { errorHandler, errorHandlerCode } from '@core/utils'
Expand Down Expand Up @@ -56,6 +55,7 @@ import {
getCoinFromPair,
getFiatFromPair,
getNextCardExists,
isFiatCurrencySupported,
NO_ACCOUNT,
NO_CHECKOUT_VALUES,
NO_FIAT_CURRENCY,
Expand Down Expand Up @@ -1296,7 +1296,7 @@ export default ({ api, coreSagas, networks }: { api: APIType; coreSagas: any; ne
yield put(actions.modals.showModal('SIMPLE_BUY_MODAL', { cryptoCurrency, origin }))
const fiatCurrency = selectors.core.settings
.getCurrency(yield select())
.getOrElse('USD') as WalletFiatType
.getOrElse('USD') as FiatType

// When user closes the QR code modal and opens it via one of the pending
// buy buttons in the app. We need to take them to the qrcode screen and
Expand Down Expand Up @@ -1344,7 +1344,10 @@ export default ({ api, coreSagas, networks }: { api: APIType; coreSagas: any; ne
break
}
} else {
yield put(A.setStep({ cryptoCurrency, fiatCurrency, step: 'CRYPTO_SELECTION' }))
const originalFiatCurrency = isFiatCurrencySupported(fiatCurrency) ? undefined : fiatCurrency
yield put(
A.setStep({ cryptoCurrency, fiatCurrency, originalFiatCurrency, step: 'CRYPTO_SELECTION' })
)
}
}

Expand Down Expand Up @@ -1393,6 +1396,35 @@ export default ({ api, coreSagas, networks }: { api: APIType; coreSagas: any; ne
}
}

const setFiatTradingCurrency = function* () {
try {
const state = yield select()
const cryptoCurrency = S.getCryptoCurrency(state) || 'BTC'
const fiatCurrency = S.getFiatCurrency(state) || 'USD'
const orderType = S.getOrderType(state) || 'BUY'
yield put(A.fetchPairs({ coin: cryptoCurrency, currency: fiatCurrency }))
// wait to load new pairs
yield take([A.fetchPairsSuccess.type, A.fetchPairsFailure.type])
// state has been changed we need most recent pairs
const pairs = S.getBSPairs(yield select()).getOrElse([])

// find a pair
const pair = pairs.filter((pair) => pair.pair === `${cryptoCurrency}-${fiatCurrency}`)[0]
yield put(A.fetchPaymentMethods(fiatCurrency))
yield put(
A.setStep({
cryptoCurrency,
fiatCurrency,
orderType,
pair,
step: 'ENTER_AMOUNT'
})
)
} catch (e) {
// do nothing
}
}

return {
activateBSCard,
addCardDetails,
Expand Down Expand Up @@ -1430,6 +1462,7 @@ export default ({ api, coreSagas, networks }: { api: APIType; coreSagas: any; ne
pollBSBalances,
pollBSCard,
pollBSOrder,
setFiatTradingCurrency,
setStepChange,
showModal,
switchFix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ export const getStep = (state: RootState) => state.components.buySell.step

export const getSwapAccount = (state: RootState) => state.components.buySell.swapAccount

export const getOriginalFiatCurrency = (state: RootState) =>
state.components.buySell.originalFiatCurrency

// Sell specific (for now!)
// used for sell only now, eventually buy as well
// TODO: use swap2 quote for buy AND sell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const initialState: BuySellState = {
orderType: undefined,
orders: Remote.NotAsked,
origin: undefined,
originalFiatCurrency: undefined,
pair: undefined,
pairs: Remote.NotAsked,
payment: Remote.NotAsked,
Expand Down Expand Up @@ -104,6 +105,7 @@ const getPayloadObjectForStep = (payload: StepActionsPayload) => {
cryptoCurrency: payload.cryptoCurrency,
fiatCurrency: payload.fiatCurrency,
orderType: payload.orderType,
originalFiatCurrency: payload.originalFiatCurrency,
step: payload.step
}
case 'BANK_WIRE_DETAILS':
Expand Down Expand Up @@ -275,7 +277,7 @@ const buySellSlice = createSlice({
fetchOrdersSuccess: (state, action: PayloadAction<BSOrderType[]>) => {
state.orders = Remote.Success(action.payload)
},
fetchPairs: (state, action: PayloadAction<{ coin?: CoinType; currency: FiatType }>) => {},
fetchPairs: (state, action: PayloadAction<{ coin?: CoinType; currency?: FiatType }>) => {},
fetchPairsFailure: (state, action: PayloadAction<string>) => {
state.pairs = Remote.Failure(action.payload)
},
Expand Down Expand Up @@ -413,6 +415,9 @@ const buySellSlice = createSlice({
setFiatCurrency: (state, action: PayloadAction<FiatType>) => {
state.fiatCurrency = action.payload
},
setFiatTradingCurrency: (state, action: PayloadAction<FiatType>) => {
state.fiatCurrency = action.payload
},
setMethod: (state, action: PayloadAction<BSPaymentMethodType>) => {
state.method = action.payload
},
Expand All @@ -436,6 +441,7 @@ const buySellSlice = createSlice({
state.addBank = undefined
state.cryptoCurrency = stepPayload.cryptoCurrency
state.fiatCurrency = stepPayload.fiatCurrency
state.originalFiatCurrency = stepPayload.originalFiatCurrency
state.orderType = stepPayload.orderType
state.step = stepPayload.step
state.swapAccount = undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export enum BuySellStepType {
'OPEN_BANKING_CONNECT',
'PAYMENT_METHODS',
'PREVIEW_SELL',
'TRADING_CURRENCY_SELECTOR',
'ORDER_SUMMARY',
'SELL_ORDER_SUMMARY',
'TRANSFER_DETAILS',
Expand Down Expand Up @@ -140,6 +141,7 @@ export type BuySellState = {
orderType?: BSOrderActionType
orders: RemoteDataType<string, Array<BSOrderType>>
origin?: BSShowModalOriginType
originalFiatCurrency: undefined | FiatType
pair: undefined | BSPairType
pairs: RemoteDataType<string, Array<BSPairType>>
payment: RemoteDataType<string, undefined | PaymentValue>
Expand Down Expand Up @@ -188,6 +190,7 @@ export type StepActionsPayload =
cryptoCurrency?: CoinType
fiatCurrency: FiatType
orderType?: BSOrderActionType
originalFiatCurrency?: FiatType
step: 'CRYPTO_SELECTION'
}
| {
Expand Down Expand Up @@ -231,5 +234,6 @@ export type StepActionsPayload =
| 'KYC_REQUIRED'
| 'UPGRADE_TO_GOLD'
| 'LOADING'
| 'TRADING_CURRENCY_SELECTOR'
| 'FREQUENCY'
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { any, map, values } from 'ramda'
import { Form, InjectedFormProps, reduxForm } from 'redux-form'
import styled from 'styled-components'

import { OrderType, BSPairType } from '@core/types'
import { BSPairType, OrderType } from '@core/types'
import { Icon, Image, TabMenu, TabMenuItem, Text } from 'blockchain-info-components'
import { FlyoutWrapper } from 'components/Flyout'
import { CoinAccountListOption } from 'components/Form'
Expand Down Expand Up @@ -88,6 +88,13 @@ const CryptoSelector: React.FC<InjectedFormProps<{}, Props> & Props> = (props) =
})
}

// in case of not directly supported fiat currency lend user to select trading currency from list
if (props.originalFiatCurrency) {
return props.buySellActions.setStep({
step: 'TRADING_CURRENCY_SELECTOR'
})
}

// default continue to enter amount step
return props.buySellActions.setStep({
cryptoCurrency: getCoinFromPair(pair.pair),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { connect, ConnectedProps } from 'react-redux'
import { bindActionCreators, Dispatch } from 'redux'

import { Remote } from '@core'
import { ExtractSuccess } from '@core/types'
import { ExtractSuccess, WalletFiatEnum } from '@core/types'
import { FlyoutOopsError } from 'components/Flyout'
import { actions, selectors } from 'data'
import { RootState } from 'data/rootReducer'
Expand All @@ -15,7 +15,10 @@ import Success from './template.success'
class CryptoSelection extends PureComponent<Props> {
componentDidMount() {
if (this.props.fiatCurrency && !Remote.Success.is(this.props.data)) {
this.props.buySellActions.fetchPairs({ currency: this.props.fiatCurrency })
const currentCurrencyIsInSupportedFiat = this.props.fiatCurrency in WalletFiatEnum
// for other currencies use as pre fill USD
const currency = currentCurrencyIsInSupportedFiat ? this.props.fiatCurrency : 'USD'
this.props.buySellActions.fetchPairs({ currency })
this.props.buySellActions.fetchFiatEligible(this.props.fiatCurrency)
this.props.buySellActions.fetchSDDEligibility()
this.props.buySellActions.fetchOrders()
Expand Down Expand Up @@ -49,6 +52,7 @@ const mapStateToProps = (state: RootState) => ({
data: getData(state),
fiatCurrency: selectors.components.buySell.getFiatCurrency(state) || 'USD',
isFirstLogin: selectors.auth.getFirstLogin(state),
originalFiatCurrency: selectors.components.buySell.getOriginalFiatCurrency(state),
sddTransactionFinished: selectors.components.buySell.getSddTransactionFinished(state)
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@ import { BuySellLimitReached } from 'components/Flyout'

import { Props as OwnProps, SuccessStateType } from '.'
import CryptoSelector from './CryptoSelector'
import Unsupported from './template.unsupported'

const Success: React.FC<Props> = (props) => {
const isUserEligible = props.pairs.length && props.eligibility.eligible && props.fiatCurrency
const isUserSddEligible = props.sddEligible && props.sddEligible.eligible
const userHitMaxPendingDeposits =
props.eligibility.maxPendingDepositSimpleBuyTrades ===
props.eligibility.pendingDepositSimpleBuyTrades

if (isUserEligible || isUserSddEligible) {
return <CryptoSelector {...props} />
}
if (!isUserEligible && userHitMaxPendingDeposits) {
return (
<BuySellLimitReached
Expand All @@ -24,7 +19,8 @@ const Success: React.FC<Props> = (props) => {
/>
)
}
return <Unsupported {...props} />
// now we always return this list
return <CryptoSelector {...props} />
}

export type Props = OwnProps & SuccessStateType
Expand Down

0 comments on commit 148ac1c

Please sign in to comment.