Смена сети: chainId, switch и add

Контракт живёт в конкретной сети. Если пользователь не в той сети, запросы провалятся — учимся проверять и переключать сеть.

chainId — числовой идентификатор сети (1 — Ethereum mainnet, 137 — Polygon, 11155111 — Sepolia). Контракт по одному адресу в разных сетях — это разные контракты.

Самая обидная ошибка новичка: dApp задеплоен в Polygon, а пользователь сидит в Ethereum mainnet. Вызовы идут «в пустоту» — по адресу контракта в mainnet ничего нет. Фронт обязан проверить сеть и помочь переключиться.

Проверка текущей сети

const chainIdHex = await window.ethereum.request({ method: "eth_chainId" });
const chainId = parseInt(chainIdHex, 16);
const EXPECTED = 137; // Polygon
if (chainId !== EXPECTED) {
  // показать баннер "Переключитесь на Polygon"
}

Переключение сети программно

Кошелёк позволяет попросить пользователя переключиться методом wallet_switchEthereumChain. Если сеть в кошельке не добавлена, прилетит ошибка с кодом 4902 — тогда сеть надо сперва добавить методом wallet_addEthereumChain:

async function switchToPolygon() {
  try {
    await window.ethereum.request({
      method: "wallet_switchEthereumChain",
      params: [{ chainId: "0x89" }], // 137 в hex
    });
  } catch (e) {
    if (e.code === 4902) {
      // сети нет в кошельке — добавим
      await window.ethereum.request({
        method: "wallet_addEthereumChain",
        params: [{
          chainId: "0x89",
          chainName: "Polygon",
          nativeCurrency: { name: "MATIC", symbol: "MATIC", decimals: 18 },
          rpcUrls: ["https://polygon-rpc.com"],
          blockExplorerUrls: ["https://polygonscan.com"],
        }],
      });
    }
  }
}

Конвертация chainId в hex — чистая логика

chainId в кошельковых методах передаётся строкой в hex. Перевод туда-обратно — обычная арифметика, которую легко проверить прямо здесь:

const toHex = (id) => "0x" + id.toString(16);
const fromHex = (h) => parseInt(h, 16);

console.log(toHex(137));        // 0x89
console.log(toHex(1));          // 0x1
console.log(fromHex("0xaa36a7")); // 11155111 (Sepolia)

Вывод:

0x89
0x1
11155111

Как работает под капотом

wallet_switchEthereumChain — это не транзакция, а запрос к кошельку сменить активную сеть. Пользователь подтверждает в окне; затем кошелёк эмитит событие chainChanged, на которое вы уже подписаны. Код 4902 («Unrecognized chain ID») — сигнал, что в кошельке такой сети просто нет в списке, и её надо добавить с параметрами RPC и обозревателя.

Частые ошибки

  • Не проверять сеть перед записью. Транзакция уйдёт не в ту сеть или провалится; пользователь потеряет газ впустую.
  • Передавать chainId числом, а не hex-строкой. Кошельковые методы ждут "0x89", а не 137.
  • Не обрабатывать код 4902. У пользователя может не быть нужной сети — её нужно предложить добавить.

Итоги

  • chainId определяет сеть; контракт привязан к конкретной сети.
  • Проверяйте сеть и предлагайте переключение через wallet_switchEthereumChain.
  • Код 4902 означает «сеть не добавлена» — добавьте её через wallet_addEthereumChain.
Проверьте себя
1. Что произойдёт, если контракт задеплоен в Polygon, а пользователь в Ethereum mainnet?
AВызовы автоматически перенаправятся
BПо адресу в mainnet контракта нет — вызовы провалятся
CКошелёк сам сменит сеть
DКонтракт скопируется в mainnet
2. Какой код ошибки означает, что нужной сети нет в кошельке?
A4001
B4902
C500
D0x89
3. В каком виде кошельковые методы ждут chainId?
AДесятичным числом 137
BHex-строкой '0x89'
CНазванием 'Polygon'
DБулевым флагом