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 6, 2022
1 parent 8a1548d commit 0a87755
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 4 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 @@ -223,7 +226,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 @@ -239,7 +244,7 @@ export default () => {
} else {
showLockOption();
}
} else {
} else if (!checkingBiometricForSending) {
dispatch(AppActions.showBlur(true));
}
}
Expand All @@ -252,6 +257,7 @@ export default () => {
pinLockActive,
lockAuthorizedUntil,
biometricLockActive,
checkingBiometricForSending,
appIsLoading,
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,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 @@ -133,6 +133,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 @@ -260,6 +260,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 @@ -510,6 +510,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 @@ -412,6 +412,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 @@ -266,3 +266,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 @@ -76,6 +76,7 @@ export interface AppState {
showKeyMigrationFailureModal: boolean;
keyMigrationFailureModalHasBeenShown: boolean;
activeModalId: ModalId | null;
checkingBiometricForSending: boolean;
}

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

export const appReducer = (
Expand Down Expand Up @@ -443,6 +445,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 @@ -63,6 +63,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 @@ -283,6 +284,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 @@ -330,4 +336,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 @@ -23,6 +23,7 @@ import {
import {checkEncryptPassword} from '../wallet/utils/wallet';
import {WrongPasswordError} from '../../navigation/wallet/components/ErrorMessages';
import {LogActions} from '../log';
import {checkBiometricForSending} from '../wallet/effects/send/send';

const BWC = BwcProvider.getInstance();

Expand Down Expand Up @@ -345,10 +346,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
48 changes: 47 additions & 1 deletion 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,
showBottomNotificationModal,
Expand All @@ -44,6 +45,13 @@ import {CommonActions} from '@react-navigation/native';
import {BwcProvider} from '../../../../lib/bwc';
import {ToCashAddress} from '../address/address';
import {WalletRowProps} from '../../../../components/list/WalletRow';
import TouchID from 'react-native-touch-id';
import {
authOptionalConfigObject,
BiometricErrorNotification,
isSupportedOptionalConfigObject,
TO_HANDLE_ERRORS,
} from '../../../../constants/BiometricError';

export const createProposalAndBuildTxDetails =
(
Expand Down Expand Up @@ -534,9 +542,20 @@ export const publishAndSign =
wallet: Wallet;
recipient?: Recipient;
}): Effect<Promise<Partial<TransactionProposal> | void>> =>
async dispatch => {
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 @@ -982,3 +1001,30 @@ export const showNoWalletsModal =
}),
);
};

export const checkBiometricForSending =
(): Effect<Promise<any>> => async dispatch => {
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 0a87755

Please sign in to comment.