1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-26 20:39:08 +01:00
metamask-extension/app/scripts/controllers/permissions/permissionsMethodMiddleware.js
Erik Marks 76a2a9bb8b
@metamask/eslint config@5.0.0 (#10358)
* @metamask/eslint-config@5.0.0
* Update eslintrc and prettierrc
* yarn lint:fix
2021-02-04 10:15:23 -08:00

113 lines
3.2 KiB
JavaScript

import { createAsyncMiddleware } from 'json-rpc-engine';
import { ethErrors } from 'eth-rpc-errors';
/**
* Create middleware for handling certain methods and preprocessing permissions requests.
*/
export default function createPermissionsMethodMiddleware({
addDomainMetadata,
getAccounts,
getUnlockPromise,
hasPermission,
notifyAccountsChanged,
requestAccountsPermission,
}) {
let isProcessingRequestAccounts = false;
return createAsyncMiddleware(async (req, res, next) => {
let responseHandler;
switch (req.method) {
// Intercepting eth_accounts requests for backwards compatibility:
// The getAccounts call below wraps the rpc-cap middleware, and returns
// an empty array in case of errors (such as 4100:unauthorized)
case 'eth_accounts': {
res.result = await getAccounts();
return;
}
case 'eth_requestAccounts': {
if (isProcessingRequestAccounts) {
res.error = ethErrors.rpc.resourceUnavailable(
'Already processing eth_requestAccounts. Please wait.',
);
return;
}
if (hasPermission('eth_accounts')) {
isProcessingRequestAccounts = true;
await getUnlockPromise();
isProcessingRequestAccounts = false;
}
// first, just try to get accounts
let accounts = await getAccounts();
if (accounts.length > 0) {
res.result = accounts;
return;
}
// if no accounts, request the accounts permission
try {
await requestAccountsPermission();
} catch (err) {
res.error = err;
return;
}
// get the accounts again
accounts = await getAccounts();
/* istanbul ignore else: too hard to induce, see below comment */
if (accounts.length > 0) {
res.result = accounts;
} else {
// this should never happen, because it should be caught in the
// above catch clause
res.error = ethErrors.rpc.internal(
'Accounts unexpectedly unavailable. Please report this bug.',
);
}
return;
}
// custom method for getting metadata from the requesting domain,
// sent automatically by the inpage provider when it's initialized
case 'metamask_sendDomainMetadata': {
if (typeof req.params?.name === 'string') {
addDomainMetadata(req.origin, req.params);
}
res.result = true;
return;
}
// register return handler to send accountsChanged notification
case 'wallet_requestPermissions': {
if ('eth_accounts' in req.params?.[0]) {
responseHandler = async () => {
if (Array.isArray(res.result)) {
for (const permission of res.result) {
if (permission.parentCapability === 'eth_accounts') {
notifyAccountsChanged(await getAccounts());
}
}
}
};
}
break;
}
default:
break;
}
// when this promise resolves, the response is on its way back
// eslint-disable-next-line node/callback-return
await next();
if (responseHandler) {
responseHandler();
}
});
}