1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-12 20:57:12 +01:00
metamask-extension/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js
Olusegun Akintayo 7ecb37ddf2
Fixes an issue where metamask popup is not loading on eth_accounts (#13840)
(first time).

Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com>
2022-03-07 19:09:03 +04:00

109 lines
3.2 KiB
JavaScript

import { ethErrors } from 'eth-rpc-errors';
import { MESSAGE_TYPE } from '../../../../../shared/constants/app';
/**
* This method attempts to retrieve the Ethereum accounts available to the
* requester, or initiate a request for account access if none are currently
* available. It is essentially a wrapper of wallet_requestPermissions that
* only errors if the user rejects the request. We maintain the method for
* backwards compatibility reasons.
*/
const requestEthereumAccounts = {
methodNames: [MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS],
implementation: requestEthereumAccountsHandler,
hookNames: {
origin: true,
getAccounts: true,
getUnlockPromise: true,
hasPermission: true,
requestAccountsPermission: true,
},
};
export default requestEthereumAccounts;
// Used to rate-limit pending requests to one per origin
const locks = new Set();
/**
* @typedef {Record<string, string | Function>} RequestEthereumAccountsOptions
* @property {string} origin - The requesting origin.
* @property {Function} getAccounts - Gets the accounts for the requesting
* origin.
* @property {Function} getUnlockPromise - Gets a promise that resolves when
* the extension unlocks.
* @property {Function} hasPermission - Returns whether the requesting origin
* has the specified permission.
* @property {Function} requestAccountsPermission - Requests the `eth_accounts`
* permission for the requesting origin.
*/
/**
*
* @param {import('json-rpc-engine').JsonRpcRequest<unknown>} _req - The JSON-RPC request object.
* @param {import('json-rpc-engine').JsonRpcResponse<true>} res - The JSON-RPC response object.
* @param {Function} _next - The json-rpc-engine 'next' callback.
* @param {Function} end - The json-rpc-engine 'end' callback.
* @param {RequestEthereumAccountsOptions} options - The RPC method hooks.
*/
async function requestEthereumAccountsHandler(
_req,
res,
_next,
end,
{
origin,
getAccounts,
getUnlockPromise,
hasPermission,
requestAccountsPermission,
},
) {
if (locks.has(origin)) {
res.error = ethErrors.rpc.resourceUnavailable(
`Already processing ${MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS}. Please wait.`,
);
return end();
}
if (hasPermission(MESSAGE_TYPE.ETH_ACCOUNTS)) {
// We wait for the extension to unlock in this case only, because permission
// requests are handled when the extension is unlocked, regardless of the
// lock state when they were received.
try {
locks.add(origin);
await getUnlockPromise(true);
res.result = await getAccounts();
end();
} catch (error) {
end(error);
} finally {
locks.delete(origin);
}
return undefined;
}
// If no accounts, request the accounts permission
try {
await requestAccountsPermission();
} catch (err) {
res.error = err;
return end();
}
// Get the approved accounts
const 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 end();
}