Skip to content

Commit

Permalink
feat(simple buy): using an added card
Browse files Browse the repository at this point in the history
  • Loading branch information
Philip London committed Apr 24, 2020
1 parent 8532b3d commit e2eb3b9
Show file tree
Hide file tree
Showing 17 changed files with 263 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ export const ACTIVATE_SB_CARD_SUCCESS = '@EVENT.ACTIVATE_SB_CARD_SUCCESS'

export const CANCEL_ORDER = '@EVENT.CANCEL_SB_ORDER'
export const CREATE_ORDER = '@EVENT.CREATE_SB_ORDER'
export const CONFIRM_ORDER = '@EVENT.CONFIRM_SB_ORDER'
export const CONFIRM_BANK_TRANSFER_ORDER =
'@EVENT.CONFIRM_SB_BANK_TRANSFER_ORDER'
export const CONFIRM_CREDIT_CARD_ORDER = '@EVENT.CONFIRM_SB_CREDIT_CARD_ORDER'

export const DESTROY_CHECKOUT = '@EVENT.DESTROY_SB_CHECKOUT'

Expand Down Expand Up @@ -85,6 +87,7 @@ export const HANDLE_SB_SUGGESTED_AMOUNT_CLICK =
export const INITIALIZE_CHECKOUT = '@EVENT.INITIALIZE_SB_CHECKOUT'

export const POLL_SB_CARD = '@EVENT.POLL_SB_CARD'
export const POLL_SB_ORDER = '@EVENT.POLL_SB_ORDER'

export const SET_STEP = '@EVENT.SET_SB_STEP'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,15 @@ export const createSBOrder = (paymentMethodId?: SBCardType['id']) => ({
paymentMethodId
})

export const confirmSBOrder = () => ({
type: AT.CONFIRM_ORDER
export const confirmSBBankTransferOrder = () => ({
type: AT.CONFIRM_BANK_TRANSFER_ORDER
})

export const confirmSBCreditCardOrder = (
paymentMethodId: SBCardType['id']
) => ({
type: AT.CONFIRM_CREDIT_CARD_ORDER,
paymentMethodId
})

export const destroyCheckout = () => ({
Expand Down Expand Up @@ -363,6 +370,13 @@ export const pollSBCard = (cardId: SBCardType['id']) => ({
}
})

export const pollSBOrder = (orderId: string) => ({
type: AT.POLL_SB_ORDER,
payload: {
orderId
}
})

export const setStep = (
payload:
| {
Expand All @@ -379,7 +393,8 @@ export const setStep = (
step: 'ENTER_AMOUNT'
}
| { cardId?: string; step: 'ADD_CARD' }
| { step: 'CURRENCY_SELECTION' | '3DS_HANDLER' }
| { order?: SBOrderType; step: '3DS_HANDLER' }
| { step: 'CURRENCY_SELECTION' }
): SimpleBuyActionTypes => ({
type: AT.SET_STEP,
payload:
Expand All @@ -396,6 +411,8 @@ export const setStep = (
? { step: payload.step, order: payload.order }
: payload.step === 'ADD_CARD'
? { step: payload.step, cardId: payload.cardId }
: payload.step === '3DS_HANDLER'
? { step: payload.step, order: payload.order }
: {
step: payload.step
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ export function simpleBuyReducer (
fiatCurrency: action.payload.fiatCurrency,
step: action.payload.step
}
case '3DS_HANDLER':
case 'CHECKOUT_CONFIRM':
case 'ORDER_SUMMARY':
case 'TRANSFER_DETAILS':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ export default ({ api, coreSagas, networks }) => {
yield takeLatest(AT.ACTIVATE_SB_CARD, simpleBuySagas.activateSBCard)
yield takeLatest(AT.CANCEL_ORDER, simpleBuySagas.cancelSBOrder)
yield takeLatest(AT.CREATE_ORDER, simpleBuySagas.createSBOrder)
yield takeLatest(AT.CONFIRM_ORDER, simpleBuySagas.confirmSBOrder)
yield takeLatest(
AT.CONFIRM_BANK_TRANSFER_ORDER,
simpleBuySagas.confirmSBBankTransferOrder
)
yield takeLatest(
AT.CONFIRM_CREDIT_CARD_ORDER,
simpleBuySagas.confirmSBCreditCardOrder
)
yield takeLatest(
AT.FETCH_EVERYPAY_3DS_DETAILS,
simpleBuySagas.fetchEverypay3DSDetails
Expand Down Expand Up @@ -42,6 +49,7 @@ export default ({ api, coreSagas, networks }) => {
)
yield takeLatest(AT.INITIALIZE_CHECKOUT, simpleBuySagas.initializeCheckout)
yield takeLatest(AT.POLL_SB_CARD, simpleBuySagas.pollSBCard)
yield takeLatest(AT.POLL_SB_ORDER, simpleBuySagas.pollSBOrder)
yield takeLatest(AT.SHOW_MODAL, simpleBuySagas.showModal)
// Fetch balances when profile/user is fetched
yield takeLatest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export default ({
}
}

const confirmSBOrder = function * () {
const confirmSBBankTransferOrder = function * () {
try {
const order = S.getSBOrder(yield select())
if (!order) throw new Error('NO_ORDER_EXISTS_TO_CONFIRM')
Expand All @@ -150,6 +150,36 @@ export default ({
}
}

const confirmSBCreditCardOrder = function * () {
try {
const order = S.getSBOrder(yield select())
if (!order) throw new Error('NO_ORDER_EXISTS_TO_CONFIRM')
yield put(actions.form.startSubmit('sbCheckoutConfirm'))
const domainsR = selectors.core.walletOptions.getDomains(yield select())
const domains = domainsR.getOrElse({
walletHelper: 'https://wallet-helper.blockchain.com'
})
const attributes = order.paymentMethodId
? {
everypay: {
customerUrl: `${domains.walletHelper}/wallet-helper/everypay/#/response-handler`
}
}
: undefined
const confirmedOrder: SBOrderType = yield call(
api.confirmSBOrder,
order,
attributes
)
yield put(actions.form.stopSubmit('sbCheckoutConfirm'))
yield put(A.setStep({ step: '3DS_HANDLER', order: confirmedOrder }))
yield put(A.fetchSBOrders())
} catch (e) {
const error = errorHandler(e)
yield put(actions.form.stopSubmit('sbCheckoutConfirm', { _error: error }))
}
}

const fetchEverypay3DSDetails = function * () {
try {
yield put(actions.form.startSubmit('addCCForm'))
Expand Down Expand Up @@ -420,7 +450,6 @@ export default ({

while (
(card.state === 'CREATED' || card.state === 'PENDING') &&
(card.state === 'PENDING' && !card.card) &&
retryAttempts < maxRetryAttempts
) {
card = yield call(api.getSBCard, cardId)
Expand All @@ -439,6 +468,28 @@ export default ({
}
}

const pollSBOrder = function * ({ payload }: ReturnType<typeof A.pollSBOrder>) {
let retryAttempts = 0
let maxRetryAttempts = 20

const { orderId } = payload
let order: ReturnType<typeof api.getSBOrder> = yield call(
api.getSBOrder,
orderId
)

while (
order.state === 'PENDING_DEPOSIT' &&
retryAttempts < maxRetryAttempts
) {
order = yield call(api.getSBOrder, orderId)
retryAttempts++
yield delay(3000)
}

yield put(A.setStep({ step: 'ORDER_SUMMARY', order }))
}

const showModal = function * ({ payload }: ReturnType<typeof A.showModal>) {
const { origin, cryptoCurrency } = payload
yield put(
Expand All @@ -458,7 +509,8 @@ export default ({
return {
activateSBCard,
cancelSBOrder,
confirmSBOrder,
confirmSBBankTransferOrder,
confirmSBCreditCardOrder,
createSBOrder,
fetchEverypay3DSDetails,
fetchSBBalances,
Expand All @@ -474,6 +526,7 @@ export default ({
handleSBSuggestedAmountClick,
initializeCheckout,
pollSBCard,
pollSBOrder,
showModal
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ export type SBAddCardFormValuesType = {
}
export type SBCheckoutFormValuesType = {
amount: string
method?: SBPaymentMethodType
method?:
| SBPaymentMethodType
| SBCardType & {
limits: SBPaymentMethodType['limits']
type: 'USER_CARD'
}
orderType: 'BUY' | 'SELL'
pair?: SBPairType
}
Expand All @@ -37,8 +42,8 @@ export enum SimpleBuyStepType {
'CURRENCY_SELECTION',
'ENTER_AMOUNT',
'ADD_CARD',
'3DS_HANDLER',
'CHECKOUT_CONFIRM',
'3DS_HANDLER',
'ORDER_SUMMARY',
'TRANSFER_DETAILS',
'CANCEL_ORDER'
Expand Down Expand Up @@ -280,6 +285,7 @@ interface SetStepAction {
step: 'ADD_CARD'
}
| {
order?: SBOrderType
step: '3DS_HANDLER'
}
| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ class CheckoutConfirm extends PureComponent<Props> {
}

handleSubmit = () => {
this.props.simpleBuyActions.confirmSBOrder()
if (this.props.order.paymentMethodId) {
this.props.simpleBuyActions.confirmSBCreditCardOrder(
this.props.order.paymentMethodId
)
} else {
this.props.simpleBuyActions.confirmSBBankTransferOrder()
}
}

render () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FormattedMessage } from 'react-intl'
import { getOutputAmount } from 'data/components/simpleBuy/model'
import { InjectedFormProps, reduxForm } from 'redux-form'
import { Props as OwnProps, SuccessStateType } from '.'
import BigNumber from 'bignumber.js'
import React from 'react'
import styled from 'styled-components'

Expand Down Expand Up @@ -102,8 +103,9 @@ const Success: React.FC<InjectedFormProps<{}, Props> & Props> = props => {
defaultMessage='Payment Method'
/>
</Title>
{/* TODO: Simple Buy - payment method types */}
<Value>Bank Transfer</Value>
<Value>
{props.order.paymentMethodId ? 'Credit Card' : 'Bank Transfer'}
</Value>
</Row>
<Row>
<Title>
Expand All @@ -113,7 +115,10 @@ const Success: React.FC<InjectedFormProps<{}, Props> & Props> = props => {
/>
</Title>
<Value>
{displayFiat(props.quote.fee)} {props.order.inputCurrency}
{props.order.fee
? displayFiat(props.order.fee)
: displayFiat(props.quote.fee)}{' '}
{props.order.inputCurrency}
</Value>
</Row>
<Row>
Expand All @@ -124,7 +129,12 @@ const Success: React.FC<InjectedFormProps<{}, Props> & Props> = props => {
/>
</Title>
<Value>
{displayFiat(props.order.inputQuantity)} {props.order.inputCurrency}
{displayFiat(
new BigNumber(props.order.inputQuantity)
.plus(props.order.fee || '0')
.toString()
)}{' '}
{props.order.inputCurrency}
</Value>
</Row>
<Bottom>
Expand All @@ -134,16 +144,6 @@ const Success: React.FC<InjectedFormProps<{}, Props> & Props> = props => {
defaultMessage='Your final amount may change due to market activity.'
/>
</Text>
{props.error && (
<ErrorCartridge>
<Icon
name='alert-filled'
color='red600'
style={{ marginRight: '4px' }}
/>
Error: {props.error}
</ErrorCartridge>
)}
<Button
fullwidth
nature='primary'
Expand All @@ -165,6 +165,7 @@ const Success: React.FC<InjectedFormProps<{}, Props> & Props> = props => {
</Button>
<Button
data-e2e='sbCancelCheckout'
disabled={props.submitting}
size='16px'
height='48px'
nature='light'
Expand All @@ -178,6 +179,16 @@ const Success: React.FC<InjectedFormProps<{}, Props> & Props> = props => {
>
<FormattedMessage id='buttons.cancel' defaultMessage='Cancel' />
</Button>
{props.error && (
<ErrorCartridge style={{ marginTop: '16px' }}>
<Icon
name='alert-filled'
color='red600'
style={{ marginRight: '4px' }}
/>
Error: {props.error}
</ErrorCartridge>
)}
</Bottom>
</CustomForm>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Field } from 'redux-form'
import { getFiatFromPair } from 'data/components/simpleBuy/model'
import { Icon, Text } from 'blockchain-info-components'
import { Props } from '../template.success'
import { SBCardType, SBPaymentMethodType } from 'core/types'
import { SBCheckoutFormValuesType } from 'data/types'
import { SelectBox } from 'components/Form'
import React, { PureComponent, ReactElement } from 'react'
import styled from 'styled-components'
Expand Down Expand Up @@ -108,7 +108,9 @@ class MethodSelect extends PureComponent<Props> {
}

renderElements = () => {
const availableCards = this.props.cards.filter(({ card }) => !!card)
const availableCards = this.props.cards.filter(
card => card.state === 'ACTIVE'
)
const defaultCardMethod = this.props.paymentMethods.methods.find(
m => m.type === 'CARD'
)
Expand Down Expand Up @@ -180,11 +182,6 @@ class MethodSelect extends PureComponent<Props> {
}
}

type ElementValueType =
| SBPaymentMethodType
| SBCardType & {
limits: SBPaymentMethodType['limits']
type: 'USER_CARD'
}
type ElementValueType = Exclude<SBCheckoutFormValuesType['method'], undefined>

export default MethodSelect

0 comments on commit e2eb3b9

Please sign in to comment.