import { PPOM } from '@blockaid/ppom'; import { PPOMController } from '@metamask/ppom-validator'; import { BlockaidReason, BlockaidResultType, } from '../../../../shared/constants/security-provider'; import PreferencesController from '../../controllers/preferences'; const { sentry } = global as any; const ConfirmationMethods = Object.freeze([ 'eth_sendRawTransaction', 'eth_sendTransaction', 'eth_sign', 'eth_signTypedData', 'eth_signTypedData_v1', 'eth_signTypedData_v3', 'eth_signTypedData_v4', 'personal_sign', ]); /** * Middleware function that handles JSON RPC requests. * This function will be called for every JSON RPC request. * It will call the PPOM to check if the request is malicious or benign. * If the request is benign, it will be forwarded to the next middleware. * If the request is malicious or warning, it will trigger the PPOM alert dialog, * after the user has confirmed or rejected the request, * the request will be forwarded to the next middleware, together with the PPOM response. * * @param ppomController - Instance of PPOMController. * @param preferencesController - Instance of PreferenceController. * @returns PPOMMiddleware function. */ export function createPPOMMiddleware( ppomController: PPOMController, preferencesController: PreferencesController, ) { return async (req: any, _res: any, next: () => void) => { try { const securityAlertsEnabled = preferencesController.store.getState()?.securityAlertsEnabled; if (securityAlertsEnabled && ConfirmationMethods.includes(req.method)) { // eslint-disable-next-line require-atomic-updates req.securityAlertResponse = await ppomController.usePPOM( async (ppom: PPOM) => { return ppom.validateJsonRpc(req); }, ); } } catch (error: any) { sentry?.captureException(error); console.error('Error validating JSON RPC using PPOM: ', error); req.securityAlertResponse = { result_type: BlockaidResultType.Failed, reason: BlockaidReason.failed, description: 'Validating the confirmation failed by throwing error.', }; } finally { next(); } }; }