Інтеграція гаманця з MetaMask

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Інтеграція гаманця з MetaMask
Простий
~2-3 дні
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1306
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1218
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    920
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1147
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    610
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    885

Інтеграція кошелька з MetaMask

MetaMask інжектує window.ethereum в сторінку — та прямана робота з провайдером звичайно закінчується. У 2024 році писати window.ethereum.request({ method: 'eth_requestAccounts' }) напрямки — це або прототип, або технічний борг. Правильна інтеграція через wagmi + viem обробляє всі edge cases: кілька кошельків у браузері, зміна мережі, розрив з'єднання, мобільний MetaMask через deeplink.

Стек та підключення

wagmi v2 + viem — стандарт для сучасних dApp. Wagmi управляє станом підключення, автоматичним переподключенням, подіями. Viem — типізований low-level клієнт замість ethers.js.

import { createConfig, http } from 'wagmi'
import { mainnet, base } from 'wagmi/chains'
import { metaMask } from 'wagmi/connectors'

export const config = createConfig({
  chains: [mainnet, base],
  connectors: [metaMask()],
  transports: {
    [mainnet.id]: http(),
    [base.id]: http(),
  },
})

Кнопка підключення:

import { useConnect, useAccount, useDisconnect } from 'wagmi'

function ConnectButton() {
  const { address, isConnected } = useAccount()
  const { connect, connectors } = useConnect()
  const { disconnect } = useDisconnect()

  if (isConnected) {
    return (
      <button onClick={() => disconnect()}>
        {address?.slice(0, 6)}...{address?.slice(-4)}
      </button>
    )
  }

  const metamask = connectors.find(c => c.id === 'metaMaskSDK')
  return (
    <button onClick={() => connect({ connector: metamask! })}>
      Connect MetaMask
    </button>
  )
}

Зміна мережі та додавання кастомної мережі

Часта проблема: користувач на Ethereum mainnet, dApp працює на Base. Потрібно запросити переключення, а якщо мережа не додана — додати її.

import { useSwitchChain } from 'wagmi'

function NetworkGuard({ children, requiredChainId }: Props) {
  const { chainId } = useAccount()
  const { switchChain, isPending } = useSwitchChain()

  if (chainId !== requiredChainId) {
    return (
      <button
        onClick={() => switchChain({ chainId: requiredChainId })}
        disabled={isPending}
      >
        Switch to Base
      </button>
    )
  }
  return children
}

wagmi автоматично викликає wallet_addEthereumChain якщо wallet_switchEthereumChain повертає помилку 4902 (chain not found).

Підпис повідомлень та транзакції

EIP-712 typed data signing — для структурованих підписів (permit, orders, auth tokens):

import { useSignTypedData } from 'wagmi'

const { signTypedData } = useSignTypedData()

signTypedData({
  domain: { name: 'MyApp', version: '1', chainId: 8453 },
  types: {
    Login: [
      { name: 'address', type: 'address' },
      { name: 'nonce', type: 'string' },
    ],
  },
  primaryType: 'Login',
  message: { address: userAddress, nonce: sessionNonce },
})

Для SIWE (Sign-In with Ethereum) — бібліотека siwe генерує стандартизоване повідомлення, backend верифікує через SiweMessage.verify().

Обробка помилок

MetaMask повертає специфічні error codes:

  • 4001 — користувач відхилив запит
  • 4902 — мережа не знайдена
  • -32002 — запит вже чекає на підтвердження (другий вклик connect поки перший висить)
  • -32603 — internal JSON-RPC error (зазвичай insufficient gas або revert)
const { error } = useConnect()

useEffect(() => {
  if (error?.name === 'UserRejectedRequestError') {
    toast('Підключення скасовано')
  } else if (error?.name === 'ConnectorAlreadyConnectedError') {
    // вже підключено, ігноруємо
  }
}, [error])

Mobile deeplink

На мобільних MetaMask відкривається через deeplink metamask://dapp/<your-url>. wagmi MetaMask connector автоматично обробляє це через MetaMask SDK. Для коректної роботи на iOS потрібен HTTPS (не HTTP) та правильно налаштований WagmiProvider на верхньому рівні додатку.