Смена сети — addChain и switchChain
Как переключить MetaMask на нужную сеть через wallet_switchEthereumChain и добавить сеть через wallet_addEthereumChain, если её ещё нет в кошельке.
Зачем dApp переключает сеть
dApp работает только в той сети, где задеплоены её контракты.
Если контракт находится в Base, а пользователь открыл сайт с выбранным Ethereum Mainnet в MetaMask, транзакция уйдёт не туда или вообще не соберётся. Поэтому приложение должно проверить сеть и попросить кошелёк переключиться.
Переключаем MetaMask на Base
import { BrowserProvider } from "ethers";
type EthereumProvider = {
request(args: {
method: string;
params?: unknown[] | Record<string, unknown>;
}): Promise<unknown>;
};
declare global {
interface Window {
ethereum?: EthereumProvider;
}
}
const baseMainnet = {
chainId: "0x2105",
chainName: "Base",
nativeCurrency: {
name: "Ether",
symbol: "ETH",
decimals: 18,
},
rpcUrls: ["https://mainnet.base.org"],
blockExplorerUrls: ["https://basescan.org"],
};
const app = document.createElement("main");
app.innerHTML = `
<button id="switch-network">Переключиться на Base</button>
<pre id="network-info">Сеть не проверена</pre>
`;
document.body.appendChild(app);
const button = document.querySelector<HTMLButtonElement>("#switch-network");
const output = document.querySelector<HTMLPreElement>("#network-info");
if (!button || !output) {
throw new Error("Не удалось найти элементы интерфейса");
}
function getErrorCode(error: unknown): number | undefined {
if (typeof error === "object" && error !== null && "code" in error) {
const code = (error as { code: unknown }).code;
return typeof code === "number" ? code : undefined;
}
return undefined;
}
async function switchToBase() {
if (!window.ethereum) {
output.textContent = "MetaMask не найден. Установите расширение браузера.";
return;
}
try {
await window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: baseMainnet.chainId }],
});
} catch (error: unknown) {
if (getErrorCode(error) !== 4902) {
throw error;
}
await window.ethereum.request({
method: "wallet_addEthereumChain",
params: [baseMainnet],
});
await window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: baseMainnet.chainId }],
});
}
const provider = new BrowserProvider(window.ethereum);
const network = await provider.getNetwork();
output.textContent = `Текущая сеть: ${network.name} (${network.chainId})`;
}
button.addEventListener("click", () => {
switchToBase().catch((error: unknown) => {
const message = error instanceof Error ? error.message : "Неизвестная ошибка";
output.textContent = `Ошибка смены сети: ${message}`;
});
});Этот код должен выполняться в браузере. MetaMask показывает пользователю подтверждение перед сменой или добавлением сети.
Как это работает
chainId: "0x2105" — идентификатор Base Mainnet в шестнадцатеричном формате. MetaMask требует именно 0x-строку, а не число 8453.
wallet_switchEthereumChain — просит кошелёк переключиться на сеть с указанным chainId.
4902 — код ошибки MetaMask: такой сети ещё нет в кошельке пользователя.
wallet_addEthereumChain — просит добавить новую сеть. Для этого нужны chainName, rpcUrls, nativeCurrency и желательно blockExplorerUrls.
new BrowserProvider(window.ethereum) — после переключения читает активную сеть через ethers.js.
addChain не заменяет switchChain
wallet_addEthereumChain добавляет сеть в кошелёк, но приложение всё равно должно убедиться, что она стала активной.
Поэтому надёжный порядок такой:
1. Пробуем wallet_switchEthereumChain
2. Если получили 4902 — вызываем wallet_addEthereumChain
3. После добавления снова вызываем wallet_switchEthereumChain
4. Читаем provider.getNetwork() и проверяем результатТак приложение не зависит от того, переключил ли кошелёк сеть автоматически после добавления.
Частые ошибки
Передавать chainId как число → используйте строку в hex-формате: "0x2105", "0x1", "0x89".
Добавлять сеть без проверки ошибки 4902 → сначала пробуйте wallet_switchEthereumChain. Если сеть уже есть, добавлять её заново не нужно.
Использовать непроверенный RPC URL → пользователь доверяет сети, которую предлагает dApp. Указывайте официальный RPC или надёжного провайдера.
Что дальше
- Подключение MetaMask через BrowserProvider — подключить кошелёк перед сменой сети
- JsonRpcProvider и WebSocketProvider — понять, чем RPC-подключение отличается от браузерного кошелька
- Как работает транзакция изнутри — разобраться, почему сеть важна для подписи и отправки транзакций