Skip to content

Commit

Permalink
Merge pull request #2533 from SelfKeyFoundation/2512-moonpay-auth
Browse files Browse the repository at this point in the history
2512 moonpay auth
  • Loading branch information
sk91 authored Dec 29, 2020
2 parents 292fcfc + b3fac12 commit d75c445
Show file tree
Hide file tree
Showing 58 changed files with 2,314 additions and 82 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"@material-ui/icons": "4.9.1",
"@material-ui/lab": "4.0.0-alpha.48",
"@material-ui/styles": "4.9.6",
"@reduxjs/toolkit": "1.5.0",
"@sentry/electron": "0.17.1",
"@trodi/electron-splashscreen": "0.3.4",
"@walletconnect/client": "1.3.1",
Expand Down Expand Up @@ -113,6 +114,7 @@
"md5": "2.2.1",
"mime-types": "2.1.23",
"moment": "2.24.0",
"nanoid": "3.1.20",
"node-fetch": "2.3.0",
"node-machine-id": "1.1.10",
"normalizr": "3.6.0",
Expand Down
13 changes: 8 additions & 5 deletions src/common/app/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getGlobalContext } from 'common/context';
import _ from 'lodash';
import crypto from 'crypto';
import { createAliasedAction } from 'electron-redux';
import { walletOperations, walletSelectors } from '../wallet';
Expand All @@ -16,14 +17,16 @@ const log = new Logger('app-redux');

const eventEmitter = new EventEmitter();

export const appSelectors = {};

const transformErrorMessage = msg => {
if (msg === 'Key derivation failed - possibly wrong password') {
return 'Wrong password. Please try again';
}
return msg;
};

export const initialState = {
const initialState = {
walletsLoading: false,
wallets: [],
seed: null,
Expand All @@ -42,7 +45,7 @@ export const initialState = {
keyStoreValue: null
};

export const appTypes = {
const appTypes = {
APP_SET_WALLETS: 'app/set/WALLETS',
APP_SET_SEED: 'app/set/SEED',
APP_SET_WALLETS_LOADING: 'app/set/WALLETS_LOADING',
Expand Down Expand Up @@ -741,7 +744,7 @@ const selectKeystoreValue = state => selectApp(state).keyStoreValue;

const selectSeed = state => selectApp(state).seed;

const appSelectors = {
_.merge(appSelectors, {
selectApp,
hasConnected,
hasAcceptedTracking,
Expand All @@ -754,8 +757,8 @@ const appSelectors = {
selectCanExportWallet,
selectKeystoreValue,
selectSeed
};
});

export { appSelectors, appReducers, appActions, appOperations };
export { appReducers, appActions, appOperations, appTypes, initialState };

export default reducer;
5 changes: 5 additions & 0 deletions src/common/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ const dev = {
deepLinks: true,
moonpay: true
},
moonPayApiKey: 'pk_test_WLWaG0mO6kbetXr3tOODlXGsnzs3HR',
moonPayApiEndpoint: 'https://api.moonpay.com/v3',
testWalletAddress: '0x23d233933c86f93b74705cf0d236b39f474249f8',
testDidAddress: '0xee10a3335f48e10b444e299cf017d57879109c1e32cec3e31103ceca7718d0ec',
attributeTypeSource: ATTRIBUTE_TYPE_SOURCE_OVERRIDE || 'development'
Expand Down Expand Up @@ -248,6 +250,9 @@ const prod = {
deepLinks: true,
moonpay: false
},
// TODO: change to prod before release
moonPayApiKey: 'pk_test_WLWaG0mO6kbetXr3tOODlXGsnzs3HR',
moonPayApiEndpoint: 'https://api.moonpay.com/v3',
attributeTypeSource: ATTRIBUTE_TYPE_SOURCE_OVERRIDE || 'production'
};

Expand Down
134 changes: 134 additions & 0 deletions src/common/hardware-wallet/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Logger } from 'common/logger';
import config from 'common/config';
import { createAliasedSlice } from '../utils/duck';
import { createSelector } from 'reselect';
import { appSelectors } from 'common/app';
import { push } from 'connected-react-router';
import { navigationFlowOperations, navigationFlowSelectors } from '../navigation/flow';

const log = new Logger('HardwareWalletDuck');
const SLICE_NAME = 'hardwareWallet';
const CONFIRMATION_TIMEOUT = config.hwConfirmTimeout || 30000;
let timeout = null;
const initialState = {
active: false,
error: false
};

const selectSelf = state => state[SLICE_NAME];

const isActive = createSelector(
selectSelf,
({ active }) => active
);

const isHardwareWallet = createSelector(
appSelectors.selectApp,
({ walletType }) => {
return ['trezor', 'ledger'].includes(walletType);
}
);

const selectors = { isHardwareWallet, isActive };

const useHardwareWalletOperation = ops => (
exec,
{ silent = false, cancelUrl, completeUrl }
) => async (dispatch, getState) => {
try {
await dispatch(
navigationFlowOperations.startFlow({
cancel: cancelUrl,
complete: completeUrl,
name: 'hd-auth'
})
);
if (!isHardwareWallet(getState())) {
const res = await exec();
await dispatch(navigationFlowOperations.navigateCompleteOperation());
return res;
}
clearTimeout(timeout);
if (isActive(getState())) {
log.debug('starting hw operation while another is in progress');
await dispatch(ops.cancel());
}
const timeoutPromise = new Promise((resolve, reject) => {
timeout = setTimeout(async () => {
reject(new Error('timeout'));
}, CONFIRMATION_TIMEOUT);
});

await dispatch(push('/main/hd-timer'));

const res = await Promise.race(timeoutPromise, exec());
await dispatch(navigationFlowOperations());
return res;
} catch (error) {
log.error(error);
if (isHardwareWallet(getState()) && isActive(getState())) {
await dispatch(ops.error());
clearTimeout(timeout);
if (error.statusText === 'CONDITIONS_OF_USE_NOT_SATISFIED') {
await dispatch(push('/main/hd-declined'));
} else if (error.code === 'Failure_ActionCancelled') {
await dispatch(push('/main/hd-declined'));
} else if (error.statusText === 'UNKNOWN_ERROR') {
await dispatch(push('/main/hd-unlock'));
} else if (error.message === 'timeout') {
await dispatch(push('/main/hd-timeout'));
} else {
await dispatch(push('/main/hd-error'));
if (!silent) throw error;
}
return;
} else if (!silent) {
throw error;
}
await dispatch(ops.cancelAuthOperation());
}
};

const cancelAuthOperation = ops => (opts = {}) => async (dispatch, getState) => {
if (isActive(getState())) {
await dispatch(ops.cancel());
}

const flow = navigationFlowSelectors.getCurrentFlow(getState());

if (!flow || flow.name !== 'hd-auth') {
if (opts.cancelRoute) {
await dispatch(push(opts.cancelRoute));
}
return;
}

await dispatch(navigationFlowOperations.navigateCancelOperation());
};

const hardwareWalletSlice = createAliasedSlice({
name: SLICE_NAME,
initialState,
reducers: {
start(state) {
state.active = true;
},
error(state) {
state.error = true;
},
cancel(state) {
state.active = false;
state.error = false;
}
},
operations: {
useHardwareWalletOperation,
cancelAuthOperation
}
});

const { reducer, operations } = hardwareWalletSlice;

export { operations as hardwareWalletOperations, selectors as hardwareWalletSelectors };

export default reducer;
56 changes: 56 additions & 0 deletions src/common/identity/identity-duck.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,32 @@ describe('Identity Duck', () => {
identitySelectors.selectIdentity(state, { identityId: 3, type: 'individual' })
).toEqual({ id: 3, type: 'individual' });
});

it('should memoize select identity', () => {
const res1 = identitySelectors.selectIdentity(state, {
identityId: 3,
type: 'individual'
});
const res2 = identitySelectors.selectIdentity(state, {
identityId: 3,
type: 'individual'
});
expect(res1).toBe(res2);
});
it('selectIdentity current', () => {
state.identity.currentIdentity = 3;
expect(identitySelectors.selectIdentity(state)).toEqual({
id: 3,
type: 'individual'
});
});
it('should memoize current identity', () => {
state.identity.currentIdentity = 3;
const res1 = identitySelectors.selectIdentity(state);
const res2 = identitySelectors.selectIdentity(state);

expect(res1).toBe(res2);
});
});
});
describe('Repositories', () => {
Expand Down Expand Up @@ -293,6 +312,43 @@ describe('Identity Duck', () => {
})
).toEqual(testIdAttributeTypes[0]);
});

describe('selectAttributeTypesByUrlsFactory', () => {
it('should select types by urls', () => {
const selector = identitySelectors.selectAttributeTypesByUrlsFactory();
const attributeTypeUrls = testIdAttributeTypes.slice(0, 2).map(t => t.url);
expect(selector(state, { attributeTypeUrls })).toEqual(
testIdAttributeTypes.slice(0, 2)
);
});

it('should memoize returned values', () => {
const selector = identitySelectors.selectAttributeTypesByUrlsFactory();
const attributeTypeUrls = testIdAttributeTypes.slice(0, 2).map(t => t.url);
const res1 = selector(state, { attributeTypeUrls });
const res2 = selector(state, { attributeTypeUrls });
expect(res1).toBe(res2);
});
});

describe('selectAttributeTypesByUrlsMappedFactory', () => {
it('should select types map by urls', () => {
const selector = identitySelectors.selectAttributeTypesByUrlsMappedFactory();
const attributeTypeUrls = testIdAttributeTypes.slice(0, 2).map(t => t.url);
expect(selector(state, { attributeTypeUrls })).toEqual({
[testIdAttributeTypes[0].id]: testIdAttributeTypes[0],
[testIdAttributeTypes[1].id]: testIdAttributeTypes[1]
});
});

it('should memoize returned values', () => {
const selector = identitySelectors.selectAttributeTypesByUrlsMappedFactory();
const attributeTypeUrls = testIdAttributeTypes.slice(0, 2).map(t => t.url);
const res1 = selector(state, { attributeTypeUrls });
const res2 = selector(state, { attributeTypeUrls });
expect(res1).toBe(res2);
});
});
});
});
describe('uiSchemas', () => {
Expand Down
14 changes: 14 additions & 0 deletions src/common/identity/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ export const identityReducers = {
};

const reducer = (state = initialState, action) => {
const { appTypes } = require('common/app');
switch (action.type) {
case identityTypes.IDENTITY_COUNTRIES_SET:
return identityReducers.setCountries(state, action);
Expand Down Expand Up @@ -282,6 +283,19 @@ const reducer = (state = initialState, action) => {
return identityReducers.updateIdentityReducer(state, action);
case identityTypes.IDENTITY_CURRENT_SET:
return identityReducers.setCurrentIdentityReducer(state, action);
case appTypes.APP_RESET:
return {
...initialState,
..._.pick(state, [
'repositories',
'repositoriesById',
'idAtrributeTypes',
'idAtrributeTypesById',
'uiSchemas',
'uiSchemasById',
'countries'
])
};
}
return state;
};
Expand Down
Loading

0 comments on commit d75c445

Please sign in to comment.