Skip to content

Commit

Permalink
[FEAT] biometric for sending
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielbazan7 committed Jun 22, 2022
1 parent 9ebfd0c commit 821c95f
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 3 deletions.
10 changes: 8 additions & 2 deletions src/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ export default () => {
);
const introCompleted = useAppSelector(({APP}) => APP.introCompleted);
const appIsLoading = useAppSelector(({APP}) => APP.appIsLoading);
const checkingBiometricForSending = useAppSelector(
({APP}) => APP.checkingBiometricForSending,
);
const appColorScheme = useAppSelector(({APP}) => APP.colorScheme);
const currentRoute = useAppSelector(({APP}) => APP.currentRoute);
const appLanguage = useAppSelector(({APP}) => APP.defaultLanguage);
Expand Down Expand Up @@ -220,7 +223,9 @@ export default () => {
};

if (onboardingCompleted) {
if (status === 'active' && !appIsLoading) {
if (status === 'active' && checkingBiometricForSending) {
dispatch(AppActions.checkingBiometricForSending(false));
} else if (status === 'active' && !appIsLoading) {
if (lockAuthorizedUntil) {
const now = Math.floor(Date.now() / 1000);
const totalSecs = lockAuthorizedUntil - now;
Expand All @@ -236,7 +241,7 @@ export default () => {
} else {
showLockOption();
}
} else {
} else if (!checkingBiometricForSending) {
dispatch(AppActions.showBlur(true));
}
}
Expand All @@ -249,6 +254,7 @@ export default () => {
pinLockActive,
lockAuthorizedUntil,
biometricLockActive,
checkingBiometricForSending,
appIsLoading,
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ const ChangellyCheckout: React.FC = () => {
case 'password canceled':
setResetSwipeButton(true);
break;
case 'biometric check failed':
setResetSwipeButton(true);
break;
default:
logger.error(JSON.stringify(err));
// TODO: handle this case
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ const WalletConnectConfirm = () => {
case 'password canceled':
setResetSwipeButton(true);
break;
case 'biometric check failed':
setResetSwipeButton(true);
break;
default:
await showErrorMessage(
CustomErrorMessage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ const WalletConnectRequestDetails = () => {
switch (err) {
case 'invalid password':
case 'password canceled':
case 'biometric check failed':
await sleep(800);
setApproveButtonState('loading');
await sleep(200);
Expand Down
3 changes: 3 additions & 0 deletions src/navigation/wallet/screens/TransactionProposalDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ const TransactionProposalDetails = () => {
case 'password canceled':
setResetSwipeButton(true);
break;
case 'biometric check failed':
setResetSwipeButton(true);
break;
default:
await showErrorMessage(
CustomErrorMessage({
Expand Down
3 changes: 3 additions & 0 deletions src/navigation/wallet/screens/send/confirm/Confirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@ const Confirm = () => {
case 'password canceled':
setResetSwipeButton(true);
break;
case 'biometric check failed':
setResetSwipeButton(true);
break;
default:
await showErrorMessage(
CustomErrorMessage({
Expand Down
7 changes: 7 additions & 0 deletions src/store/app/app.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,10 @@ export const activeModalUpdated = (id: ModalId | null): AppActionType => ({
type: AppActionTypes.ACTIVE_MODAL_UPDATED,
payload: id,
});

export const checkingBiometricForSending = (
checkingBiometricForSending: boolean,
): AppActionType => ({
type: AppActionTypes.CHECKING_BIOMETRIC_FOR_SENDING,
checkingBiometricForSending,
});
8 changes: 8 additions & 0 deletions src/store/app/app.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export interface AppState {
showKeyMigrationFailureModal: boolean;
keyMigrationFailureModalHasBeenShown: boolean;
activeModalId: ModalId | null;
checkingBiometricForSending: boolean;
}

const initialState: AppState = {
Expand Down Expand Up @@ -139,6 +140,7 @@ const initialState: AppState = {
showKeyMigrationFailureModal: false,
keyMigrationFailureModalHasBeenShown: false,
activeModalId: null,
checkingBiometricForSending: false,
};

export const appReducer = (
Expand Down Expand Up @@ -468,6 +470,12 @@ export const appReducer = (
activeModalId: action.payload,
};

case AppActionTypes.CHECKING_BIOMETRIC_FOR_SENDING:
return {
...state,
checkingBiometricForSending: action.checkingBiometricForSending,
};

default:
return state;
}
Expand Down
9 changes: 8 additions & 1 deletion src/store/app/app.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export enum AppActionTypes {
SET_SHOW_KEY_MIGRATION_FAILURE_MODAL = 'APP/SET_SHOW_KEY_MIGRATION_FAILURE_MODAL',
SET_KEY_MIGRATION_FAILURE_MODAL_HAS_BEEN_SHOWN = 'APP/SET_KEY_MIGRATION_FAILURE_MODAL_HAS_BEEN_SHOWN',
ACTIVE_MODAL_UPDATED = 'APP/ACTIVE_MODAL_UPDATED',
CHECKING_BIOMETRIC_FOR_SENDING = 'APP/CHECKING_BIOMETRIC_FOR_SENDING',
}

interface NetworkChanged {
Expand Down Expand Up @@ -293,6 +294,11 @@ interface ActiveModalUpdated {
payload: ModalId | null;
}

interface checkingBiometricForSending {
type: typeof AppActionTypes.CHECKING_BIOMETRIC_FOR_SENDING;
checkingBiometricForSending: boolean;
}

export type AppActionType =
| NetworkChanged
| SuccessAppInit
Expand Down Expand Up @@ -342,4 +348,5 @@ export type AppActionType =
| SetShowKeyMigrationFailureModal
| SetKeyMigrationFailureModalHasBeenShown
| SetDefaultAltCurrency
| ActiveModalUpdated;
| ActiveModalUpdated
| checkingBiometricForSending;
10 changes: 10 additions & 0 deletions src/store/wallet-connect/wallet-connect.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {checkEncryptPassword} from '../wallet/utils/wallet';
import {WrongPasswordError} from '../../navigation/wallet/components/ErrorMessages';
import {LogActions} from '../log';
import {t} from 'i18next';
import {checkBiometricForSending} from '../wallet/effects/send/send';

const BWC = BwcProvider.getInstance();

Expand Down Expand Up @@ -347,10 +348,19 @@ const getPrivKey =
return new Promise(async (resolve, reject) => {
try {
const {keys} = getState().WALLET;
const {biometricLockActive} = getState().APP;
const key: Key = keys[keyId];

let password: string | undefined;

if (biometricLockActive) {
try {
await dispatch(checkBiometricForSending());
} catch (error) {
return reject(error);
}
}

if (key.isPrivKeyEncrypted) {
password = await new Promise<string>((_resolve, _reject) => {
dispatch(
Expand Down
50 changes: 50 additions & 0 deletions src/store/wallet/effects/send/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {BWCErrorMessage, getErrorName} from '../../../../constants/BWCError';
import {Invoice} from '../../../shop/shop.models';
import {GetPayProDetails, HandlePayPro, PayProOptions} from '../paypro/paypro';
import {
checkingBiometricForSending,
dismissBottomNotificationModal,
dismissDecryptPasswordModal,
dismissOnGoingProcessModal,
Expand All @@ -48,6 +49,14 @@ import {WalletRowProps} from '../../../../components/list/WalletRow';
import {t} from 'i18next';
import {startOnGoingProcessModal} from '../../../app/app.effects';
import {OnGoingProcessMessages} from '../../../../components/modal/ongoing-process/OngoingProcess';
import TouchID from 'react-native-touch-id';
import {
authOptionalConfigObject,
BiometricErrorNotification,
isSupportedOptionalConfigObject,
TO_HANDLE_ERRORS,
} from '../../../../constants/BiometricError';
import {Platform} from 'react-native';

export const createProposalAndBuildTxDetails =
(
Expand Down Expand Up @@ -677,6 +686,17 @@ export const publishAndSign =
async (dispatch, getState) => {
return new Promise(async (resolve, reject) => {
let password;
const {
APP: {biometricLockActive},
} = getState();

if (biometricLockActive) {
try {
await dispatch(checkBiometricForSending());
} catch (error) {
return reject(error);
}
}
if (key.isPrivKeyEncrypted) {
try {
password = await new Promise<string>((_resolve, _reject) => {
Expand Down Expand Up @@ -1137,3 +1157,33 @@ export const showNoWalletsModal =
}),
);
};

export const checkBiometricForSending =
(): Effect<Promise<any>> => async dispatch => {
// preventing for asking biometric again when the app goes to background ( ios only )
if (Platform.OS === 'ios') {
dispatch(checkingBiometricForSending(true));
}
await TouchID.isSupported(isSupportedOptionalConfigObject)
.then(biometryType => {
if (biometryType === 'FaceID') {
console.log('FaceID is supported.');
} else {
console.log('TouchID is supported.');
}
return TouchID.authenticate(
'Authentication Check',
authOptionalConfigObject,
);
})
.catch(error => {
if (error.code && TO_HANDLE_ERRORS[error.code]) {
const err = TO_HANDLE_ERRORS[error.code];
dispatch(
showBottomNotificationModal(BiometricErrorNotification(err)),
);
}
return Promise.reject('biometric check failed');
});
return Promise.resolve();
};

0 comments on commit 821c95f

Please sign in to comment.