mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
The network controller method `setProviderType` is now async, and the async operation `_setProviderConfig` called at the end of the method is now awaited. Because the only async operation was the last step, this should have no impact upon the flow of execution. The only functional change is that now any callers have the option of waiting until the network switch operation has completed. One such change was made, in the `switch-ethereum-chain` middleware. As a result, an error thrown while the network is switching will now be thrown in this middleware and returned to the dapp as an internal error. Relates to https://github.com/MetaMask/metamask-extension/issues/18587
133 lines
3.5 KiB
JavaScript
133 lines
3.5 KiB
JavaScript
import { ethErrors } from 'eth-rpc-errors';
|
|
import { omit } from 'lodash';
|
|
import { MESSAGE_TYPE } from '../../../../../shared/constants/app';
|
|
import {
|
|
CHAIN_ID_TO_TYPE_MAP,
|
|
NETWORK_TO_NAME_MAP,
|
|
CHAIN_ID_TO_RPC_URL_MAP,
|
|
CURRENCY_SYMBOLS,
|
|
NETWORK_TYPES,
|
|
} from '../../../../../shared/constants/network';
|
|
import {
|
|
isPrefixedFormattedHexString,
|
|
isSafeChainId,
|
|
} from '../../../../../shared/modules/network.utils';
|
|
|
|
const switchEthereumChain = {
|
|
methodNames: [MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN],
|
|
implementation: switchEthereumChainHandler,
|
|
hookNames: {
|
|
getCurrentChainId: true,
|
|
findNetworkConfigurationBy: true,
|
|
setProviderType: true,
|
|
setActiveNetwork: true,
|
|
requestUserApproval: true,
|
|
},
|
|
};
|
|
export default switchEthereumChain;
|
|
|
|
function findExistingNetwork(chainId, findNetworkConfigurationBy) {
|
|
if (chainId in CHAIN_ID_TO_TYPE_MAP) {
|
|
return {
|
|
chainId,
|
|
ticker: CURRENCY_SYMBOLS.ETH,
|
|
nickname: NETWORK_TO_NAME_MAP[chainId],
|
|
rpcUrl: CHAIN_ID_TO_RPC_URL_MAP[chainId],
|
|
type: CHAIN_ID_TO_TYPE_MAP[chainId],
|
|
};
|
|
}
|
|
|
|
return findNetworkConfigurationBy({ chainId });
|
|
}
|
|
|
|
async function switchEthereumChainHandler(
|
|
req,
|
|
res,
|
|
_next,
|
|
end,
|
|
{
|
|
getCurrentChainId,
|
|
findNetworkConfigurationBy,
|
|
setProviderType,
|
|
setActiveNetwork,
|
|
requestUserApproval,
|
|
},
|
|
) {
|
|
if (!req.params?.[0] || typeof req.params[0] !== 'object') {
|
|
return end(
|
|
ethErrors.rpc.invalidParams({
|
|
message: `Expected single, object parameter. Received:\n${JSON.stringify(
|
|
req.params,
|
|
)}`,
|
|
}),
|
|
);
|
|
}
|
|
|
|
const { origin } = req;
|
|
|
|
const { chainId } = req.params[0];
|
|
|
|
const otherKeys = Object.keys(omit(req.params[0], ['chainId']));
|
|
|
|
if (otherKeys.length > 0) {
|
|
return end(
|
|
ethErrors.rpc.invalidParams({
|
|
message: `Received unexpected keys on object parameter. Unsupported keys:\n${otherKeys}`,
|
|
}),
|
|
);
|
|
}
|
|
|
|
const _chainId = typeof chainId === 'string' && chainId.toLowerCase();
|
|
|
|
if (!isPrefixedFormattedHexString(_chainId)) {
|
|
return end(
|
|
ethErrors.rpc.invalidParams({
|
|
message: `Expected 0x-prefixed, unpadded, non-zero hexadecimal string 'chainId'. Received:\n${chainId}`,
|
|
}),
|
|
);
|
|
}
|
|
|
|
if (!isSafeChainId(parseInt(_chainId, 16))) {
|
|
return end(
|
|
ethErrors.rpc.invalidParams({
|
|
message: `Invalid chain ID "${_chainId}": numerical value greater than max safe value. Received:\n${chainId}`,
|
|
}),
|
|
);
|
|
}
|
|
|
|
const requestData = findExistingNetwork(_chainId, findNetworkConfigurationBy);
|
|
if (requestData) {
|
|
const currentChainId = getCurrentChainId();
|
|
if (currentChainId === _chainId) {
|
|
res.result = null;
|
|
return end();
|
|
}
|
|
try {
|
|
const approvedRequestData = await requestUserApproval({
|
|
origin,
|
|
type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN,
|
|
requestData,
|
|
});
|
|
if (
|
|
chainId in CHAIN_ID_TO_TYPE_MAP &&
|
|
approvedRequestData.type !== NETWORK_TYPES.LOCALHOST &&
|
|
approvedRequestData.type !== NETWORK_TYPES.LINEA_TESTNET
|
|
) {
|
|
await setProviderType(approvedRequestData.type);
|
|
} else {
|
|
await setActiveNetwork(approvedRequestData.id);
|
|
}
|
|
res.result = null;
|
|
} catch (error) {
|
|
return end(error);
|
|
}
|
|
return end();
|
|
}
|
|
return end(
|
|
ethErrors.provider.custom({
|
|
code: 4902, // To-be-standardized "unrecognized chain ID" error
|
|
message: `Unrecognized chain ID "${chainId}". Try adding the chain using ${MESSAGE_TYPE.ADD_ETHEREUM_CHAIN} first.`,
|
|
}),
|
|
);
|
|
}
|