-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into improve-account-details-e2es
- Loading branch information
Showing
39 changed files
with
1,413 additions
and
322 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { createPPOMMiddleware } from './ppom-middleware'; | ||
|
||
Object.defineProperty(globalThis, 'fetch', { | ||
writable: true, | ||
value: () => undefined, | ||
}); | ||
|
||
Object.defineProperty(globalThis, 'performance', { | ||
writable: true, | ||
value: () => undefined, | ||
}); | ||
|
||
describe('PPOMMiddleware', () => { | ||
it('should call ppomController.usePPOM for requests of type confirmation', async () => { | ||
const useMock = jest.fn(); | ||
const controller = { | ||
usePPOM: useMock, | ||
}; | ||
const middlewareFunction = createPPOMMiddleware(controller as any); | ||
await middlewareFunction( | ||
{ method: 'eth_sendTransaction' }, | ||
undefined, | ||
() => undefined, | ||
); | ||
expect(useMock).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should add validation response on confirmation requests', async () => { | ||
const controller = { | ||
usePPOM: async () => Promise.resolve('VALIDATION_RESULT'), | ||
}; | ||
const middlewareFunction = createPPOMMiddleware(controller as any); | ||
const req = { method: 'eth_sendTransaction', ppomResponse: undefined }; | ||
await middlewareFunction(req, undefined, () => undefined); | ||
expect(req.ppomResponse).toBeDefined(); | ||
}); | ||
|
||
it('should call next method when ppomController.usePPOM completes', async () => { | ||
const ppom = { | ||
validateJsonRpc: () => undefined, | ||
}; | ||
const controller = { | ||
usePPOM: async (callback: any) => { | ||
callback(ppom); | ||
}, | ||
}; | ||
const middlewareFunction = createPPOMMiddleware(controller as any); | ||
const nextMock = jest.fn(); | ||
await middlewareFunction( | ||
{ method: 'eth_sendTransaction' }, | ||
undefined, | ||
nextMock, | ||
); | ||
expect(nextMock).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should call next method when ppomController.usePPOM throws error', async () => { | ||
const controller = { | ||
usePPOM: async (_callback: any) => { | ||
throw Error('Some error'); | ||
}, | ||
}; | ||
const middlewareFunction = createPPOMMiddleware(controller as any); | ||
const nextMock = jest.fn(); | ||
await middlewareFunction( | ||
{ method: 'eth_sendTransaction' }, | ||
undefined, | ||
nextMock, | ||
); | ||
expect(nextMock).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should call ppom.validateJsonRpc when invoked', async () => { | ||
const validateMock = jest.fn(); | ||
const ppom = { | ||
validateJsonRpc: validateMock, | ||
}; | ||
const controller = { | ||
usePPOM: async (callback: any) => { | ||
callback(ppom); | ||
}, | ||
}; | ||
const middlewareFunction = createPPOMMiddleware(controller as any); | ||
await middlewareFunction( | ||
{ method: 'eth_sendTransaction' }, | ||
undefined, | ||
() => undefined, | ||
); | ||
expect(validateMock).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should not call ppom.validateJsonRpc when request is not for confirmation method', async () => { | ||
const validateMock = jest.fn(); | ||
const ppom = { | ||
validateJsonRpc: validateMock, | ||
}; | ||
const controller = { | ||
usePPOM: async (callback: any) => { | ||
callback(ppom); | ||
}, | ||
}; | ||
const middlewareFunction = createPPOMMiddleware(controller as any); | ||
await middlewareFunction( | ||
{ method: 'eth_someRequest' }, | ||
undefined, | ||
() => undefined, | ||
); | ||
expect(validateMock).toHaveBeenCalledTimes(0); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { PPOM } from '@blockaid/ppom'; | ||
|
||
import { PPOMController } from '@metamask/ppom-validator'; | ||
|
||
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. | ||
* @returns PPOMMiddleware function. | ||
*/ | ||
export function createPPOMMiddleware(ppomController: PPOMController) { | ||
return async (req: any, _res: any, next: () => void) => { | ||
try { | ||
if (ConfirmationMethods.includes(req.method)) { | ||
// eslint-disable-next-line require-atomic-updates | ||
req.ppomResponse = await ppomController.usePPOM(async (ppom: PPOM) => { | ||
return ppom.validateJsonRpc(req); | ||
}); | ||
} | ||
} catch (error: unknown) { | ||
console.error('Error validating JSON RPC using PPOM: ', error); | ||
} finally { | ||
next(); | ||
} | ||
}; | ||
} |
Oops, something went wrong.