refactored the tx validator method

This commit is contained in:
Sadaqat Ali 2023-09-27 15:06:41 +05:00
parent 5e45fdeb69
commit e8aafe22cc
2 changed files with 89 additions and 108 deletions

View File

@ -16,10 +16,10 @@ import {
import { deepLinkParser } from '../../utils/deepLinkParser'; import { deepLinkParser } from '../../utils/deepLinkParser';
import RootNavigation from '../../navigation/rootNavigation'; import RootNavigation from '../../navigation/rootNavigation';
import getWindowDimensions from '../../utils/getWindowDimensions'; import getWindowDimensions from '../../utils/getWindowDimensions';
import { isHiveUri, validateParsedHiveUri } from '../../utils/hive-uri'; import { isHiveUri, getFormattedTx } from '../../utils/hive-uri';
import { handleHiveUriOperation, resolveTransaction } from '../../providers/hive/dhive'; import { handleHiveUriOperation, resolveTransaction } from '../../providers/hive/dhive';
import bugsnagInstance from '../../config/bugsnag'; import bugsnagInstance from '../../config/bugsnag';
import { get, isArray } from 'lodash'; import { get } from 'lodash';
import showLoginAlert from '../../utils/showLoginAlert'; import showLoginAlert from '../../utils/showLoginAlert';
import authType from '../../constants/authType'; import authType from '../../constants/authType';
import { delay } from '../../utils/editor'; import { delay } from '../../utils/editor';
@ -162,66 +162,64 @@ export const QRModal = ({}: QRModalProps) => {
authoritiesMap.set('owner', currentAccount?.local?.ownerKey ? true : false); authoritiesMap.set('owner', currentAccount?.local?.ownerKey ? true : false);
authoritiesMap.set('memo', currentAccount?.local?.memoKey ? true : false); authoritiesMap.set('memo', currentAccount?.local?.memoKey ? true : false);
const parsedHiveUriValidation = validateParsedHiveUri(parsed, authoritiesMap); getFormattedTx(parsed.tx, authoritiesMap)
if (parsedHiveUriValidation.error) { .then(async (formattedTx) => {
// show alert to user if parsed uri contains invalid operation data // resolve the decoded tx and params to a signable tx
Alert.alert( const tx = await resolveTransaction(formattedTx.tx, parsed.params, currentAccount.name);
intl.formatMessage( const ops = get(tx, 'operations', []);
{ id: parsedHiveUriValidation.key1 }, const op = ops[0];
{ key: parsedHiveUriValidation.keyType },
),
intl.formatMessage(
{
id: parsedHiveUriValidation.key2,
},
{ key: parsedHiveUriValidation.keyType },
),
);
return;
}
// resolve the decoded tx and params to a signable tx
const tx = await resolveTransaction(parsed.tx, parsed.params, currentAccount.name);
const ops = get(tx, 'operations', []);
const op = ops[0];
dispatch( dispatch(
showActionModal({ showActionModal({
title: intl.formatMessage({ title: intl.formatMessage({
id: 'qr.confirmTransaction', id: 'qr.confirmTransaction',
}),
bodyContent: _renderActionModalBody(op, parsedHiveUriValidation.opName),
buttons: [
{
text: intl.formatMessage({
id: 'qr.cancel',
}), }),
onPress: () => {}, bodyContent: _renderActionModalBody(op, formattedTx.opName),
style: 'cancel', buttons: [
}, {
{ text: intl.formatMessage({
text: intl.formatMessage({ id: 'qr.cancel',
id: 'qr.approve', }),
}), onPress: () => {},
onPress: () => { style: 'cancel',
handleHiveUriOperation(currentAccount, pinCode, tx) },
.then(() => { {
dispatch(toastNotification(intl.formatMessage({ id: 'alert.successful' }))); text: intl.formatMessage({
}) id: 'qr.approve',
.catch((err) => { }),
bugsnagInstance.notify(err); onPress: () => {
if (err) { handleHiveUriOperation(currentAccount, pinCode, tx)
dispatch(toastNotification(intl.formatMessage({ id: err }))); .then(() => {
} else { dispatch(toastNotification(intl.formatMessage({ id: 'alert.successful' })));
dispatch( })
toastNotification(intl.formatMessage({ id: 'qr.transaction_failed' })), .catch((err) => {
); bugsnagInstance.notify(err);
} if (err) {
}); dispatch(toastNotification(intl.formatMessage({ id: err })));
} else {
dispatch(
toastNotification(intl.formatMessage({ id: 'qr.transaction_failed' })),
);
}
});
},
},
],
}),
);
})
.catch((errObj) => {
Alert.alert(
intl.formatMessage({ id: errObj.errorKey1 }, { key: errObj.authorityKeyType }),
intl.formatMessage(
{
id: errObj.errorKey2,
}, },
}, { key: errObj.authorityKeyType },
], ),
}), );
); return;
});
}; };
const _handleDeepLink = async (url) => { const _handleDeepLink = async (url) => {

View File

@ -61,86 +61,69 @@ const _formatAmount = (amount: string) => {
}; };
/** /**
* Validates parsed data from hive-uri, checks if operation length is not greater than one and __signer is present in operation * Validates tx from parsed data from hive-uri, checks if operation length is not greater than one and __signer is present in operation
* Accepts parsed uri from decode method of hive-uri * Accepts tx object of parsed uri from decode method of hive-uri
* Returns an object with error status, keys for showing errors, and operation name parsed from operations.json * Returns promise with keys for showing errors, and operation name parsed from operations.json and in case of success returns formatted tx
* *
* */ * */
export const validateParsedHiveUri = (parsedUri: any, authoritiesMap: Map<string, boolean>) => { export const getFormattedTx = (tx: any, authoritiesMap: Map<string, boolean>) => {
let validateObj = { let opName;
error: false, let errorObj = {
key1: '', errorKey1: '',
key2: '', errorKey2: '',
opName: '', authorityKeyType: '',
keyType: '',
tx: parsedUri.tx,
}; };
const ops = get(parsedUri.tx, 'operations', []); const ops = get(tx, 'operations', []);
const isValidOp = _checkOpsArray(ops); const isValidOp = _checkOpsArray(ops);
if (!isValidOp) { if (!isValidOp) {
validateObj.error = true; errorObj.errorKey1 = 'qr.multi_array_ops_alert';
validateObj.key1 = 'qr.multi_array_ops_alert'; errorObj.errorKey2 = 'qr.multi_array_ops_aler_desct';
validateObj.key2 = 'qr.multi_array_ops_aler_desct'; return Promise.reject(errorObj);
return validateObj;
} }
const op = ops[0]; // single operation const op = ops[0]; // single operation
const operationName = op[0]; // operation name const operationName = op[0]; // operation name
let operationObj = op[1]; // operation object let operationObj = op[1]; // operation object
if (!operationName) { if (!operationName) {
validateObj.error = true; errorObj.errorKey1 = 'qr.invalid_op';
validateObj.key1 = 'qr.invalid_op'; errorObj.errorKey2 = 'qr.invalid_op_desc';
validateObj.key2 = 'qr.invalid_op_desc'; return Promise.reject(errorObj);
return validateObj;
} }
const opProps = getOperationProps(operationName); // get operation props from operations.json file i-e signer field and operation name const opProps = getOperationProps(operationName); // get operation props from operations.json file i-e signer field and operation name
validateObj.keyType = opProps?.opAuthority || ''; // set key type to validate object errorObj.authorityKeyType = opProps?.opAuthority || ''; // set key type to validate object
if (!opProps) { if (!opProps) {
validateObj.error = true; errorObj.errorKey1 = 'qr.invalid_op';
validateObj.key1 = 'qr.invalid_op'; errorObj.errorKey2 = 'qr.invalid_op_desc';
validateObj.key2 = 'qr.invalid_op_desc'; return Promise.reject(errorObj);
return validateObj;
} }
if (authoritiesMap && !authoritiesMap.get(opProps.opAuthority)) { if (authoritiesMap && !authoritiesMap.get(opProps.opAuthority)) {
validateObj.error = true; errorObj.errorKey1 = 'qr.invalid_key';
validateObj.key1 = 'qr.invalid_key'; errorObj.errorKey2 = 'qr.invalid_key_desc';
validateObj.key2 = 'qr.invalid_key_desc'; return Promise.reject(errorObj);
return validateObj;
} }
// if amount field present in operation, validate and check for proper formatting and format to 3 decimal places // if amount field present in operation, validate and check for proper formatting and format to 3 decimal places
if (operationObj.hasOwnProperty('amount')) { if (operationObj.hasOwnProperty('amount')) {
const amount = _formatAmount(operationObj.amount); const amount = _formatAmount(operationObj.amount);
operationObj.amount = amount; operationObj.amount = amount;
if (!amount) { if (!amount) {
validateObj.error = true; errorObj.errorKey1 = 'qr.invalid_amount';
validateObj.key1 = 'qr.invalid_amount'; errorObj.errorKey2 = 'qr.invalid_amount_desc';
validateObj.key2 = 'qr.invalid_amount_desc'; return Promise.reject(errorObj);
return validateObj;
} }
} }
const opSignerValue = get(op[1], opProps.signerField, ''); const opSignerValue = get(op[1], opProps.signerField, '');
// if signer field contains empty value, fill it with __signer // if signer field contains empty value, fill it with __signer
if (!opSignerValue) { if (!opSignerValue) {
operationObj[opProps.signerField] = '__signer'; operationObj[opProps.signerField] = '__signer';
validateObj.error = false;
validateObj.key1 = '';
validateObj.key2 = '';
validateObj.opName = opProps.opName;
validateObj.tx = {
...validateObj.tx,
operations: [[operationName, operationObj]],
};
return validateObj;
} }
validateObj.error = false;
validateObj.key1 = ''; opName = opProps.opName;
validateObj.key2 = ''; tx = {
validateObj.opName = opProps.opName; ...tx,
validateObj.tx = {
...validateObj.tx,
operations: [[operationName, operationObj]], operations: [[operationName, operationObj]],
}; };
return validateObj; // resolve with formatted tx and opName
return Promise.resolve({ tx: tx, opName: opName });
}; };