window.ethereum и EIP-1193

Что такое window.ethereum, стандарт EIP-1193 и почему все кошельки разговаривают одним языком.

EIP-1193 — стандарт интерфейса провайдера кошелька: единый объект window.ethereum с методом request() и событиями, через который dApp общается с любым кошельком.

Когда пользователь устанавливает MetaMask, расширение внедряет в каждую страницу объект window.ethereum. Это и есть мост между вашим фронтом и кошельком. Благодаря стандарту EIP-1193 не важно, какой именно кошелёк стоит — интерфейс один.

Главный метод: request

Всё общение с кошельком идёт через один метод ethereum.request({ method, params }), возвращающий Promise. Имена методов — те же JSON-RPC плюс «кошельковые» расширения:

// Запросить подключение аккаунтов (откроет окно MetaMask)
const accounts = await window.ethereum.request({
  method: "eth_requestAccounts"
});
console.log("адрес:", accounts[0]);

// Узнать текущую сеть (chainId в hex)
const chainId = await window.ethereum.request({ method: "eth_chainId" });
console.log("chainId:", chainId); // напр. "0x1" для Ethereum mainnet

На практике вы редко зовёте request вручную — ethers.js и wagmi оборачивают его в удобные методы. Но понимать базовый слой важно: всё в итоге сводится к этому вызову.

eth_accounts против eth_requestAccounts

Тонкий, но важный момент:

  • eth_accountsтихо вернёт уже подключённые аккаунты (или пустой массив). Окно не открывает. Используется при загрузке, чтобы понять «а мы уже подключены?».
  • eth_requestAccountsактивно просит доступ: открывает окно кошелька. Зовите только по клику пользователя на кнопку «Подключить».

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

Объект window.ethereum — это прокси, который сериализует ваш вызов и через защищённый канал передаёт его в фоновый процесс расширения. Расширение решает, показать ли пользователю окно (для чувствительных методов вроде подключения и подписи) или ответить сразу (для безобидных чтений). Ответ возвращается обратно в Promise. Сам приватный ключ никогда не пересекает границу страницы — наружу выходит только результат (адрес, подпись, хеш транзакции).

Проверка наличия кошелька

Если кошелька нет, window.ethereum будет undefined. Всегда проверяйте перед использованием и предлагайте установить кошелёк:

if (typeof window.ethereum === "undefined") {
  // показать кнопку "Установить MetaMask"
} else {
  // кошелёк есть — можно подключаться
}

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

  • Звать eth_requestAccounts при загрузке страницы. Это навязчиво и блокируется браузерами; делайте только по клику.
  • Не проверять наличие window.ethereum. У части пользователей кошелька нет — приложение упадёт.
  • Считать, что кошелёк один. Несколько расширений могут конфликтовать за window.ethereum; стандарт EIP-6963 решает это, но базово помните о проблеме.

Итоги

  • window.ethereum — единый объект кошелька по стандарту EIP-1193.
  • Всё общение — через request({ method, params }).
  • eth_accounts читает тихо, eth_requestAccounts открывает окно (только по клику).
Проверьте себя
1. Какой метод открывает окно кошелька с запросом на подключение?
Aeth_accounts
Beth_chainId
Ceth_requestAccounts
Deth_blockNumber
2. Что вернёт eth_accounts, если кошелёк ещё не подключён к сайту?
AОткроет окно подключения
BПустой массив, тихо
CОшибку
DПриватный ключ
3. Зачем проверять typeof window.ethereum перед использованием?
AЭто требование TypeScript
BУ пользователя может не быть кошелька (undefined)
CЧтобы ускорить рендер
DЧтобы получить приватный ключ