Skip to content

Commit

Permalink
POC: Configure two Web Wallet applications (Root Document & Main Proc…
Browse files Browse the repository at this point in the history
…ess) to coexist.
  • Loading branch information
Empowerful committed May 8, 2019
1 parent a708ee6 commit f22a528
Show file tree
Hide file tree
Showing 102 changed files with 4,215 additions and 1,606 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ Testing is done via [Jest](https://facebook.github.io/jest/) and [Enzyme](http:/
_Note: if you see errors that Jest cannot resolve package imports, you may need to run `yarn test` before testing specific packages (eg, `yarn test:frontend`)_

#### Running Tests via Watch
* `yarn test:watch` Watches and then runs desired tests
* `yarn test:components:watch` Watches and then runs desired tests for only [blockchain-info-components](./packages/blockchain-info-components)
* `yarn test:core:watch` Watches and then runs desired tests for only [blockchain-wallet-v4](./packages/blockchain-wallet-v4)
* `yarn test:frontend:watch` Watches and then runs desired tests for only [blockchain-wallet-v4-frontend](./packages/blockchain-wallet-v4-frontend)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,11 @@
},
"dependencies": {
"@blockchain-com/components": "5.1.1",
"@ledgerhq/hw-app-eth": "4.26.0-beta.ebeb3540",
"@ledgerhq/hw-app-btc": "4.30.0",
"@ledgerhq/hw-app-eth": "4.26.0-beta.ebeb3540",
"@ledgerhq/hw-app-str": "4.26.0-beta.ebeb3540",
"@ledgerhq/hw-transport-u2f": "4.31.0",
"@nodeguy/channel": "0.6.5",
"awesome-phonenumber": "2.2.6",
"base-64": "0.1.0",
"bignumber.js": "8.0.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as router from 'connected-react-router'
import * as R from 'ramda'

import * as coreTypes from 'blockchain-wallet-v4/src/redux/actionTypes'
import * as types from '../data/actionTypes'

const alreadyForwarded = ({ meta }) => meta && meta.forwarded

const dispatchToBoth = ({ rootDocumentDispatch, next }, action) => {
if (!alreadyForwarded(action)) {
rootDocumentDispatch(action)
}

next(action)
}

const dispatchToRootDocument = ({ rootDocumentDispatch }, action) => {
rootDocumentDispatch(action)
}

const tag = action => ({
...action,
meta: { ...action.meta, forwarded: true }
})

const handlers = {
// This requires the GUID.
[coreTypes.data.misc.FETCH_LOGS]: dispatchToRootDocument,

// This requires the GUID.
[coreTypes.settings.FETCH_SETTINGS]: dispatchToRootDocument,

// Tell the Root Document to merge our wrapper with its own.
[coreTypes.wallet.MERGE_WRAPPER]: dispatchToRootDocument,

// Inform the root document about routing changes so that it can switch which
// application is displayed.
[router.LOCATION_CHANGE]: dispatchToBoth,

// Tell the root document to reload itself when we do.
[types.auth.LOGOUT]: dispatchToBoth,

// This requires the GUID.
[types.modules.settings.UPDATE_LANGUAGE]: dispatchToRootDocument
}

export default ({ actionsChannel, rootDocumentDispatch }) => store => {
// Now that we have access to the store, dispatch stored actions from the Root
// Document to it.
actionsChannel.forEach(store.dispatch)

return next => action => {
const { type } = action

const context = {
rootDocumentDispatch: R.pipe(
tag,
rootDocumentDispatch
),
next,
store
}

if (type in handlers) {
return handlers[type](context, action)
} else {
return next(action)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Channel from '@nodeguy/channel'

import { serializer } from 'blockchain-wallet-v4/src/types'
import Middleware from './Middleware'
import { RealmConnectionModule } from '../../../web-microkernel/src'

const { RealmConnection, sanitizeFunction } = RealmConnectionModule({
ErrorEvent,
EventTarget,
getRandomValues: typedArray => window.crypto.getRandomValues(typedArray)
})

export default async ({ input, output, outputOrigin }) => {
// We need to export a function for dispatching actions from the Root
// Document before the store is created so use a channel to save them until
// the store is ready.
const actionsChannel = Channel()

const connection = await RealmConnection({
exports: { dispatch: actionsChannel.push },
input,
output,
outputOrigin,
reviver: serializer.reviver
})

return {
connection,

middleware: Middleware({
actionsChannel,
rootDocumentDispatch: connection.imports.dispatch
}),

sanitizeFunction
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`PhoneNumberBox renders correctly 1`] = `
<PhoneNumberBox__Container>
<Styled(mockConstructor)
_$p_={
_css={
Array [
"intl-tel-input",
"form-control",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ exports[`ListItemContainer renders correctly 1`] = `
"deleteHdAddressLabel": [Function],
"deleteLegacyAddress": [Function],
"deleteWrapper": [Function],
"mergeWrapper": [Function],
"refreshWrapper": [Function],
"setAccountArchived": [Function],
"setAccountLabel": [Function],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const DEAUTHORIZE_BROWSER = 'DEAUTHORIZE_BROWSER'
export const LOGIN = 'LOGIN'
export const LOGIN_FAILURE = 'LOGIN_FAILURE'
export const LOGIN_LOADING = 'LOGIN_LOADING'
export const LOGIN_ROUTINE = 'LOGIN_ROUTINE'
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'
export const LOGOUT = 'LOGOUT'
export const LOGOUT_CLEAR_REDUX_STORE = 'LOGOUT_CLEAR_REDUX_STORE'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export const login = (guid, password, code, sharedKey, mobileLogin) => ({
payload: { guid, password, code, sharedKey, mobileLogin }
})
export const loginLoading = () => ({ type: AT.LOGIN_LOADING })

export const loginRoutine = (mobileLogin = false, firstLogin = false) => ({
type: AT.LOGIN_ROUTINE,
payload: { firstLogin, mobileLogin }
})

export const loginSuccess = () => ({ type: AT.LOGIN_SUCCESS, payload: {} })
export const loginFailure = err => ({
type: AT.LOGIN_FAILURE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { takeLatest } from 'redux-saga/effects'
import * as AT from './actionTypes'
import sagas from './sagas'

export default ({ api, coreSagas }) => {
const authSagas = sagas({ api, coreSagas })
export default (...args) => {
const authSagas = sagas(...args)

return function* authSaga () {
yield takeLatest(AT.DEAUTHORIZE_BROWSER, authSagas.deauthorizeBrowser)
yield takeLatest(AT.LOGIN, authSagas.login)
yield takeLatest(AT.LOGIN_ROUTINE, authSagas.loginRoutineSaga)
yield takeLatest(AT.LOGOUT, authSagas.logout)
yield takeLatest(
AT.LOGOUT_CLEAR_REDUX_STORE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const emailMismatch2faErrorMessage =
export const wrongCaptcha2faErrorMessage = 'Error: Captcha Code Incorrect'
export const wrongAuthCodeErrorMessage = 'Authentication code is incorrect'

export default ({ api, coreSagas }) => {
export default ({ api, coreSagas, rootDocument }) => {
const upgradeWallet = function*() {
try {
let password = yield call(promptForSecondPassword)
Expand Down Expand Up @@ -92,15 +92,16 @@ export default ({ api, coreSagas }) => {
if (userFlowSupported) yield put(actions.modules.profile.signIn())
}

const loginRoutineSaga = function*(mobileLogin, firstLogin) {
const loginRoutineSaga = function*({ payload: { mobileLogin, firstLogin } }) {
try {
// If needed, the user should upgrade its wallet before being able to open the wallet
const isHdWallet = yield select(selectors.core.wallet.isHdWallet)
if (!isHdWallet) {
yield call(upgradeWalletSaga)
}
yield put(actions.auth.authenticate())

yield call(coreSagas.kvStore.root.fetchRoot, askSecondPasswordEnhancer)

// If there was no ethereum metadata kv store entry, we need to create one and that requires the second password.
yield call(
coreSagas.kvStore.ethereum.fetchMetadataEthereum,
Expand All @@ -118,19 +119,13 @@ export default ({ api, coreSagas }) => {
yield put(actions.middleware.webSocket.eth.startSocket())
yield put(actions.middleware.webSocket.xlm.startStreams())
yield put(actions.router.push('/home'))
yield call(coreSagas.settings.fetchSettings)
yield put(actions.core.settings.fetchSettings())
yield call(coreSagas.data.xlm.fetchLedgerDetails)
yield call(coreSagas.data.xlm.fetchData)
yield call(authNabu)
yield call(upgradeAddressLabelsSaga)
yield put(actions.auth.loginSuccess())
yield put(actions.auth.startLogoutTimer())
// store guid in cache for future logins
const guid = yield select(selectors.core.wallet.getGuid)
yield put(actions.cache.guidEntered(guid))
// reset auth type and clear previous login form state
yield put(actions.auth.setAuthType(0))
yield put(actions.form.destroy('login'))
// set payload language to settings language
const language = yield select(selectors.preferences.getLanguage)
yield put(actions.modules.settings.updateLanguage(language))
Expand Down Expand Up @@ -222,7 +217,7 @@ export default ({ api, coreSagas }) => {
password,
code
})
yield call(loginRoutineSaga, mobileLogin)
yield put(actions.auth.loginRoutine(mobileLogin))
} catch (error) {
const initialError = prop('initial_error', error)
const authRequired = prop('authorization_required', error)
Expand All @@ -245,7 +240,7 @@ export default ({ api, coreSagas }) => {
session,
password
})
yield call(loginRoutineSaga, mobileLogin)
yield put(actions.auth.loginRoutine(mobileLogin))
} catch (error) {
if (error && error.auth_type > 0) {
yield put(actions.auth.setAuthType(error.auth_type))
Expand Down Expand Up @@ -334,7 +329,7 @@ export default ({ api, coreSagas }) => {
yield put(actions.alerts.displayInfo(C.CREATE_WALLET_INFO))
yield call(coreSagas.wallet.createWalletSaga, action.payload)
yield put(actions.alerts.displaySuccess(C.REGISTER_SUCCESS))
yield call(loginRoutineSaga, false, true)
yield put(actions.auth.loginRoutine(false, true))
yield put(actions.auth.registerSuccess())
} catch (e) {
yield put(actions.auth.registerFailure())
Expand All @@ -349,7 +344,7 @@ export default ({ api, coreSagas }) => {
yield put(actions.alerts.displayInfo(C.RESTORE_WALLET_INFO))
yield call(coreSagas.wallet.restoreWalletSaga, action.payload)
yield put(actions.alerts.displaySuccess(C.RESTORE_SUCCESS))
yield call(loginRoutineSaga, false, true)
yield put(actions.auth.loginRoutine(false, true))
yield put(actions.auth.restoreSuccess())
} catch (e) {
yield put(actions.auth.restoreFailure())
Expand Down

0 comments on commit f22a528

Please sign in to comment.