Skip to content

Commit

Permalink
fix(component): ensure lockbox sagas with connection polling stop pol…
Browse files Browse the repository at this point in the history
…ling on modal close
  • Loading branch information
schnogz committed Dec 11, 2018
1 parent 8378ba4 commit f955017
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// ROUTING
export const DETERMINE_LOCKBOX_ROUTE = '@LOCKBOX.DETERMINE_LOCKBOX_ROUTE'

// CONNECTIONS
export const POLL_FOR_DEVICE_APP = '@LOCKBOX.POLL_FOR_DEVICE_APP'
export const RESET_CONNECTION_STATUS = '@LOCKBOX.RESET_CONNECTION_STATUS'
Expand Down Expand Up @@ -71,3 +68,7 @@ export const APP_CHANGE_LOADING = '@LOCKBOX.APP_CHANGE_LOADING'
export const APP_CHANGE_SUCCESS = '@LOCKBOX.APP_CHANGE_SUCCESS'
export const APP_CHANGE_FAILURE = '@LOCKBOX.APP_CHANGE_FAILURE'
export const RESET_APP_CHANGE_STATUS = '@LOCKBOX.RESET_APP_CHANGE_STATUS'

// MISC
export const DETERMINE_LOCKBOX_ROUTE = '@LOCKBOX.DETERMINE_LOCKBOX_ROUTE'
export const LOCKBOX_MODAL_CLOSE = '@LOCKBOX.LOCKBOX_MODAL_CLOSE'
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import * as AT from './actionTypes'

// ROUTING
export const determineLockboxRoute = () => ({
type: AT.DETERMINE_LOCKBOX_ROUTE
})

// CONNECTIONS
export const pollForDeviceApp = (
appRequested,
Expand Down Expand Up @@ -179,8 +174,15 @@ export const newDeviceBtcInstall = () => ({
export const resetAppChangeStatus = () => ({
type: AT.RESET_APP_CHANGE_STATUS
})
// new coins

// MISC
export const determineLockboxRoute = () => ({
type: AT.DETERMINE_LOCKBOX_ROUTE
})
export const saveCoinMD = (deviceIndex, coin) => ({
type: AT.SAVE_COIN_MD,
payload: { deviceIndex, coin }
})
export const lockboxModalClose = () => ({
type: AT.LOCKBOX_MODAL_CLOSE
})
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
import { takeLatest } from 'redux-saga/effects'
import { takeLatest, race, take, call } from 'redux-saga/effects'
import * as AT from './actionTypes'
import sagas from './sagas'

export default ({ api, coreSagas }) => {
const lockboxSagas = sagas({ api, coreSagas })

return function*() {
yield takeLatest(AT.INITIALIZE_NEW_DEVICE_SETUP, function*(...args) {
yield race({
task: call(lockboxSagas.initializeNewDeviceSetup, ...args),
cancel: take(AT.LOCKBOX_MODAL_CLOSE)
})
})
yield takeLatest(AT.POLL_FOR_DEVICE_APP, function*(...args) {
yield race({
task: call(lockboxSagas.pollForDeviceApp, ...args),
cancel: take(AT.LOCKBOX_MODAL_CLOSE)
})
})
yield takeLatest(AT.UPDATE_DEVICE_FIRMWARE, function*(...args) {
yield race({
task: call(lockboxSagas.updateDeviceFirmware, ...args),
cancel: take(AT.LOCKBOX_MODAL_CLOSE)
})
})
yield takeLatest(AT.INSTALL_APPLICATION, lockboxSagas.installApplication)
yield takeLatest(
AT.INITIALIZE_NEW_DEVICE_SETUP,
lockboxSagas.initializeNewDeviceSetup
)
yield takeLatest(
AT.UPDATE_DEVICE_FIRMWARE,
lockboxSagas.updateDeviceFirmware
)
yield takeLatest(
AT.UPDATE_TRANSACTION_LIST,
lockboxSagas.updateTransactionList
Expand All @@ -28,7 +38,6 @@ export default ({ api, coreSagas }) => {
lockboxSagas.saveNewDeviceKvStore
)
yield takeLatest(AT.DELETE_DEVICE, lockboxSagas.deleteDevice)
yield takeLatest(AT.POLL_FOR_DEVICE_APP, lockboxSagas.pollForDeviceApp)
yield takeLatest(
AT.CHECK_DEVICE_AUTHENTICITY,
lockboxSagas.checkDeviceAuthenticity
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { call, put, take, select, takeEvery } from 'redux-saga/effects'
import {
call,
cancelled,
put,
take,
select,
takeEvery
} from 'redux-saga/effects'
import {
head,
contains,
Expand All @@ -20,6 +27,7 @@ import * as Lockbox from 'services/LockboxService'
import { confirm, promptForLockbox } from 'services/SagaService'

const logLocation = 'components/lockbox/sagas'
const sagaCancelledMsg = 'Saga cancelled from user modal close'

export default ({ api }) => {
// variables for deviceType and app polling during new device setup
Expand Down Expand Up @@ -104,7 +112,17 @@ export default ({ api }) => {
closePoll = true
} catch (e) {
yield put(A.setConnectionError(e))
yield put(actions.logs.logErrorMessage(logLocation, 'connectDevice', e))
yield put(
actions.logs.logErrorMessage(logLocation, 'pollForDeviceApp', e)
)
} finally {
if (yield cancelled()) {
actions.logs.logInfoMessage(
logLocation,
'pollForDeviceApp',
sagaCancelledMsg
)
}
}
}

Expand Down Expand Up @@ -226,6 +244,7 @@ export default ({ api }) => {
}
}

// saves xPubs/addresses for requested coin to kvStore
const saveCoinMD = function*(action) {
try {
const { deviceIndex, coin } = action.payload
Expand Down Expand Up @@ -434,6 +453,16 @@ export default ({ api }) => {
yield put(
actions.logs.logErrorMessage(logLocation, 'initializeNewDeviceSetup', e)
)
} finally {
if (yield cancelled()) {
yield put(A.resetConnectionStatus())
yield put(A.resetDeviceAuthenticity())
actions.logs.logInfoMessage(
logLocation,
'initializeNewDeviceSetup',
sagaCancelledMsg
)
}
}
}

Expand Down Expand Up @@ -618,6 +647,14 @@ export default ({ api }) => {
yield put(
actions.logs.logErrorMessage(logLocation, 'updateDeviceFirmware', e)
)
} finally {
if (yield cancelled()) {
actions.logs.updateDeviceFirmware(
logLocation,
'pollForDeviceApp',
sagaCancelledMsg
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ class LockboxSetupContainer extends React.PureComponent {
this.props.lockboxActions.resetConnectionStatus()
this.props.lockboxActions.changeDeviceSetupStep('setup-type')
}
onClose = () => {
this.props.lockboxActions.lockboxModalClose()
this.props.closeAll()
}

render () {
const { currentStep, position, total, closeAll, setupType } = this.props
const { currentStep, position, total, setupType } = this.props
let steps = {
'setup-type': { num: 0, template: () => <SetupTypeStep /> },
'connect-device': { num: 1, template: () => <ConnectDeviceStep /> },
Expand Down Expand Up @@ -55,8 +59,7 @@ class LockboxSetupContainer extends React.PureComponent {
<LockboxSetup
total={total}
position={position}
closeAll={closeAll}
handleClose={this.handleClose}
onClose={this.onClose}
totalSteps={setupType === 'existing' ? 4 : 5}
step={step.num}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React from 'react'
import PropTypes from 'prop-types'
import ModalStepper from 'components/ModalStepper'
import { Modal, ModalBody } from 'blockchain-info-components'
import { Modal, ModalBody, ModalHeader } from 'blockchain-info-components'

const LockboxSetup = props => {
const { children, position, total, totalSteps, step } = props
const { children, position, total, totalSteps, step, onClose } = props
const atBounds = step === 0 || step > totalSteps

return (
<Modal size={atBounds ? 'auto' : 'small'} position={position} total={total}>
<ModalHeader onClose={onClose} />
{!atBounds && <ModalStepper currentStep={step} totalSteps={totalSteps} />}
<ModalBody>{children}</ModalBody>
</Modal>
Expand All @@ -18,7 +19,7 @@ const LockboxSetup = props => {
LockboxSetup.propTypes = {
position: PropTypes.number.isRequired,
total: PropTypes.number.isRequired,
closeAll: PropTypes.func.isRequired
onClose: PropTypes.func.isRequired
}

export default LockboxSetup
6 changes: 3 additions & 3 deletions packages/blockchain-wallet-v4-frontend/src/modals/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ const Modals = props => (
<IdentityVerification />
<ImportBtcAddress />
<LockboxAppManager disableOutsideClose />
<LockboxFirmware />
<LockboxSetup />
<LockboxFirmware disableOutsideClose />
<LockboxSetup disableOutsideClose />
<PromptLockbox disableOutsideClose />
<MobileNumberChange />
<MobileNumberVerify />
<MobileLogin />
<Onfido />
<PairingCode />
<PromptInput />
<PromptLockbox />
<QRCode />
<RequestBch />
<RequestBtc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ const pollForAppConnection = (deviceType, app, timeout = 45000) => {
// transport.setDebugMode(true)
transport.setExchangeTimeout(timeout)
transport.setScrambleKey(scrambleKey)
//console.info('POLL:START', deviceType, scrambleKey, app, timeout)
console.info('POLL:START', deviceType, scrambleKey, app, timeout)
// send NO_OP cmd until response is received (success) or timeout is hit (reject)
transport.send(...constants.apdus.no_op).then(
() => {},
res => {
// since no_op wont be recognized by any app as a valid cmd, this is always going
// to fail but a response, means a device is connected and unlocked
//console.info('POLL:END', deviceType, scrambleKey, app, timeout)
console.info('POLL:END', deviceType, scrambleKey, app, timeout)
if (res.originalError) {
reject(res.originalError.metaData)
}
Expand Down Expand Up @@ -83,16 +83,16 @@ const createDeviceSocket = (transport, url) => {
}

ws.onopen = () => {
//console.info('OPENED', { url })
console.info('OPENED', { url })
}

ws.onerror = e => {
//console.info('ERROR', { message: e.message, stack: e.stack })
console.info('ERROR', { message: e.message, stack: e.stack })
o.error(e.message, { url })
}

ws.onclose = () => {
//console.info('CLOSE')
console.info('CLOSE')
o.next(lastMessage || '')
o.complete()
}
Expand All @@ -103,10 +103,10 @@ const createDeviceSocket = (transport, url) => {
if (!(msg.query in handlers)) {
throw new Error({ message: 's0ck3t' }, { url })
}
//console.info('RECEIVE', msg)
console.info('RECEIVE', msg)
await handlers[msg.query](msg)
} catch (err) {
//console.info('ERROR', { message: err.message, stack: err.stack })
console.info('ERROR', { message: err.message, stack: err.stack })
o.error(err)
}
}
Expand All @@ -117,7 +117,7 @@ const createDeviceSocket = (transport, url) => {
response,
data
}
//console.info('SEND', msg)
console.info('SEND', msg)
const strMsg = JSON.stringify(msg)
ws.send(strMsg)
}
Expand Down Expand Up @@ -163,7 +163,7 @@ const createDeviceSocket = (transport, url) => {
},

error: msg => {
//console.info('ERROR', { data: msg.data })
console.info('ERROR', { data: msg.data })
ws.close()
throw new Error(msg.data, { url })
}
Expand Down

0 comments on commit f955017

Please sign in to comment.